]> git.neil.brown.name Git - history.git/commitdiff
irda update 5/7:
authorJean Tourrilhes <jt@hpl.hp.com>
Tue, 30 Apr 2002 18:07:16 +0000 (14:07 -0400)
committerLinus Torvalds <torvalds@home.transmeta.com>
Tue, 30 Apr 2002 18:07:16 +0000 (14:07 -0400)
o [CORRECT] Load dongle module with irq disabled in irtty

drivers/net/irda/irtty.c
net/irda/irda_device.c

index ee6463aa42575e0dd7afa464f70b626f97f5a527..244d7495535692ac516ace669b413a18bc7791cc 100644 (file)
@@ -970,9 +970,14 @@ static int irtty_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 
        IRDA_DEBUG(3, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd);
        
-       /* Disable interrupts & save flags */
-       save_flags(flags);
-       cli();
+       /* Locking :
+        * irda_device_dongle_init() can't be locked.
+        * irda_task_execute() doesn't need to be locked (but
+        * irtty_change_speed() should protect itself).
+        * As this driver doesn't have spinlock protection, keep
+        * old fashion locking :-(
+        * Jean II
+        */
        
        switch (cmd) {
        case SIOCSBANDWIDTH: /* Set bandwidth */
@@ -998,14 +1003,17 @@ static int irtty_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                dongle->write       = irtty_raw_write;
                dongle->set_dtr_rts = irtty_set_dtr_rts;
                
-               self->dongle = dongle;
-
-               /* Now initialize the dongle!  */
+               /* Now initialize the dongle!
+                * Safe to do unlocked : self->dongle is still NULL. */ 
                dongle->issue->open(dongle, &self->qos);
                
                /* Reset dongle */
                irda_task_execute(dongle, dongle->issue->reset, NULL, NULL, 
                                  NULL);        
+
+               /* Make dongle available to driver only now to avoid
+                * race conditions - Jean II */
+               self->dongle = dongle;
                break;
        case SIOCSMEDIABUSY: /* Set media busy */
                if (!capable(CAP_NET_ADMIN))
@@ -1019,21 +1027,27 @@ static int irtty_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
        case SIOCSDTRRTS:
                if (!capable(CAP_NET_ADMIN))
                        ret = -EPERM;
-               else
+               else {
+                       save_flags(flags);
+                       cli();
                        irtty_set_dtr_rts(dev, irq->ifr_dtr, irq->ifr_rts);
+                       restore_flags(flags);
+               }
                break;
        case SIOCSMODE:
                if (!capable(CAP_NET_ADMIN))
                        ret = -EPERM;
-               else
+               else {
+                       save_flags(flags);
+                       cli();
                        irtty_set_mode(dev, irq->ifr_mode);
+                       restore_flags(flags);
+               }
                break;
        default:
                ret = -EOPNOTSUPP;
        }
        
-       restore_flags(flags);
-       
        return ret;
 }
 
index 9d445f3131612f6e6bbb88651efc55b70d93d321..c49b75643b94f5ca6fa0fd3c726b7b48587daa7c 100644 (file)
@@ -368,6 +368,12 @@ int irda_task_kick(struct irda_task *task)
  *    time to complete. We do it this hairy way since we may have been
  *    called from interrupt context, so it's not possible to use
  *    schedule_timeout() 
+ * Two important notes :
+ *     o Make sure you irda_task_delete(task); in case you delete the
+ *       calling instance.
+ *     o No real need to lock when calling this function, but you may
+ *       want to lock within the task handler.
+ * Jean II
  */
 struct irda_task *irda_task_execute(void *instance, 
                                    IRDA_TASK_CALLBACK function, 
@@ -466,6 +472,9 @@ int irda_device_txqueue_empty(struct net_device *dev)
  * Function irda_device_init_dongle (self, type, qos)
  *
  *    Initialize attached dongle.
+ *
+ * Important : request_module require us to call this function with
+ * a process context and irq enabled. - Jean II
  */
 dongle_t *irda_device_dongle_init(struct net_device *dev, int type)
 {
@@ -477,6 +486,7 @@ dongle_t *irda_device_dongle_init(struct net_device *dev, int type)
 #ifdef CONFIG_KMOD
        {
        char modname[32];
+       ASSERT(!in_interrupt(), return NULL;);
        /* Try to load the module needed */
        sprintf(modname, "irda-dongle-%d", type);
        request_module(modname);