Am Montag, 26. Februar 2007 23:58 schrieb Alfred E. Heggestad:
 
> > static DECLARE_RWSEM(sysfs_rwsema);
> > 
> > A mutex is enough. You never do anything but down_write().
> > 
> 
> ok that can be fixed. but I am not sure yet how to use the sysfs
> interface. at the moment the external buzzer is activated via
> doing "echo 1 > /sys/.../buzzer" so that is write only as you
> say. But in the future we might want to read/write the EEPROM
> via the sysfs interface.

Nevertheless a simple mutex will do. There's no need to worry
about contention here.

> ideally I would like to use a more standard user interface
> for the buzzer, like SND_BELL/SND_TONE. I added some code
> in input_ev() for triggering the buzzer, but unfortunately
> it crashes the whole box .. also I am not sure how to

How does it crash? Any oops report?

> actually turn *off* the buzzer if using the input event API.
> any ideas?

You might ask on the input list.
 
> > static void input_close(struct input_dev *dev)
> > {
> >     struct cm109_dev *cmd = dev->private;
> > 
> >     usb_kill_urb(cmd->urb_ctl);
> >     usb_kill_urb(cmd->urb_irq);
> > }
> > 
> > This is a race condition. Due to your special requirement of submitting
> > the URBs from each other's completion handler the guarantees of 
> > usb_kill_urb()
> > are not strong enough for you. You need to use a flag under a spin_lock.
> > 
> 
> I added "struct mutex io_mutex" to my device object. Should this be
> locked in the USB irq/ctl handlers ?

No. You cannot use a mutex in interrupt. In fact that mutex currently has no
function in your code.

The problem is as follows:

CPU A                                           CPU B
urb_irq_callback() called
                                                        usb_kill_urb(urb_irq) 
//will wait for the callback to finish
usb_submit_urb(urb_ctl) //still allowed
urb_ctl_callback()
usb_submit_urb(urb_irq)
                                                        usb_kill_urb(urb_ctl)

Your URBs are still running.
You need to make conditional submitting the URBs on a flag and
the whole thing protected by a spinlock, eg in urb_ctl_callback:

        spin_lock(&dev->submit_lock);
        /* ask for a response */
        if (!dev->disconnecting)
                ret = usb_submit_urb(dev->urb_irq, GFP_KERNEL);
        spin_unlock(&dev->submit_lock);

And in usb_disconnect:

        spin_lock_irq(&dev->submit_lock);
        dev->disconnecting = 1;
        spin_unlock_irq(&dev->submit_lock);
and now cleanup

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to