Problem Description: smu_release() in drivers/macintosh/smu.c calls schedule() while holding the spinlock pp->lock. AFAIK this should not be done as schedule() might sleep. further the code might produce a deadlock, in certain conditions pp->lock is acquired recursivly, first at the beginning of the function, then inside the for (;;) loop static int smu_release(struct inode *inode, struct file *file) { struct smu_private *pp = file->private_data; unsigned long flags; unsigned int busy; if (pp == 0) return 0; file->private_data = NULL; /* Mark file as closing to avoid races with new request */ spin_lock_irqsave(&pp->lock, flags); pp->mode = smu_file_closing; busy = pp->busy; /* Wait for any pending request to complete */ if (busy && pp->cmd.status == 1) { DECLARE_WAITQUEUE(wait, current); add_wait_queue(&pp->wait, &wait); for (;;) { set_current_state(TASK_UNINTERRUPTIBLE); if (pp->cmd.status != 1) break; spin_lock_irqsave(&pp->lock, flags); schedule(); spin_unlock_irqrestore(&pp->lock, flags); } set_current_state(TASK_RUNNING); remove_wait_queue(&pp->wait, &wait); } spin_unlock_irqrestore(&pp->lock, flags); spin_lock_irqsave(&smu_clist_lock, flags); list_del(&pp->list); spin_unlock_irqrestore(&smu_clist_lock, flags); kfree(pp); return 0; }
I queued a fix, thanks.