Commit db21e578 authored by Jeff Garzik's avatar Jeff Garzik

Merge branch 'upstream' of...

Merge branch 'upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6 into upstream
parents 6ed14254 df8ccb9b
...@@ -2768,7 +2768,7 @@ static int airo_test_wpa_capable(struct airo_info *ai) ...@@ -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 */ /* Only firmware versions 5.30.17 or better can do WPA */
if ((cap_rid.softVer > 0x530) 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."); airo_print_info(name, "WPA is supported.");
return 1; return 1;
} }
......
...@@ -128,13 +128,15 @@ MODULE_PARM_DESC(fwpostfix, "Postfix for .fw files. Useful for debugging."); ...@@ -128,13 +128,15 @@ MODULE_PARM_DESC(fwpostfix, "Postfix for .fw files. Useful for debugging.");
static struct pci_device_id bcm43xx_pci_tbl[] = { static struct pci_device_id bcm43xx_pci_tbl[] = {
/* Broadcom 4303 802.11b */ /* Broadcom 4303 802.11b */
{ PCI_VENDOR_ID_BROADCOM, 0x4301, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { 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 }, { 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 }, { 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 */ /* Broadcom 4306 802.11b/g */
{ PCI_VENDOR_ID_BROADCOM, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { 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 }, // { PCI_VENDOR_ID_BROADCOM, 0x4321, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
/* Broadcom 4309 802.11a/b/g */ /* Broadcom 4309 802.11a/b/g */
{ PCI_VENDOR_ID_BROADCOM, 0x4324, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { PCI_VENDOR_ID_BROADCOM, 0x4324, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
......
...@@ -534,5 +534,4 @@ int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -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); EXPORT_SYMBOL(hostap_master_start_xmit);
...@@ -3276,17 +3276,6 @@ EXPORT_SYMBOL(hostap_init_data); ...@@ -3276,17 +3276,6 @@ EXPORT_SYMBOL(hostap_init_data);
EXPORT_SYMBOL(hostap_init_ap_proc); EXPORT_SYMBOL(hostap_init_ap_proc);
EXPORT_SYMBOL(hostap_free_data); EXPORT_SYMBOL(hostap_free_data);
EXPORT_SYMBOL(hostap_check_sta_fw_version); 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_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 #ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
EXPORT_SYMBOL(hostap_deauth_all_stas);
#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ #endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
...@@ -881,6 +881,12 @@ static struct pcmcia_device_id hostap_cs_ids[] = { ...@@ -881,6 +881,12 @@ static struct pcmcia_device_id hostap_cs_ids[] = {
PCMCIA_DEVICE_PROD_ID12( PCMCIA_DEVICE_PROD_ID12(
"ZoomAir 11Mbps High", "Rate wireless Networking", "ZoomAir 11Mbps High", "Rate wireless Networking",
0x273fe3db, 0x32a1eaee), 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 PCMCIA_DEVICE_NULL
}; };
MODULE_DEVICE_TABLE(pcmcia, hostap_cs_ids); MODULE_DEVICE_TABLE(pcmcia, hostap_cs_ids);
......
...@@ -1125,11 +1125,9 @@ EXPORT_SYMBOL(hostap_set_auth_algs); ...@@ -1125,11 +1125,9 @@ EXPORT_SYMBOL(hostap_set_auth_algs);
EXPORT_SYMBOL(hostap_dump_rx_header); EXPORT_SYMBOL(hostap_dump_rx_header);
EXPORT_SYMBOL(hostap_dump_tx_header); EXPORT_SYMBOL(hostap_dump_tx_header);
EXPORT_SYMBOL(hostap_80211_header_parse); EXPORT_SYMBOL(hostap_80211_header_parse);
EXPORT_SYMBOL(hostap_80211_prism_header_parse);
EXPORT_SYMBOL(hostap_80211_get_hdrlen); EXPORT_SYMBOL(hostap_80211_get_hdrlen);
EXPORT_SYMBOL(hostap_get_stats); EXPORT_SYMBOL(hostap_get_stats);
EXPORT_SYMBOL(hostap_setup_dev); EXPORT_SYMBOL(hostap_setup_dev);
EXPORT_SYMBOL(hostap_proc);
EXPORT_SYMBOL(hostap_set_multicast_list_queue); EXPORT_SYMBOL(hostap_set_multicast_list_queue);
EXPORT_SYMBOL(hostap_set_hostapd); EXPORT_SYMBOL(hostap_set_hostapd);
EXPORT_SYMBOL(hostap_set_hostapd_sta); EXPORT_SYMBOL(hostap_set_hostapd_sta);
......
...@@ -147,14 +147,11 @@ static void orinoco_cs_detach(struct pcmcia_device *link) ...@@ -147,14 +147,11 @@ static void orinoco_cs_detach(struct pcmcia_device *link)
{ {
struct net_device *dev = link->priv; struct net_device *dev = link->priv;
if (link->dev_node)
unregister_netdev(dev);
orinoco_cs_release(link); 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); free_orinocodev(dev);
} /* orinoco_cs_detach */ } /* orinoco_cs_detach */
...@@ -346,19 +343,10 @@ orinoco_cs_config(struct pcmcia_device *link) ...@@ -346,19 +343,10 @@ orinoco_cs_config(struct pcmcia_device *link)
net_device has been registered */ net_device has been registered */
/* Finally, report what we've done */ /* Finally, report what we've done */
printk(KERN_DEBUG "%s: index 0x%02x: ", printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s, irq %d, io "
dev->name, link->conf.ConfigIndex); "0x%04x-0x%04x\n", dev->name, dev->class_dev.dev->bus_id,
if (link->conf.Vpp) link->irq.AssignedIRQ, link->io.BasePort1,
printk(", Vpp %d.%d", link->conf.Vpp / 10, link->io.BasePort1 + link->io.NumPorts1 - 1);
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");
return 0; return 0;
...@@ -427,7 +415,6 @@ static int orinoco_cs_resume(struct pcmcia_device *link) ...@@ -427,7 +415,6 @@ static int orinoco_cs_resume(struct pcmcia_device *link)
struct orinoco_private *priv = netdev_priv(dev); struct orinoco_private *priv = netdev_priv(dev);
struct orinoco_pccard *card = priv->card; struct orinoco_pccard *card = priv->card;
int err = 0; int err = 0;
unsigned long flags;
if (! test_bit(0, &card->hard_reset_in_progress)) { if (! test_bit(0, &card->hard_reset_in_progress)) {
err = orinoco_reinit_firmware(dev); err = orinoco_reinit_firmware(dev);
...@@ -437,7 +424,7 @@ static int orinoco_cs_resume(struct pcmcia_device *link) ...@@ -437,7 +424,7 @@ static int orinoco_cs_resume(struct pcmcia_device *link)
return -EIO; return -EIO;
} }
spin_lock_irqsave(&priv->lock, flags); spin_lock(&priv->lock);
netif_device_attach(dev); netif_device_attach(dev);
priv->hw_unavailable--; priv->hw_unavailable--;
...@@ -449,10 +436,10 @@ static int orinoco_cs_resume(struct pcmcia_device *link) ...@@ -449,10 +436,10 @@ static int orinoco_cs_resume(struct pcmcia_device *link)
dev->name, err); dev->name, err);
} }
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock(&priv->lock);
} }
return 0; return err;
} }
......
...@@ -206,7 +206,6 @@ static int orinoco_nortel_init_one(struct pci_dev *pdev, ...@@ -206,7 +206,6 @@ static int orinoco_nortel_init_one(struct pci_dev *pdev,
err = -EBUSY; err = -EBUSY;
goto fail_irq; goto fail_irq;
} }
orinoco_pci_setup_netdev(dev, pdev, 2);
err = orinoco_nortel_hw_init(card); err = orinoco_nortel_hw_init(card);
if (err) { if (err) {
...@@ -227,6 +226,8 @@ static int orinoco_nortel_init_one(struct pci_dev *pdev, ...@@ -227,6 +226,8 @@ static int orinoco_nortel_init_one(struct pci_dev *pdev,
} }
pci_set_drvdata(pdev, dev); pci_set_drvdata(pdev, dev);
printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s\n", dev->name,
pci_name(pdev));
return 0; return 0;
...@@ -265,7 +266,7 @@ static void __devexit orinoco_nortel_remove_one(struct pci_dev *pdev) ...@@ -265,7 +266,7 @@ static void __devexit orinoco_nortel_remove_one(struct pci_dev *pdev)
iowrite16(0, card->bridge_io + 10); iowrite16(0, card->bridge_io + 10);
unregister_netdev(dev); unregister_netdev(dev);
free_irq(dev->irq, dev); free_irq(pdev->irq, dev);
pci_set_drvdata(pdev, NULL); pci_set_drvdata(pdev, NULL);
free_orinocodev(dev); free_orinocodev(dev);
pci_iounmap(pdev, priv->hw.iobase); pci_iounmap(pdev, priv->hw.iobase);
......
...@@ -161,7 +161,6 @@ static int orinoco_pci_init_one(struct pci_dev *pdev, ...@@ -161,7 +161,6 @@ static int orinoco_pci_init_one(struct pci_dev *pdev,
err = -EBUSY; err = -EBUSY;
goto fail_irq; goto fail_irq;
} }
orinoco_pci_setup_netdev(dev, pdev, 0);
err = orinoco_pci_cor_reset(priv); err = orinoco_pci_cor_reset(priv);
if (err) { if (err) {
...@@ -176,6 +175,8 @@ static int orinoco_pci_init_one(struct pci_dev *pdev, ...@@ -176,6 +175,8 @@ static int orinoco_pci_init_one(struct pci_dev *pdev,
} }
pci_set_drvdata(pdev, dev); pci_set_drvdata(pdev, dev);
printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s\n", dev->name,
pci_name(pdev));
return 0; return 0;
...@@ -204,7 +205,7 @@ static void __devexit orinoco_pci_remove_one(struct pci_dev *pdev) ...@@ -204,7 +205,7 @@ static void __devexit orinoco_pci_remove_one(struct pci_dev *pdev)
struct orinoco_private *priv = netdev_priv(dev); struct orinoco_private *priv = netdev_priv(dev);
unregister_netdev(dev); unregister_netdev(dev);
free_irq(dev->irq, dev); free_irq(pdev->irq, dev);
pci_set_drvdata(pdev, NULL); pci_set_drvdata(pdev, NULL);
free_orinocodev(dev); free_orinocodev(dev);
pci_iounmap(pdev, priv->hw.iobase); pci_iounmap(pdev, priv->hw.iobase);
......
...@@ -18,32 +18,7 @@ struct orinoco_pci_card { ...@@ -18,32 +18,7 @@ struct orinoco_pci_card {
void __iomem *attr_io; void __iomem *attr_io;
}; };
/* Set base address or memory range of the network device based on #ifdef CONFIG_PM
* 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);
}
static int orinoco_pci_suspend(struct pci_dev *pdev, pm_message_t state) static int orinoco_pci_suspend(struct pci_dev *pdev, pm_message_t state)
{ {
struct net_device *dev = pci_get_drvdata(pdev); struct net_device *dev = pci_get_drvdata(pdev);
...@@ -121,5 +96,9 @@ static int orinoco_pci_resume(struct pci_dev *pdev) ...@@ -121,5 +96,9 @@ static int orinoco_pci_resume(struct pci_dev *pdev)
return 0; return 0;
} }
#else
#define orinoco_pci_suspend NULL
#define orinoco_pci_resume NULL
#endif
#endif /* _ORINOCO_PCI_H */ #endif /* _ORINOCO_PCI_H */
...@@ -245,7 +245,6 @@ static int orinoco_plx_init_one(struct pci_dev *pdev, ...@@ -245,7 +245,6 @@ static int orinoco_plx_init_one(struct pci_dev *pdev,
err = -EBUSY; err = -EBUSY;
goto fail_irq; goto fail_irq;
} }
orinoco_pci_setup_netdev(dev, pdev, 2);
err = orinoco_plx_hw_init(card); err = orinoco_plx_hw_init(card);
if (err) { if (err) {
...@@ -266,6 +265,8 @@ static int orinoco_plx_init_one(struct pci_dev *pdev, ...@@ -266,6 +265,8 @@ static int orinoco_plx_init_one(struct pci_dev *pdev,
} }
pci_set_drvdata(pdev, dev); pci_set_drvdata(pdev, dev);
printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s\n", dev->name,
pci_name(pdev));
return 0; return 0;
...@@ -301,7 +302,7 @@ static void __devexit orinoco_plx_remove_one(struct pci_dev *pdev) ...@@ -301,7 +302,7 @@ static void __devexit orinoco_plx_remove_one(struct pci_dev *pdev)
struct orinoco_pci_card *card = priv->card; struct orinoco_pci_card *card = priv->card;
unregister_netdev(dev); unregister_netdev(dev);
free_irq(dev->irq, dev); free_irq(pdev->irq, dev);
pci_set_drvdata(pdev, NULL); pci_set_drvdata(pdev, NULL);
free_orinocodev(dev); free_orinocodev(dev);
pci_iounmap(pdev, priv->hw.iobase); pci_iounmap(pdev, priv->hw.iobase);
......
...@@ -147,7 +147,6 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev, ...@@ -147,7 +147,6 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev,
err = -EBUSY; err = -EBUSY;
goto fail_irq; goto fail_irq;
} }
orinoco_pci_setup_netdev(dev, pdev, 2);
err = orinoco_tmd_cor_reset(priv); err = orinoco_tmd_cor_reset(priv);
if (err) { if (err) {
...@@ -162,6 +161,8 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev, ...@@ -162,6 +161,8 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev,
} }
pci_set_drvdata(pdev, dev); pci_set_drvdata(pdev, dev);
printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s\n", dev->name,
pci_name(pdev));
return 0; return 0;
...@@ -194,7 +195,7 @@ static void __devexit orinoco_tmd_remove_one(struct pci_dev *pdev) ...@@ -194,7 +195,7 @@ static void __devexit orinoco_tmd_remove_one(struct pci_dev *pdev)
struct orinoco_pci_card *card = priv->card; struct orinoco_pci_card *card = priv->card;
unregister_netdev(dev); unregister_netdev(dev);
free_irq(dev->irq, dev); free_irq(pdev->irq, dev);
pci_set_drvdata(pdev, NULL); pci_set_drvdata(pdev, NULL);
free_orinocodev(dev); free_orinocodev(dev);
pci_iounmap(pdev, priv->hw.iobase); pci_iounmap(pdev, priv->hw.iobase);
......
...@@ -625,14 +625,11 @@ static void spectrum_cs_detach(struct pcmcia_device *link) ...@@ -625,14 +625,11 @@ static void spectrum_cs_detach(struct pcmcia_device *link)
{ {
struct net_device *dev = link->priv; struct net_device *dev = link->priv;
if (link->dev_node)
unregister_netdev(dev);
spectrum_cs_release(link); 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); free_orinocodev(dev);
} /* spectrum_cs_detach */ } /* spectrum_cs_detach */
...@@ -825,19 +822,10 @@ spectrum_cs_config(struct pcmcia_device *link) ...@@ -825,19 +822,10 @@ spectrum_cs_config(struct pcmcia_device *link)
net_device has been registered */ net_device has been registered */
/* Finally, report what we've done */ /* Finally, report what we've done */
printk(KERN_DEBUG "%s: index 0x%02x: ", printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s, irq %d, io "
dev->name, link->conf.ConfigIndex); "0x%04x-0x%04x\n", dev->name, dev->class_dev.dev->bus_id,
if (link->conf.Vpp) link->irq.AssignedIRQ, link->io.BasePort1,
printk(", Vpp %d.%d", link->conf.Vpp / 10, link->io.BasePort1 + link->io.NumPorts1 - 1);
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");
return 0; return 0;
...@@ -878,11 +866,10 @@ spectrum_cs_suspend(struct pcmcia_device *link) ...@@ -878,11 +866,10 @@ spectrum_cs_suspend(struct pcmcia_device *link)
{ {
struct net_device *dev = link->priv; struct net_device *dev = link->priv;
struct orinoco_private *priv = netdev_priv(dev); struct orinoco_private *priv = netdev_priv(dev);
unsigned long flags;
int err = 0; int err = 0;
/* Mark the device as stopped, to block IO until later */ /* Mark the device as stopped, to block IO until later */
spin_lock_irqsave(&priv->lock, flags); spin_lock(&priv->lock);
err = __orinoco_down(dev); err = __orinoco_down(dev);
if (err) if (err)
...@@ -892,9 +879,9 @@ spectrum_cs_suspend(struct pcmcia_device *link) ...@@ -892,9 +879,9 @@ spectrum_cs_suspend(struct pcmcia_device *link)
netif_device_detach(dev); netif_device_detach(dev);
priv->hw_unavailable++; priv->hw_unavailable++;
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock(&priv->lock);
return 0; return err;
} }
static int static int
......
...@@ -86,6 +86,9 @@ struct ieee80211softmac_assoc_info { ...@@ -86,6 +86,9 @@ struct ieee80211softmac_assoc_info {
/* BSSID we're trying to associate to */ /* BSSID we're trying to associate to */
char bssid[ETH_ALEN]; char bssid[ETH_ALEN];
/* Rates supported by the network */
struct ieee80211softmac_ratesinfo supported_rates;
/* some flags. /* some flags.
* static_essid is valid if the essid is constant, * static_essid is valid if the essid is constant,
...@@ -132,23 +135,26 @@ enum { ...@@ -132,23 +135,26 @@ enum {
struct ieee80211softmac_txrates { struct ieee80211softmac_txrates {
/* The Bit-Rate to be used for multicast frames. */ /* The Bit-Rate to be used for multicast frames. */
u8 mcast_rate; u8 mcast_rate;
/* The Bit-Rate to be used for multicast fallback
* (If the device supports fallback and hardware-retry) /* The Bit-Rate to be used for multicast management frames. */
*/ u8 mgt_mcast_rate;
u8 mcast_fallback;
/* The Bit-Rate to be used for any other (normal) data packet. */ /* The Bit-Rate to be used for any other (normal) data packet. */
u8 default_rate; u8 default_rate;
/* The Bit-Rate to be used for default fallback /* The Bit-Rate to be used for default fallback
* (If the device supports fallback and hardware-retry) * (If the device supports fallback and hardware-retry)
*/ */
u8 default_fallback; u8 default_fallback;
/* This is the rate that the user asked for */
u8 user_rate;
}; };
/* Bits for txrates_change callback. */ /* Bits for txrates_change callback. */
#define IEEE80211SOFTMAC_TXRATECHG_DEFAULT (1 << 0) /* default_rate */ #define IEEE80211SOFTMAC_TXRATECHG_DEFAULT (1 << 0) /* default_rate */
#define IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK (1 << 1) /* default_fallback */ #define IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK (1 << 1) /* default_fallback */
#define IEEE80211SOFTMAC_TXRATECHG_MCAST (1 << 2) /* mcast_rate */ #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 { struct ieee80211softmac_device {
/* 802.11 structure for data stuff */ /* 802.11 structure for data stuff */
...@@ -250,6 +256,28 @@ extern void ieee80211softmac_fragment_lost(struct net_device *dev, ...@@ -250,6 +256,28 @@ extern void ieee80211softmac_fragment_lost(struct net_device *dev,
* Note that the rates need to be sorted. */ * Note that the rates need to be sorted. */
extern void ieee80211softmac_set_rates(struct net_device *dev, u8 count, u8 *rates); 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 /* Start the SoftMAC. Call this after you initialized the device
* and it is ready to run. * and it is ready to run.
*/ */
......
...@@ -503,7 +503,7 @@ int ieee80211_wx_get_encode(struct ieee80211_device *ieee, ...@@ -503,7 +503,7 @@ int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
len = sec->key_sizes[key]; len = sec->key_sizes[key];
memcpy(keybuf, sec->keys[key], len); memcpy(keybuf, sec->keys[key], len);
erq->length = (len >= 0 ? len : 0); erq->length = len;
erq->flags |= IW_ENCODE_ENABLED; erq->flags |= IW_ENCODE_ENABLED;
if (ieee->open_wep) if (ieee->open_wep)
......
...@@ -82,51 +82,52 @@ ieee80211softmac_assoc_timeout(void *d) ...@@ -82,51 +82,52 @@ ieee80211softmac_assoc_timeout(void *d)
ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_TIMEOUT, NULL); ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_TIMEOUT, NULL);
} }
/* Sends out a disassociation request to the desired AP */
void void
ieee80211softmac_disassoc(struct ieee80211softmac_device *mac, u16 reason) ieee80211softmac_disassoc(struct ieee80211softmac_device *mac)
{ {
unsigned long flags; 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; struct ieee80211softmac_network *found;
if (mac->associnfo.bssvalid && mac->associated) { if (mac->associnfo.bssvalid && mac->associated) {
found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid); found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid);
if (found) if (found)
ieee80211softmac_send_mgt_frame(mac, found, IEEE80211_STYPE_DISASSOC, reason); ieee80211softmac_send_mgt_frame(mac, found, IEEE80211_STYPE_DISASSOC, reason);
} else if (mac->associnfo.associating) {
cancel_delayed_work(&mac->associnfo.timeout);
} }
/* Change our state */ ieee80211softmac_disassoc(mac);
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);
} }
static inline int static inline int
we_support_all_basic_rates(struct ieee80211softmac_device *mac, u8 *from, u8 from_len) we_support_all_basic_rates(struct ieee80211softmac_device *mac, u8 *from, u8 from_len)
{ {
int idx, search, found; int idx;
u8 rate, search_rate; u8 rate;
for (idx = 0; idx < (from_len); idx++) { for (idx = 0; idx < (from_len); idx++) {
rate = (from)[idx]; rate = (from)[idx];
if (!(rate & IEEE80211_BASIC_RATE_MASK)) if (!(rate & IEEE80211_BASIC_RATE_MASK))
continue; continue;
found = 0;
rate &= ~IEEE80211_BASIC_RATE_MASK; rate &= ~IEEE80211_BASIC_RATE_MASK;
for (search = 0; search < mac->ratesinfo.count; search++) { if (!ieee80211softmac_ratesinfo_rate_supported(&mac->ratesinfo, rate))
search_rate = mac->ratesinfo.rates[search];
search_rate &= ~IEEE80211_BASIC_RATE_MASK;
if (rate == search_rate) {
found = 1;
break;
}
}
if (!found)
return 0; return 0;
} }
return 1; return 1;
...@@ -176,14 +177,18 @@ ieee80211softmac_assoc_work(void *d) ...@@ -176,14 +177,18 @@ ieee80211softmac_assoc_work(void *d)
struct ieee80211softmac_device *mac = (struct ieee80211softmac_device *)d; struct ieee80211softmac_device *mac = (struct ieee80211softmac_device *)d;
struct ieee80211softmac_network *found = NULL; struct ieee80211softmac_network *found = NULL;
struct ieee80211_network *net = NULL, *best = NULL; struct ieee80211_network *net = NULL, *best = NULL;
int bssvalid;
unsigned long flags; unsigned long flags;
/* ieee80211_disassoc might clear this */
bssvalid = mac->associnfo.bssvalid;
/* meh */ /* meh */
if (mac->associated) 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 */ /* 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); 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, /* 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, ...@@ -297,6 +302,9 @@ ieee80211softmac_associated(struct ieee80211softmac_device *mac,
struct ieee80211softmac_network *net) struct ieee80211softmac_network *net)
{ {
mac->associnfo.associating = 0; mac->associnfo.associating = 0;
mac->associnfo.supported_rates = net->supported_rates;
ieee80211softmac_recalc_txrates(mac);
mac->associated = 1; mac->associated = 1;
if (mac->set_bssid_filter) if (mac->set_bssid_filter)
mac->set_bssid_filter(mac->dev, net->bssid); mac->set_bssid_filter(mac->dev, net->bssid);
...@@ -380,7 +388,6 @@ ieee80211softmac_handle_disassoc(struct net_device * dev, ...@@ -380,7 +388,6 @@ ieee80211softmac_handle_disassoc(struct net_device * dev,
struct ieee80211_disassoc *disassoc) struct ieee80211_disassoc *disassoc)
{ {
struct ieee80211softmac_device *mac = ieee80211_priv(dev); struct ieee80211softmac_device *mac = ieee80211_priv(dev);
unsigned long flags;
if (unlikely(!mac->running)) if (unlikely(!mac->running))
return -ENODEV; return -ENODEV;
...@@ -392,14 +399,11 @@ ieee80211softmac_handle_disassoc(struct net_device * dev, ...@@ -392,14 +399,11 @@ ieee80211softmac_handle_disassoc(struct net_device * dev,
return 0; return 0;
dprintk(KERN_INFO PFX "got disassoc frame\n"); dprintk(KERN_INFO PFX "got disassoc frame\n");
netif_carrier_off(dev); ieee80211softmac_disassoc(mac);
spin_lock_irqsave(&mac->lock, flags);
mac->associnfo.bssvalid = 0; /* try to reassociate */
mac->associated = 0;
ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_DISASSOCIATED, NULL);
schedule_work(&mac->associnfo.work); schedule_work(&mac->associnfo.work);
spin_unlock_irqrestore(&mac->lock, flags);
return 0; return 0;
} }
......
...@@ -279,6 +279,9 @@ ieee80211softmac_deauth_from_net(struct ieee80211softmac_device *mac, ...@@ -279,6 +279,9 @@ ieee80211softmac_deauth_from_net(struct ieee80211softmac_device *mac,
struct list_head *list_ptr; struct list_head *list_ptr;
unsigned long flags; unsigned long flags;
/* deauthentication implies disassociation */
ieee80211softmac_disassoc(mac);
/* Lock and reset status flags */ /* Lock and reset status flags */
spin_lock_irqsave(&mac->lock, flags); spin_lock_irqsave(&mac->lock, flags);
net->authenticating = 0; net->authenticating = 0;
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "ieee80211softmac_priv.h" #include "ieee80211softmac_priv.h"
#include <linux/sort.h> #include <linux/sort.h>
#include <linux/etherdevice.h>
struct net_device *alloc_ieee80211softmac(int sizeof_priv) struct net_device *alloc_ieee80211softmac(int sizeof_priv)
{ {
...@@ -61,14 +62,6 @@ 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->wait_for_scan = ieee80211softmac_wait_for_scan_implementation;
softmac->stop_scan = ieee80211softmac_stop_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 ... */ /* to start with, we can't send anything ... */
netif_carrier_off(dev); netif_carrier_off(dev);
...@@ -170,15 +163,82 @@ static void ieee80211softmac_start_check_rates(struct ieee80211softmac_device *m ...@@ -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; struct ieee80211_device *ieee = mac->ieee;
u32 change = 0; u32 change = 0;
struct ieee80211softmac_txrates *txrates = &mac->txrates;
struct ieee80211softmac_txrates oldrates; struct ieee80211softmac_txrates oldrates;
ieee80211softmac_start_check_rates(mac);
/* TODO: We need some kind of state machine to lower the default rates /* TODO: We need some kind of state machine to lower the default rates
* if we loose too many packets. * if we loose too many packets.
*/ */
...@@ -193,22 +253,37 @@ void ieee80211softmac_start(struct net_device *dev) ...@@ -193,22 +253,37 @@ void ieee80211softmac_start(struct net_device *dev)
more reliable. Note similar logic in more reliable. Note similar logic in
ieee80211softmac_wx_set_rate() */ ieee80211softmac_wx_set_rate() */
if (ieee->modulation & IEEE80211_CCK_MODULATION) { if (ieee->modulation & IEEE80211_CCK_MODULATION) {
mac->txrates.default_rate = IEEE80211_CCK_RATE_11MB; txrates->user_rate = IEEE80211_CCK_RATE_11MB;
change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
mac->txrates.default_fallback = IEEE80211_CCK_RATE_5MB;
change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK;
} else if (ieee->modulation & IEEE80211_OFDM_MODULATION) { } else if (ieee->modulation & IEEE80211_OFDM_MODULATION) {
mac->txrates.default_rate = IEEE80211_OFDM_RATE_54MB; txrates->user_rate = IEEE80211_OFDM_RATE_54MB;
change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT;
mac->txrates.default_fallback = IEEE80211_OFDM_RATE_24MB;
change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK;
} else } else
assert(0); 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) if (mac->txrates_change)
mac->txrates_change(dev, change, &oldrates); mac->txrates_change(mac->dev, change, &oldrates);
mac->running = 1; 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); EXPORT_SYMBOL_GPL(ieee80211softmac_start);
void ieee80211softmac_stop(struct net_device *dev) void ieee80211softmac_stop(struct net_device *dev)
......
...@@ -116,7 +116,10 @@ ieee80211softmac_get_network_by_essid(struct ieee80211softmac_device *mac, ...@@ -116,7 +116,10 @@ ieee80211softmac_get_network_by_essid(struct ieee80211softmac_device *mac,
struct ieee80211softmac_essid *essid); struct ieee80211softmac_essid *essid);
/* Rates related */ /* 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); 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) { static inline u8 lower_rate(struct ieee80211softmac_device *mac, u8 rate) {
return ieee80211softmac_lower_rate_delta(mac, rate, 1); return ieee80211softmac_lower_rate_delta(mac, rate, 1);
} }
...@@ -150,7 +153,8 @@ int ieee80211softmac_handle_disassoc(struct net_device * dev, ...@@ -150,7 +153,8 @@ int ieee80211softmac_handle_disassoc(struct net_device * dev,
int ieee80211softmac_handle_reassoc_req(struct net_device * dev, int ieee80211softmac_handle_reassoc_req(struct net_device * dev,
struct ieee80211_reassoc_request * reassoc); struct ieee80211_reassoc_request * reassoc);
void ieee80211softmac_assoc_timeout(void *d); 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 */ /* some helper functions */
static inline int ieee80211softmac_scan_handlers_check_self(struct ieee80211softmac_device *sm) static inline int ieee80211softmac_scan_handlers_check_self(struct ieee80211softmac_device *sm)
......
...@@ -211,8 +211,8 @@ ieee80211softmac_wx_set_rate(struct net_device *net_dev, ...@@ -211,8 +211,8 @@ ieee80211softmac_wx_set_rate(struct net_device *net_dev,
if (is_ofdm && !(ieee->modulation & IEEE80211_OFDM_MODULATION)) if (is_ofdm && !(ieee->modulation & IEEE80211_OFDM_MODULATION))
goto out_unlock; goto out_unlock;
mac->txrates.default_rate = rate; mac->txrates.user_rate = rate;
mac->txrates.default_fallback = lower_rate(mac, rate); ieee80211softmac_recalc_txrates(mac);
err = 0; err = 0;
out_unlock: out_unlock:
...@@ -456,7 +456,7 @@ ieee80211softmac_wx_set_mlme(struct net_device *dev, ...@@ -456,7 +456,7 @@ ieee80211softmac_wx_set_mlme(struct net_device *dev,
} }
return ieee80211softmac_deauth_req(mac, net, reason); return ieee80211softmac_deauth_req(mac, net, reason);
case IW_MLME_DISASSOC: case IW_MLME_DISASSOC:
ieee80211softmac_disassoc(mac, reason); ieee80211softmac_send_disassoc_req(mac, reason);
return 0; return 0;
default: default:
return -EOPNOTSUPP; return -EOPNOTSUPP;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment