aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Garzik <jeff@garzik.org>2006-05-24 00:29:57 -0400
committerJeff Garzik <jeff@garzik.org>2006-05-24 00:29:57 -0400
commitdb21e578e551421d76641d72cb3f8296ed3f9e61 (patch)
tree73968aeda7ed0051b5cff6950ad513011a3c7a5f
parent6ed14254cb6e269030ff09bed8673473b7be0283 (diff)
parentdf8ccb9bf1ca360581a94c2245efb9fa613fbb29 (diff)
Merge branch 'upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6 into upstream
-rw-r--r--drivers/net/wireless/airo.c2
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_main.c8
-rw-r--r--drivers/net/wireless/hostap/hostap_80211_tx.c1
-rw-r--r--drivers/net/wireless/hostap/hostap_ap.c11
-rw-r--r--drivers/net/wireless/hostap/hostap_cs.c6
-rw-r--r--drivers/net/wireless/hostap/hostap_main.c2
-rw-r--r--drivers/net/wireless/orinoco_cs.c33
-rw-r--r--drivers/net/wireless/orinoco_nortel.c5
-rw-r--r--drivers/net/wireless/orinoco_pci.c5
-rw-r--r--drivers/net/wireless/orinoco_pci.h31
-rw-r--r--drivers/net/wireless/orinoco_plx.c5
-rw-r--r--drivers/net/wireless/orinoco_tmd.c5
-rw-r--r--drivers/net/wireless/spectrum_cs.c33
-rw-r--r--include/net/ieee80211softmac.h38
-rw-r--r--net/ieee80211/ieee80211_wx.c2
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_assoc.c72
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_auth.c3
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_module.c117
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_priv.h6
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_wx.c6
20 files changed, 228 insertions, 163 deletions
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 7f2dacf634e..4069b79d825 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -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;
}
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
index 2adf02ac400..c0502905a95 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
@@ -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 },
diff --git a/drivers/net/wireless/hostap/hostap_80211_tx.c b/drivers/net/wireless/hostap/hostap_80211_tx.c
index 06a5214145e..4a5be70c041 100644
--- a/drivers/net/wireless/hostap/hostap_80211_tx.c
+++ b/drivers/net/wireless/hostap/hostap_80211_tx.c
@@ -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);
diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c
index 06c3fa32b31..ba13125024c 100644
--- a/drivers/net/wireless/hostap/hostap_ap.c
+++ b/drivers/net/wireless/hostap/hostap_ap.c
@@ -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 */
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
index 55bed923fbe..db03dc2646d 100644
--- a/drivers/net/wireless/hostap/hostap_cs.c
+++ b/drivers/net/wireless/hostap/hostap_cs.c
@@ -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);
diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c
index 8dd4c4446a6..93786f4218f 100644
--- a/drivers/net/wireless/hostap/hostap_main.c
+++ b/drivers/net/wireless/hostap/hostap_main.c
@@ -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);
diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c
index d2c48ac60f4..b2aec4d9fbb 100644
--- a/drivers/net/wireless/orinoco_cs.c
+++ b/drivers/net/wireless/orinoco_cs.c
@@ -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;
}
diff --git a/drivers/net/wireless/orinoco_nortel.c b/drivers/net/wireless/orinoco_nortel.c
index 1596182f741..74b9d5b2ba9 100644
--- a/drivers/net/wireless/orinoco_nortel.c
+++ b/drivers/net/wireless/orinoco_nortel.c
@@ -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);
diff --git a/drivers/net/wireless/orinoco_pci.c b/drivers/net/wireless/orinoco_pci.c
index df37b95607f..1c105f40f8d 100644
--- a/drivers/net/wireless/orinoco_pci.c
+++ b/drivers/net/wireless/orinoco_pci.c
@@ -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);
diff --git a/drivers/net/wireless/orinoco_pci.h b/drivers/net/wireless/orinoco_pci.h
index b05a9a5b1f5..7eb1e08113e 100644
--- a/drivers/net/wireless/orinoco_pci.h
+++ b/drivers/net/wireless/orinoco_pci.h
@@ -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 */
diff --git a/drivers/net/wireless/orinoco_plx.c b/drivers/net/wireless/orinoco_plx.c
index 7b940509638..84f696c7755 100644
--- a/drivers/net/wireless/orinoco_plx.c
+++ b/drivers/net/wireless/orinoco_plx.c
@@ -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);
diff --git a/drivers/net/wireless/orinoco_tmd.c b/drivers/net/wireless/orinoco_tmd.c
index 0496663e837..d2b4decb7a7 100644
--- a/drivers/net/wireless/orinoco_tmd.c
+++ b/drivers/net/wireless/orinoco_tmd.c
@@ -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);
diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/spectrum_cs.c
index aeb38d93883..7f9aa139c34 100644
--- a/drivers/net/wireless/spectrum_cs.c
+++ b/drivers/net/wireless/spectrum_cs.c
@@ -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
diff --git a/include/net/ieee80211softmac.h b/include/net/ieee80211softmac.h
index 052ed596a4e..703463a8828 100644
--- a/include/net/ieee80211softmac.h
+++ b/include/net/ieee80211softmac.h
@@ -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.
*/
diff --git a/net/ieee80211/ieee80211_wx.c b/net/ieee80211/ieee80211_wx.c
index 0ea55cb5f17..a78c4f845f6 100644
--- a/net/ieee80211/ieee80211_wx.c
+++ b/net/ieee80211/ieee80211_wx.c
@@ -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)
diff --git a/net/ieee80211/softmac/ieee80211softmac_assoc.c b/net/ieee80211/softmac/ieee80211softmac_assoc.c
index d4c79ce1687..5d90b9a6ee5 100644
--- a/net/ieee80211/softmac/ieee80211softmac_assoc.c
+++ b/net/ieee80211/softmac/ieee80211softmac_assoc.c
@@ -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;
}
diff --git a/net/ieee80211/softmac/ieee80211softmac_auth.c b/net/ieee80211/softmac/ieee80211softmac_auth.c
index 06e33262466..084b6211f29 100644
--- a/net/ieee80211/softmac/ieee80211softmac_auth.c
+++ b/net/ieee80211/softmac/ieee80211softmac_auth.c
@@ -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;
diff --git a/net/ieee80211/softmac/ieee80211softmac_module.c b/net/ieee80211/softmac/ieee80211softmac_module.c
index 6252be2c0db..4b2e57d1241 100644
--- a/net/ieee80211/softmac/ieee80211softmac_module.c
+++ b/net/ieee80211/softmac/ieee80211softmac_module.c
@@ -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)
diff --git a/net/ieee80211/softmac/ieee80211softmac_priv.h b/net/ieee80211/softmac/ieee80211softmac_priv.h
index 8c95b3abe0c..fa1f8e3acfc 100644
--- a/net/ieee80211/softmac/ieee80211softmac_priv.h
+++ b/net/ieee80211/softmac/ieee80211softmac_priv.h
@@ -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)
diff --git a/net/ieee80211/softmac/ieee80211softmac_wx.c b/net/ieee80211/softmac/ieee80211softmac_wx.c
index 8d0c22641ca..22aa6199185 100644
--- a/net/ieee80211/softmac/ieee80211softmac_wx.c
+++ b/net/ieee80211/softmac/ieee80211softmac_wx.c
@@ -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;