diff options
Diffstat (limited to 'drivers/xen')
-rw-r--r-- | drivers/xen/balloon.c | 12 | ||||
-rw-r--r-- | drivers/xen/events.c | 10 | ||||
-rw-r--r-- | drivers/xen/gntdev.c | 39 | ||||
-rw-r--r-- | drivers/xen/grant-table.c | 6 | ||||
-rw-r--r-- | drivers/xen/xen-selfballoon.c | 67 | ||||
-rw-r--r-- | drivers/xen/xenbus/xenbus_probe_backend.c | 2 |
6 files changed, 114 insertions, 22 deletions
diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index fc43b53651d7..5876e1ae6c2d 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c | |||
@@ -501,20 +501,24 @@ EXPORT_SYMBOL_GPL(balloon_set_new_target); | |||
501 | * alloc_xenballooned_pages - get pages that have been ballooned out | 501 | * alloc_xenballooned_pages - get pages that have been ballooned out |
502 | * @nr_pages: Number of pages to get | 502 | * @nr_pages: Number of pages to get |
503 | * @pages: pages returned | 503 | * @pages: pages returned |
504 | * @highmem: highmem or lowmem pages | ||
504 | * @return 0 on success, error otherwise | 505 | * @return 0 on success, error otherwise |
505 | */ | 506 | */ |
506 | int alloc_xenballooned_pages(int nr_pages, struct page** pages) | 507 | int alloc_xenballooned_pages(int nr_pages, struct page **pages, bool highmem) |
507 | { | 508 | { |
508 | int pgno = 0; | 509 | int pgno = 0; |
509 | struct page* page; | 510 | struct page* page; |
510 | mutex_lock(&balloon_mutex); | 511 | mutex_lock(&balloon_mutex); |
511 | while (pgno < nr_pages) { | 512 | while (pgno < nr_pages) { |
512 | page = balloon_retrieve(true); | 513 | page = balloon_retrieve(highmem); |
513 | if (page) { | 514 | if (page && PageHighMem(page) == highmem) { |
514 | pages[pgno++] = page; | 515 | pages[pgno++] = page; |
515 | } else { | 516 | } else { |
516 | enum bp_state st; | 517 | enum bp_state st; |
517 | st = decrease_reservation(nr_pages - pgno, GFP_HIGHUSER); | 518 | if (page) |
519 | balloon_append(page); | ||
520 | st = decrease_reservation(nr_pages - pgno, | ||
521 | highmem ? GFP_HIGHUSER : GFP_USER); | ||
518 | if (st != BP_DONE) | 522 | if (st != BP_DONE) |
519 | goto out_undo; | 523 | goto out_undo; |
520 | } | 524 | } |
diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 7523719bf8a4..212a5c871bf4 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c | |||
@@ -432,7 +432,8 @@ static int __must_check xen_allocate_irq_dynamic(void) | |||
432 | 432 | ||
433 | irq = irq_alloc_desc_from(first, -1); | 433 | irq = irq_alloc_desc_from(first, -1); |
434 | 434 | ||
435 | xen_irq_init(irq); | 435 | if (irq >= 0) |
436 | xen_irq_init(irq); | ||
436 | 437 | ||
437 | return irq; | 438 | return irq; |
438 | } | 439 | } |
@@ -713,7 +714,7 @@ int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc, | |||
713 | mutex_lock(&irq_mapping_update_lock); | 714 | mutex_lock(&irq_mapping_update_lock); |
714 | 715 | ||
715 | irq = xen_allocate_irq_dynamic(); | 716 | irq = xen_allocate_irq_dynamic(); |
716 | if (irq == -1) | 717 | if (irq < 0) |
717 | goto out; | 718 | goto out; |
718 | 719 | ||
719 | irq_set_chip_and_handler_name(irq, &xen_pirq_chip, handle_edge_irq, | 720 | irq_set_chip_and_handler_name(irq, &xen_pirq_chip, handle_edge_irq, |
@@ -729,7 +730,7 @@ out: | |||
729 | error_irq: | 730 | error_irq: |
730 | mutex_unlock(&irq_mapping_update_lock); | 731 | mutex_unlock(&irq_mapping_update_lock); |
731 | xen_free_irq(irq); | 732 | xen_free_irq(irq); |
732 | return -1; | 733 | return ret; |
733 | } | 734 | } |
734 | #endif | 735 | #endif |
735 | 736 | ||
@@ -779,7 +780,7 @@ int xen_irq_from_pirq(unsigned pirq) | |||
779 | mutex_lock(&irq_mapping_update_lock); | 780 | mutex_lock(&irq_mapping_update_lock); |
780 | 781 | ||
781 | list_for_each_entry(info, &xen_irq_list_head, list) { | 782 | list_for_each_entry(info, &xen_irq_list_head, list) { |
782 | if (info == NULL || info->type != IRQT_PIRQ) | 783 | if (info->type != IRQT_PIRQ) |
783 | continue; | 784 | continue; |
784 | irq = info->irq; | 785 | irq = info->irq; |
785 | if (info->u.pirq.pirq == pirq) | 786 | if (info->u.pirq.pirq == pirq) |
@@ -1670,6 +1671,7 @@ void __init xen_init_IRQ(void) | |||
1670 | 1671 | ||
1671 | evtchn_to_irq = kcalloc(NR_EVENT_CHANNELS, sizeof(*evtchn_to_irq), | 1672 | evtchn_to_irq = kcalloc(NR_EVENT_CHANNELS, sizeof(*evtchn_to_irq), |
1672 | GFP_KERNEL); | 1673 | GFP_KERNEL); |
1674 | BUG_ON(!evtchn_to_irq); | ||
1673 | for (i = 0; i < NR_EVENT_CHANNELS; i++) | 1675 | for (i = 0; i < NR_EVENT_CHANNELS; i++) |
1674 | evtchn_to_irq[i] = -1; | 1676 | evtchn_to_irq[i] = -1; |
1675 | 1677 | ||
diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c index f914b26cf0c2..880798aae2f2 100644 --- a/drivers/xen/gntdev.c +++ b/drivers/xen/gntdev.c | |||
@@ -83,6 +83,7 @@ struct grant_map { | |||
83 | struct ioctl_gntdev_grant_ref *grants; | 83 | struct ioctl_gntdev_grant_ref *grants; |
84 | struct gnttab_map_grant_ref *map_ops; | 84 | struct gnttab_map_grant_ref *map_ops; |
85 | struct gnttab_unmap_grant_ref *unmap_ops; | 85 | struct gnttab_unmap_grant_ref *unmap_ops; |
86 | struct gnttab_map_grant_ref *kmap_ops; | ||
86 | struct page **pages; | 87 | struct page **pages; |
87 | }; | 88 | }; |
88 | 89 | ||
@@ -116,19 +117,22 @@ static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count) | |||
116 | add->grants = kzalloc(sizeof(add->grants[0]) * count, GFP_KERNEL); | 117 | add->grants = kzalloc(sizeof(add->grants[0]) * count, GFP_KERNEL); |
117 | add->map_ops = kzalloc(sizeof(add->map_ops[0]) * count, GFP_KERNEL); | 118 | add->map_ops = kzalloc(sizeof(add->map_ops[0]) * count, GFP_KERNEL); |
118 | add->unmap_ops = kzalloc(sizeof(add->unmap_ops[0]) * count, GFP_KERNEL); | 119 | add->unmap_ops = kzalloc(sizeof(add->unmap_ops[0]) * count, GFP_KERNEL); |
120 | add->kmap_ops = kzalloc(sizeof(add->kmap_ops[0]) * count, GFP_KERNEL); | ||
119 | add->pages = kzalloc(sizeof(add->pages[0]) * count, GFP_KERNEL); | 121 | add->pages = kzalloc(sizeof(add->pages[0]) * count, GFP_KERNEL); |
120 | if (NULL == add->grants || | 122 | if (NULL == add->grants || |
121 | NULL == add->map_ops || | 123 | NULL == add->map_ops || |
122 | NULL == add->unmap_ops || | 124 | NULL == add->unmap_ops || |
125 | NULL == add->kmap_ops || | ||
123 | NULL == add->pages) | 126 | NULL == add->pages) |
124 | goto err; | 127 | goto err; |
125 | 128 | ||
126 | if (alloc_xenballooned_pages(count, add->pages)) | 129 | if (alloc_xenballooned_pages(count, add->pages, false /* lowmem */)) |
127 | goto err; | 130 | goto err; |
128 | 131 | ||
129 | for (i = 0; i < count; i++) { | 132 | for (i = 0; i < count; i++) { |
130 | add->map_ops[i].handle = -1; | 133 | add->map_ops[i].handle = -1; |
131 | add->unmap_ops[i].handle = -1; | 134 | add->unmap_ops[i].handle = -1; |
135 | add->kmap_ops[i].handle = -1; | ||
132 | } | 136 | } |
133 | 137 | ||
134 | add->index = 0; | 138 | add->index = 0; |
@@ -142,6 +146,7 @@ err: | |||
142 | kfree(add->grants); | 146 | kfree(add->grants); |
143 | kfree(add->map_ops); | 147 | kfree(add->map_ops); |
144 | kfree(add->unmap_ops); | 148 | kfree(add->unmap_ops); |
149 | kfree(add->kmap_ops); | ||
145 | kfree(add); | 150 | kfree(add); |
146 | return NULL; | 151 | return NULL; |
147 | } | 152 | } |
@@ -243,10 +248,35 @@ static int map_grant_pages(struct grant_map *map) | |||
243 | gnttab_set_unmap_op(&map->unmap_ops[i], addr, | 248 | gnttab_set_unmap_op(&map->unmap_ops[i], addr, |
244 | map->flags, -1 /* handle */); | 249 | map->flags, -1 /* handle */); |
245 | } | 250 | } |
251 | } else { | ||
252 | /* | ||
253 | * Setup the map_ops corresponding to the pte entries pointing | ||
254 | * to the kernel linear addresses of the struct pages. | ||
255 | * These ptes are completely different from the user ptes dealt | ||
256 | * with find_grant_ptes. | ||
257 | */ | ||
258 | for (i = 0; i < map->count; i++) { | ||
259 | unsigned level; | ||
260 | unsigned long address = (unsigned long) | ||
261 | pfn_to_kaddr(page_to_pfn(map->pages[i])); | ||
262 | pte_t *ptep; | ||
263 | u64 pte_maddr = 0; | ||
264 | BUG_ON(PageHighMem(map->pages[i])); | ||
265 | |||
266 | ptep = lookup_address(address, &level); | ||
267 | pte_maddr = arbitrary_virt_to_machine(ptep).maddr; | ||
268 | gnttab_set_map_op(&map->kmap_ops[i], pte_maddr, | ||
269 | map->flags | | ||
270 | GNTMAP_host_map | | ||
271 | GNTMAP_contains_pte, | ||
272 | map->grants[i].ref, | ||
273 | map->grants[i].domid); | ||
274 | } | ||
246 | } | 275 | } |
247 | 276 | ||
248 | pr_debug("map %d+%d\n", map->index, map->count); | 277 | pr_debug("map %d+%d\n", map->index, map->count); |
249 | err = gnttab_map_refs(map->map_ops, map->pages, map->count); | 278 | err = gnttab_map_refs(map->map_ops, use_ptemod ? map->kmap_ops : NULL, |
279 | map->pages, map->count); | ||
250 | if (err) | 280 | if (err) |
251 | return err; | 281 | return err; |
252 | 282 | ||
@@ -462,13 +492,11 @@ static int gntdev_release(struct inode *inode, struct file *flip) | |||
462 | 492 | ||
463 | pr_debug("priv %p\n", priv); | 493 | pr_debug("priv %p\n", priv); |
464 | 494 | ||
465 | spin_lock(&priv->lock); | ||
466 | while (!list_empty(&priv->maps)) { | 495 | while (!list_empty(&priv->maps)) { |
467 | map = list_entry(priv->maps.next, struct grant_map, next); | 496 | map = list_entry(priv->maps.next, struct grant_map, next); |
468 | list_del(&map->next); | 497 | list_del(&map->next); |
469 | gntdev_put_map(map); | 498 | gntdev_put_map(map); |
470 | } | 499 | } |
471 | spin_unlock(&priv->lock); | ||
472 | 500 | ||
473 | if (use_ptemod) | 501 | if (use_ptemod) |
474 | mmu_notifier_unregister(&priv->mn, priv->mm); | 502 | mmu_notifier_unregister(&priv->mn, priv->mm); |
@@ -532,10 +560,11 @@ static long gntdev_ioctl_unmap_grant_ref(struct gntdev_priv *priv, | |||
532 | map = gntdev_find_map_index(priv, op.index >> PAGE_SHIFT, op.count); | 560 | map = gntdev_find_map_index(priv, op.index >> PAGE_SHIFT, op.count); |
533 | if (map) { | 561 | if (map) { |
534 | list_del(&map->next); | 562 | list_del(&map->next); |
535 | gntdev_put_map(map); | ||
536 | err = 0; | 563 | err = 0; |
537 | } | 564 | } |
538 | spin_unlock(&priv->lock); | 565 | spin_unlock(&priv->lock); |
566 | if (map) | ||
567 | gntdev_put_map(map); | ||
539 | return err; | 568 | return err; |
540 | } | 569 | } |
541 | 570 | ||
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c index 4f44b347b24a..8c71ab801756 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c | |||
@@ -448,7 +448,8 @@ unsigned int gnttab_max_grant_frames(void) | |||
448 | EXPORT_SYMBOL_GPL(gnttab_max_grant_frames); | 448 | EXPORT_SYMBOL_GPL(gnttab_max_grant_frames); |
449 | 449 | ||
450 | int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops, | 450 | int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops, |
451 | struct page **pages, unsigned int count) | 451 | struct gnttab_map_grant_ref *kmap_ops, |
452 | struct page **pages, unsigned int count) | ||
452 | { | 453 | { |
453 | int i, ret; | 454 | int i, ret; |
454 | pte_t *pte; | 455 | pte_t *pte; |
@@ -488,8 +489,7 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops, | |||
488 | */ | 489 | */ |
489 | return -EOPNOTSUPP; | 490 | return -EOPNOTSUPP; |
490 | } | 491 | } |
491 | ret = m2p_add_override(mfn, pages[i], | 492 | ret = m2p_add_override(mfn, pages[i], &kmap_ops[i]); |
492 | map_ops[i].flags & GNTMAP_contains_pte); | ||
493 | if (ret) | 493 | if (ret) |
494 | return ret; | 494 | return ret; |
495 | } | 495 | } |
diff --git a/drivers/xen/xen-selfballoon.c b/drivers/xen/xen-selfballoon.c index 6ea852e25162..d93c70857e03 100644 --- a/drivers/xen/xen-selfballoon.c +++ b/drivers/xen/xen-selfballoon.c | |||
@@ -68,6 +68,8 @@ | |||
68 | */ | 68 | */ |
69 | 69 | ||
70 | #include <linux/kernel.h> | 70 | #include <linux/kernel.h> |
71 | #include <linux/bootmem.h> | ||
72 | #include <linux/swap.h> | ||
71 | #include <linux/mm.h> | 73 | #include <linux/mm.h> |
72 | #include <linux/mman.h> | 74 | #include <linux/mman.h> |
73 | #include <linux/module.h> | 75 | #include <linux/module.h> |
@@ -93,6 +95,15 @@ static unsigned int selfballoon_uphysteresis __read_mostly = 1; | |||
93 | /* In HZ, controls frequency of worker invocation. */ | 95 | /* In HZ, controls frequency of worker invocation. */ |
94 | static unsigned int selfballoon_interval __read_mostly = 5; | 96 | static unsigned int selfballoon_interval __read_mostly = 5; |
95 | 97 | ||
98 | /* | ||
99 | * Minimum usable RAM in MB for selfballooning target for balloon. | ||
100 | * If non-zero, it is added to totalreserve_pages and self-ballooning | ||
101 | * will not balloon below the sum. If zero, a piecewise linear function | ||
102 | * is calculated as a minimum and added to totalreserve_pages. Note that | ||
103 | * setting this value indiscriminately may cause OOMs and crashes. | ||
104 | */ | ||
105 | static unsigned int selfballoon_min_usable_mb; | ||
106 | |||
96 | static void selfballoon_process(struct work_struct *work); | 107 | static void selfballoon_process(struct work_struct *work); |
97 | static DECLARE_DELAYED_WORK(selfballoon_worker, selfballoon_process); | 108 | static DECLARE_DELAYED_WORK(selfballoon_worker, selfballoon_process); |
98 | 109 | ||
@@ -189,20 +200,23 @@ static int __init xen_selfballooning_setup(char *s) | |||
189 | __setup("selfballooning", xen_selfballooning_setup); | 200 | __setup("selfballooning", xen_selfballooning_setup); |
190 | #endif /* CONFIG_FRONTSWAP */ | 201 | #endif /* CONFIG_FRONTSWAP */ |
191 | 202 | ||
203 | #define MB2PAGES(mb) ((mb) << (20 - PAGE_SHIFT)) | ||
204 | |||
192 | /* | 205 | /* |
193 | * Use current balloon size, the goal (vm_committed_as), and hysteresis | 206 | * Use current balloon size, the goal (vm_committed_as), and hysteresis |
194 | * parameters to set a new target balloon size | 207 | * parameters to set a new target balloon size |
195 | */ | 208 | */ |
196 | static void selfballoon_process(struct work_struct *work) | 209 | static void selfballoon_process(struct work_struct *work) |
197 | { | 210 | { |
198 | unsigned long cur_pages, goal_pages, tgt_pages; | 211 | unsigned long cur_pages, goal_pages, tgt_pages, floor_pages; |
212 | unsigned long useful_pages; | ||
199 | bool reset_timer = false; | 213 | bool reset_timer = false; |
200 | 214 | ||
201 | if (xen_selfballooning_enabled) { | 215 | if (xen_selfballooning_enabled) { |
202 | cur_pages = balloon_stats.current_pages; | 216 | cur_pages = totalram_pages; |
203 | tgt_pages = cur_pages; /* default is no change */ | 217 | tgt_pages = cur_pages; /* default is no change */ |
204 | goal_pages = percpu_counter_read_positive(&vm_committed_as) + | 218 | goal_pages = percpu_counter_read_positive(&vm_committed_as) + |
205 | balloon_stats.current_pages - totalram_pages; | 219 | totalreserve_pages; |
206 | #ifdef CONFIG_FRONTSWAP | 220 | #ifdef CONFIG_FRONTSWAP |
207 | /* allow space for frontswap pages to be repatriated */ | 221 | /* allow space for frontswap pages to be repatriated */ |
208 | if (frontswap_selfshrinking && frontswap_enabled) | 222 | if (frontswap_selfshrinking && frontswap_enabled) |
@@ -217,7 +231,26 @@ static void selfballoon_process(struct work_struct *work) | |||
217 | ((goal_pages - cur_pages) / | 231 | ((goal_pages - cur_pages) / |
218 | selfballoon_uphysteresis); | 232 | selfballoon_uphysteresis); |
219 | /* else if cur_pages == goal_pages, no change */ | 233 | /* else if cur_pages == goal_pages, no change */ |
220 | balloon_set_new_target(tgt_pages); | 234 | useful_pages = max_pfn - totalreserve_pages; |
235 | if (selfballoon_min_usable_mb != 0) | ||
236 | floor_pages = totalreserve_pages + | ||
237 | MB2PAGES(selfballoon_min_usable_mb); | ||
238 | /* piecewise linear function ending in ~3% slope */ | ||
239 | else if (useful_pages < MB2PAGES(16)) | ||
240 | floor_pages = max_pfn; /* not worth ballooning */ | ||
241 | else if (useful_pages < MB2PAGES(64)) | ||
242 | floor_pages = totalreserve_pages + MB2PAGES(16) + | ||
243 | ((useful_pages - MB2PAGES(16)) >> 1); | ||
244 | else if (useful_pages < MB2PAGES(512)) | ||
245 | floor_pages = totalreserve_pages + MB2PAGES(40) + | ||
246 | ((useful_pages - MB2PAGES(40)) >> 3); | ||
247 | else /* useful_pages >= MB2PAGES(512) */ | ||
248 | floor_pages = totalreserve_pages + MB2PAGES(99) + | ||
249 | ((useful_pages - MB2PAGES(99)) >> 5); | ||
250 | if (tgt_pages < floor_pages) | ||
251 | tgt_pages = floor_pages; | ||
252 | balloon_set_new_target(tgt_pages + | ||
253 | balloon_stats.current_pages - totalram_pages); | ||
221 | reset_timer = true; | 254 | reset_timer = true; |
222 | } | 255 | } |
223 | #ifdef CONFIG_FRONTSWAP | 256 | #ifdef CONFIG_FRONTSWAP |
@@ -340,6 +373,31 @@ static ssize_t store_selfballoon_uphys(struct sys_device *dev, | |||
340 | static SYSDEV_ATTR(selfballoon_uphysteresis, S_IRUGO | S_IWUSR, | 373 | static SYSDEV_ATTR(selfballoon_uphysteresis, S_IRUGO | S_IWUSR, |
341 | show_selfballoon_uphys, store_selfballoon_uphys); | 374 | show_selfballoon_uphys, store_selfballoon_uphys); |
342 | 375 | ||
376 | SELFBALLOON_SHOW(selfballoon_min_usable_mb, "%d\n", | ||
377 | selfballoon_min_usable_mb); | ||
378 | |||
379 | static ssize_t store_selfballoon_min_usable_mb(struct sys_device *dev, | ||
380 | struct sysdev_attribute *attr, | ||
381 | const char *buf, | ||
382 | size_t count) | ||
383 | { | ||
384 | unsigned long val; | ||
385 | int err; | ||
386 | |||
387 | if (!capable(CAP_SYS_ADMIN)) | ||
388 | return -EPERM; | ||
389 | err = strict_strtoul(buf, 10, &val); | ||
390 | if (err || val == 0) | ||
391 | return -EINVAL; | ||
392 | selfballoon_min_usable_mb = val; | ||
393 | return count; | ||
394 | } | ||
395 | |||
396 | static SYSDEV_ATTR(selfballoon_min_usable_mb, S_IRUGO | S_IWUSR, | ||
397 | show_selfballoon_min_usable_mb, | ||
398 | store_selfballoon_min_usable_mb); | ||
399 | |||
400 | |||
343 | #ifdef CONFIG_FRONTSWAP | 401 | #ifdef CONFIG_FRONTSWAP |
344 | SELFBALLOON_SHOW(frontswap_selfshrinking, "%d\n", frontswap_selfshrinking); | 402 | SELFBALLOON_SHOW(frontswap_selfshrinking, "%d\n", frontswap_selfshrinking); |
345 | 403 | ||
@@ -421,6 +479,7 @@ static struct attribute *selfballoon_attrs[] = { | |||
421 | &attr_selfballoon_interval.attr, | 479 | &attr_selfballoon_interval.attr, |
422 | &attr_selfballoon_downhysteresis.attr, | 480 | &attr_selfballoon_downhysteresis.attr, |
423 | &attr_selfballoon_uphysteresis.attr, | 481 | &attr_selfballoon_uphysteresis.attr, |
482 | &attr_selfballoon_min_usable_mb.attr, | ||
424 | #ifdef CONFIG_FRONTSWAP | 483 | #ifdef CONFIG_FRONTSWAP |
425 | &attr_frontswap_selfshrinking.attr, | 484 | &attr_frontswap_selfshrinking.attr, |
426 | &attr_frontswap_hysteresis.attr, | 485 | &attr_frontswap_hysteresis.attr, |
diff --git a/drivers/xen/xenbus/xenbus_probe_backend.c b/drivers/xen/xenbus/xenbus_probe_backend.c index 60adf919d78d..32417b5064fd 100644 --- a/drivers/xen/xenbus/xenbus_probe_backend.c +++ b/drivers/xen/xenbus/xenbus_probe_backend.c | |||
@@ -104,8 +104,6 @@ static int xenbus_uevent_backend(struct device *dev, | |||
104 | 104 | ||
105 | xdev = to_xenbus_device(dev); | 105 | xdev = to_xenbus_device(dev); |
106 | bus = container_of(xdev->dev.bus, struct xen_bus_type, bus); | 106 | bus = container_of(xdev->dev.bus, struct xen_bus_type, bus); |
107 | if (xdev == NULL) | ||
108 | return -ENODEV; | ||
109 | 107 | ||
110 | if (add_uevent_var(env, "MODALIAS=xen-backend:%s", xdev->devicetype)) | 108 | if (add_uevent_var(env, "MODALIAS=xen-backend:%s", xdev->devicetype)) |
111 | return -ENOMEM; | 109 | return -ENOMEM; |