Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

PM: Use spinlock instead of mutex in clock management functions

The lock member of struct pm_clk_data is of type struct mutex,
which is a problem, because the suspend and resume routines
defined in drivers/base/power/clock_ops.c cannot be executed
with interrupts disabled for this reason. Modify
struct pm_clk_data so that its lock member is a spinlock.

Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Magnus Damm <damm@opensource.se>

+22 -18
+22 -18
drivers/base/power/clock_ops.c
··· 19 19 20 20 struct pm_clk_data { 21 21 struct list_head clock_list; 22 - struct mutex lock; 22 + spinlock_t lock; 23 23 }; 24 24 25 25 enum pce_status { ··· 73 73 } 74 74 } 75 75 76 - mutex_lock(&pcd->lock); 76 + spin_lock_irq(&pcd->lock); 77 77 list_add_tail(&ce->node, &pcd->clock_list); 78 - mutex_unlock(&pcd->lock); 78 + spin_unlock_irq(&pcd->lock); 79 79 return 0; 80 80 } 81 81 ··· 83 83 * __pm_clk_remove - Destroy PM clock entry. 84 84 * @ce: PM clock entry to destroy. 85 85 * 86 - * This routine must be called under the mutex protecting the PM list of clocks 87 - * corresponding the the @ce's device. 86 + * This routine must be called under the spinlock protecting the PM list of 87 + * clocks corresponding the the @ce's device. 88 88 */ 89 89 static void __pm_clk_remove(struct pm_clock_entry *ce) 90 90 { ··· 123 123 if (!pcd) 124 124 return; 125 125 126 - mutex_lock(&pcd->lock); 126 + spin_lock_irq(&pcd->lock); 127 127 128 128 list_for_each_entry(ce, &pcd->clock_list, node) { 129 129 if (!con_id && !ce->con_id) { ··· 137 137 } 138 138 } 139 139 140 - mutex_unlock(&pcd->lock); 140 + spin_unlock_irq(&pcd->lock); 141 141 } 142 142 143 143 /** ··· 158 158 } 159 159 160 160 INIT_LIST_HEAD(&pcd->clock_list); 161 - mutex_init(&pcd->lock); 161 + spin_lock_init(&pcd->lock); 162 162 dev->power.subsys_data = pcd; 163 163 return 0; 164 164 } ··· 181 181 182 182 dev->power.subsys_data = NULL; 183 183 184 - mutex_lock(&pcd->lock); 184 + spin_lock_irq(&pcd->lock); 185 185 186 186 list_for_each_entry_safe_reverse(ce, c, &pcd->clock_list, node) 187 187 __pm_clk_remove(ce); 188 188 189 - mutex_unlock(&pcd->lock); 189 + spin_unlock_irq(&pcd->lock); 190 190 191 191 kfree(pcd); 192 192 } ··· 220 220 { 221 221 struct pm_clk_data *pcd = __to_pcd(dev); 222 222 struct pm_clock_entry *ce; 223 + unsigned long flags; 223 224 224 225 dev_dbg(dev, "%s()\n", __func__); 225 226 226 227 if (!pcd) 227 228 return 0; 228 229 229 - mutex_lock(&pcd->lock); 230 + spin_lock_irqsave(&pcd->lock, flags); 230 231 231 232 list_for_each_entry_reverse(ce, &pcd->clock_list, node) { 232 233 if (ce->status == PCE_STATUS_NONE) ··· 239 238 } 240 239 } 241 240 242 - mutex_unlock(&pcd->lock); 241 + spin_unlock_irqrestore(&pcd->lock, flags); 243 242 244 243 return 0; 245 244 } ··· 252 251 { 253 252 struct pm_clk_data *pcd = __to_pcd(dev); 254 253 struct pm_clock_entry *ce; 254 + unsigned long flags; 255 255 256 256 dev_dbg(dev, "%s()\n", __func__); 257 257 258 258 if (!pcd) 259 259 return 0; 260 260 261 - mutex_lock(&pcd->lock); 261 + spin_lock_irqsave(&pcd->lock, flags); 262 262 263 263 list_for_each_entry(ce, &pcd->clock_list, node) { 264 264 if (ce->status == PCE_STATUS_NONE) ··· 271 269 } 272 270 } 273 271 274 - mutex_unlock(&pcd->lock); 272 + spin_unlock_irqrestore(&pcd->lock, flags); 275 273 276 274 return 0; 277 275 } ··· 346 344 { 347 345 struct pm_clk_data *pcd = __to_pcd(dev); 348 346 struct pm_clock_entry *ce; 347 + unsigned long flags; 349 348 350 349 dev_dbg(dev, "%s()\n", __func__); 351 350 ··· 354 351 if (!pcd || !dev->driver) 355 352 return 0; 356 353 357 - mutex_lock(&pcd->lock); 354 + spin_lock_irqsave(&pcd->lock, flags); 358 355 359 356 list_for_each_entry_reverse(ce, &pcd->clock_list, node) 360 357 clk_disable(ce->clk); 361 358 362 - mutex_unlock(&pcd->lock); 359 + spin_unlock_irqrestore(&pcd->lock, flags); 363 360 364 361 return 0; 365 362 } ··· 372 369 { 373 370 struct pm_clk_data *pcd = __to_pcd(dev); 374 371 struct pm_clock_entry *ce; 372 + unsigned long flags; 375 373 376 374 dev_dbg(dev, "%s()\n", __func__); 377 375 ··· 380 376 if (!pcd || !dev->driver) 381 377 return 0; 382 378 383 - mutex_lock(&pcd->lock); 379 + spin_lock_irqsave(&pcd->lock, flags); 384 380 385 381 list_for_each_entry(ce, &pcd->clock_list, node) 386 382 clk_enable(ce->clk); 387 383 388 - mutex_unlock(&pcd->lock); 384 + spin_unlock_irqrestore(&pcd->lock, flags); 389 385 390 386 return 0; 391 387 }