| .. | .. |
|---|
| 31 | 31 | */ |
|---|
| 32 | 32 | |
|---|
| 33 | 33 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
|---|
| 34 | +#define dev_fmt pr_fmt |
|---|
| 34 | 35 | |
|---|
| 35 | 36 | #define DPRINTK(fmt, args...) \ |
|---|
| 36 | 37 | pr_debug("xenbus_probe (%s:%d) " fmt ".\n", \ |
|---|
| .. | .. |
|---|
| 51 | 52 | #include <linux/module.h> |
|---|
| 52 | 53 | |
|---|
| 53 | 54 | #include <asm/page.h> |
|---|
| 54 | | -#include <asm/pgtable.h> |
|---|
| 55 | 55 | #include <asm/xen/hypervisor.h> |
|---|
| 56 | 56 | |
|---|
| 57 | 57 | #include <xen/xen.h> |
|---|
| .. | .. |
|---|
| 233 | 233 | return err; |
|---|
| 234 | 234 | } |
|---|
| 235 | 235 | |
|---|
| 236 | | - err = drv->probe(dev, id); |
|---|
| 237 | | - if (err) |
|---|
| 236 | + if (!try_module_get(drv->driver.owner)) { |
|---|
| 237 | + dev_warn(&dev->dev, "failed to acquire module reference on '%s'\n", |
|---|
| 238 | + drv->driver.name); |
|---|
| 239 | + err = -ESRCH; |
|---|
| 238 | 240 | goto fail; |
|---|
| 241 | + } |
|---|
| 242 | + |
|---|
| 243 | + down(&dev->reclaim_sem); |
|---|
| 244 | + err = drv->probe(dev, id); |
|---|
| 245 | + up(&dev->reclaim_sem); |
|---|
| 246 | + if (err) |
|---|
| 247 | + goto fail_put; |
|---|
| 239 | 248 | |
|---|
| 240 | 249 | err = watch_otherend(dev); |
|---|
| 241 | 250 | if (err) { |
|---|
| .. | .. |
|---|
| 245 | 254 | } |
|---|
| 246 | 255 | |
|---|
| 247 | 256 | return 0; |
|---|
| 257 | +fail_put: |
|---|
| 258 | + module_put(drv->driver.owner); |
|---|
| 248 | 259 | fail: |
|---|
| 249 | 260 | xenbus_dev_error(dev, err, "xenbus_dev_probe on %s", dev->nodename); |
|---|
| 250 | | - xenbus_switch_state(dev, XenbusStateClosed); |
|---|
| 251 | 261 | return err; |
|---|
| 252 | 262 | } |
|---|
| 253 | 263 | EXPORT_SYMBOL_GPL(xenbus_dev_probe); |
|---|
| .. | .. |
|---|
| 261 | 271 | |
|---|
| 262 | 272 | free_otherend_watch(dev); |
|---|
| 263 | 273 | |
|---|
| 264 | | - if (drv->remove) |
|---|
| 274 | + if (drv->remove) { |
|---|
| 275 | + down(&dev->reclaim_sem); |
|---|
| 265 | 276 | drv->remove(dev); |
|---|
| 277 | + up(&dev->reclaim_sem); |
|---|
| 278 | + } |
|---|
| 279 | + |
|---|
| 280 | + module_put(drv->driver.owner); |
|---|
| 266 | 281 | |
|---|
| 267 | 282 | free_otherend_details(dev); |
|---|
| 268 | 283 | |
|---|
| 269 | | - xenbus_switch_state(dev, XenbusStateClosed); |
|---|
| 284 | + /* |
|---|
| 285 | + * If the toolstack has forced the device state to closing then set |
|---|
| 286 | + * the state to closed now to allow it to be cleaned up. |
|---|
| 287 | + * Similarly, if the driver does not support re-bind, set the |
|---|
| 288 | + * closed. |
|---|
| 289 | + */ |
|---|
| 290 | + if (!drv->allow_rebind || |
|---|
| 291 | + xenbus_read_driver_state(dev->nodename) == XenbusStateClosing) |
|---|
| 292 | + xenbus_switch_state(dev, XenbusStateClosed); |
|---|
| 293 | + |
|---|
| 270 | 294 | return 0; |
|---|
| 271 | 295 | } |
|---|
| 272 | 296 | EXPORT_SYMBOL_GPL(xenbus_dev_remove); |
|---|
| 273 | | - |
|---|
| 274 | | -void xenbus_dev_shutdown(struct device *_dev) |
|---|
| 275 | | -{ |
|---|
| 276 | | - struct xenbus_device *dev = to_xenbus_device(_dev); |
|---|
| 277 | | - unsigned long timeout = 5*HZ; |
|---|
| 278 | | - |
|---|
| 279 | | - DPRINTK("%s", dev->nodename); |
|---|
| 280 | | - |
|---|
| 281 | | - get_device(&dev->dev); |
|---|
| 282 | | - if (dev->state != XenbusStateConnected) { |
|---|
| 283 | | - pr_info("%s: %s: %s != Connected, skipping\n", |
|---|
| 284 | | - __func__, dev->nodename, xenbus_strstate(dev->state)); |
|---|
| 285 | | - goto out; |
|---|
| 286 | | - } |
|---|
| 287 | | - xenbus_switch_state(dev, XenbusStateClosing); |
|---|
| 288 | | - timeout = wait_for_completion_timeout(&dev->down, timeout); |
|---|
| 289 | | - if (!timeout) |
|---|
| 290 | | - pr_info("%s: %s timeout closing device\n", |
|---|
| 291 | | - __func__, dev->nodename); |
|---|
| 292 | | - out: |
|---|
| 293 | | - put_device(&dev->dev); |
|---|
| 294 | | -} |
|---|
| 295 | | -EXPORT_SYMBOL_GPL(xenbus_dev_shutdown); |
|---|
| 296 | 297 | |
|---|
| 297 | 298 | int xenbus_register_driver_common(struct xenbus_driver *drv, |
|---|
| 298 | 299 | struct xen_bus_type *bus, |
|---|
| .. | .. |
|---|
| 473 | 474 | goto fail; |
|---|
| 474 | 475 | |
|---|
| 475 | 476 | dev_set_name(&xendev->dev, "%s", devname); |
|---|
| 477 | + sema_init(&xendev->reclaim_sem, 1); |
|---|
| 476 | 478 | |
|---|
| 477 | 479 | /* Register with generic device framework. */ |
|---|
| 478 | 480 | err = device_register(&xendev->dev); |
|---|
| .. | .. |
|---|
| 607 | 609 | if (drv->suspend) |
|---|
| 608 | 610 | err = drv->suspend(xdev); |
|---|
| 609 | 611 | if (err) |
|---|
| 610 | | - pr_warn("suspend %s failed: %i\n", dev_name(dev), err); |
|---|
| 612 | + dev_warn(dev, "suspend failed: %i\n", err); |
|---|
| 611 | 613 | return 0; |
|---|
| 612 | 614 | } |
|---|
| 613 | 615 | EXPORT_SYMBOL_GPL(xenbus_dev_suspend); |
|---|
| .. | .. |
|---|
| 626 | 628 | drv = to_xenbus_driver(dev->driver); |
|---|
| 627 | 629 | err = talk_to_otherend(xdev); |
|---|
| 628 | 630 | if (err) { |
|---|
| 629 | | - pr_warn("resume (talk_to_otherend) %s failed: %i\n", |
|---|
| 630 | | - dev_name(dev), err); |
|---|
| 631 | + dev_warn(dev, "resume (talk_to_otherend) failed: %i\n", err); |
|---|
| 631 | 632 | return err; |
|---|
| 632 | 633 | } |
|---|
| 633 | 634 | |
|---|
| .. | .. |
|---|
| 636 | 637 | if (drv->resume) { |
|---|
| 637 | 638 | err = drv->resume(xdev); |
|---|
| 638 | 639 | if (err) { |
|---|
| 639 | | - pr_warn("resume %s failed: %i\n", dev_name(dev), err); |
|---|
| 640 | + dev_warn(dev, "resume failed: %i\n", err); |
|---|
| 640 | 641 | return err; |
|---|
| 641 | 642 | } |
|---|
| 642 | 643 | } |
|---|
| 643 | 644 | |
|---|
| 644 | 645 | err = watch_otherend(xdev); |
|---|
| 645 | 646 | if (err) { |
|---|
| 646 | | - pr_warn("resume (watch_otherend) %s failed: %d.\n", |
|---|
| 647 | | - dev_name(dev), err); |
|---|
| 647 | + dev_warn(dev, "resume (watch_otherend) failed: %d\n", err); |
|---|
| 648 | 648 | return err; |
|---|
| 649 | 649 | } |
|---|
| 650 | 650 | |
|---|