Jivin Wolfgang Wegner lays it down ...
> Hi,
> 
> after I solved the startup problem I could now investigate another
> thing.
> 
> From time to time, I have problems with some drivers (namely QSPI
> in interrupt mode and my self-hacked I2C driver in interrupt mode)
> getting stuck when sleeping on a waitqueue. This happens on an
> MCF5373L, using the code for MCF532x as they are compatible except
> the additional devices on MCF532x.
> 
> In my I2C driver, the code is the following:
> 
> static
> irqreturn_t coldfire_i2c_interrupt(int irq, void *dev_id)
> {
>       /* check if we are called with the correct IRQ number */
>       if(irq != (MCFINT_VECBASE + MCFINT_I2C))
>         return IRQ_NONE;
> 
>       /* check if I2C int flag is set and send the event to waiting queue */
>       if(*MCF_I2C_I2SR & MCF_I2C_I2SR_IIF) {
>               *MCF_I2C_I2SR &= ~MCF_I2C_I2SR_IIF;
>               atomic_set(&coldfire_i2c_irq_happened, 1);
>               wake_up_interruptible(&coldfire_i2c_queue);
>       }
>       return IRQ_HANDLED;
> }
> 
> static int coldfire_wait_transfer(void) {
> 
>       int timeout;
> 
>       /* wait for data transfer to complete */
>       timeout = wait_event_interruptible_timeout(coldfire_i2c_queue,
>                                                  1 == 
> atomic_read(&coldfire_i2c_irq_happened),
>                                                  COLDFIRE_I2C_TIMEOUT);
> 

What happens if you get an interrupt between here ...

>       if ((timeout <= 0 ) || (*MCF_I2C_I2SR & MCF_I2C_I2SR_IAL)) {
>               printk("wt: timeout = %d, I2SR = %x\n, ih = %d",timeout, 
> *MCF_I2C_I2SR, atomic_read(&coldfire_i2c_irq_happened));
>               return -1;
>       }
>       else {

And here ?  Won't coldfire_i2c_irq_happened get cleared when an
interrupt service is pending ?

>               atomic_set(&coldfire_i2c_irq_happened, 0);
>               return 0;
>       }
> };

Just check the HW in coldfire_wait_transfer,

        while (1) {
                spinlock_irq(xxx)
                irqpending = (*MCF_I2C_I2SR & MCF_I2C_I2SR_IAL);
                spinunlock_irq(xxx)
                if (irqpending) {
                        /* remember to protect HW register accesses in here */
                        service interrupt
                }
        }

You can probably do away with coldfire_i2c_irq_happened,  which will
make it easier to get the code right :-)

Cheers,
Davidm

> From time to time, the timeout happens and I get the message:
> 
> wt: timeout = 0, I2SR = a0, ih = 1
> 
> So obviously the interrupt happens and is correctly handled, but the
> waitqueue is not awoken.
> 
> Did anybody else experience such a problem, or is it again something
> peculiar to my setup?

-- 
David McCullough,  [EMAIL PROTECTED],   Ph:+61 734352815
Secure Computing - SnapGear  http://www.uCdot.org http://www.cyberguard.com
_______________________________________________
uClinux-dev mailing list
[email protected]
http://mailman.uclinux.org/mailman/listinfo/uclinux-dev
This message was resent by [email protected]
To unsubscribe see:
http://mailman.uclinux.org/mailman/options/uclinux-dev

Reply via email to