diff options
| -rw-r--r-- | drivers/pnp/driver.c | 37 | ||||
| -rw-r--r-- | drivers/pnp/manager.c | 78 | ||||
| -rw-r--r-- | include/linux/pnp.h | 4 |
3 files changed, 95 insertions, 24 deletions
diff --git a/drivers/pnp/driver.c b/drivers/pnp/driver.c index ea2cb9a8b21d..15fb758a9e52 100644 --- a/drivers/pnp/driver.c +++ b/drivers/pnp/driver.c | |||
| @@ -150,19 +150,46 @@ static int pnp_bus_suspend(struct device *dev, pm_message_t state) | |||
| 150 | { | 150 | { |
| 151 | struct pnp_dev * pnp_dev = to_pnp_dev(dev); | 151 | struct pnp_dev * pnp_dev = to_pnp_dev(dev); |
| 152 | struct pnp_driver * pnp_drv = pnp_dev->driver; | 152 | struct pnp_driver * pnp_drv = pnp_dev->driver; |
| 153 | int error; | ||
| 154 | |||
| 155 | if (!pnp_drv) | ||
| 156 | return 0; | ||
| 157 | |||
| 158 | if (pnp_drv->suspend) { | ||
| 159 | error = pnp_drv->suspend(pnp_dev, state); | ||
| 160 | if (error) | ||
| 161 | return error; | ||
| 162 | } | ||
| 163 | |||
| 164 | if (!(pnp_drv->flags & PNP_DRIVER_RES_DO_NOT_CHANGE) && | ||
| 165 | pnp_can_disable(pnp_dev)) { | ||
| 166 | error = pnp_stop_dev(pnp_dev); | ||
| 167 | if (error) | ||
| 168 | return error; | ||
| 169 | } | ||
| 153 | 170 | ||
| 154 | if (pnp_drv && pnp_drv->suspend) | ||
| 155 | return pnp_drv->suspend(pnp_dev, state); | ||
| 156 | return 0; | 171 | return 0; |
| 157 | } | 172 | } |
| 158 | 173 | ||
| 159 | static void pnp_bus_resume(struct device *dev) | 174 | static int pnp_bus_resume(struct device *dev) |
| 160 | { | 175 | { |
| 161 | struct pnp_dev * pnp_dev = to_pnp_dev(dev); | 176 | struct pnp_dev * pnp_dev = to_pnp_dev(dev); |
| 162 | struct pnp_driver * pnp_drv = pnp_dev->driver; | 177 | struct pnp_driver * pnp_drv = pnp_dev->driver; |
| 178 | int error; | ||
| 179 | |||
| 180 | if (!pnp_drv) | ||
| 181 | return 0; | ||
| 182 | |||
| 183 | if (!(pnp_drv->flags & PNP_DRIVER_RES_DO_NOT_CHANGE)) { | ||
| 184 | error = pnp_start_dev(pnp_dev); | ||
| 185 | if (error) | ||
| 186 | return error; | ||
| 187 | } | ||
| 163 | 188 | ||
| 164 | if (pnp_drv && pnp_drv->resume) | 189 | if (pnp_drv->resume) |
| 165 | pnp_drv->resume(pnp_dev); | 190 | return pnp_drv->resume(pnp_dev); |
| 191 | |||
| 192 | return 0; | ||
| 166 | } | 193 | } |
| 167 | 194 | ||
| 168 | struct bus_type pnp_bus_type = { | 195 | struct bus_type pnp_bus_type = { |
diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c index 261668618b2d..c4256aa32bcb 100644 --- a/drivers/pnp/manager.c +++ b/drivers/pnp/manager.c | |||
| @@ -470,6 +470,53 @@ int pnp_auto_config_dev(struct pnp_dev *dev) | |||
| 470 | } | 470 | } |
| 471 | 471 | ||
| 472 | /** | 472 | /** |
| 473 | * pnp_start_dev - low-level start of the PnP device | ||
| 474 | * @dev: pointer to the desired device | ||
| 475 | * | ||
| 476 | * assumes that resources have alread been allocated | ||
| 477 | */ | ||
| 478 | |||
| 479 | int pnp_start_dev(struct pnp_dev *dev) | ||
| 480 | { | ||
| 481 | if (!pnp_can_write(dev)) { | ||
| 482 | pnp_info("Device %s does not supported activation.", dev->dev.bus_id); | ||
| 483 | return -EINVAL; | ||
| 484 | } | ||
| 485 | |||
| 486 | if (dev->protocol->set(dev, &dev->res)<0) { | ||
| 487 | pnp_err("Failed to activate device %s.", dev->dev.bus_id); | ||
| 488 | return -EIO; | ||
| 489 | } | ||
| 490 | |||
| 491 | pnp_info("Device %s activated.", dev->dev.bus_id); | ||
| 492 | |||
| 493 | return 0; | ||
| 494 | } | ||
| 495 | |||
| 496 | /** | ||
| 497 | * pnp_stop_dev - low-level disable of the PnP device | ||
| 498 | * @dev: pointer to the desired device | ||
| 499 | * | ||
| 500 | * does not free resources | ||
| 501 | */ | ||
| 502 | |||
| 503 | int pnp_stop_dev(struct pnp_dev *dev) | ||
| 504 | { | ||
| 505 | if (!pnp_can_disable(dev)) { | ||
| 506 | pnp_info("Device %s does not supported disabling.", dev->dev.bus_id); | ||
| 507 | return -EINVAL; | ||
| 508 | } | ||
| 509 | if (dev->protocol->disable(dev)<0) { | ||
| 510 | pnp_err("Failed to disable device %s.", dev->dev.bus_id); | ||
| 511 | return -EIO; | ||
| 512 | } | ||
| 513 | |||
| 514 | pnp_info("Device %s disabled.", dev->dev.bus_id); | ||
| 515 | |||
| 516 | return 0; | ||
| 517 | } | ||
| 518 | |||
| 519 | /** | ||
| 473 | * pnp_activate_dev - activates a PnP device for use | 520 | * pnp_activate_dev - activates a PnP device for use |
| 474 | * @dev: pointer to the desired device | 521 | * @dev: pointer to the desired device |
| 475 | * | 522 | * |
| @@ -477,6 +524,8 @@ int pnp_auto_config_dev(struct pnp_dev *dev) | |||
| 477 | */ | 524 | */ |
| 478 | int pnp_activate_dev(struct pnp_dev *dev) | 525 | int pnp_activate_dev(struct pnp_dev *dev) |
| 479 | { | 526 | { |
| 527 | int error; | ||
| 528 | |||
| 480 | if (!dev) | 529 | if (!dev) |
| 481 | return -EINVAL; | 530 | return -EINVAL; |
| 482 | if (dev->active) { | 531 | if (dev->active) { |
| @@ -487,18 +536,11 @@ int pnp_activate_dev(struct pnp_dev *dev) | |||
| 487 | if (pnp_auto_config_dev(dev)) | 536 | if (pnp_auto_config_dev(dev)) |
| 488 | return -EBUSY; | 537 | return -EBUSY; |
| 489 | 538 | ||
| 490 | if (!pnp_can_write(dev)) { | 539 | error = pnp_start_dev(dev); |
| 491 | pnp_info("Device %s does not supported activation.", dev->dev.bus_id); | 540 | if (error) |
| 492 | return -EINVAL; | 541 | return error; |
| 493 | } | ||
| 494 | |||
| 495 | if (dev->protocol->set(dev, &dev->res)<0) { | ||
| 496 | pnp_err("Failed to activate device %s.", dev->dev.bus_id); | ||
| 497 | return -EIO; | ||
| 498 | } | ||
| 499 | 542 | ||
| 500 | dev->active = 1; | 543 | dev->active = 1; |
| 501 | pnp_info("Device %s activated.", dev->dev.bus_id); | ||
| 502 | 544 | ||
| 503 | return 1; | 545 | return 1; |
| 504 | } | 546 | } |
| @@ -511,23 +553,19 @@ int pnp_activate_dev(struct pnp_dev *dev) | |||
| 511 | */ | 553 | */ |
| 512 | int pnp_disable_dev(struct pnp_dev *dev) | 554 | int pnp_disable_dev(struct pnp_dev *dev) |
| 513 | { | 555 | { |
| 556 | int error; | ||
| 557 | |||
| 514 | if (!dev) | 558 | if (!dev) |
| 515 | return -EINVAL; | 559 | return -EINVAL; |
| 516 | if (!dev->active) { | 560 | if (!dev->active) { |
| 517 | return 0; /* the device is already disabled */ | 561 | return 0; /* the device is already disabled */ |
| 518 | } | 562 | } |
| 519 | 563 | ||
| 520 | if (!pnp_can_disable(dev)) { | 564 | error = pnp_stop_dev(dev); |
| 521 | pnp_info("Device %s does not supported disabling.", dev->dev.bus_id); | 565 | if (error) |
| 522 | return -EINVAL; | 566 | return error; |
| 523 | } | ||
| 524 | if (dev->protocol->disable(dev)<0) { | ||
| 525 | pnp_err("Failed to disable device %s.", dev->dev.bus_id); | ||
| 526 | return -EIO; | ||
| 527 | } | ||
| 528 | 567 | ||
| 529 | dev->active = 0; | 568 | dev->active = 0; |
| 530 | pnp_info("Device %s disabled.", dev->dev.bus_id); | ||
| 531 | 569 | ||
| 532 | /* release the resources so that other devices can use them */ | 570 | /* release the resources so that other devices can use them */ |
| 533 | down(&pnp_res_mutex); | 571 | down(&pnp_res_mutex); |
| @@ -558,6 +596,8 @@ EXPORT_SYMBOL(pnp_manual_config_dev); | |||
| 558 | #if 0 | 596 | #if 0 |
| 559 | EXPORT_SYMBOL(pnp_auto_config_dev); | 597 | EXPORT_SYMBOL(pnp_auto_config_dev); |
| 560 | #endif | 598 | #endif |
| 599 | EXPORT_SYMBOL(pnp_start_dev); | ||
| 600 | EXPORT_SYMBOL(pnp_stop_dev); | ||
| 561 | EXPORT_SYMBOL(pnp_activate_dev); | 601 | EXPORT_SYMBOL(pnp_activate_dev); |
| 562 | EXPORT_SYMBOL(pnp_disable_dev); | 602 | EXPORT_SYMBOL(pnp_disable_dev); |
| 563 | EXPORT_SYMBOL(pnp_resource_change); | 603 | EXPORT_SYMBOL(pnp_resource_change); |
diff --git a/include/linux/pnp.h b/include/linux/pnp.h index 472319fcf631..93b0959eb40f 100644 --- a/include/linux/pnp.h +++ b/include/linux/pnp.h | |||
| @@ -385,6 +385,8 @@ void pnp_init_resource_table(struct pnp_resource_table *table); | |||
| 385 | int pnp_manual_config_dev(struct pnp_dev *dev, struct pnp_resource_table *res, int mode); | 385 | int pnp_manual_config_dev(struct pnp_dev *dev, struct pnp_resource_table *res, int mode); |
| 386 | int pnp_auto_config_dev(struct pnp_dev *dev); | 386 | int pnp_auto_config_dev(struct pnp_dev *dev); |
| 387 | int pnp_validate_config(struct pnp_dev *dev); | 387 | int pnp_validate_config(struct pnp_dev *dev); |
| 388 | int pnp_start_dev(struct pnp_dev *dev); | ||
| 389 | int pnp_stop_dev(struct pnp_dev *dev); | ||
| 388 | int pnp_activate_dev(struct pnp_dev *dev); | 390 | int pnp_activate_dev(struct pnp_dev *dev); |
| 389 | int pnp_disable_dev(struct pnp_dev *dev); | 391 | int pnp_disable_dev(struct pnp_dev *dev); |
| 390 | void pnp_resource_change(struct resource *resource, unsigned long start, unsigned long size); | 392 | void pnp_resource_change(struct resource *resource, unsigned long start, unsigned long size); |
| @@ -428,6 +430,8 @@ static inline void pnp_init_resource_table(struct pnp_resource_table *table) { } | |||
| 428 | static inline int pnp_manual_config_dev(struct pnp_dev *dev, struct pnp_resource_table *res, int mode) { return -ENODEV; } | 430 | static inline int pnp_manual_config_dev(struct pnp_dev *dev, struct pnp_resource_table *res, int mode) { return -ENODEV; } |
| 429 | static inline int pnp_auto_config_dev(struct pnp_dev *dev) { return -ENODEV; } | 431 | static inline int pnp_auto_config_dev(struct pnp_dev *dev) { return -ENODEV; } |
| 430 | static inline int pnp_validate_config(struct pnp_dev *dev) { return -ENODEV; } | 432 | static inline int pnp_validate_config(struct pnp_dev *dev) { return -ENODEV; } |
| 433 | static inline int pnp_start_dev(struct pnp_dev *dev) { return -ENODEV; } | ||
| 434 | static inline int pnp_stop_dev(struct pnp_dev *dev) { return -ENODEV; } | ||
| 431 | static inline int pnp_activate_dev(struct pnp_dev *dev) { return -ENODEV; } | 435 | static inline int pnp_activate_dev(struct pnp_dev *dev) { return -ENODEV; } |
| 432 | static inline int pnp_disable_dev(struct pnp_dev *dev) { return -ENODEV; } | 436 | static inline int pnp_disable_dev(struct pnp_dev *dev) { return -ENODEV; } |
| 433 | static inline void pnp_resource_change(struct resource *resource, unsigned long start, unsigned long size) { } | 437 | static inline void pnp_resource_change(struct resource *resource, unsigned long start, unsigned long size) { } |
