******************************************************************************/
#include "ipw2200.h"
+#include <linux/version.h>
-#define IPW2200_VERSION "1.0.5"
+#define IPW2200_VERSION "git-1.0.8"
#define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2200/2915 Network Driver"
#define DRV_COPYRIGHT "Copyright(c) 2003-2005 Intel Corporation"
#define DRV_VERSION IPW2200_VERSION
*qos_param);
#endif /* CONFIG_IPW_QOS */
+static struct iw_statistics *ipw_get_wireless_stats(struct net_device *dev);
static void ipw_remove_current_network(struct ipw_priv *priv);
static void ipw_rx(struct ipw_priv *priv);
static int ipw_queue_tx_reclaim(struct ipw_priv *priv,
for (i = 0; i < error->log_len; i++)
IPW_ERROR("%i\t0x%08x\t%i\n",
error->log[i].time,
- error->log[i].event, error->log[i].data);
+ error->log[i].data, error->log[i].event);
}
#endif
return -EAGAIN;
}
- if (priv->status & STATUS_ASSOCIATING) {
- IPW_DEBUG_HC("abandon a command while associating\n");
- spin_unlock_irqrestore(&priv->lock, flags);
- return -1;
- }
-
- if (priv->status & STATUS_DISASSOCIATING) {
- IPW_DEBUG_HC("abandon a command while disassociating\n");
- spin_unlock_irqrestore(&priv->lock, flags);
- return -1;
- }
-
priv->status |= STATUS_HCMD_ACTIVE;
if (priv->cmdlog) {
};
#define IPW_FW_MAJOR_VERSION 2
-#define IPW_FW_MINOR_VERSION 3
+#define IPW_FW_MINOR_VERSION 4
#define IPW_FW_MINOR(x) ((x & 0xff) >> 8)
#define IPW_FW_MAJOR(x) (x & 0xff)
MAC_ARG(priv->assoc_request.bssid),
priv->assoc_request.channel);
+ priv->status &= ~(STATUS_ASSOCIATING | STATUS_ASSOCIATED);
+ priv->status |= STATUS_DISASSOCIATING;
+
if (quiet)
priv->assoc_request.assoc_type = HC_DISASSOC_QUIET;
else
priv->assoc_request.assoc_type = HC_DISASSOCIATE;
+
err = ipw_send_associate(priv, &priv->assoc_request);
if (err) {
IPW_DEBUG_HC("Attempt to send [dis]associate command "
return;
}
- priv->status &= ~(STATUS_ASSOCIATING | STATUS_ASSOCIATED);
- priv->status |= STATUS_DISASSOCIATING;
-
}
static int ipw_disassociate(void *data)
up(&priv->sem);
}
+/* Missed beacon behavior:
+ * 1st missed -> roaming_threshold, just wait, don't do any scan/roam.
+ * roaming_threshold -> disassociate_threshold, scan and roam for better signal.
+ * Above disassociate threshold, give up and stop scanning.
+ * Roaming is disabled if disassociate_threshold <= roaming_threshold */
static inline void ipw_handle_missed_beacon(struct ipw_priv *priv,
int missed_count)
{
return;
}
- if (missed_count > priv->roaming_threshold) {
+ if (missed_count > priv->roaming_threshold &&
+ missed_count <= priv->disassociate_threshold) {
/* If we are not already roaming, set the ROAM
- * bit in the status and kick off a scan */
+ * bit in the status and kick off a scan.
+ * This can happen several times before we reach
+ * disassociate_threshold. */
IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE,
"Missed beacon: %d - initiate "
"roaming\n", missed_count);
STATUS_DISASSOCIATING)))
queue_work(priv->workqueue, &priv->associate);
else if (priv->status & STATUS_ROAMING) {
- /* If a scan completed and we are in roam mode, then
- * the scan that completed was the one requested as a
- * result of entering roam... so, schedule the
- * roam work */
- queue_work(priv->workqueue, &priv->roam);
+ if (x->status == SCAN_COMPLETED_STATUS_COMPLETE)
+ /* If a scan completed and we are in roam mode, then
+ * the scan that completed was the one requested as a
+ * result of entering roam... so, schedule the
+ * roam work */
+ queue_work(priv->workqueue,
+ &priv->roam);
+ else
+ /* Don't schedule if we aborted the scan */
+ priv->status &= ~STATUS_ROAMING;
} else if (priv->status & STATUS_SCAN_PENDING)
queue_work(priv->workqueue,
&priv->request_scan);
up(&priv->sem);
}
-#if WIRELESS_EXT < 18
-/* Support for wpa_supplicant before WE-18, deprecated. */
-
-/* following definitions must match definitions in driver_ipw.c */
-
-#define IPW_IOCTL_WPA_SUPPLICANT SIOCIWFIRSTPRIV+30
-
-#define IPW_CMD_SET_WPA_PARAM 1
-#define IPW_CMD_SET_WPA_IE 2
-#define IPW_CMD_SET_ENCRYPTION 3
-#define IPW_CMD_MLME 4
-
-#define IPW_PARAM_WPA_ENABLED 1
-#define IPW_PARAM_TKIP_COUNTERMEASURES 2
-#define IPW_PARAM_DROP_UNENCRYPTED 3
-#define IPW_PARAM_PRIVACY_INVOKED 4
-#define IPW_PARAM_AUTH_ALGS 5
-#define IPW_PARAM_IEEE_802_1X 6
-
-#define IPW_MLME_STA_DEAUTH 1
-#define IPW_MLME_STA_DISASSOC 2
-
-#define IPW_CRYPT_ERR_UNKNOWN_ALG 2
-#define IPW_CRYPT_ERR_UNKNOWN_ADDR 3
-#define IPW_CRYPT_ERR_CRYPT_INIT_FAILED 4
-#define IPW_CRYPT_ERR_KEY_SET_FAILED 5
-#define IPW_CRYPT_ERR_TX_KEY_SET_FAILED 6
-#define IPW_CRYPT_ERR_CARD_CONF_FAILED 7
-
-#define IPW_CRYPT_ALG_NAME_LEN 16
-
-struct ipw_param {
- u32 cmd;
- u8 sta_addr[ETH_ALEN];
- union {
- struct {
- u8 name;
- u32 value;
- } wpa_param;
- struct {
- u32 len;
- u8 reserved[32];
- u8 data[0];
- } wpa_ie;
- struct {
- u32 command;
- u32 reason_code;
- } mlme;
- struct {
- u8 alg[IPW_CRYPT_ALG_NAME_LEN];
- u8 set_tx;
- u32 err;
- u8 idx;
- u8 seq[8]; /* sequence counter (set: RX, get: TX) */
- u16 key_len;
- u8 key[0];
- } crypt;
-
- } u;
-};
-
-/* end of driver_ipw.c code */
-#endif
-
static int ipw_wpa_enable(struct ipw_priv *priv, int value)
{
/* This is called when wpa_supplicant loads and closes the driver
return 0;
}
-#if WIRELESS_EXT < 18
-#define IW_AUTH_ALG_OPEN_SYSTEM 0x1
-#define IW_AUTH_ALG_SHARED_KEY 0x2
-#endif
-
static int ipw_wpa_set_auth_algs(struct ipw_priv *priv, int value)
{
struct ieee80211_device *ieee = priv->ieee;
return ipw_send_cmd(priv, &cmd);
}
-#if WIRELESS_EXT < 18
-static int ipw_wpa_set_param(struct net_device *dev, u8 name, u32 value)
-{
- struct ipw_priv *priv = ieee80211_priv(dev);
- struct ieee80211_crypt_data *crypt;
- unsigned long flags;
- int ret = 0;
-
- switch (name) {
- case IPW_PARAM_WPA_ENABLED:
- ret = ipw_wpa_enable(priv, value);
- break;
-
- case IPW_PARAM_TKIP_COUNTERMEASURES:
- crypt = priv->ieee->crypt[priv->ieee->tx_keyidx];
- if (!crypt || !crypt->ops->set_flags || !crypt->ops->get_flags) {
- IPW_WARNING("Can't set TKIP countermeasures: "
- "crypt not set!\n");
- break;
- }
-
- flags = crypt->ops->get_flags(crypt->priv);
-
- if (value)
- flags |= IEEE80211_CRYPTO_TKIP_COUNTERMEASURES;
- else
- flags &= ~IEEE80211_CRYPTO_TKIP_COUNTERMEASURES;
-
- crypt->ops->set_flags(flags, crypt->priv);
-
- break;
-
- case IPW_PARAM_DROP_UNENCRYPTED:{
- /* HACK:
- *
- * wpa_supplicant calls set_wpa_enabled when the driver
- * is loaded and unloaded, regardless of if WPA is being
- * used. No other calls are made which can be used to
- * determine if encryption will be used or not prior to
- * association being expected. If encryption is not being
- * used, drop_unencrypted is set to false, else true -- we
- * can use this to determine if the CAP_PRIVACY_ON bit should
- * be set.
- */
- struct ieee80211_security sec = {
- .flags = SEC_ENABLED,
- .enabled = value,
- };
- priv->ieee->drop_unencrypted = value;
- /* We only change SEC_LEVEL for open mode. Others
- * are set by ipw_wpa_set_encryption.
- */
- if (!value) {
- sec.flags |= SEC_LEVEL;
- sec.level = SEC_LEVEL_0;
- } else {
- sec.flags |= SEC_LEVEL;
- sec.level = SEC_LEVEL_1;
- }
- if (priv->ieee->set_security)
- priv->ieee->set_security(priv->ieee->dev, &sec);
- break;
- }
-
- case IPW_PARAM_PRIVACY_INVOKED:
- priv->ieee->privacy_invoked = value;
- break;
-
- case IPW_PARAM_AUTH_ALGS:
- ret = ipw_wpa_set_auth_algs(priv, value);
- break;
-
- case IPW_PARAM_IEEE_802_1X:
- priv->ieee->ieee802_1x = value;
- break;
-
- default:
- IPW_ERROR("%s: Unknown WPA param: %d\n", dev->name, name);
- ret = -EOPNOTSUPP;
- }
-
- return ret;
-}
-
-static int ipw_wpa_mlme(struct net_device *dev, int command, int reason)
-{
- struct ipw_priv *priv = ieee80211_priv(dev);
- int ret = 0;
-
- switch (command) {
- case IPW_MLME_STA_DEAUTH:
- // silently ignore
- break;
-
- case IPW_MLME_STA_DISASSOC:
- ipw_disassociate(priv);
- break;
-
- default:
- IPW_ERROR("%s: Unknown MLME request: %d\n", dev->name, command);
- ret = -EOPNOTSUPP;
- }
-
- return ret;
-}
-
-static int ipw_wpa_ie_cipher2level(u8 cipher)
-{
- switch (cipher) {
- case 4: /* CCMP */
- return SEC_LEVEL_3;
- case 2: /* TKIP */
- return SEC_LEVEL_2;
- case 5: /* WEP104 */
- case 1: /* WEP40 */
- return SEC_LEVEL_1;
- case 0: /* NONE */
- return SEC_LEVEL_0;
- default:
- return -1;
- }
-}
-
-static int ipw_wpa_set_wpa_ie(struct net_device *dev,
- struct ipw_param *param, int plen)
-{
- struct ipw_priv *priv = ieee80211_priv(dev);
- struct ieee80211_device *ieee = priv->ieee;
- u8 *buf;
- u8 *ptk, *gtk;
- int level;
-
- if (param->u.wpa_ie.len > MAX_WPA_IE_LEN ||
- (param->u.wpa_ie.len && param->u.wpa_ie.data == NULL))
- return -EINVAL;
-
- if (param->u.wpa_ie.len) {
- buf = kmalloc(param->u.wpa_ie.len, GFP_KERNEL);
- if (buf == NULL)
- return -ENOMEM;
-
- memcpy(buf, param->u.wpa_ie.data, param->u.wpa_ie.len);
- kfree(ieee->wpa_ie);
- ieee->wpa_ie = buf;
- ieee->wpa_ie_len = param->u.wpa_ie.len;
- } else {
- kfree(ieee->wpa_ie);
- ieee->wpa_ie = NULL;
- ieee->wpa_ie_len = 0;
- goto done;
- }
-
- if (priv->ieee->host_encrypt)
- goto done;
-
- /* HACK: Parse wpa_ie here to get pairwise suite, otherwise
- * we need to change driver_ipw.c from wpa_supplicant. This
- * is OK since -Dipw is deprecated. The -Dwext driver has a
- * clean way to handle this. */
- gtk = ptk = (u8 *) ieee->wpa_ie;
- if (ieee->wpa_ie[0] == 0x30) { /* RSN IE */
- gtk += 4 + 3;
- ptk += 4 + 4 + 2 + 3;
- } else { /* WPA IE */
- gtk += 8 + 3;
- ptk += 8 + 4 + 2 + 3;
- }
-
- if (ptk - (u8 *) ieee->wpa_ie > ieee->wpa_ie_len)
- return -EINVAL;
-
- level = ipw_wpa_ie_cipher2level(*gtk);
- ipw_set_hw_decrypt_multicast(priv, level);
-
- level = ipw_wpa_ie_cipher2level(*ptk);
- ipw_set_hw_decrypt_unicast(priv, level);
-
- done:
- ipw_wpa_assoc_frame(priv, ieee->wpa_ie, ieee->wpa_ie_len);
- return 0;
-}
-
-/* implementation borrowed from hostap driver */
-
-static int ipw_wpa_set_encryption(struct net_device *dev,
- struct ipw_param *param, int param_len)
-{
- int ret = 0;
- int group_key = 0;
- struct ipw_priv *priv = ieee80211_priv(dev);
- struct ieee80211_device *ieee = priv->ieee;
- struct ieee80211_crypto_ops *ops;
- struct ieee80211_crypt_data **crypt;
-
- struct ieee80211_security sec = {
- .flags = 0,
- };
-
- param->u.crypt.err = 0;
- param->u.crypt.alg[IPW_CRYPT_ALG_NAME_LEN - 1] = '\0';
-
- if (param_len !=
- (int)((char *)param->u.crypt.key - (char *)param) +
- param->u.crypt.key_len) {
- IPW_DEBUG_INFO("Len mismatch %d, %d\n", param_len,
- param->u.crypt.key_len);
- return -EINVAL;
- }
- if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
- param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
- param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
- if (param->u.crypt.idx >= WEP_KEYS)
- return -EINVAL;
- crypt = &ieee->crypt[param->u.crypt.idx];
- } else {
- return -EINVAL;
- }
-
- if (param->u.crypt.idx != 0)
- group_key = 1;
-
- sec.flags |= SEC_ENABLED | SEC_ENCRYPT;
- if (strcmp(param->u.crypt.alg, "none") == 0) {
- if (crypt) {
- sec.enabled = 0;
- sec.encrypt = 0;
- sec.level = SEC_LEVEL_0;
- sec.flags |= SEC_LEVEL;
- ieee80211_crypt_delayed_deinit(ieee, crypt);
- }
- goto done;
- }
- sec.enabled = 1;
- sec.encrypt = 1;
-
- /* IPW HW cannot build TKIP MIC, host decryption still needed. */
- if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
- if (group_key)
- ieee->host_mc_decrypt = 1;
- else
- ieee->host_encrypt_msdu = 1;
- }
-
- /*if (!(ieee->host_encrypt || ieee->host_encrypt_msdu ||
- ieee->host_decrypt))
- goto skip_host_crypt; */
- if (group_key ? !ieee->host_mc_decrypt :
- !(ieee->host_encrypt || ieee->host_decrypt ||
- ieee->host_encrypt_msdu))
- goto skip_host_crypt;
-
- ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
- if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0) {
- request_module("ieee80211_crypt_wep");
- ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
- } else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0) {
- request_module("ieee80211_crypt_tkip");
- ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
- } else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0) {
- request_module("ieee80211_crypt_ccmp");
- ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
- }
- if (ops == NULL) {
- IPW_DEBUG_INFO("%s: unknown crypto alg '%s'\n",
- dev->name, param->u.crypt.alg);
- param->u.crypt.err = IPW_CRYPT_ERR_UNKNOWN_ALG;
- ret = -EINVAL;
- goto done;
- }
-
- if (*crypt == NULL || (*crypt)->ops != ops) {
- struct ieee80211_crypt_data *new_crypt;
-
- ieee80211_crypt_delayed_deinit(ieee, crypt);
-
- new_crypt = (struct ieee80211_crypt_data *)
- kmalloc(sizeof(*new_crypt), GFP_KERNEL);
- if (new_crypt == NULL) {
- ret = -ENOMEM;
- goto done;
- }
- memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
- new_crypt->ops = ops;
- if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
- new_crypt->priv =
- new_crypt->ops->init(param->u.crypt.idx);
-
- if (new_crypt->priv == NULL) {
- kfree(new_crypt);
- param->u.crypt.err = IPW_CRYPT_ERR_CRYPT_INIT_FAILED;
- ret = -EINVAL;
- goto done;
- }
-
- *crypt = new_crypt;
- }
-
- if (param->u.crypt.key_len > 0 && (*crypt)->ops->set_key &&
- (*crypt)->ops->set_key(param->u.crypt.key,
- param->u.crypt.key_len, param->u.crypt.seq,
- (*crypt)->priv) < 0) {
- IPW_DEBUG_INFO("%s: key setting failed\n", dev->name);
- param->u.crypt.err = IPW_CRYPT_ERR_KEY_SET_FAILED;
- ret = -EINVAL;
- goto done;
- }
-
- skip_host_crypt:
- if (param->u.crypt.set_tx) {
- ieee->tx_keyidx = param->u.crypt.idx;
- sec.active_key = param->u.crypt.idx;
- sec.flags |= SEC_ACTIVE_KEY;
- } else
- sec.flags &= ~SEC_ACTIVE_KEY;
-
- if (param->u.crypt.alg != NULL) {
- memcpy(sec.keys[param->u.crypt.idx],
- param->u.crypt.key, param->u.crypt.key_len);
- sec.key_sizes[param->u.crypt.idx] = param->u.crypt.key_len;
- sec.flags |= (1 << param->u.crypt.idx);
-
- if (strcmp(param->u.crypt.alg, "WEP") == 0) {
- sec.flags |= SEC_LEVEL;
- sec.level = SEC_LEVEL_1;
- } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
- sec.flags |= SEC_LEVEL;
- sec.level = SEC_LEVEL_2;
- } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
- sec.flags |= SEC_LEVEL;
- sec.level = SEC_LEVEL_3;
- }
- /* Don't set sec level for group keys. */
- if (group_key)
- sec.flags &= ~SEC_LEVEL;
- }
- done:
- if (ieee->set_security)
- ieee->set_security(ieee->dev, &sec);
-
- /* Do not reset port if card is in Managed mode since resetting will
- * generate new IEEE 802.11 authentication which may end up in looping
- * with IEEE 802.1X. If your hardware requires a reset after WEP
- * configuration (for example... Prism2), implement the reset_port in
- * the callbacks structures used to initialize the 802.11 stack. */
- if (ieee->reset_on_keychange &&
- ieee->iw_mode != IW_MODE_INFRA &&
- ieee->reset_port && ieee->reset_port(dev)) {
- IPW_DEBUG_INFO("%s: reset_port failed\n", dev->name);
- param->u.crypt.err = IPW_CRYPT_ERR_CARD_CONF_FAILED;
- return -EINVAL;
- }
-
- return ret;
-}
-
-static int ipw_wpa_supplicant(struct net_device *dev, struct iw_point *p)
-{
- struct ipw_param *param;
- struct ipw_priv *priv = ieee80211_priv(dev);
- int ret = 0;
-
- IPW_DEBUG_INFO("wpa_supplicant: len=%d\n", p->length);
-
- if (p->length < sizeof(struct ipw_param) || !p->pointer)
- return -EINVAL;
-
- param = (struct ipw_param *)kmalloc(p->length, GFP_KERNEL);
- if (param == NULL)
- return -ENOMEM;
-
- if (copy_from_user(param, p->pointer, p->length)) {
- kfree(param);
- return -EFAULT;
- }
-
- down(&priv->sem);
- switch (param->cmd) {
-
- case IPW_CMD_SET_WPA_PARAM:
- ret = ipw_wpa_set_param(dev, param->u.wpa_param.name,
- param->u.wpa_param.value);
- break;
-
- case IPW_CMD_SET_WPA_IE:
- ret = ipw_wpa_set_wpa_ie(dev, param, p->length);
- break;
-
- case IPW_CMD_SET_ENCRYPTION:
- ret = ipw_wpa_set_encryption(dev, param, p->length);
- break;
-
- case IPW_CMD_MLME:
- ret = ipw_wpa_mlme(dev, param->u.mlme.command,
- param->u.mlme.reason_code);
- break;
-
- default:
- IPW_ERROR("%s: Unknown WPA supplicant request: %d\n",
- dev->name, param->cmd);
- ret = -EOPNOTSUPP;
- }
-
- up(&priv->sem);
- if (ret == 0 && copy_to_user(p->pointer, param, p->length))
- ret = -EFAULT;
-
- kfree(param);
- return ret;
-}
-#else
/*
* WE-18 support
*/
case IW_AUTH_TKIP_COUNTERMEASURES:
crypt = priv->ieee->crypt[priv->ieee->tx_keyidx];
- if (!crypt || !crypt->ops->set_flags || !crypt->ops->get_flags) {
- IPW_WARNING("Can't set TKIP countermeasures: "
- "crypt not set!\n");
+ if (!crypt || !crypt->ops->set_flags || !crypt->ops->get_flags)
break;
- }
flags = crypt->ops->get_flags(crypt->priv);
case IW_AUTH_TKIP_COUNTERMEASURES:
crypt = priv->ieee->crypt[priv->ieee->tx_keyidx];
- if (!crypt || !crypt->ops->get_flags) {
- IPW_WARNING("Can't get TKIP countermeasures: "
- "crypt not set!\n");
+ if (!crypt || !crypt->ops->get_flags)
break;
- }
param->value = (crypt->ops->get_flags(crypt->priv) &
IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) ? 1 : 0;
}
return 0;
}
-#endif
#ifdef CONFIG_IPW_QOS
*/
priv->channel = network->channel;
memcpy(priv->bssid, network->bssid, ETH_ALEN);
+ priv->status |= STATUS_ASSOCIATING;
+ priv->status &= ~STATUS_SECURITY_UPDATED;
priv->assoc_network = network;
return err;
}
- priv->status |= STATUS_ASSOCIATING;
- priv->status &= ~STATUS_SECURITY_UPDATED;
-
IPW_DEBUG(IPW_DL_STATE, "associating: '%s' " MAC_FMT " \n",
escape_essid(priv->essid, priv->essid_len),
MAC_ARG(priv->bssid));
return 0;
}
+ if (priv->status & STATUS_DISASSOCIATING) {
+ IPW_DEBUG_ASSOC("Not attempting association (in "
+ "disassociating)\n ");
+ queue_work(priv->workqueue, &priv->associate);
+ return 0;
+ }
+
if (!ipw_is_init(priv) || (priv->status & STATUS_SCANNING)) {
IPW_DEBUG_ASSOC("Not attempting association (scanning or not "
"initialized)\n");
/* HW decrypt will not clear the WEP bit, MIC, PN, etc. */
hdr = (struct ieee80211_hdr_4addr *)rxb->skb->data;
if (priv->ieee->iw_mode != IW_MODE_MONITOR &&
- (is_multicast_ether_addr(hdr->addr1) ?
+ ((is_multicast_ether_addr(hdr->addr1) ||
+ is_broadcast_ether_addr(hdr->addr1)) ?
!priv->ieee->host_mc_decrypt : !priv->ieee->host_decrypt))
ipw_rebuild_decrypted_skb(priv, rxb->skb);
range->num_frequency = i;
up(&priv->sem);
+
+ /* Event capability (kernel + driver) */
+ range->event_capa[0] = (IW_EVENT_CAPA_K_0 |
+ IW_EVENT_CAPA_MASK(SIOCGIWTHRSPY) |
+ IW_EVENT_CAPA_MASK(SIOCGIWAP));
+ range->event_capa[1] = IW_EVENT_CAPA_K_1;
+
IPW_DEBUG_WX("GET Range\n");
return 0;
}
return 0;
}
-#if WIRELESS_EXT > 17
static int ipw_request_direct_scan(struct ipw_priv *priv, char *essid,
int essid_len)
{
up(&priv->sem);
return err;
}
-#endif /* WIRELESS_EXT > 17 */
static int ipw_wx_set_scan(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
struct ipw_priv *priv = ieee80211_priv(dev);
-#if WIRELESS_EXT > 17
struct iw_scan_req *req = NULL;
if (wrqu->data.length
&& wrqu->data.length == sizeof(struct iw_scan_req)) {
return 0;
}
}
-#endif
+
IPW_DEBUG_WX("Start scan\n");
queue_work(priv->workqueue, &priv->request_scan);
IW_IOCTL(SIOCGIWSPY) = iw_handler_get_spy,
IW_IOCTL(SIOCSIWTHRSPY) = iw_handler_set_thrspy,
IW_IOCTL(SIOCGIWTHRSPY) = iw_handler_get_thrspy,
-#if WIRELESS_EXT > 17
IW_IOCTL(SIOCSIWGENIE) = ipw_wx_set_genie,
IW_IOCTL(SIOCGIWGENIE) = ipw_wx_get_genie,
IW_IOCTL(SIOCSIWMLME) = ipw_wx_set_mlme,
IW_IOCTL(SIOCGIWAUTH) = ipw_wx_get_auth,
IW_IOCTL(SIOCSIWENCODEEXT) = ipw_wx_set_encodeext,
IW_IOCTL(SIOCGIWENCODEEXT) = ipw_wx_get_encodeext,
-#endif
};
enum {
.num_private_args = ARRAY_SIZE(ipw_priv_args),
.private = ipw_priv_handler,
.private_args = ipw_priv_args,
+ .get_wireless_stats = ipw_get_wireless_stats,
};
-static struct iw_public_data ipw_wx_data;
-
/*
* Get wireless statistics.
* Called by /proc/net/wireless
switch (priv->ieee->iw_mode) {
case IW_MODE_ADHOC:
hdr_len = IEEE80211_3ADDR_LEN;
- unicast = !is_multicast_ether_addr(hdr->addr1);
+ unicast = !(is_multicast_ether_addr(hdr->addr1) ||
+ is_broadcast_ether_addr(hdr->addr1));
id = ipw_find_station(priv, hdr->addr1);
if (id == IPW_INVALID_STATION) {
id = ipw_add_station(priv, hdr->addr1);
case IW_MODE_INFRA:
default:
- unicast = !is_multicast_ether_addr(hdr->addr3);
+ unicast = !(is_multicast_ether_addr(hdr->addr3) ||
+ is_broadcast_ether_addr(hdr->addr3));
hdr_len = IEEE80211_3ADDR_LEN;
id = 0;
break;
{5210, 42}, {5230, 46}},
},
+ { /* Rest of World */
+ "ZZR",
+ .bg_channels = 14,
+ .bg = {{2412, 1}, {2417, 2}, {2422, 3},
+ {2427, 4}, {2432, 5}, {2437, 6},
+ {2442, 7}, {2447, 8}, {2452, 9},
+ {2457, 10}, {2462, 11}, {2467, 12},
+ {2472, 13}, {2484, 14, IEEE80211_CH_B_ONLY |
+ IEEE80211_CH_PASSIVE_ONLY}},
+ },
+
{ /* High Band */
"ZZH",
.bg_channels = 13,
ipw_geos[j].name, 3))
break;
}
- if (j == ARRAY_SIZE(ipw_geos))
+ if (j == ARRAY_SIZE(ipw_geos)) {
+ IPW_WARNING("SKU [%c%c%c] not recognized.\n",
+ priv->eeprom[EEPROM_COUNTRY_CODE + 0],
+ priv->eeprom[EEPROM_COUNTRY_CODE + 1],
+ priv->eeprom[EEPROM_COUNTRY_CODE + 2]);
j = 0;
+ }
if (ipw_set_geo(priv->ieee, &ipw_geos[j])) {
IPW_WARNING("Could not set geography.");
return 0;
up(&priv->sem);
}
-#if WIRELESS_EXT < 18
-static int ipw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
- struct iwreq *wrq = (struct iwreq *)rq;
- int ret = -1;
- switch (cmd) {
- case IPW_IOCTL_WPA_SUPPLICANT:
- ret = ipw_wpa_supplicant(dev, &wrq->u.data);
- return ret;
-
- default:
- return -EOPNOTSUPP;
- }
-
- return -EOPNOTSUPP;
-}
-#endif
-
/* Called by register_netdev() */
static int ipw_net_init(struct net_device *dev)
{
SET_MODULE_OWNER(net_dev);
SET_NETDEV_DEV(net_dev, &pdev->dev);
- ipw_wx_data.spy_data = &priv->ieee->spy_data;
- ipw_wx_data.ieee80211 = priv->ieee;
-
down(&priv->sem);
priv->ieee->hard_start_xmit = ipw_net_hard_start_xmit;
net_dev->open = ipw_net_open;
net_dev->stop = ipw_net_stop;
net_dev->init = ipw_net_init;
-#if WIRELESS_EXT < 18
- net_dev->do_ioctl = ipw_ioctl;
-#endif
net_dev->get_stats = ipw_net_get_stats;
net_dev->set_multicast_list = ipw_net_set_multicast_list;
net_dev->set_mac_address = ipw_net_set_mac_address;
- net_dev->get_wireless_stats = ipw_get_wireless_stats;
- net_dev->wireless_data = &ipw_wx_data;
+ priv->wireless_data.spy_data = &priv->ieee->spy_data;
+ priv->wireless_data.ieee80211 = priv->ieee;
+ net_dev->wireless_data = &priv->wireless_data;
net_dev->wireless_handlers = &ipw_wx_handler_def;
net_dev->ethtool_ops = &ipw_ethtool_ops;
net_dev->irq = pdev->irq;