Merge branch 'upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/linville...
authorJeff Garzik <jeff@garzik.org>
Wed, 24 May 2006 04:29:57 +0000 (00:29 -0400)
committerJeff Garzik <jeff@garzik.org>
Wed, 24 May 2006 04:29:57 +0000 (00:29 -0400)
20 files changed:
drivers/net/wireless/airo.c
drivers/net/wireless/bcm43xx/bcm43xx_main.c
drivers/net/wireless/hostap/hostap_80211_tx.c
drivers/net/wireless/hostap/hostap_ap.c
drivers/net/wireless/hostap/hostap_cs.c
drivers/net/wireless/hostap/hostap_main.c
drivers/net/wireless/orinoco_cs.c
drivers/net/wireless/orinoco_nortel.c
drivers/net/wireless/orinoco_pci.c
drivers/net/wireless/orinoco_pci.h
drivers/net/wireless/orinoco_plx.c
drivers/net/wireless/orinoco_tmd.c
drivers/net/wireless/spectrum_cs.c
include/net/ieee80211softmac.h
net/ieee80211/ieee80211_wx.c
net/ieee80211/softmac/ieee80211softmac_assoc.c
net/ieee80211/softmac/ieee80211softmac_auth.c
net/ieee80211/softmac/ieee80211softmac_module.c
net/ieee80211/softmac/ieee80211softmac_priv.h
net/ieee80211/softmac/ieee80211softmac_wx.c

index 7f2dacf634ee0c3c5a5d18d1053e8869df585dce..4069b79d825972b4fb3ad21c7aad31d73edb07d4 100644 (file)
@@ -2768,7 +2768,7 @@ static int airo_test_wpa_capable(struct airo_info *ai)
 
        /* Only firmware versions 5.30.17 or better can do WPA */
        if ((cap_rid.softVer > 0x530)
-         || ((cap_rid.softVer == 0x530) && (cap_rid.softSubVer >= 0x17))) {
+         || ((cap_rid.softVer == 0x530) && (cap_rid.softSubVer >= 17))) {
                airo_print_info(name, "WPA is supported.");
                return 1;
        }
index 2adf02ac400ee82a50275ac2bdc9a8cf7989b6a5..c0502905a9564e25f0a103378f24a68d782df3c8 100644 (file)
@@ -128,13 +128,15 @@ MODULE_PARM_DESC(fwpostfix, "Postfix for .fw files. Useful for debugging.");
        static struct pci_device_id bcm43xx_pci_tbl[] = {
        /* Broadcom 4303 802.11b */
        { PCI_VENDOR_ID_BROADCOM, 0x4301, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-               /* Broadcom 4307 802.11b */
+       /* Broadcom 4307 802.11b */
        { PCI_VENDOR_ID_BROADCOM, 0x4307, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-               /* Broadcom 4318 802.11b/g */
+       /* Broadcom 4318 802.11b/g */
        { PCI_VENDOR_ID_BROADCOM, 0x4318, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+       /* Broadcom 4319 802.11a/b/g */
+       { PCI_VENDOR_ID_BROADCOM, 0x4319, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
        /* Broadcom 4306 802.11b/g */
        { PCI_VENDOR_ID_BROADCOM, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-               /* Broadcom 4306 802.11a */
+       /* Broadcom 4306 802.11a */
 //     { PCI_VENDOR_ID_BROADCOM, 0x4321, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
        /* Broadcom 4309 802.11a/b/g */
        { PCI_VENDOR_ID_BROADCOM, 0x4324, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
index 06a5214145e3124d6d7ccc738abeadb24c6d0a38..4a5be70c04195c412aca816fb796cfc4e96cb8f3 100644 (file)
@@ -534,5 +534,4 @@ int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev)
 }
 
 
-EXPORT_SYMBOL(hostap_dump_tx_80211);
 EXPORT_SYMBOL(hostap_master_start_xmit);
index 06c3fa32b310e41e0af0eea71fbf9fabf6a66a89..ba13125024cb35d54fa882a518d640a5f665c2c7 100644 (file)
@@ -3276,17 +3276,6 @@ EXPORT_SYMBOL(hostap_init_data);
 EXPORT_SYMBOL(hostap_init_ap_proc);
 EXPORT_SYMBOL(hostap_free_data);
 EXPORT_SYMBOL(hostap_check_sta_fw_version);
-EXPORT_SYMBOL(hostap_handle_sta_tx);
-EXPORT_SYMBOL(hostap_handle_sta_release);
 EXPORT_SYMBOL(hostap_handle_sta_tx_exc);
-EXPORT_SYMBOL(hostap_update_sta_ps);
-EXPORT_SYMBOL(hostap_handle_sta_rx);
-EXPORT_SYMBOL(hostap_is_sta_assoc);
-EXPORT_SYMBOL(hostap_is_sta_authorized);
-EXPORT_SYMBOL(hostap_add_sta);
-EXPORT_SYMBOL(hostap_update_rates);
-EXPORT_SYMBOL(hostap_add_wds_links);
-EXPORT_SYMBOL(hostap_wds_link_oper);
 #ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
-EXPORT_SYMBOL(hostap_deauth_all_stas);
 #endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
index 55bed923fbe9fcc6104588303166ab60111c7b70..db03dc2646dfb08d27b741f57774ca66303de609 100644 (file)
@@ -881,6 +881,12 @@ static struct pcmcia_device_id hostap_cs_ids[] = {
        PCMCIA_DEVICE_PROD_ID12(
                "ZoomAir 11Mbps High", "Rate wireless Networking",
                0x273fe3db, 0x32a1eaee),
+       PCMCIA_DEVICE_PROD_ID123(
+               "Pretec", "CompactWLAN Card 802.11b", "2.5",
+               0x1cadd3e5, 0xe697636c, 0x7a5bfcf1),
+       PCMCIA_DEVICE_PROD_ID123(
+               "U.S. Robotics", "IEEE 802.11b PC-CARD", "Version 01.02",
+               0xc7b8df9d, 0x1700d087, 0x4b74baa0),
        PCMCIA_DEVICE_NULL
 };
 MODULE_DEVICE_TABLE(pcmcia, hostap_cs_ids);
index 8dd4c4446a640bf6b3b14f89e054f62ef47a3ec9..93786f4218f0d422092813dd17bb9b9e083d8997 100644 (file)
@@ -1125,11 +1125,9 @@ EXPORT_SYMBOL(hostap_set_auth_algs);
 EXPORT_SYMBOL(hostap_dump_rx_header);
 EXPORT_SYMBOL(hostap_dump_tx_header);
 EXPORT_SYMBOL(hostap_80211_header_parse);
-EXPORT_SYMBOL(hostap_80211_prism_header_parse);
 EXPORT_SYMBOL(hostap_80211_get_hdrlen);
 EXPORT_SYMBOL(hostap_get_stats);
 EXPORT_SYMBOL(hostap_setup_dev);
-EXPORT_SYMBOL(hostap_proc);
 EXPORT_SYMBOL(hostap_set_multicast_list_queue);
 EXPORT_SYMBOL(hostap_set_hostapd);
 EXPORT_SYMBOL(hostap_set_hostapd_sta);
index d2c48ac60f4658ebeebfb26be371fc1bbbe5365a..b2aec4d9fbb12b3dc759233564722ac43975daf5 100644 (file)
@@ -147,14 +147,11 @@ static void orinoco_cs_detach(struct pcmcia_device *link)
 {
        struct net_device *dev = link->priv;
 
+       if (link->dev_node)
+               unregister_netdev(dev);
+
        orinoco_cs_release(link);
 
-       DEBUG(0, PFX "detach: link=%p link->dev_node=%p\n", link, link->dev_node);
-       if (link->dev_node) {
-               DEBUG(0, PFX "About to unregister net device %p\n",
-                     dev);
-               unregister_netdev(dev);
-       }
        free_orinocodev(dev);
 }                              /* orinoco_cs_detach */
 
@@ -346,19 +343,10 @@ orinoco_cs_config(struct pcmcia_device *link)
                                     net_device has been registered */
 
        /* Finally, report what we've done */
-       printk(KERN_DEBUG "%s: index 0x%02x: ",
-              dev->name, link->conf.ConfigIndex);
-       if (link->conf.Vpp)
-               printk(", Vpp %d.%d", link->conf.Vpp / 10,
-                      link->conf.Vpp % 10);
-       printk(", irq %d", link->irq.AssignedIRQ);
-       if (link->io.NumPorts1)
-               printk(", io 0x%04x-0x%04x", link->io.BasePort1,
-                      link->io.BasePort1 + link->io.NumPorts1 - 1);
-       if (link->io.NumPorts2)
-               printk(" & 0x%04x-0x%04x", link->io.BasePort2,
-                      link->io.BasePort2 + link->io.NumPorts2 - 1);
-       printk("\n");
+       printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s, irq %d, io "
+              "0x%04x-0x%04x\n", dev->name, dev->class_dev.dev->bus_id,
+              link->irq.AssignedIRQ, link->io.BasePort1,
+              link->io.BasePort1 + link->io.NumPorts1 - 1);
 
        return 0;
 
@@ -427,7 +415,6 @@ static int orinoco_cs_resume(struct pcmcia_device *link)
        struct orinoco_private *priv = netdev_priv(dev);
        struct orinoco_pccard *card = priv->card;
        int err = 0;
-       unsigned long flags;
 
        if (! test_bit(0, &card->hard_reset_in_progress)) {
                err = orinoco_reinit_firmware(dev);
@@ -437,7 +424,7 @@ static int orinoco_cs_resume(struct pcmcia_device *link)
                        return -EIO;
                }
 
-               spin_lock_irqsave(&priv->lock, flags);
+               spin_lock(&priv->lock);
 
                netif_device_attach(dev);
                priv->hw_unavailable--;
@@ -449,10 +436,10 @@ static int orinoco_cs_resume(struct pcmcia_device *link)
                                       dev->name, err);
                }
 
-               spin_unlock_irqrestore(&priv->lock, flags);
+               spin_unlock(&priv->lock);
        }
 
-       return 0;
+       return err;
 }
 
 
index 1596182f7412996a8772effe935e4fb9ce1760ad..74b9d5b2ba9ee00005586938f832cf4c1f36911e 100644 (file)
@@ -206,7 +206,6 @@ static int orinoco_nortel_init_one(struct pci_dev *pdev,
                err = -EBUSY;
                goto fail_irq;
        }
-       orinoco_pci_setup_netdev(dev, pdev, 2);
 
        err = orinoco_nortel_hw_init(card);
        if (err) {
@@ -227,6 +226,8 @@ static int orinoco_nortel_init_one(struct pci_dev *pdev,
        }
 
        pci_set_drvdata(pdev, dev);
+       printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s\n", dev->name,
+              pci_name(pdev));
 
        return 0;
 
@@ -265,7 +266,7 @@ static void __devexit orinoco_nortel_remove_one(struct pci_dev *pdev)
        iowrite16(0, card->bridge_io + 10);
 
        unregister_netdev(dev);
-       free_irq(dev->irq, dev);
+       free_irq(pdev->irq, dev);
        pci_set_drvdata(pdev, NULL);
        free_orinocodev(dev);
        pci_iounmap(pdev, priv->hw.iobase);
index df37b95607ff3825f3cc0d6da8185a4a08415fe5..1c105f40f8d55f250f344f0e2427baf150bcb3d8 100644 (file)
@@ -161,7 +161,6 @@ static int orinoco_pci_init_one(struct pci_dev *pdev,
                err = -EBUSY;
                goto fail_irq;
        }
-       orinoco_pci_setup_netdev(dev, pdev, 0);
 
        err = orinoco_pci_cor_reset(priv);
        if (err) {
@@ -176,6 +175,8 @@ static int orinoco_pci_init_one(struct pci_dev *pdev,
        }
 
        pci_set_drvdata(pdev, dev);
+       printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s\n", dev->name,
+              pci_name(pdev));
 
        return 0;
 
@@ -204,7 +205,7 @@ static void __devexit orinoco_pci_remove_one(struct pci_dev *pdev)
        struct orinoco_private *priv = netdev_priv(dev);
 
        unregister_netdev(dev);
-       free_irq(dev->irq, dev);
+       free_irq(pdev->irq, dev);
        pci_set_drvdata(pdev, NULL);
        free_orinocodev(dev);
        pci_iounmap(pdev, priv->hw.iobase);
index b05a9a5b1f5fb97fbdcee5ad445d58343c7a0650..7eb1e08113e0886fa1b9e3ddfc9d0e529991ecb1 100644 (file)
@@ -18,32 +18,7 @@ struct orinoco_pci_card {
        void __iomem *attr_io;
 };
 
-/* Set base address or memory range of the network device based on
- * the PCI device it's using.  Specify BAR of the "main" resource.
- * To be used after request_irq().  */
-static inline void orinoco_pci_setup_netdev(struct net_device *dev,
-                                           struct pci_dev *pdev, int bar)
-{
-       char *range_type;
-       unsigned long start = pci_resource_start(pdev, bar);
-       unsigned long len = pci_resource_len(pdev, bar);
-       unsigned long flags = pci_resource_flags(pdev, bar);
-       unsigned long end = start + len - 1;
-
-       dev->irq = pdev->irq;
-       if (flags & IORESOURCE_IO) {
-               dev->base_addr = start;
-               range_type = "ports";
-       } else {
-               dev->mem_start = start;
-               dev->mem_end = end;
-               range_type = "memory";
-       }
-
-       printk(KERN_DEBUG PFX "%s: irq %d, %s 0x%lx-0x%lx\n",
-              pci_name(pdev), pdev->irq, range_type, start, end);
-}
-
+#ifdef CONFIG_PM
 static int orinoco_pci_suspend(struct pci_dev *pdev, pm_message_t state)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
@@ -121,5 +96,9 @@ static int orinoco_pci_resume(struct pci_dev *pdev)
 
        return 0;
 }
+#else
+#define orinoco_pci_suspend NULL
+#define orinoco_pci_resume NULL
+#endif
 
 #endif /* _ORINOCO_PCI_H */
index 7b9405096389586615ca86467dbc35351d739d56..84f696c77551e1ce420a6e7341e0a3f0717e73c7 100644 (file)
@@ -245,7 +245,6 @@ static int orinoco_plx_init_one(struct pci_dev *pdev,
                err = -EBUSY;
                goto fail_irq;
        }
-       orinoco_pci_setup_netdev(dev, pdev, 2);
 
        err = orinoco_plx_hw_init(card);
        if (err) {
@@ -266,6 +265,8 @@ static int orinoco_plx_init_one(struct pci_dev *pdev,
        }
 
        pci_set_drvdata(pdev, dev);
+       printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s\n", dev->name,
+              pci_name(pdev));
 
        return 0;
 
@@ -301,7 +302,7 @@ static void __devexit orinoco_plx_remove_one(struct pci_dev *pdev)
        struct orinoco_pci_card *card = priv->card;
 
        unregister_netdev(dev);
-       free_irq(dev->irq, dev);
+       free_irq(pdev->irq, dev);
        pci_set_drvdata(pdev, NULL);
        free_orinocodev(dev);
        pci_iounmap(pdev, priv->hw.iobase);
index 0496663e837c5d4b6e9dacb7eca48ffd5ad51bc8..d2b4decb7a7d005cdf87c2c91d9269f7f5e8cd92 100644 (file)
@@ -147,7 +147,6 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev,
                err = -EBUSY;
                goto fail_irq;
        }
-       orinoco_pci_setup_netdev(dev, pdev, 2);
 
        err = orinoco_tmd_cor_reset(priv);
        if (err) {
@@ -162,6 +161,8 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev,
        }
 
        pci_set_drvdata(pdev, dev);
+       printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s\n", dev->name,
+              pci_name(pdev));
 
        return 0;
 
@@ -194,7 +195,7 @@ static void __devexit orinoco_tmd_remove_one(struct pci_dev *pdev)
        struct orinoco_pci_card *card = priv->card;
 
        unregister_netdev(dev);
-       free_irq(dev->irq, dev);
+       free_irq(pdev->irq, dev);
        pci_set_drvdata(pdev, NULL);
        free_orinocodev(dev);
        pci_iounmap(pdev, priv->hw.iobase);
index aeb38d9388327c23101f8bb87d62e67ab4a7f96c..7f9aa139c3475fb11e526433fd85566ada350c48 100644 (file)
@@ -625,14 +625,11 @@ static void spectrum_cs_detach(struct pcmcia_device *link)
 {
        struct net_device *dev = link->priv;
 
+       if (link->dev_node)
+               unregister_netdev(dev);
+
        spectrum_cs_release(link);
 
-       DEBUG(0, PFX "detach: link=%p link->dev_node=%p\n", link, link->dev_node);
-       if (link->dev_node) {
-               DEBUG(0, PFX "About to unregister net device %p\n",
-                     dev);
-               unregister_netdev(dev);
-       }
        free_orinocodev(dev);
 }                              /* spectrum_cs_detach */
 
@@ -825,19 +822,10 @@ spectrum_cs_config(struct pcmcia_device *link)
                                     net_device has been registered */
 
        /* Finally, report what we've done */
-       printk(KERN_DEBUG "%s: index 0x%02x: ",
-              dev->name, link->conf.ConfigIndex);
-       if (link->conf.Vpp)
-               printk(", Vpp %d.%d", link->conf.Vpp / 10,
-                      link->conf.Vpp % 10);
-       printk(", irq %d", link->irq.AssignedIRQ);
-       if (link->io.NumPorts1)
-               printk(", io 0x%04x-0x%04x", link->io.BasePort1,
-                      link->io.BasePort1 + link->io.NumPorts1 - 1);
-       if (link->io.NumPorts2)
-               printk(" & 0x%04x-0x%04x", link->io.BasePort2,
-                      link->io.BasePort2 + link->io.NumPorts2 - 1);
-       printk("\n");
+       printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s, irq %d, io "
+              "0x%04x-0x%04x\n", dev->name, dev->class_dev.dev->bus_id,
+              link->irq.AssignedIRQ, link->io.BasePort1,
+              link->io.BasePort1 + link->io.NumPorts1 - 1);
 
        return 0;
 
@@ -878,11 +866,10 @@ spectrum_cs_suspend(struct pcmcia_device *link)
 {
        struct net_device *dev = link->priv;
        struct orinoco_private *priv = netdev_priv(dev);
-       unsigned long flags;
        int err = 0;
 
        /* Mark the device as stopped, to block IO until later */
-       spin_lock_irqsave(&priv->lock, flags);
+       spin_lock(&priv->lock);
 
        err = __orinoco_down(dev);
        if (err)
@@ -892,9 +879,9 @@ spectrum_cs_suspend(struct pcmcia_device *link)
        netif_device_detach(dev);
        priv->hw_unavailable++;
 
-       spin_unlock_irqrestore(&priv->lock, flags);
+       spin_unlock(&priv->lock);
 
-       return 0;
+       return err;
 }
 
 static int
index 052ed596a4e487de798d0513f472ce842b66ba21..703463a8828b2f8e5ba3a14f6214f968c4fd3c3e 100644 (file)
@@ -86,6 +86,9 @@ struct ieee80211softmac_assoc_info {
        
        /* BSSID we're trying to associate to */
        char bssid[ETH_ALEN];
+
+       /* Rates supported by the network */
+       struct ieee80211softmac_ratesinfo supported_rates;
        
        /* some flags.
         * static_essid is valid if the essid is constant,
@@ -132,23 +135,26 @@ enum {
 struct ieee80211softmac_txrates {
        /* The Bit-Rate to be used for multicast frames. */
        u8 mcast_rate;
-       /* The Bit-Rate to be used for multicast fallback
-        * (If the device supports fallback and hardware-retry)
-        */
-       u8 mcast_fallback;
+
+       /* The Bit-Rate to be used for multicast management frames. */
+       u8 mgt_mcast_rate;
+
        /* The Bit-Rate to be used for any other (normal) data packet. */
        u8 default_rate;
        /* The Bit-Rate to be used for default fallback
         * (If the device supports fallback and hardware-retry)
         */
        u8 default_fallback;
+
+       /* This is the rate that the user asked for */
+       u8 user_rate;
 };
 
 /* Bits for txrates_change callback. */
 #define IEEE80211SOFTMAC_TXRATECHG_DEFAULT             (1 << 0) /* default_rate */
 #define IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK       (1 << 1) /* default_fallback */
 #define IEEE80211SOFTMAC_TXRATECHG_MCAST               (1 << 2) /* mcast_rate */
-#define IEEE80211SOFTMAC_TXRATECHG_MCAST_FBACK         (1 << 3) /* mcast_fallback */
+#define IEEE80211SOFTMAC_TXRATECHG_MGT_MCAST           (1 << 3) /* mgt_mcast_rate */
 
 struct ieee80211softmac_device {
        /* 802.11 structure for data stuff */
@@ -250,6 +256,28 @@ extern void ieee80211softmac_fragment_lost(struct net_device *dev,
  * Note that the rates need to be sorted. */
 extern void ieee80211softmac_set_rates(struct net_device *dev, u8 count, u8 *rates);
 
+/* Helper function which advises you the rate at which a frame should be
+ * transmitted at. */
+static inline u8 ieee80211softmac_suggest_txrate(struct ieee80211softmac_device *mac,
+                                                int is_multicast,
+                                                int is_mgt)
+{
+       struct ieee80211softmac_txrates *txrates = &mac->txrates;
+
+       if (!mac->associated)
+               return txrates->mgt_mcast_rate;
+
+       /* We are associated, sending unicast frame */
+       if (!is_multicast)
+               return txrates->default_rate;
+
+       /* We are associated, sending multicast frame */
+       if (is_mgt)
+               return txrates->mgt_mcast_rate;
+       else
+               return txrates->mcast_rate;
+}
+
 /* Start the SoftMAC. Call this after you initialized the device
  * and it is ready to run.
  */
index 0ea55cb5f17252a1fa3a81d6d6081748bc215375..a78c4f845f66a88f3a2f95fb59adc8790c6af723 100644 (file)
@@ -503,7 +503,7 @@ int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
        len = sec->key_sizes[key];
        memcpy(keybuf, sec->keys[key], len);
 
-       erq->length = (len >= 0 ? len : 0);
+       erq->length = len;
        erq->flags |= IW_ENCODE_ENABLED;
 
        if (ieee->open_wep)
index d4c79ce16871447ef17f411c7feae1ffbc227d59..5d90b9a6ee50f5863027a1e957b1d918bbdfa0b7 100644 (file)
@@ -82,51 +82,52 @@ ieee80211softmac_assoc_timeout(void *d)
        ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_TIMEOUT, NULL);
 }
 
-/* Sends out a disassociation request to the desired AP */
 void
-ieee80211softmac_disassoc(struct ieee80211softmac_device *mac, u16 reason)
+ieee80211softmac_disassoc(struct ieee80211softmac_device *mac)
 {
        unsigned long flags;
+
+       spin_lock_irqsave(&mac->lock, flags);
+       if (mac->associnfo.associating)
+               cancel_delayed_work(&mac->associnfo.timeout);
+
+       netif_carrier_off(mac->dev);
+
+       mac->associated = 0;
+       mac->associnfo.bssvalid = 0;
+       mac->associnfo.associating = 0;
+       ieee80211softmac_init_txrates(mac);
+       ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_DISASSOCIATED, NULL);
+       spin_unlock_irqrestore(&mac->lock, flags);
+}
+
+/* Sends out a disassociation request to the desired AP */
+void
+ieee80211softmac_send_disassoc_req(struct ieee80211softmac_device *mac, u16 reason)
+{
        struct ieee80211softmac_network *found;
 
        if (mac->associnfo.bssvalid && mac->associated) {
                found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid);
                if (found)
                        ieee80211softmac_send_mgt_frame(mac, found, IEEE80211_STYPE_DISASSOC, reason);
-       } else if (mac->associnfo.associating) {
-               cancel_delayed_work(&mac->associnfo.timeout);
        }
 
-       /* Change our state */
-       spin_lock_irqsave(&mac->lock, flags);
-       /* Do NOT clear bssvalid as that will break ieee80211softmac_assoc_work! */
-       mac->associated = 0;
-       mac->associnfo.associating = 0;
-       ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_DISASSOCIATED, NULL);
-       spin_unlock_irqrestore(&mac->lock, flags);
+       ieee80211softmac_disassoc(mac);
 }
 
 static inline int
 we_support_all_basic_rates(struct ieee80211softmac_device *mac, u8 *from, u8 from_len)
 {
-       int idx, search, found;
-       u8 rate, search_rate;
+       int idx;
+       u8 rate;
 
        for (idx = 0; idx < (from_len); idx++) {
                rate = (from)[idx];
                if (!(rate & IEEE80211_BASIC_RATE_MASK))
                        continue;
-               found = 0;
                rate &= ~IEEE80211_BASIC_RATE_MASK;
-               for (search = 0; search < mac->ratesinfo.count; search++) {
-                       search_rate = mac->ratesinfo.rates[search];
-                       search_rate &= ~IEEE80211_BASIC_RATE_MASK;
-                       if (rate == search_rate) {
-                               found = 1;
-                               break;
-                       }
-               }
-               if (!found)
+               if (!ieee80211softmac_ratesinfo_rate_supported(&mac->ratesinfo, rate))
                        return 0;
        }
        return 1;
@@ -176,14 +177,18 @@ ieee80211softmac_assoc_work(void *d)
        struct ieee80211softmac_device *mac = (struct ieee80211softmac_device *)d;
        struct ieee80211softmac_network *found = NULL;
        struct ieee80211_network *net = NULL, *best = NULL;
+       int bssvalid;
        unsigned long flags;
-       
+
+       /* ieee80211_disassoc might clear this */
+       bssvalid = mac->associnfo.bssvalid;
+
        /* meh */
        if (mac->associated)
-               ieee80211softmac_disassoc(mac, WLAN_REASON_DISASSOC_STA_HAS_LEFT);
+               ieee80211softmac_send_disassoc_req(mac, WLAN_REASON_DISASSOC_STA_HAS_LEFT);
 
        /* try to find the requested network in our list, if we found one already */
-       if (mac->associnfo.bssvalid || mac->associnfo.bssfixed)
+       if (bssvalid || mac->associnfo.bssfixed)
                found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid);       
        
        /* Search the ieee80211 networks for this network if we didn't find it by bssid,
@@ -297,6 +302,9 @@ ieee80211softmac_associated(struct ieee80211softmac_device *mac,
        struct ieee80211softmac_network *net)
 {
        mac->associnfo.associating = 0;
+       mac->associnfo.supported_rates = net->supported_rates;
+       ieee80211softmac_recalc_txrates(mac);
+
        mac->associated = 1;
        if (mac->set_bssid_filter)
                mac->set_bssid_filter(mac->dev, net->bssid);
@@ -380,7 +388,6 @@ ieee80211softmac_handle_disassoc(struct net_device * dev,
                                 struct ieee80211_disassoc *disassoc)
 {
        struct ieee80211softmac_device *mac = ieee80211_priv(dev);
-       unsigned long flags;
 
        if (unlikely(!mac->running))
                return -ENODEV;
@@ -392,14 +399,11 @@ ieee80211softmac_handle_disassoc(struct net_device * dev,
                return 0;
 
        dprintk(KERN_INFO PFX "got disassoc frame\n");
-       netif_carrier_off(dev);
-       spin_lock_irqsave(&mac->lock, flags);
-       mac->associnfo.bssvalid = 0;
-       mac->associated = 0;
-       ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_DISASSOCIATED, NULL);
+       ieee80211softmac_disassoc(mac);
+
+       /* try to reassociate */
        schedule_work(&mac->associnfo.work);
-       spin_unlock_irqrestore(&mac->lock, flags);
-       
+
        return 0;
 }
 
index 06e332624665e8d456c505a376788993451d4ccb..084b6211f293e30c0cbcf1505d918d02f4b9d0f0 100644 (file)
@@ -279,6 +279,9 @@ ieee80211softmac_deauth_from_net(struct ieee80211softmac_device *mac,
        struct list_head *list_ptr;
        unsigned long flags;
 
+       /* deauthentication implies disassociation */
+       ieee80211softmac_disassoc(mac);
+
        /* Lock and reset status flags */
        spin_lock_irqsave(&mac->lock, flags);
        net->authenticating = 0;
index 6252be2c0db9af8a60e35e503e94a2bab0e482f2..4b2e57d12418a901185b6124ac3104dbd0e8d69a 100644 (file)
@@ -26,6 +26,7 @@
 
 #include "ieee80211softmac_priv.h"
 #include <linux/sort.h>
+#include <linux/etherdevice.h>
 
 struct net_device *alloc_ieee80211softmac(int sizeof_priv)
 {
@@ -61,14 +62,6 @@ struct net_device *alloc_ieee80211softmac(int sizeof_priv)
        softmac->wait_for_scan = ieee80211softmac_wait_for_scan_implementation;
        softmac->stop_scan = ieee80211softmac_stop_scan_implementation;
 
-       //TODO: The mcast rate has to be assigned dynamically somewhere (in scanning, association. Not sure...)
-       //      It has to be set to the highest rate all stations in the current network can handle.
-       softmac->txrates.mcast_rate = IEEE80211_CCK_RATE_1MB;
-       softmac->txrates.mcast_fallback = IEEE80211_CCK_RATE_1MB;
-       /* This is reassigned in ieee80211softmac_start to sane values. */
-       softmac->txrates.default_rate = IEEE80211_CCK_RATE_1MB;
-       softmac->txrates.default_fallback = IEEE80211_CCK_RATE_1MB;
-
        /* to start with, we can't send anything ... */
        netif_carrier_off(dev);
        
@@ -170,15 +163,82 @@ static void ieee80211softmac_start_check_rates(struct ieee80211softmac_device *m
        }
 }
 
-void ieee80211softmac_start(struct net_device *dev)
+int ieee80211softmac_ratesinfo_rate_supported(struct ieee80211softmac_ratesinfo *ri, u8 rate)
+{
+       int search;
+       u8 search_rate;
+
+       for (search = 0; search < ri->count; search++) {
+               search_rate = ri->rates[search];
+               search_rate &= ~IEEE80211_BASIC_RATE_MASK;
+               if (rate == search_rate)
+                       return 1;
+       }
+
+       return 0;
+}
+
+/* Finds the highest rate which is:
+ *  1. Present in ri (optionally a basic rate)
+ *  2. Supported by the device
+ *  3. Less than or equal to the user-defined rate
+ */
+static u8 highest_supported_rate(struct ieee80211softmac_device *mac,
+       struct ieee80211softmac_ratesinfo *ri, int basic_only)
+{
+       u8 user_rate = mac->txrates.user_rate;
+       int i;
+
+       if (ri->count == 0) {
+               dprintk(KERN_ERR PFX "empty ratesinfo?\n");
+               return IEEE80211_CCK_RATE_1MB;
+       }
+
+       for (i = ri->count - 1; i >= 0; i--) {
+               u8 rate = ri->rates[i];
+               if (basic_only && !(rate & IEEE80211_BASIC_RATE_MASK))
+                       continue;
+               rate &= ~IEEE80211_BASIC_RATE_MASK;
+               if (rate > user_rate)
+                       continue;
+               if (ieee80211softmac_ratesinfo_rate_supported(&mac->ratesinfo, rate))
+                       return rate;
+       }
+
+       /* If we haven't found a suitable rate by now, just trust the user */
+       return user_rate;
+}
+
+void ieee80211softmac_recalc_txrates(struct ieee80211softmac_device *mac)
+{
+       struct ieee80211softmac_txrates *txrates = &mac->txrates;
+       struct ieee80211softmac_txrates oldrates;
+       u32 change = 0;
+
+       if (mac->txrates_change)
+               oldrates = mac->txrates;
+
+       change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
+       txrates->default_rate = highest_supported_rate(mac, &mac->associnfo.supported_rates, 0);
+
+       change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK;
+       txrates->default_fallback = lower_rate(mac, txrates->default_rate);
+
+       change |= IEEE80211SOFTMAC_TXRATECHG_MCAST;
+       txrates->mcast_rate = highest_supported_rate(mac, &mac->associnfo.supported_rates, 1);
+
+       if (mac->txrates_change)
+               mac->txrates_change(mac->dev, change, &oldrates);
+
+}
+
+void ieee80211softmac_init_txrates(struct ieee80211softmac_device *mac)
 {
-       struct ieee80211softmac_device *mac = ieee80211_priv(dev);
        struct ieee80211_device *ieee = mac->ieee;
        u32 change = 0;
+       struct ieee80211softmac_txrates *txrates = &mac->txrates;
        struct ieee80211softmac_txrates oldrates;
 
-       ieee80211softmac_start_check_rates(mac);
-
        /* TODO: We need some kind of state machine to lower the default rates
         *       if we loose too many packets.
         */
@@ -193,22 +253,37 @@ void ieee80211softmac_start(struct net_device *dev)
           more reliable. Note similar logic in
           ieee80211softmac_wx_set_rate() */     
        if (ieee->modulation & IEEE80211_CCK_MODULATION) {
-               mac->txrates.default_rate = IEEE80211_CCK_RATE_11MB;
-               change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
-               mac->txrates.default_fallback = IEEE80211_CCK_RATE_5MB;
-               change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK;
+               txrates->user_rate = IEEE80211_CCK_RATE_11MB;
        } else if (ieee->modulation & IEEE80211_OFDM_MODULATION) {
-               mac->txrates.default_rate = IEEE80211_OFDM_RATE_54MB;
-               change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
-               mac->txrates.default_fallback = IEEE80211_OFDM_RATE_24MB;
-               change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK;
+               txrates->user_rate = IEEE80211_OFDM_RATE_54MB;
        } else
                assert(0);
+
+       txrates->default_rate = IEEE80211_CCK_RATE_1MB;
+       change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
+
+       txrates->default_fallback = IEEE80211_CCK_RATE_1MB;
+       change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK;
+
+       txrates->mcast_rate = IEEE80211_CCK_RATE_1MB;
+       change |= IEEE80211SOFTMAC_TXRATECHG_MCAST;
+
+       txrates->mgt_mcast_rate = IEEE80211_CCK_RATE_1MB;
+       change |= IEEE80211SOFTMAC_TXRATECHG_MGT_MCAST;
+
        if (mac->txrates_change)
-               mac->txrates_change(dev, change, &oldrates);
+               mac->txrates_change(mac->dev, change, &oldrates);
 
        mac->running = 1;
 }
+
+void ieee80211softmac_start(struct net_device *dev)
+{
+       struct ieee80211softmac_device *mac = ieee80211_priv(dev);
+
+       ieee80211softmac_start_check_rates(mac);
+       ieee80211softmac_init_txrates(mac);
+}
 EXPORT_SYMBOL_GPL(ieee80211softmac_start);
 
 void ieee80211softmac_stop(struct net_device *dev)
index 8c95b3abe0cc5120eb856872ed7f7a8a460977ca..fa1f8e3acfc07f0370567e026bef2d4379eeeedc 100644 (file)
@@ -116,7 +116,10 @@ ieee80211softmac_get_network_by_essid(struct ieee80211softmac_device *mac,
        struct ieee80211softmac_essid *essid);
 
 /* Rates related */
+int ieee80211softmac_ratesinfo_rate_supported(struct ieee80211softmac_ratesinfo *ri, u8 rate);
 u8 ieee80211softmac_lower_rate_delta(struct ieee80211softmac_device *mac, u8 rate, int delta);
+void ieee80211softmac_init_txrates(struct ieee80211softmac_device *mac);
+void ieee80211softmac_recalc_txrates(struct ieee80211softmac_device *mac);
 static inline u8 lower_rate(struct ieee80211softmac_device *mac, u8 rate) {
        return ieee80211softmac_lower_rate_delta(mac, rate, 1);
 }
@@ -150,7 +153,8 @@ int ieee80211softmac_handle_disassoc(struct net_device * dev,
 int ieee80211softmac_handle_reassoc_req(struct net_device * dev,
                                        struct ieee80211_reassoc_request * reassoc);
 void ieee80211softmac_assoc_timeout(void *d);
-void ieee80211softmac_disassoc(struct ieee80211softmac_device *mac, u16 reason);
+void ieee80211softmac_send_disassoc_req(struct ieee80211softmac_device *mac, u16 reason);
+void ieee80211softmac_disassoc(struct ieee80211softmac_device *mac);
 
 /* some helper functions */
 static inline int ieee80211softmac_scan_handlers_check_self(struct ieee80211softmac_device *sm)
index 8d0c22641ca8886f5a65e8fcaa8e04aee7be045f..22aa6199185b4161c820f9ca351a24e0450cda7c 100644 (file)
@@ -211,8 +211,8 @@ ieee80211softmac_wx_set_rate(struct net_device *net_dev,
        if (is_ofdm && !(ieee->modulation & IEEE80211_OFDM_MODULATION))
                goto out_unlock;
 
-       mac->txrates.default_rate = rate;
-       mac->txrates.default_fallback = lower_rate(mac, rate);
+       mac->txrates.user_rate = rate;
+       ieee80211softmac_recalc_txrates(mac);
        err = 0;
 
 out_unlock:    
@@ -456,7 +456,7 @@ ieee80211softmac_wx_set_mlme(struct net_device *dev,
                }
                return ieee80211softmac_deauth_req(mac, net, reason);
        case IW_MLME_DISASSOC:
-               ieee80211softmac_disassoc(mac, reason);
+               ieee80211softmac_send_disassoc_req(mac, reason);
                return 0;
        default:
                return -EOPNOTSUPP;