Merge branch 'upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6 into upstream

This commit is contained in:
Jeff Garzik 2006-05-24 00:29:57 -04:00
commit db21e578e5
20 changed files with 228 additions and 163 deletions

View 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;
}

View 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 },

View 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);

View 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 */

View 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);

View 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);

View 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;
}

View 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);

View 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);

View 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 */

View 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);

View 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);

View 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

View 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.
*/

View 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)

View 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;
}

View 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;

View 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)

View 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)

View 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;