PM / Runtime: Reduce code duplication in core helper functions

Reduce code duplication in rpm_idle(), rpm_suspend() and rpm_resume()
by using local pointers to store callback addresses and moving some
duplicated code into a separate function.

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Reviewed-by: Alan Stern <stern@rowland.harvard.edu>

+55 -69
+55 -69
drivers/base/power/runtime.c
··· 153 153 return retval; 154 154 } 155 155 156 - 157 156 /** 158 157 * rpm_idle - Notify device bus type if the device can be suspended. 159 158 * @dev: Device to notify the bus type about. ··· 166 167 * This function must be called under dev->power.lock with interrupts disabled. 167 168 */ 168 169 static int rpm_idle(struct device *dev, int rpmflags) 169 - __releases(&dev->power.lock) __acquires(&dev->power.lock) 170 170 { 171 + int (*callback)(struct device *); 171 172 int retval; 172 173 173 174 retval = rpm_check_suspend_allowed(dev); ··· 213 214 214 215 dev->power.idle_notification = true; 215 216 216 - if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_idle) { 217 + if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_idle) 218 + callback = dev->bus->pm->runtime_idle; 219 + else if (dev->type && dev->type->pm && dev->type->pm->runtime_idle) 220 + callback = dev->type->pm->runtime_idle; 221 + else if (dev->class && dev->class->pm) 222 + callback = dev->class->pm->runtime_idle; 223 + else 224 + callback = NULL; 225 + 226 + if (callback) { 217 227 spin_unlock_irq(&dev->power.lock); 218 228 219 - dev->bus->pm->runtime_idle(dev); 220 - 221 - spin_lock_irq(&dev->power.lock); 222 - } else if (dev->type && dev->type->pm && dev->type->pm->runtime_idle) { 223 - spin_unlock_irq(&dev->power.lock); 224 - 225 - dev->type->pm->runtime_idle(dev); 226 - 227 - spin_lock_irq(&dev->power.lock); 228 - } else if (dev->class && dev->class->pm 229 - && dev->class->pm->runtime_idle) { 230 - spin_unlock_irq(&dev->power.lock); 231 - 232 - dev->class->pm->runtime_idle(dev); 229 + callback(dev); 233 230 234 231 spin_lock_irq(&dev->power.lock); 235 232 } ··· 234 239 wake_up_all(&dev->power.wait_queue); 235 240 236 241 out: 242 + return retval; 243 + } 244 + 245 + /** 246 + * rpm_callback - Run a given runtime PM callback for a given device. 247 + * @cb: Runtime PM callback to run. 248 + * @dev: Device to run the callback for. 249 + */ 250 + static int rpm_callback(int (*cb)(struct device *), struct device *dev) 251 + __releases(&dev->power.lock) __acquires(&dev->power.lock) 252 + { 253 + int retval; 254 + 255 + if (!cb) 256 + return -ENOSYS; 257 + 258 + spin_unlock_irq(&dev->power.lock); 259 + 260 + retval = cb(dev); 261 + 262 + spin_lock_irq(&dev->power.lock); 263 + dev->power.runtime_error = retval; 264 + 237 265 return retval; 238 266 } 239 267 ··· 279 261 static int rpm_suspend(struct device *dev, int rpmflags) 280 262 __releases(&dev->power.lock) __acquires(&dev->power.lock) 281 263 { 264 + int (*callback)(struct device *); 282 265 struct device *parent = NULL; 283 266 bool notify = false; 284 267 int retval; ··· 370 351 371 352 __update_runtime_status(dev, RPM_SUSPENDING); 372 353 373 - if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_suspend) { 374 - spin_unlock_irq(&dev->power.lock); 354 + if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_suspend) 355 + callback = dev->bus->pm->runtime_suspend; 356 + else if (dev->type && dev->type->pm && dev->type->pm->runtime_suspend) 357 + callback = dev->type->pm->runtime_suspend; 358 + else if (dev->class && dev->class->pm) 359 + callback = dev->class->pm->runtime_suspend; 360 + else 361 + callback = NULL; 375 362 376 - retval = dev->bus->pm->runtime_suspend(dev); 377 - 378 - spin_lock_irq(&dev->power.lock); 379 - dev->power.runtime_error = retval; 380 - } else if (dev->type && dev->type->pm 381 - && dev->type->pm->runtime_suspend) { 382 - spin_unlock_irq(&dev->power.lock); 383 - 384 - retval = dev->type->pm->runtime_suspend(dev); 385 - 386 - spin_lock_irq(&dev->power.lock); 387 - dev->power.runtime_error = retval; 388 - } else if (dev->class && dev->class->pm 389 - && dev->class->pm->runtime_suspend) { 390 - spin_unlock_irq(&dev->power.lock); 391 - 392 - retval = dev->class->pm->runtime_suspend(dev); 393 - 394 - spin_lock_irq(&dev->power.lock); 395 - dev->power.runtime_error = retval; 396 - } else { 397 - retval = -ENOSYS; 398 - } 399 - 363 + retval = rpm_callback(callback, dev); 400 364 if (retval) { 401 365 __update_runtime_status(dev, RPM_ACTIVE); 402 366 dev->power.deferred_resume = 0; ··· 445 443 static int rpm_resume(struct device *dev, int rpmflags) 446 444 __releases(&dev->power.lock) __acquires(&dev->power.lock) 447 445 { 446 + int (*callback)(struct device *); 448 447 struct device *parent = NULL; 449 448 int retval = 0; 450 449 ··· 566 563 567 564 __update_runtime_status(dev, RPM_RESUMING); 568 565 569 - if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_resume) { 570 - spin_unlock_irq(&dev->power.lock); 566 + if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_resume) 567 + callback = dev->bus->pm->runtime_resume; 568 + else if (dev->type && dev->type->pm && dev->type->pm->runtime_resume) 569 + callback = dev->type->pm->runtime_resume; 570 + else if (dev->class && dev->class->pm) 571 + callback = dev->class->pm->runtime_resume; 572 + else 573 + callback = NULL; 571 574 572 - retval = dev->bus->pm->runtime_resume(dev); 573 - 574 - spin_lock_irq(&dev->power.lock); 575 - dev->power.runtime_error = retval; 576 - } else if (dev->type && dev->type->pm 577 - && dev->type->pm->runtime_resume) { 578 - spin_unlock_irq(&dev->power.lock); 579 - 580 - retval = dev->type->pm->runtime_resume(dev); 581 - 582 - spin_lock_irq(&dev->power.lock); 583 - dev->power.runtime_error = retval; 584 - } else if (dev->class && dev->class->pm 585 - && dev->class->pm->runtime_resume) { 586 - spin_unlock_irq(&dev->power.lock); 587 - 588 - retval = dev->class->pm->runtime_resume(dev); 589 - 590 - spin_lock_irq(&dev->power.lock); 591 - dev->power.runtime_error = retval; 592 - } else { 593 - retval = -ENOSYS; 594 - } 595 - 575 + retval = rpm_callback(callback, dev); 596 576 if (retval) { 597 577 __update_runtime_status(dev, RPM_SUSPENDED); 598 578 pm_runtime_cancel_pending(dev);