Don't disable IRQs, just tasklets, when taking the drm lock spinlock.
parent
9ba3aaaa1a
commit
10b9a116a7
|
@ -373,7 +373,6 @@ int drm_release(struct inode *inode, struct file *filp)
|
||||||
struct drm_file *file_priv = filp->private_data;
|
struct drm_file *file_priv = filp->private_data;
|
||||||
struct drm_device *dev = file_priv->minor->dev;
|
struct drm_device *dev = file_priv->minor->dev;
|
||||||
int retcode = 0;
|
int retcode = 0;
|
||||||
unsigned long irqflags;
|
|
||||||
|
|
||||||
lock_kernel();
|
lock_kernel();
|
||||||
|
|
||||||
|
@ -404,11 +403,9 @@ int drm_release(struct inode *inode, struct file *filp)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
do{
|
do{
|
||||||
spin_lock_irqsave(&dev->lock.spinlock,
|
spin_lock_bh(&dev->lock.spinlock);
|
||||||
irqflags);
|
|
||||||
locked = dev->lock.idle_has_lock;
|
locked = dev->lock.idle_has_lock;
|
||||||
spin_unlock_irqrestore(&dev->lock.spinlock,
|
spin_unlock_bh(&dev->lock.spinlock);
|
||||||
irqflags);
|
|
||||||
if (locked)
|
if (locked)
|
||||||
break;
|
break;
|
||||||
schedule();
|
schedule();
|
||||||
|
|
|
@ -53,7 +53,6 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
||||||
DECLARE_WAITQUEUE(entry, current);
|
DECLARE_WAITQUEUE(entry, current);
|
||||||
struct drm_lock *lock = data;
|
struct drm_lock *lock = data;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
unsigned long irqflags;
|
|
||||||
|
|
||||||
++file_priv->lock_count;
|
++file_priv->lock_count;
|
||||||
|
|
||||||
|
@ -72,9 +71,9 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
add_wait_queue(&dev->lock.lock_queue, &entry);
|
add_wait_queue(&dev->lock.lock_queue, &entry);
|
||||||
spin_lock_irqsave(&dev->lock.spinlock, irqflags);
|
spin_lock_bh(&dev->lock.spinlock);
|
||||||
dev->lock.user_waiters++;
|
dev->lock.user_waiters++;
|
||||||
spin_unlock_irqrestore(&dev->lock.spinlock, irqflags);
|
spin_unlock_bh(&dev->lock.spinlock);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
__set_current_state(TASK_INTERRUPTIBLE);
|
__set_current_state(TASK_INTERRUPTIBLE);
|
||||||
if (!dev->lock.hw_lock) {
|
if (!dev->lock.hw_lock) {
|
||||||
|
@ -96,9 +95,9 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
spin_lock_irqsave(&dev->lock.spinlock, irqflags);
|
spin_lock_bh(&dev->lock.spinlock);
|
||||||
dev->lock.user_waiters--;
|
dev->lock.user_waiters--;
|
||||||
spin_unlock_irqrestore(&dev->lock.spinlock, irqflags);
|
spin_unlock_bh(&dev->lock.spinlock);
|
||||||
__set_current_state(TASK_RUNNING);
|
__set_current_state(TASK_RUNNING);
|
||||||
remove_wait_queue(&dev->lock.lock_queue, &entry);
|
remove_wait_queue(&dev->lock.lock_queue, &entry);
|
||||||
|
|
||||||
|
@ -199,9 +198,8 @@ int drm_lock_take(struct drm_lock_data *lock_data,
|
||||||
{
|
{
|
||||||
unsigned int old, new, prev;
|
unsigned int old, new, prev;
|
||||||
volatile unsigned int *lock = &lock_data->hw_lock->lock;
|
volatile unsigned int *lock = &lock_data->hw_lock->lock;
|
||||||
unsigned long irqflags;
|
|
||||||
|
|
||||||
spin_lock_irqsave(&lock_data->spinlock, irqflags);
|
spin_lock_bh(&lock_data->spinlock);
|
||||||
do {
|
do {
|
||||||
old = *lock;
|
old = *lock;
|
||||||
if (old & _DRM_LOCK_HELD)
|
if (old & _DRM_LOCK_HELD)
|
||||||
|
@ -213,7 +211,7 @@ int drm_lock_take(struct drm_lock_data *lock_data,
|
||||||
}
|
}
|
||||||
prev = cmpxchg(lock, old, new);
|
prev = cmpxchg(lock, old, new);
|
||||||
} while (prev != old);
|
} while (prev != old);
|
||||||
spin_unlock_irqrestore(&lock_data->spinlock, irqflags);
|
spin_unlock_bh(&lock_data->spinlock);
|
||||||
|
|
||||||
if (_DRM_LOCKING_CONTEXT(old) == context) {
|
if (_DRM_LOCKING_CONTEXT(old) == context) {
|
||||||
if (old & _DRM_LOCK_HELD) {
|
if (old & _DRM_LOCK_HELD) {
|
||||||
|
@ -275,16 +273,15 @@ int drm_lock_free(struct drm_lock_data *lock_data, unsigned int context)
|
||||||
{
|
{
|
||||||
unsigned int old, new, prev;
|
unsigned int old, new, prev;
|
||||||
volatile unsigned int *lock = &lock_data->hw_lock->lock;
|
volatile unsigned int *lock = &lock_data->hw_lock->lock;
|
||||||
unsigned long irqflags;
|
|
||||||
|
|
||||||
spin_lock_irqsave(&lock_data->spinlock, irqflags);
|
spin_lock_bh(&lock_data->spinlock);
|
||||||
if (lock_data->kernel_waiters != 0) {
|
if (lock_data->kernel_waiters != 0) {
|
||||||
drm_lock_transfer(lock_data, 0);
|
drm_lock_transfer(lock_data, 0);
|
||||||
lock_data->idle_has_lock = 1;
|
lock_data->idle_has_lock = 1;
|
||||||
spin_unlock_irqrestore(&lock_data->spinlock, irqflags);
|
spin_unlock_bh(&lock_data->spinlock);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&lock_data->spinlock, irqflags);
|
spin_unlock_bh(&lock_data->spinlock);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
old = *lock;
|
old = *lock;
|
||||||
|
@ -348,20 +345,19 @@ static int drm_notifier(void *priv)
|
||||||
void drm_idlelock_take(struct drm_lock_data *lock_data)
|
void drm_idlelock_take(struct drm_lock_data *lock_data)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
unsigned long irqflags;
|
|
||||||
|
|
||||||
spin_lock_irqsave(&lock_data->spinlock, irqflags);
|
spin_lock_bh(&lock_data->spinlock);
|
||||||
lock_data->kernel_waiters++;
|
lock_data->kernel_waiters++;
|
||||||
if (!lock_data->idle_has_lock) {
|
if (!lock_data->idle_has_lock) {
|
||||||
|
|
||||||
spin_unlock_irqrestore(&lock_data->spinlock, irqflags);
|
spin_unlock_bh(&lock_data->spinlock);
|
||||||
ret = drm_lock_take(lock_data, DRM_KERNEL_CONTEXT);
|
ret = drm_lock_take(lock_data, DRM_KERNEL_CONTEXT);
|
||||||
spin_lock_irqsave(&lock_data->spinlock, irqflags);
|
spin_lock_bh(&lock_data->spinlock);
|
||||||
|
|
||||||
if (ret == 1)
|
if (ret == 1)
|
||||||
lock_data->idle_has_lock = 1;
|
lock_data->idle_has_lock = 1;
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&lock_data->spinlock, irqflags);
|
spin_unlock_bh(&lock_data->spinlock);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(drm_idlelock_take);
|
EXPORT_SYMBOL(drm_idlelock_take);
|
||||||
|
|
||||||
|
@ -369,9 +365,8 @@ void drm_idlelock_release(struct drm_lock_data *lock_data)
|
||||||
{
|
{
|
||||||
unsigned int old, prev;
|
unsigned int old, prev;
|
||||||
volatile unsigned int *lock = &lock_data->hw_lock->lock;
|
volatile unsigned int *lock = &lock_data->hw_lock->lock;
|
||||||
unsigned long irqflags;
|
|
||||||
|
|
||||||
spin_lock_irqsave(&lock_data->spinlock, irqflags);
|
spin_lock_bh(&lock_data->spinlock);
|
||||||
if (--lock_data->kernel_waiters == 0) {
|
if (--lock_data->kernel_waiters == 0) {
|
||||||
if (lock_data->idle_has_lock) {
|
if (lock_data->idle_has_lock) {
|
||||||
do {
|
do {
|
||||||
|
@ -382,7 +377,7 @@ void drm_idlelock_release(struct drm_lock_data *lock_data)
|
||||||
lock_data->idle_has_lock = 0;
|
lock_data->idle_has_lock = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&lock_data->spinlock, irqflags);
|
spin_unlock_bh(&lock_data->spinlock);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(drm_idlelock_release);
|
EXPORT_SYMBOL(drm_idlelock_release);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue