aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ipw2x00
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ipw2x00')
-rw-r--r--drivers/net/wireless/ipw2x00/Kconfig11
-rw-r--r--drivers/net/wireless/ipw2x00/ipw2100.c147
-rw-r--r--drivers/net/wireless/ipw2x00/ipw2200.c27
-rw-r--r--drivers/net/wireless/ipw2x00/libipw_module.c41
4 files changed, 168 insertions, 58 deletions
diff --git a/drivers/net/wireless/ipw2x00/Kconfig b/drivers/net/wireless/ipw2x00/Kconfig
index a813138..2715b10 100644
--- a/drivers/net/wireless/ipw2x00/Kconfig
+++ b/drivers/net/wireless/ipw2x00/Kconfig
@@ -4,8 +4,10 @@
config IPW2100
tristate "Intel PRO/Wireless 2100 Network Connection"
- depends on PCI && WLAN_80211 && CFG80211
+ depends on PCI && CFG80211
select WIRELESS_EXT
+ select WEXT_SPY
+ select WEXT_PRIV
select FW_LOADER
select LIB80211
select LIBIPW
@@ -63,8 +65,10 @@ config IPW2100_DEBUG
config IPW2200
tristate "Intel PRO/Wireless 2200BG and 2915ABG Network Connection"
- depends on PCI && WLAN_80211 && CFG80211
+ depends on PCI && CFG80211 && CFG80211_WEXT
select WIRELESS_EXT
+ select WEXT_SPY
+ select WEXT_PRIV
select FW_LOADER
select LIB80211
select LIBIPW
@@ -150,8 +154,9 @@ config IPW2200_DEBUG
config LIBIPW
tristate
- depends on PCI && WLAN_80211 && CFG80211
+ depends on PCI && CFG80211
select WIRELESS_EXT
+ select WEXT_SPY
select CRYPTO
select CRYPTO_ARC4
select CRYPTO_ECB
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c
index 240cff1..56afcf0 100644
--- a/drivers/net/wireless/ipw2x00/ipw2100.c
+++ b/drivers/net/wireless/ipw2x00/ipw2100.c
@@ -296,6 +296,33 @@ static const char *command_types[] = {
};
#endif
+#define WEXT_USECHANNELS 1
+
+static const long ipw2100_frequencies[] = {
+ 2412, 2417, 2422, 2427,
+ 2432, 2437, 2442, 2447,
+ 2452, 2457, 2462, 2467,
+ 2472, 2484
+};
+
+#define FREQ_COUNT ARRAY_SIZE(ipw2100_frequencies)
+
+static const long ipw2100_rates_11b[] = {
+ 1000000,
+ 2000000,
+ 5500000,
+ 11000000
+};
+
+static struct ieee80211_rate ipw2100_bg_rates[] = {
+ { .bitrate = 10 },
+ { .bitrate = 20, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+ { .bitrate = 55, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+ { .bitrate = 110, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+};
+
+#define RATE_COUNT ARRAY_SIZE(ipw2100_rates_11b)
+
/* Pre-decl until we get the code solid and then we can clean it up */
static void ipw2100_tx_send_commands(struct ipw2100_priv *priv);
static void ipw2100_tx_send_data(struct ipw2100_priv *priv);
@@ -551,7 +578,7 @@ static int ipw2100_get_ordinal(struct ipw2100_priv *priv, u32 ord,
/* get number of entries */
field_count = *(((u16 *) & field_info) + 1);
- /* abort if no enought memory */
+ /* abort if no enough memory */
total_length = field_len * field_count;
if (total_length > *len) {
*len = total_length;
@@ -1141,6 +1168,7 @@ static int rf_kill_active(struct ipw2100_priv *priv)
int i;
if (!(priv->hw_features & HW_FEATURE_RFKILL)) {
+ wiphy_rfkill_set_hw_state(priv->ieee->wdev.wiphy, false);
priv->status &= ~STATUS_RF_KILL_HW;
return 0;
}
@@ -1151,10 +1179,13 @@ static int rf_kill_active(struct ipw2100_priv *priv)
value = (value << 1) | ((reg & IPW_BIT_GPIO_RF_KILL) ? 0 : 1);
}
- if (value == 0)
+ if (value == 0) {
+ wiphy_rfkill_set_hw_state(priv->ieee->wdev.wiphy, true);
priv->status |= STATUS_RF_KILL_HW;
- else
+ } else {
+ wiphy_rfkill_set_hw_state(priv->ieee->wdev.wiphy, false);
priv->status &= ~STATUS_RF_KILL_HW;
+ }
return (value == 0);
}
@@ -1814,13 +1845,6 @@ static int ipw2100_up(struct ipw2100_priv *priv, int deferred)
return rc;
}
-/* Called by register_netdev() */
-static int ipw2100_net_init(struct net_device *dev)
-{
- struct ipw2100_priv *priv = libipw_priv(dev);
- return ipw2100_up(priv, 1);
-}
-
static void ipw2100_down(struct ipw2100_priv *priv)
{
unsigned long flags;
@@ -1875,6 +1899,64 @@ static void ipw2100_down(struct ipw2100_priv *priv)
netif_stop_queue(priv->net_dev);
}
+/* Called by register_netdev() */
+static int ipw2100_net_init(struct net_device *dev)
+{
+ struct ipw2100_priv *priv = libipw_priv(dev);
+ const struct libipw_geo *geo = libipw_get_geo(priv->ieee);
+ struct wireless_dev *wdev = &priv->ieee->wdev;
+ int ret;
+ int i;
+
+ ret = ipw2100_up(priv, 1);
+ if (ret)
+ return ret;
+
+ memcpy(wdev->wiphy->perm_addr, priv->mac_addr, ETH_ALEN);
+
+ /* fill-out priv->ieee->bg_band */
+ if (geo->bg_channels) {
+ struct ieee80211_supported_band *bg_band = &priv->ieee->bg_band;
+
+ bg_band->band = IEEE80211_BAND_2GHZ;
+ bg_band->n_channels = geo->bg_channels;
+ bg_band->channels =
+ kzalloc(geo->bg_channels *
+ sizeof(struct ieee80211_channel), GFP_KERNEL);
+ /* translate geo->bg to bg_band.channels */
+ for (i = 0; i < geo->bg_channels; i++) {
+ bg_band->channels[i].band = IEEE80211_BAND_2GHZ;
+ bg_band->channels[i].center_freq = geo->bg[i].freq;
+ bg_band->channels[i].hw_value = geo->bg[i].channel;
+ bg_band->channels[i].max_power = geo->bg[i].max_power;
+ if (geo->bg[i].flags & LIBIPW_CH_PASSIVE_ONLY)
+ bg_band->channels[i].flags |=
+ IEEE80211_CHAN_PASSIVE_SCAN;
+ if (geo->bg[i].flags & LIBIPW_CH_NO_IBSS)
+ bg_band->channels[i].flags |=
+ IEEE80211_CHAN_NO_IBSS;
+ if (geo->bg[i].flags & LIBIPW_CH_RADAR_DETECT)
+ bg_band->channels[i].flags |=
+ IEEE80211_CHAN_RADAR;
+ /* No equivalent for LIBIPW_CH_80211H_RULES,
+ LIBIPW_CH_UNIFORM_SPREADING, or
+ LIBIPW_CH_B_ONLY... */
+ }
+ /* point at bitrate info */
+ bg_band->bitrates = ipw2100_bg_rates;
+ bg_band->n_bitrates = RATE_COUNT;
+
+ wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = bg_band;
+ }
+
+ set_wiphy_dev(wdev->wiphy, &priv->pci_dev->dev);
+ if (wiphy_register(wdev->wiphy)) {
+ ipw2100_down(priv);
+ return -EIO;
+ }
+ return 0;
+}
+
static void ipw2100_reset_adapter(struct work_struct *work)
{
struct ipw2100_priv *priv =
@@ -2090,6 +2172,7 @@ static void isr_indicate_rf_kill(struct ipw2100_priv *priv, u32 status)
priv->net_dev->name);
/* RF_KILL is now enabled (else we wouldn't be here) */
+ wiphy_rfkill_set_hw_state(priv->ieee->wdev.wiphy, true);
priv->status |= STATUS_RF_KILL_HW;
/* Make sure the RF Kill check timer is running */
@@ -3044,7 +3127,7 @@ static void ipw2100_tx_send_data(struct ipw2100_priv *priv)
IPW_MAX_BDS)) {
/* TODO: Support merging buffers if more than
* IPW_MAX_BDS are used */
- IPW_DEBUG_INFO("%s: Maximum BD theshold exceeded. "
+ IPW_DEBUG_INFO("%s: Maximum BD threshold exceeded. "
"Increase fragmentation level.\n",
priv->net_dev->name);
}
@@ -6400,6 +6483,9 @@ static void __devexit ipw2100_pci_remove_one(struct pci_dev *pci_dev)
if (dev->base_addr)
iounmap((void __iomem *)dev->base_addr);
+ /* wiphy_unregister needs to be here, before free_ieee80211 */
+ wiphy_unregister(priv->ieee->wdev.wiphy);
+ kfree(priv->ieee->bg_band.channels);
free_ieee80211(dev, 0);
}
@@ -6487,6 +6573,16 @@ static int ipw2100_resume(struct pci_dev *pci_dev)
}
#endif
+static void ipw2100_shutdown(struct pci_dev *pci_dev)
+{
+ struct ipw2100_priv *priv = pci_get_drvdata(pci_dev);
+
+ /* Take down the device; powers it off, etc. */
+ ipw2100_down(priv);
+
+ pci_disable_device(pci_dev);
+}
+
#define IPW2100_DEV_ID(x) { PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, x }
static struct pci_device_id ipw2100_pci_id_table[] __devinitdata = {
@@ -6550,6 +6646,7 @@ static struct pci_driver ipw2100_pci_driver = {
.suspend = ipw2100_suspend,
.resume = ipw2100_resume,
#endif
+ .shutdown = ipw2100_shutdown,
};
/**
@@ -6601,26 +6698,6 @@ static void __exit ipw2100_exit(void)
module_init(ipw2100_init);
module_exit(ipw2100_exit);
-#define WEXT_USECHANNELS 1
-
-static const long ipw2100_frequencies[] = {
- 2412, 2417, 2422, 2427,
- 2432, 2437, 2442, 2447,
- 2452, 2457, 2462, 2467,
- 2472, 2484
-};
-
-#define FREQ_COUNT ARRAY_SIZE(ipw2100_frequencies)
-
-static const long ipw2100_rates_11b[] = {
- 1000000,
- 2000000,
- 5500000,
- 11000000
-};
-
-#define RATE_COUNT ARRAY_SIZE(ipw2100_rates_11b)
-
static int ipw2100_wx_get_name(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
@@ -6820,7 +6897,7 @@ static int ipw2100_wx_get_range(struct net_device *dev,
range->max_qual.updated = 7; /* Updated all three */
range->avg_qual.qual = 70; /* > 8% missed beacons is 'bad' */
- /* TODO: Find real 'good' to 'bad' threshol value for RSSI */
+ /* TODO: Find real 'good' to 'bad' threshold value for RSSI */
range->avg_qual.level = 20 + IPW2100_RSSI_TO_DBM;
range->avg_qual.noise = 0;
range->avg_qual.updated = 7; /* Updated all three */
@@ -8462,6 +8539,12 @@ static int ipw2100_get_firmware(struct ipw2100_priv *priv,
return 0;
}
+MODULE_FIRMWARE(IPW2100_FW_NAME("-i"));
+#ifdef CONFIG_IPW2100_MONITOR
+MODULE_FIRMWARE(IPW2100_FW_NAME("-p"));
+#endif
+MODULE_FIRMWARE(IPW2100_FW_NAME(""));
+
static void ipw2100_release_firmware(struct ipw2100_priv *priv,
struct ipw2100_fw *fw)
{
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c
index 8d58e6e..09ddd3e 100644
--- a/drivers/net/wireless/ipw2x00/ipw2200.c
+++ b/drivers/net/wireless/ipw2x00/ipw2200.c
@@ -30,6 +30,7 @@
******************************************************************************/
+#include <linux/sched.h>
#include "ipw2200.h"
@@ -80,6 +81,11 @@ MODULE_DESCRIPTION(DRV_DESCRIPTION);
MODULE_VERSION(DRV_VERSION);
MODULE_AUTHOR(DRV_COPYRIGHT);
MODULE_LICENSE("GPL");
+MODULE_FIRMWARE("ipw2200-ibss.fw");
+#ifdef CONFIG_IPW2200_MONITOR
+MODULE_FIRMWARE("ipw2200-sniffer.fw");
+#endif
+MODULE_FIRMWARE("ipw2200-bss.fw");
static int cmdlog = 0;
static int debug = 0;
@@ -786,7 +792,7 @@ static int ipw_get_ordinal(struct ipw_priv *priv, u32 ord, void *val, u32 * len)
/* get number of entries */
field_count = *(((u16 *) & field_info) + 1);
- /* abort if not enought memory */
+ /* abort if not enough memory */
total_len = field_len * field_count;
if (total_len > *len) {
*len = total_len;
@@ -1752,10 +1758,13 @@ static DEVICE_ATTR(direct_dword, S_IWUSR | S_IRUGO,
static int rf_kill_active(struct ipw_priv *priv)
{
- if (0 == (ipw_read32(priv, 0x30) & 0x10000))
+ if (0 == (ipw_read32(priv, 0x30) & 0x10000)) {
priv->status |= STATUS_RF_KILL_HW;
- else
+ wiphy_rfkill_set_hw_state(priv->ieee->wdev.wiphy, true);
+ } else {
priv->status &= ~STATUS_RF_KILL_HW;
+ wiphy_rfkill_set_hw_state(priv->ieee->wdev.wiphy, false);
+ }
return (priv->status & STATUS_RF_KILL_HW) ? 1 : 0;
}
@@ -2038,6 +2047,7 @@ static void ipw_irq_tasklet(struct ipw_priv *priv)
if (inta & IPW_INTA_BIT_RF_KILL_DONE) {
IPW_DEBUG_RF_KILL("RF_KILL_DONE\n");
priv->status |= STATUS_RF_KILL_HW;
+ wiphy_rfkill_set_hw_state(priv->ieee->wdev.wiphy, true);
wake_up_interruptible(&priv->wait_command_queue);
priv->status &= ~(STATUS_ASSOCIATED | STATUS_ASSOCIATING);
cancel_delayed_work(&priv->request_scan);
@@ -7750,7 +7760,7 @@ static void ipw_rebuild_decrypted_skb(struct ipw_priv *priv,
case SEC_LEVEL_0:
break;
default:
- printk(KERN_ERR "Unknow security level %d\n",
+ printk(KERN_ERR "Unknown security level %d\n",
priv->ieee->sec.level);
break;
}
@@ -8916,7 +8926,7 @@ static int ipw_wx_get_range(struct net_device *dev,
range->max_qual.updated = 7; /* Updated all three */
range->avg_qual.qual = 70;
- /* TODO: Find real 'good' to 'bad' threshol value for RSSI */
+ /* TODO: Find real 'good' to 'bad' threshold value for RSSI */
range->avg_qual.level = 0; /* FIXME to real average level */
range->avg_qual.noise = 0;
range->avg_qual.updated = 7; /* Updated all three */
@@ -10289,7 +10299,7 @@ static int ipw_tx_skb(struct ipw_priv *priv, struct libipw_txb *txb,
case SEC_LEVEL_0:
break;
default:
- printk(KERN_ERR "Unknow security level %d\n",
+ printk(KERN_ERR "Unknown security level %d\n",
priv->ieee->sec.level);
break;
}
@@ -11275,6 +11285,7 @@ static int ipw_up(struct ipw_priv *priv)
if (!(priv->config & CFG_CUSTOM_MAC))
eeprom_parse_mac(priv, priv->mac_addr);
memcpy(priv->net_dev->dev_addr, priv->mac_addr, ETH_ALEN);
+ memcpy(priv->net_dev->perm_addr, priv->mac_addr, ETH_ALEN);
for (j = 0; j < ARRAY_SIZE(ipw_geos); j++) {
if (!memcmp(&priv->eeprom[EEPROM_COUNTRY_CODE],
@@ -11916,6 +11927,10 @@ static void __devexit ipw_pci_remove(struct pci_dev *pdev)
pci_release_regions(pdev);
pci_disable_device(pdev);
pci_set_drvdata(pdev, NULL);
+ /* wiphy_unregister needs to be here, before free_ieee80211 */
+ wiphy_unregister(priv->ieee->wdev.wiphy);
+ kfree(priv->ieee->a_band.channels);
+ kfree(priv->ieee->bg_band.channels);
free_ieee80211(priv->net_dev, 0);
free_firmware();
}
diff --git a/drivers/net/wireless/ipw2x00/libipw_module.c b/drivers/net/wireless/ipw2x00/libipw_module.c
index a0e9f6a..1ae0b2b 100644
--- a/drivers/net/wireless/ipw2x00/libipw_module.c
+++ b/drivers/net/wireless/ipw2x00/libipw_module.c
@@ -199,7 +199,7 @@ struct net_device *alloc_ieee80211(int sizeof_priv, int monitor)
ieee->host_decrypt = 1;
ieee->host_mc_decrypt = 1;
- /* Host fragementation in Open mode. Default is enabled.
+ /* Host fragmentation in Open mode. Default is enabled.
* Note: host fragmentation is always enabled if host encryption
* is enabled. For cards can do hardware encryption, they must do
* hardware fragmentation as well. So we don't need a variable
@@ -235,12 +235,8 @@ void free_ieee80211(struct net_device *dev, int monitor)
libipw_networks_free(ieee);
/* free cfg80211 resources */
- if (!monitor) {
- wiphy_unregister(ieee->wdev.wiphy);
- kfree(ieee->a_band.channels);
- kfree(ieee->bg_band.channels);
+ if (!monitor)
wiphy_free(ieee->wdev.wiphy);
- }
free_netdev(dev);
}
@@ -252,17 +248,22 @@ u32 libipw_debug_level = 0;
EXPORT_SYMBOL_GPL(libipw_debug_level);
static struct proc_dir_entry *libipw_proc = NULL;
-static int show_debug_level(char *page, char **start, off_t offset,
- int count, int *eof, void *data)
+static int debug_level_proc_show(struct seq_file *m, void *v)
+{
+ seq_printf(m, "0x%08X\n", libipw_debug_level);
+ return 0;
+}
+
+static int debug_level_proc_open(struct inode *inode, struct file *file)
{
- return snprintf(page, count, "0x%08X\n", libipw_debug_level);
+ return single_open(file, debug_level_proc_show, NULL);
}
-static int store_debug_level(struct file *file, const char __user * buffer,
- unsigned long count, void *data)
+static ssize_t debug_level_proc_write(struct file *file,
+ const char __user *buffer, size_t count, loff_t *pos)
{
char buf[] = "0x00000000\n";
- unsigned long len = min((unsigned long)sizeof(buf) - 1, count);
+ size_t len = min(sizeof(buf) - 1, count);
unsigned long val;
if (copy_from_user(buf, buffer, len))
@@ -276,6 +277,15 @@ static int store_debug_level(struct file *file, const char __user * buffer,
return strnlen(buf, len);
}
+
+static const struct file_operations debug_level_proc_fops = {
+ .owner = THIS_MODULE,
+ .open = debug_level_proc_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+ .write = debug_level_proc_write,
+};
#endif /* CONFIG_LIBIPW_DEBUG */
static int __init libipw_init(void)
@@ -290,16 +300,13 @@ static int __init libipw_init(void)
" proc directory\n");
return -EIO;
}
- e = create_proc_entry("debug_level", S_IFREG | S_IRUGO | S_IWUSR,
- libipw_proc);
+ e = proc_create("debug_level", S_IRUGO | S_IWUSR, libipw_proc,
+ &debug_level_proc_fops);
if (!e) {
remove_proc_entry(DRV_NAME, init_net.proc_net);
libipw_proc = NULL;
return -EIO;
}
- e->read_proc = show_debug_level;
- e->write_proc = store_debug_level;
- e->data = NULL;
#endif /* CONFIG_LIBIPW_DEBUG */
printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");