The pkg_temp_lock spinlock is acquired in the thermal vector handler which is truly atomic context even on PREEMPT_RT kernels. The critical sections are tiny, so change it to a raw spinlock.
Unified · Split
| @@ -63,7 +63,7 @@ static int max_id __read_mostly; · 62 unmodified lines | |||
| 63 | /* Array of zone pointers */ | 63 | /* Array of zone pointers */ |
| 64 | static struct zone_device **zones; | 64 | static struct zone_device **zones; |
| 65 | /* Serializes interrupt notification, work and hotplug */ | 65 | /* Serializes interrupt notification, work and hotplug */ |
| 66 | static DEFINE_SPINLOCK(pkg_temp_lock); | 66 | static DEFINE_RAW_SPINLOCK(pkg_temp_lock); |
| 67 | /* Protects zone operation in the work function against hotplug removal */ | 67 | /* Protects zone operation in the work function against hotplug removal */ |
| 68 | static DEFINE_MUTEX(thermal_zone_mutex); | 68 | static DEFINE_MUTEX(thermal_zone_mutex); |
| 69 | 69 | ||
| @@ -266,12 +266,12 @@ static void pkg_temp_thermal_threshold_work_fn(struct work_struct *work) · 196 unmodified lines | |||
| 266 | u64 msr_val, wr_val; | 266 | u64 msr_val, wr_val; |
| 267 | 267 | ||
| 268 | mutex_lock(&thermal_zone_mutex); | 268 | mutex_lock(&thermal_zone_mutex); |
| 269 | spin_lock_irq(&pkg_temp_lock); | 269 | raw_spin_lock_irq(&pkg_temp_lock); |
| 270 | ++pkg_work_cnt; | 270 | ++pkg_work_cnt; |
| 271 | 271 | ||
| 272 | zonedev = pkg_temp_thermal_get_dev(cpu); | 272 | zonedev = pkg_temp_thermal_get_dev(cpu); |
| 273 | if (!zonedev) { | 273 | if (!zonedev) { |
| 274 | spin_unlock_irq(&pkg_temp_lock); | 274 | raw_spin_unlock_irq(&pkg_temp_lock); |
| 275 | mutex_unlock(&thermal_zone_mutex); | 275 | mutex_unlock(&thermal_zone_mutex); |
| 276 | return; | 276 | return; |
| 277 | } | 277 | } |
| @@ -285,7 +285,7 @@ static void pkg_temp_thermal_threshold_work_fn(struct work_struct *work) · 7 unmodified lines | |||
| 285 | } | 285 | } |
| 286 | 286 | ||
| 287 | enable_pkg_thres_interrupt(); | 287 | enable_pkg_thres_interrupt(); |
| 288 | spin_unlock_irq(&pkg_temp_lock); | 288 | raw_spin_unlock_irq(&pkg_temp_lock); |
| 289 | 289 | ||
| 290 | /* | 290 | /* |
| 291 | * If tzone is not NULL, then thermal_zone_mutex will prevent the | 291 | * If tzone is not NULL, then thermal_zone_mutex will prevent the |
| @@ -310,7 +310,7 @@ static int pkg_thermal_notify(u64 msr_val) · 18 unmodified lines | |||
| 310 | struct zone_device *zonedev; | 310 | struct zone_device *zonedev; |
| 311 | unsigned long flags; | 311 | unsigned long flags; |
| 312 | 312 | ||
| 313 | spin_lock_irqsave(&pkg_temp_lock, flags); | 313 | raw_spin_lock_irqsave(&pkg_temp_lock, flags); |
| 314 | ++pkg_interrupt_cnt; | 314 | ++pkg_interrupt_cnt; |
| 315 | 315 | ||
| 316 | disable_pkg_thres_interrupt(); | 316 | disable_pkg_thres_interrupt(); |
| @@ -322,7 +322,7 @@ static int pkg_thermal_notify(u64 msr_val) · 5 unmodified lines | |||
| 322 | pkg_thermal_schedule_work(zonedev->cpu, &zonedev->work); | 322 | pkg_thermal_schedule_work(zonedev->cpu, &zonedev->work); |
| 323 | } | 323 | } |
| 324 | 324 | ||
| 325 | spin_unlock_irqrestore(&pkg_temp_lock, flags); | 325 | raw_spin_unlock_irqrestore(&pkg_temp_lock, flags); |
| 326 | return 0; | 326 | return 0; |
| 327 | } | 327 | } |
| 328 | 328 | ||
| @@ -368,9 +368,9 @@ static int pkg_temp_thermal_device_add(unsigned int cpu) · 39 unmodified lines | |||
| 368 | zonedev->msr_pkg_therm_high); | 368 | zonedev->msr_pkg_therm_high); |
| 369 | 369 | ||
| 370 | cpumask_set_cpu(cpu, &zonedev->cpumask); | 370 | cpumask_set_cpu(cpu, &zonedev->cpumask); |
| 371 | spin_lock_irq(&pkg_temp_lock); | 371 | raw_spin_lock_irq(&pkg_temp_lock); |
| 372 | zones[id] = zonedev; | 372 | zones[id] = zonedev; |
| 373 | spin_unlock_irq(&pkg_temp_lock); | 373 | raw_spin_unlock_irq(&pkg_temp_lock); |
| 374 | return 0; | 374 | return 0; |
| 375 | } | 375 | } |
| 376 | 376 | ||
| @@ -407,7 +407,7 @@ static int pkg_thermal_cpu_offline(unsigned int cpu) · 30 unmodified lines | |||
| 407 | } | 407 | } |
| 408 | 408 | ||
| 409 | /* Protect against work and interrupts */ | 409 | /* Protect against work and interrupts */ |
| 410 | spin_lock_irq(&pkg_temp_lock); | 410 | raw_spin_lock_irq(&pkg_temp_lock); |
| 411 | 411 | ||
| 412 | /* | 412 | /* |
| 413 | * Check whether this cpu was the current target and store the new | 413 | * Check whether this cpu was the current target and store the new |
| @@ -439,9 +439,9 @@ static int pkg_thermal_cpu_offline(unsigned int cpu) · 25 unmodified lines | |||
| 439 | * To cancel the work we need to drop the lock, otherwise | 439 | * To cancel the work we need to drop the lock, otherwise |
| 440 | * we might deadlock if the work needs to be flushed. | 440 | * we might deadlock if the work needs to be flushed. |
| 441 | */ | 441 | */ |
| 442 | spin_unlock_irq(&pkg_temp_lock); | 442 | raw_spin_unlock_irq(&pkg_temp_lock); |
| 443 | cancel_delayed_work_sync(&zonedev->work); | 443 | cancel_delayed_work_sync(&zonedev->work); |
| 444 | spin_lock_irq(&pkg_temp_lock); | 444 | raw_spin_lock_irq(&pkg_temp_lock); |
| 445 | /* | 445 | /* |
| 446 | * If this is not the last cpu in the package and the work | 446 | * If this is not the last cpu in the package and the work |
| 447 | * did not run after we dropped the lock above, then we | 447 | * did not run after we dropped the lock above, then we |
| @@ -452,7 +452,7 @@ static int pkg_thermal_cpu_offline(unsigned int cpu) · 4 unmodified lines | |||
| 452 | pkg_thermal_schedule_work(target, &zonedev->work); | 452 | pkg_thermal_schedule_work(target, &zonedev->work); |
| 453 | } | 453 | } |
| 454 | 454 | ||
| 455 | spin_unlock_irq(&pkg_temp_lock); | 455 | raw_spin_unlock_irq(&pkg_temp_lock); |
| 456 | 456 | ||
| 457 | /* Final cleanup if this is the last cpu */ | 457 | /* Final cleanup if this is the last cpu */ |
| 458 | if (lastcpu) | 458 | if (lastcpu) |