Merge master.kernel.org:/home/rmk/linux-2.6-arm
[powerpc.git] / drivers / net / wireless / orinoco.c
index d910b89..b1078ba 100644 (file)
@@ -657,7 +657,7 @@ static int orinoco_open(struct net_device *dev)
        return err;
 }
 
-int orinoco_stop(struct net_device *dev)
+static int orinoco_stop(struct net_device *dev)
 {
        struct orinoco_private *priv = netdev_priv(dev);
        int err = 0;
@@ -1280,9 +1280,10 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
                        len = sizeof(tallies);
                }
                
-               /* Read directly the data (no seek) */
-               hermes_read_words(hw, HERMES_DATA1, (void *) &tallies,
-                                 len / 2); /* FIXME: blech! */
+               err = hermes_bap_pread(hw, IRQ_BAP, &tallies, len,
+                                      infofid, sizeof(info));
+               if (err)
+                       break;
                
                /* Increment our various counters */
                /* wstats->discard.nwid - no wrong BSSID stuff */
@@ -1312,8 +1313,10 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
                        break;
                }
 
-               hermes_read_words(hw, HERMES_DATA1, (void *) &linkstatus,
-                                 len / 2);
+               err = hermes_bap_pread(hw, IRQ_BAP, &linkstatus, len,
+                                      infofid, sizeof(info));
+               if (err)
+                       break;
                newstatus = le16_to_cpu(linkstatus.linkstatus);
 
                connected = (newstatus == HERMES_LINKSTATUS_CONNECTED)
@@ -1355,6 +1358,8 @@ int __orinoco_up(struct net_device *dev)
        struct hermes *hw = &priv->hw;
        int err;
 
+       netif_carrier_off(dev); /* just to make sure */
+
        err = __orinoco_program_rids(dev);
        if (err) {
                printk(KERN_ERR "%s: Error %d configuring card\n",
@@ -1919,7 +1924,7 @@ static void orinoco_reset(struct net_device *dev)
 {
        struct orinoco_private *priv = netdev_priv(dev);
        struct hermes *hw = &priv->hw;
-       int err = 0;
+       int err;
        unsigned long flags;
 
        if (orinoco_lock(priv, &flags) != 0)
@@ -1941,20 +1946,20 @@ static void orinoco_reset(struct net_device *dev)
 
        orinoco_unlock(priv, &flags);
 
-       if (priv->hard_reset)
+       if (priv->hard_reset) {
                err = (*priv->hard_reset)(priv);
-       if (err) {
-               printk(KERN_ERR "%s: orinoco_reset: Error %d "
-                      "performing  hard reset\n", dev->name, err);
-               /* FIXME: shutdown of some sort */
-               return;
+               if (err) {
+                       printk(KERN_ERR "%s: orinoco_reset: Error %d "
+                              "performing hard reset\n", dev->name, err);
+                       goto disable;
+               }
        }
 
        err = orinoco_reinit_firmware(dev);
        if (err) {
                printk(KERN_ERR "%s: orinoco_reset: Error %d re-initializing firmware\n",
                       dev->name, err);
-               return;
+               goto disable;
        }
 
        spin_lock_irq(&priv->lock); /* This has to be called from user context */
@@ -1975,6 +1980,10 @@ static void orinoco_reset(struct net_device *dev)
        spin_unlock_irq(&priv->lock);
 
        return;
+ disable:
+       hermes_set_irqmask(hw, 0);
+       netif_device_detach(dev);
+       printk(KERN_ERR "%s: Device has been disabled!\n", dev->name);
 }
 
 /********************************************************************/
@@ -2059,7 +2068,7 @@ irqreturn_t orinoco_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                if (events & HERMES_EV_ALLOC)
                        __orinoco_ev_alloc(dev, hw);
                
-               hermes_write_regn(hw, EVACK, events);
+               hermes_write_regn(hw, EVACK, evstat);
 
                evstat = hermes_read_regn(hw, EVSTAT);
                events = evstat & hw->inten;
@@ -2218,6 +2227,8 @@ static int determine_firmware(struct net_device *dev)
                               firmver >= 0x31000;
                priv->has_preamble = (firmver >= 0x20000);
                priv->ibss_port = 4;
+               priv->broken_disableport = (firmver == 0x25013) ||
+                                          (firmver >= 0x30000 && firmver <= 0x31000);
                /* Tested with Intel firmware : 0x20015 => Jean II */
                /* Tested with 3Com firmware : 0x15012 & 0x22001 => Jean II */
                break;
@@ -2434,7 +2445,7 @@ struct net_device *alloc_orinocodev(int sizeof_card,
        priv = netdev_priv(dev);
        priv->ndev = dev;
        if (sizeof_card)
-               priv->card = (void *)((unsigned long)netdev_priv(dev)
+               priv->card = (void *)((unsigned long)priv
                                      + sizeof(struct orinoco_private));
        else
                priv->card = NULL;
@@ -2539,6 +2550,7 @@ static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
        }
 
        len = le16_to_cpu(essidbuf.len);
+       BUG_ON(len > IW_ESSID_MAX_SIZE);
 
        memset(buf, 0, IW_ESSID_MAX_SIZE+1);
        memcpy(buf, p, len);
@@ -2907,13 +2919,14 @@ static int orinoco_ioctl_setessid(struct net_device *dev, struct iw_point *erq)
        memset(&essidbuf, 0, sizeof(essidbuf));
 
        if (erq->flags) {
-               if (erq->length > IW_ESSID_MAX_SIZE)
+               /* iwconfig includes the NUL in the specified length */
+               if (erq->length > IW_ESSID_MAX_SIZE+1)
                        return -E2BIG;
                
                if (copy_from_user(&essidbuf, erq->pointer, erq->length))
                        return -EFAULT;
 
-               essidbuf[erq->length] = '\0';
+               essidbuf[IW_ESSID_MAX_SIZE] = '\0';
        }
 
        if (orinoco_lock(priv, &flags) != 0)
@@ -4012,7 +4025,6 @@ EXPORT_SYMBOL(free_orinocodev);
 
 EXPORT_SYMBOL(__orinoco_up);
 EXPORT_SYMBOL(__orinoco_down);
-EXPORT_SYMBOL(orinoco_stop);
 EXPORT_SYMBOL(orinoco_reinit_firmware);
 
 EXPORT_SYMBOL(orinoco_interrupt);