From e36d56b64808aec54b68b4e9976180c1da0933b2 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 9 Jun 2009 21:04:43 +0200 Subject: cfg80211: pass netdev to change_virtual_intf If there was a reason I'm passing the ifidx I cannot remember it any more and don't see one now, so let's just pass the pointer itself. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/cfg80211.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'drivers/net/wireless/iwmc3200wifi') diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.c b/drivers/net/wireless/iwmc3200wifi/cfg80211.c index 96f714e6e12b..bc89b1ef0cad 100644 --- a/drivers/net/wireless/iwmc3200wifi/cfg80211.c +++ b/drivers/net/wireless/iwmc3200wifi/cfg80211.c @@ -167,20 +167,15 @@ int iwm_cfg80211_inform_bss(struct iwm_priv *iwm) return 0; } -static int iwm_cfg80211_change_iface(struct wiphy *wiphy, int ifindex, +static int iwm_cfg80211_change_iface(struct wiphy *wiphy, + struct net_device *ndev, enum nl80211_iftype type, u32 *flags, struct vif_params *params) { - struct net_device *ndev; struct wireless_dev *wdev; struct iwm_priv *iwm; u32 old_mode; - /* we're under RTNL */ - ndev = __dev_get_by_index(&init_net, ifindex); - if (!ndev) - return -ENODEV; - wdev = ndev->ieee80211_ptr; iwm = ndev_to_iwm(ndev); old_mode = iwm->conf.mode; -- cgit v1.2.3 From 0c5553b1392dea5ba5ad678790367c1275ed1172 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Mon, 15 Jun 2009 21:59:50 +0200 Subject: iwmc3200wifi: invalidate keys when changing the BSSID While associated, we have to invalidate our key cache if we clear our BSSID through siwap. Signed-off-by: Samuel Ortiz Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/wext.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless/iwmc3200wifi') diff --git a/drivers/net/wireless/iwmc3200wifi/wext.c b/drivers/net/wireless/iwmc3200wifi/wext.c index 584c94d0f399..889194931b4e 100644 --- a/drivers/net/wireless/iwmc3200wifi/wext.c +++ b/drivers/net/wireless/iwmc3200wifi/wext.c @@ -82,6 +82,7 @@ static int iwm_wext_siwap(struct net_device *dev, struct iw_request_info *info, struct sockaddr *ap_addr, char *extra) { struct iwm_priv *iwm = ndev_to_iwm(dev); + int ret; if (iwm->conf.mode == UMAC_MODE_IBSS) return cfg80211_ibss_wext_siwap(dev, info, ap_addr, extra); @@ -104,10 +105,26 @@ static int iwm_wext_siwap(struct net_device *dev, struct iw_request_info *info, } if (iwm->umac_profile_active) { + int i; + if (!memcmp(&iwm->umac_profile->bssid[0], iwm->bssid, ETH_ALEN)) return 0; - iwm_invalidate_mlme_profile(iwm); + /* + * If we're clearing the BSSID, and we're associated, + * we have to clear the keys as they're no longer valid. + */ + if (is_zero_ether_addr(ap_addr->sa_data)) { + for (i = 0; i < IWM_NUM_KEYS; i++) + iwm->keys[i].in_use = 0; + + } + + ret = iwm_invalidate_mlme_profile(iwm); + if (ret < 0) { + IWM_ERR(iwm, "Couldn't invalidate profile\n"); + return ret; + } } if (iwm->umac_profile->ssid.ssid_len) -- cgit v1.2.3 From a70742f167424bab794ca74b9e99b598b358bb7d Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Mon, 15 Jun 2009 21:59:51 +0200 Subject: iwmc3200wifi: handling wifi_if_ntfy responses When we're calling iwm_send_wifi_if_cmd() with the resp flag set, we're currently waiting on the mlme queue, waiting for some flags here and there to show up. This patch adds a wifi_ntfy bitmap, and when we're sending a wifi_if command expecting an answers, we wait synchronously for it to show up, on a dedicated queue. The wifi_ntfy bit is set when we receive the corresponding answer. Signed-off-by: Samuel Ortiz Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/commands.c | 31 ++++++++++++++++------------ drivers/net/wireless/iwmc3200wifi/iwm.h | 3 +++ drivers/net/wireless/iwmc3200wifi/main.c | 1 + drivers/net/wireless/iwmc3200wifi/rx.c | 9 ++++++-- drivers/net/wireless/iwmc3200wifi/umac.h | 2 ++ 5 files changed, 31 insertions(+), 15 deletions(-) (limited to 'drivers/net/wireless/iwmc3200wifi') diff --git a/drivers/net/wireless/iwmc3200wifi/commands.c b/drivers/net/wireless/iwmc3200wifi/commands.c index 834a7f544e5d..337a884f52df 100644 --- a/drivers/net/wireless/iwmc3200wifi/commands.c +++ b/drivers/net/wireless/iwmc3200wifi/commands.c @@ -70,14 +70,28 @@ static int iwm_send_lmac_ptrough_cmd(struct iwm_priv *iwm, int iwm_send_wifi_if_cmd(struct iwm_priv *iwm, void *payload, u16 payload_size, bool resp) { + struct iwm_umac_wifi_if *hdr = (struct iwm_umac_wifi_if *)payload; struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT; struct iwm_umac_cmd umac_cmd; + int ret; + u8 oid = hdr->oid; umac_cmd.id = UMAC_CMD_OPCODE_WIFI_IF_WRAPPER; umac_cmd.resp = resp; - return iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, - payload, payload_size); + ret = iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, + payload, payload_size); + + if (resp) { + ret = wait_event_interruptible_timeout(iwm->wifi_ntfy_queue, + test_and_clear_bit(oid, &iwm->wifi_ntfy[0]), + 3 * HZ); + + if (!ret) + ret = -EBUSY; + } + + return ret; } static struct coex_event iwm_sta_xor_prio_tbl[COEX_EVENTS_NUM] = @@ -746,14 +760,6 @@ int iwm_send_mlme_profile(struct iwm_priv *iwm) return ret; } - /* Wait for the profile to be active */ - ret = wait_event_interruptible_timeout(iwm->mlme_queue, - iwm->umac_profile_active == 1, - 3 * HZ); - if (!ret) - return -EBUSY; - - for (i = 0; i < IWM_NUM_KEYS; i++) if (iwm->keys[i].in_use) { int default_key = 0; @@ -778,8 +784,8 @@ int iwm_send_mlme_profile(struct iwm_priv *iwm) int iwm_invalidate_mlme_profile(struct iwm_priv *iwm) { - int ret; struct iwm_umac_invalidate_profile invalid; + int ret; invalid.hdr.oid = UMAC_WIFI_IF_CMD_INVALIDATE_PROFILE; invalid.hdr.buf_size = @@ -793,8 +799,7 @@ int iwm_invalidate_mlme_profile(struct iwm_priv *iwm) return ret; ret = wait_event_interruptible_timeout(iwm->mlme_queue, - (iwm->umac_profile_active == 0), - 2 * HZ); + (iwm->umac_profile_active == 0), 2 * HZ); if (!ret) return -EBUSY; diff --git a/drivers/net/wireless/iwmc3200wifi/iwm.h b/drivers/net/wireless/iwmc3200wifi/iwm.h index 77c339f8516c..d8d4ae2d91b0 100644 --- a/drivers/net/wireless/iwmc3200wifi/iwm.h +++ b/drivers/net/wireless/iwmc3200wifi/iwm.h @@ -278,6 +278,9 @@ struct iwm_priv { struct iwm_key keys[IWM_NUM_KEYS]; struct iwm_key *default_key; + DECLARE_BITMAP(wifi_ntfy, WIFI_IF_NTFY_MAX); + wait_queue_head_t wifi_ntfy_queue; + wait_queue_head_t mlme_queue; struct iw_statistics wstats; diff --git a/drivers/net/wireless/iwmc3200wifi/main.c b/drivers/net/wireless/iwmc3200wifi/main.c index 8be206d58222..844872213a12 100644 --- a/drivers/net/wireless/iwmc3200wifi/main.c +++ b/drivers/net/wireless/iwmc3200wifi/main.c @@ -191,6 +191,7 @@ int iwm_priv_init(struct iwm_priv *iwm) INIT_LIST_HEAD(&iwm->pending_notif); init_waitqueue_head(&iwm->notif_queue); init_waitqueue_head(&iwm->nonwifi_queue); + init_waitqueue_head(&iwm->wifi_ntfy_queue); init_waitqueue_head(&iwm->mlme_queue); memcpy(&iwm->conf, &def_iwm_conf, sizeof(struct iwm_conf)); spin_lock_init(&iwm->tx_credit.lock); diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index d73cf96c6dc6..49a8be7c5396 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c @@ -993,12 +993,17 @@ static int iwm_ntf_wifi_if_wrapper(struct iwm_priv *iwm, u8 *buf, (struct iwm_umac_wifi_if *)cmd->buf.payload; IWM_DBG_NTF(iwm, DBG, "WIFI_IF_WRAPPER cmd is delivered to UMAC: " - "oid is %d\n", hdr->oid); + "oid is 0x%x\n", hdr->oid); + + if (hdr->oid <= WIFI_IF_NTFY_MAX) { + set_bit(hdr->oid, &iwm->wifi_ntfy[0]); + wake_up_interruptible(&iwm->wifi_ntfy_queue); + } else + return -EINVAL; switch (hdr->oid) { case UMAC_WIFI_IF_CMD_SET_PROFILE: iwm->umac_profile_active = 1; - wake_up_interruptible(&iwm->mlme_queue); break; default: break; diff --git a/drivers/net/wireless/iwmc3200wifi/umac.h b/drivers/net/wireless/iwmc3200wifi/umac.h index 4a95cce1f0a6..0af2a3c76281 100644 --- a/drivers/net/wireless/iwmc3200wifi/umac.h +++ b/drivers/net/wireless/iwmc3200wifi/umac.h @@ -495,6 +495,8 @@ struct iwm_fw_alive_hdr { #define WIFI_DBG_IF_NTFY_COEX_HANDLE_ENVELOP 0xE8 #define WIFI_DBG_IF_NTFY_COEX_HANDLE_RELEASE_ENVELOP 0xE9 +#define WIFI_IF_NTFY_MAX 0xff + /* Notification structures */ struct iwm_umac_notif_wifi_if { struct iwm_umac_wifi_in_hdr hdr; -- cgit v1.2.3 From 13e0fe70960e95cdea89b71aa3d046ec71efac8c Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Mon, 15 Jun 2009 21:59:52 +0200 Subject: iwmc3200wifi: cfg80211 key hooks implemetation This patch implements the new cfg80211 privacy related hooks: add/get/set_key and the set_default_key one. With this implementation we can now call the wext-compat *encode* routines and reduce our own wext code. Signed-off-by: Samuel Ortiz Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/cfg80211.c | 172 ++++++++++++++++ drivers/net/wireless/iwmc3200wifi/commands.c | 72 +++---- drivers/net/wireless/iwmc3200wifi/commands.h | 3 +- drivers/net/wireless/iwmc3200wifi/iwm.h | 14 +- drivers/net/wireless/iwmc3200wifi/main.c | 4 +- drivers/net/wireless/iwmc3200wifi/wext.c | 286 ++------------------------- 6 files changed, 219 insertions(+), 332 deletions(-) (limited to 'drivers/net/wireless/iwmc3200wifi') diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.c b/drivers/net/wireless/iwmc3200wifi/cfg80211.c index bc89b1ef0cad..739bd9b0ddea 100644 --- a/drivers/net/wireless/iwmc3200wifi/cfg80211.c +++ b/drivers/net/wireless/iwmc3200wifi/cfg80211.c @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -130,6 +131,173 @@ static struct ieee80211_supported_band iwm_band_5ghz = { .n_bitrates = iwm_a_rates_size, }; +static int iwm_key_init(struct iwm_key *key, u8 key_index, + const u8 *mac_addr, struct key_params *params) +{ + key->hdr.key_idx = key_index; + if (!mac_addr || is_broadcast_ether_addr(mac_addr)) { + key->hdr.multicast = 1; + memset(key->hdr.mac, 0xff, ETH_ALEN); + } else { + key->hdr.multicast = 0; + memcpy(key->hdr.mac, mac_addr, ETH_ALEN); + } + + if (params) { + if (params->key_len > WLAN_MAX_KEY_LEN || + params->seq_len > IW_ENCODE_SEQ_MAX_SIZE) + return -EINVAL; + + key->cipher = params->cipher; + key->key_len = params->key_len; + key->seq_len = params->seq_len; + memcpy(key->key, params->key, key->key_len); + memcpy(key->seq, params->seq, key->seq_len); + } + + return 0; +} + +static int iwm_reset_profile(struct iwm_priv *iwm) +{ + int ret; + + if (!iwm->umac_profile_active) + return 0; + + /* + * If there is a current active profile, but no + * default key, it's not worth trying to associate again. + */ + if (iwm->default_key < 0) + return 0; + + /* + * Here we have an active profile, but a key setting changed. + * We thus have to invalidate the current profile, and push the + * new one. Keys will be pushed when association takes place. + */ + ret = iwm_invalidate_mlme_profile(iwm); + if (ret < 0) { + IWM_ERR(iwm, "Couldn't invalidate profile\n"); + return ret; + } + + return iwm_send_mlme_profile(iwm); +} + +static int iwm_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, + u8 key_index, const u8 *mac_addr, + struct key_params *params) +{ + struct iwm_priv *iwm = ndev_to_iwm(ndev); + struct iwm_key *key = &iwm->keys[key_index]; + int ret; + + IWM_DBG_WEXT(iwm, DBG, "Adding key for %pM\n", mac_addr); + + memset(key, 0, sizeof(struct iwm_key)); + ret = iwm_key_init(key, key_index, mac_addr, params); + if (ret < 0) { + IWM_ERR(iwm, "Invalid key_params\n"); + return ret; + } + + /* + * The WEP keys can be set before or after setting the essid. + * We need to handle both cases by simply pushing the keys after + * we send the profile. + * If the profile is not set yet (i.e. we're pushing keys before + * the essid), we set the cipher appropriately. + * If the profile is set, we havent associated yet because our + * cipher was incorrectly set. So we invalidate and send the + * profile again. + */ + if (key->cipher == WLAN_CIPHER_SUITE_WEP40 || + key->cipher == WLAN_CIPHER_SUITE_WEP104) { + u8 *ucast_cipher = &iwm->umac_profile->sec.ucast_cipher; + u8 *mcast_cipher = &iwm->umac_profile->sec.mcast_cipher; + + IWM_DBG_WEXT(iwm, DBG, "WEP key\n"); + + if (key->cipher == WLAN_CIPHER_SUITE_WEP40) + *ucast_cipher = *mcast_cipher = UMAC_CIPHER_TYPE_WEP_40; + if (key->cipher == WLAN_CIPHER_SUITE_WEP104) + *ucast_cipher = *mcast_cipher = + UMAC_CIPHER_TYPE_WEP_104; + + return iwm_reset_profile(iwm); + } + + return iwm_set_key(iwm, 0, key); +} + +static int iwm_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev, + u8 key_index, const u8 *mac_addr, void *cookie, + void (*callback)(void *cookie, + struct key_params*)) +{ + struct iwm_priv *iwm = ndev_to_iwm(ndev); + struct iwm_key *key = &iwm->keys[key_index]; + struct key_params params; + + IWM_DBG_WEXT(iwm, DBG, "Getting key %d\n", key_index); + + memset(¶ms, 0, sizeof(params)); + + params.cipher = key->cipher; + params.key_len = key->key_len; + params.seq_len = key->seq_len; + params.seq = key->seq; + params.key = key->key; + + callback(cookie, ¶ms); + + return key->key_len ? 0 : -ENOENT; +} + + +static int iwm_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev, + u8 key_index, const u8 *mac_addr) +{ + struct iwm_priv *iwm = ndev_to_iwm(ndev); + struct iwm_key *key = &iwm->keys[key_index]; + + if (!iwm->keys[key_index].key_len) { + IWM_DBG_WEXT(iwm, DBG, "Key %d not used\n", key_index); + return 0; + } + + if (key_index == iwm->default_key) + iwm->default_key = -1; + + return iwm_set_key(iwm, 1, key); +} + +static int iwm_cfg80211_set_default_key(struct wiphy *wiphy, + struct net_device *ndev, + u8 key_index) +{ + struct iwm_priv *iwm = ndev_to_iwm(ndev); + int ret; + + IWM_DBG_WEXT(iwm, DBG, "Default key index is: %d\n", key_index); + + if (!iwm->keys[key_index].key_len) { + IWM_ERR(iwm, "Key %d not used\n", key_index); + return -EINVAL; + } + + ret = iwm_set_tx_key(iwm, key_index); + if (ret < 0) + return ret; + + iwm->default_key = key_index; + + return iwm_reset_profile(iwm); +} + + int iwm_cfg80211_inform_bss(struct iwm_priv *iwm) { struct wiphy *wiphy = iwm_to_wiphy(iwm); @@ -326,6 +494,10 @@ static int iwm_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) static struct cfg80211_ops iwm_cfg80211_ops = { .change_virtual_intf = iwm_cfg80211_change_iface, + .add_key = iwm_cfg80211_add_key, + .get_key = iwm_cfg80211_get_key, + .del_key = iwm_cfg80211_del_key, + .set_default_key = iwm_cfg80211_set_default_key, .scan = iwm_cfg80211_scan, .set_wiphy_params = iwm_cfg80211_set_wiphy_params, .join_ibss = iwm_cfg80211_join_ibss, diff --git a/drivers/net/wireless/iwmc3200wifi/commands.c b/drivers/net/wireless/iwmc3200wifi/commands.c index 337a884f52df..145f6f5ae747 100644 --- a/drivers/net/wireless/iwmc3200wifi/commands.c +++ b/drivers/net/wireless/iwmc3200wifi/commands.c @@ -524,9 +524,6 @@ int iwm_set_tx_key(struct iwm_priv *iwm, u8 key_idx) { struct iwm_umac_tx_key_id tx_key_id; - if (!iwm->default_key || !iwm->default_key->in_use) - return -EINVAL; - tx_key_id.hdr.oid = UMAC_WIFI_IF_CMD_GLOBAL_TX_KEY_ID; tx_key_id.hdr.buf_size = cpu_to_le16(sizeof(struct iwm_umac_tx_key_id) - sizeof(struct iwm_umac_wifi_if)); @@ -569,10 +566,9 @@ static int iwm_check_profile(struct iwm_priv *iwm) return 0; } -int iwm_set_key(struct iwm_priv *iwm, bool remove, bool set_tx_key, - struct iwm_key *key) +int iwm_set_key(struct iwm_priv *iwm, bool remove, struct iwm_key *key) { - int ret; + int ret = 0; u8 cmd[64], *sta_addr, *key_data, key_len; s8 key_idx; u16 cmd_size = 0; @@ -582,9 +578,6 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, bool set_tx_key, struct iwm_umac_key_tkip *tkip = (struct iwm_umac_key_tkip *)cmd; struct iwm_umac_key_ccmp *ccmp = (struct iwm_umac_key_ccmp *)cmd; - if (set_tx_key) - iwm->default_key = key; - /* * We check if our current profile is valid. * If not, we dont push the key, we just cache them, @@ -603,8 +596,7 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, bool set_tx_key, key_idx = key->hdr.key_idx; if (!remove) { - IWM_DBG_WEXT(iwm, DBG, "key_idx:%d set tx key:%d\n", - key_idx, set_tx_key); + IWM_DBG_WEXT(iwm, DBG, "key_idx:%d\n", key_idx); IWM_DBG_WEXT(iwm, DBG, "key_len:%d\n", key_len); IWM_DBG_WEXT(iwm, DBG, "MAC:%pM, idx:%d, multicast:%d\n", key_hdr->mac, key_hdr->key_idx, key_hdr->multicast); @@ -616,8 +608,8 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, bool set_tx_key, iwm->umac_profile->sec.auth_type, iwm->umac_profile->sec.flags); - switch (key->alg) { - case UMAC_CIPHER_TYPE_WEP_40: + switch (key->cipher) { + case WLAN_CIPHER_SUITE_WEP40: wep40->hdr.oid = UMAC_WIFI_IF_CMD_ADD_WEP40_KEY; wep40->hdr.buf_size = cpu_to_le16(sizeof(struct iwm_umac_key_wep40) - @@ -631,7 +623,7 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, bool set_tx_key, cmd_size = sizeof(struct iwm_umac_key_wep40); break; - case UMAC_CIPHER_TYPE_WEP_104: + case WLAN_CIPHER_SUITE_WEP104: wep104->hdr.oid = UMAC_WIFI_IF_CMD_ADD_WEP104_KEY; wep104->hdr.buf_size = cpu_to_le16(sizeof(struct iwm_umac_key_wep104) - @@ -645,7 +637,7 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, bool set_tx_key, cmd_size = sizeof(struct iwm_umac_key_wep104); break; - case UMAC_CIPHER_TYPE_CCMP: + case WLAN_CIPHER_SUITE_CCMP: key_hdr->key_idx++; ccmp->hdr.oid = UMAC_WIFI_IF_CMD_ADD_CCMP_KEY; ccmp->hdr.buf_size = @@ -657,13 +649,13 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, bool set_tx_key, memcpy(ccmp->key, key_data, key_len); - if (key->flags & IW_ENCODE_EXT_RX_SEQ_VALID) - memcpy(ccmp->iv_count, key->rx_seq, 6); + if (key->seq_len) + memcpy(ccmp->iv_count, key->seq, key->seq_len); cmd_size = sizeof(struct iwm_umac_key_ccmp); break; - case UMAC_CIPHER_TYPE_TKIP: + case WLAN_CIPHER_SUITE_TKIP: key_hdr->key_idx++; tkip->hdr.oid = UMAC_WIFI_IF_CMD_ADD_TKIP_KEY; tkip->hdr.buf_size = @@ -680,8 +672,8 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, bool set_tx_key, key_data + IWM_TKIP_KEY_SIZE + IWM_TKIP_MIC_SIZE, IWM_TKIP_MIC_SIZE); - if (key->flags & IW_ENCODE_EXT_RX_SEQ_VALID) - memcpy(ccmp->iv_count, key->rx_seq, 6); + if (key->seq_len) + memcpy(ccmp->iv_count, key->seq, key->seq_len); cmd_size = sizeof(struct iwm_umac_key_tkip); break; @@ -690,8 +682,8 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, bool set_tx_key, return -ENOTSUPP; } - if ((key->alg == UMAC_CIPHER_TYPE_CCMP) || - (key->alg == UMAC_CIPHER_TYPE_TKIP)) + if ((key->cipher == WLAN_CIPHER_SUITE_TKIP) || + (key->cipher == WLAN_CIPHER_SUITE_CCMP)) /* * UGLY_UGLY_UGLY * Copied HACK from the MWG driver. @@ -702,23 +694,11 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, bool set_tx_key, schedule_timeout_interruptible(usecs_to_jiffies(300)); ret = iwm_send_wifi_if_cmd(iwm, cmd, cmd_size, 1); - if (ret < 0) - goto err; - - /* - * We need a default key only if it is set and - * if we're doing WEP. - */ - if (iwm->default_key == key && - ((key->alg == UMAC_CIPHER_TYPE_WEP_40) || - (key->alg == UMAC_CIPHER_TYPE_WEP_104))) { - ret = iwm_set_tx_key(iwm, key_idx); - if (ret < 0) - goto err; - } } else { struct iwm_umac_key_remove key_remove; + IWM_DBG_WEXT(iwm, ERR, "Removing key_idx:%d\n", key_idx); + key_remove.hdr.oid = UMAC_WIFI_IF_CMD_REMOVE_KEY; key_remove.hdr.buf_size = cpu_to_le16(sizeof(struct iwm_umac_key_remove) - @@ -732,13 +712,9 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, bool set_tx_key, if (ret < 0) return ret; - iwm->keys[key_idx].in_use = 0; + iwm->keys[key_idx].key_len = 0; } - return 0; - - err: - kfree(key); return ret; } @@ -761,22 +737,24 @@ int iwm_send_mlme_profile(struct iwm_priv *iwm) } for (i = 0; i < IWM_NUM_KEYS; i++) - if (iwm->keys[i].in_use) { - int default_key = 0; + if (iwm->keys[i].key_len) { struct iwm_key *key = &iwm->keys[i]; - if (key == iwm->default_key) - default_key = 1; - /* Wait for the profile before sending the keys */ wait_event_interruptible_timeout(iwm->mlme_queue, (test_bit(IWM_STATUS_ASSOCIATING, &iwm->status) || test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)), 3 * HZ); - ret = iwm_set_key(iwm, 0, default_key, key); + ret = iwm_set_key(iwm, 0, key); if (ret < 0) return ret; + + if (iwm->default_key == i) { + ret = iwm_set_tx_key(iwm, i); + if (ret < 0) + return ret; + } } return 0; diff --git a/drivers/net/wireless/iwmc3200wifi/commands.h b/drivers/net/wireless/iwmc3200wifi/commands.h index 36b13a130595..3510df8ff391 100644 --- a/drivers/net/wireless/iwmc3200wifi/commands.h +++ b/drivers/net/wireless/iwmc3200wifi/commands.h @@ -406,8 +406,7 @@ int iwm_send_mlme_profile(struct iwm_priv *iwm); int iwm_invalidate_mlme_profile(struct iwm_priv *iwm); int iwm_send_packet(struct iwm_priv *iwm, struct sk_buff *skb, int pool_id); int iwm_set_tx_key(struct iwm_priv *iwm, u8 key_idx); -int iwm_set_key(struct iwm_priv *iwm, bool remove, bool set_tx_key, - struct iwm_key *key); +int iwm_set_key(struct iwm_priv *iwm, bool remove, struct iwm_key *key); int iwm_send_umac_stats_req(struct iwm_priv *iwm, u32 flags); int iwm_send_umac_channel_list(struct iwm_priv *iwm); int iwm_scan_ssids(struct iwm_priv *iwm, struct cfg80211_ssid *ssids, diff --git a/drivers/net/wireless/iwmc3200wifi/iwm.h b/drivers/net/wireless/iwmc3200wifi/iwm.h index d8d4ae2d91b0..90b05d999635 100644 --- a/drivers/net/wireless/iwmc3200wifi/iwm.h +++ b/drivers/net/wireless/iwmc3200wifi/iwm.h @@ -162,13 +162,11 @@ struct iwm_umac_key_hdr { struct iwm_key { struct iwm_umac_key_hdr hdr; - u8 in_use; - u8 alg; - u32 flags; - u8 tx_seq[IW_ENCODE_SEQ_MAX_SIZE]; - u8 rx_seq[IW_ENCODE_SEQ_MAX_SIZE]; - u8 key_len; - u8 key[32]; + u32 cipher; + u8 key[WLAN_MAX_KEY_LEN]; + u8 seq[IW_ENCODE_SEQ_MAX_SIZE]; + int key_len; + int seq_len; }; #define IWM_RX_ID_HASH 0xff @@ -276,7 +274,7 @@ struct iwm_priv { struct iwm_tx_queue txq[IWM_TX_QUEUES]; struct iwm_key keys[IWM_NUM_KEYS]; - struct iwm_key *default_key; + s8 default_key; DECLARE_BITMAP(wifi_ntfy, WIFI_IF_NTFY_MAX); wait_queue_head_t wifi_ntfy_queue; diff --git a/drivers/net/wireless/iwmc3200wifi/main.c b/drivers/net/wireless/iwmc3200wifi/main.c index 844872213a12..7f56c06a53db 100644 --- a/drivers/net/wireless/iwmc3200wifi/main.c +++ b/drivers/net/wireless/iwmc3200wifi/main.c @@ -230,7 +230,7 @@ int iwm_priv_init(struct iwm_priv *iwm) for (i = 0; i < IWM_NUM_KEYS; i++) memset(&iwm->keys[i], 0, sizeof(struct iwm_key)); - iwm->default_key = NULL; + iwm->default_key = -1; init_timer(&iwm->watchdog); iwm->watchdog.function = iwm_watchdog; @@ -709,7 +709,7 @@ int __iwm_down(struct iwm_priv *iwm) iwm->umac_profile = NULL; iwm_bss_list_clean(iwm); - iwm->default_key = NULL; + iwm->default_key = -1; iwm->core_enabled = 0; ret = iwm_bus_disable(iwm); diff --git a/drivers/net/wireless/iwmc3200wifi/wext.c b/drivers/net/wireless/iwmc3200wifi/wext.c index 889194931b4e..3062f37bbe95 100644 --- a/drivers/net/wireless/iwmc3200wifi/wext.c +++ b/drivers/net/wireless/iwmc3200wifi/wext.c @@ -84,6 +84,8 @@ static int iwm_wext_siwap(struct net_device *dev, struct iw_request_info *info, struct iwm_priv *iwm = ndev_to_iwm(dev); int ret; + IWM_DBG_WEXT(iwm, DBG, "Set BSSID: %pM\n", ap_addr->sa_data); + if (iwm->conf.mode == UMAC_MODE_IBSS) return cfg80211_ibss_wext_siwap(dev, info, ap_addr, extra); @@ -116,8 +118,7 @@ static int iwm_wext_siwap(struct net_device *dev, struct iw_request_info *info, */ if (is_zero_ether_addr(ap_addr->sa_data)) { for (i = 0; i < IWM_NUM_KEYS; i++) - iwm->keys[i].in_use = 0; - + iwm->keys[i].key_len = 0; } ret = iwm_invalidate_mlme_profile(iwm); @@ -163,6 +164,8 @@ static int iwm_wext_siwessid(struct net_device *dev, size_t len = data->length; int ret; + IWM_DBG_WEXT(iwm, DBG, "Set ESSID: >%s<\n", ssid); + if (iwm->conf.mode == UMAC_MODE_IBSS) return cfg80211_ibss_wext_siwessid(dev, info, data, ssid); @@ -212,27 +215,6 @@ static int iwm_wext_giwessid(struct net_device *dev, return 0; } -static struct iwm_key * -iwm_key_init(struct iwm_priv *iwm, u8 key_idx, bool in_use, - struct iw_encode_ext *ext, u8 alg) -{ - struct iwm_key *key = &iwm->keys[key_idx]; - - memset(key, 0, sizeof(struct iwm_key)); - memcpy(key->hdr.mac, ext->addr.sa_data, ETH_ALEN); - key->hdr.key_idx = key_idx; - if (is_broadcast_ether_addr(ext->addr.sa_data)) - key->hdr.multicast = 1; - - key->in_use = in_use; - key->flags = ext->ext_flags; - key->alg = alg; - key->key_len = ext->key_len; - memcpy(key->key, ext->key, ext->key_len); - - return key; -} - static int iwm_wext_giwrate(struct net_device *dev, struct iw_request_info *info, struct iw_param *rate, char *extra) @@ -244,184 +226,6 @@ static int iwm_wext_giwrate(struct net_device *dev, return 0; } -static int iwm_wext_siwencode(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *erq, char *key_buf) -{ - struct iwm_priv *iwm = ndev_to_iwm(dev); - struct iwm_key *uninitialized_var(key); - int idx, i, uninitialized_var(alg), remove = 0, ret; - - IWM_DBG_WEXT(iwm, DBG, "key len: %d\n", erq->length); - IWM_DBG_WEXT(iwm, DBG, "flags: 0x%x\n", erq->flags); - - if (!iwm->umac_profile) { - IWM_ERR(iwm, "UMAC profile not allocated yet\n"); - return -ENODEV; - } - - if (erq->length == WLAN_KEY_LEN_WEP40) { - alg = UMAC_CIPHER_TYPE_WEP_40; - iwm->umac_profile->sec.ucast_cipher = UMAC_CIPHER_TYPE_WEP_40; - iwm->umac_profile->sec.mcast_cipher = UMAC_CIPHER_TYPE_WEP_40; - } else if (erq->length == WLAN_KEY_LEN_WEP104) { - alg = UMAC_CIPHER_TYPE_WEP_104; - iwm->umac_profile->sec.ucast_cipher = UMAC_CIPHER_TYPE_WEP_104; - iwm->umac_profile->sec.mcast_cipher = UMAC_CIPHER_TYPE_WEP_104; - } - - if (erq->flags & IW_ENCODE_RESTRICTED) - iwm->umac_profile->sec.auth_type = UMAC_AUTH_TYPE_LEGACY_PSK; - else - iwm->umac_profile->sec.auth_type = UMAC_AUTH_TYPE_OPEN; - - idx = erq->flags & IW_ENCODE_INDEX; - if (idx == 0) { - if (iwm->default_key) - for (i = 0; i < IWM_NUM_KEYS; i++) { - if (iwm->default_key == &iwm->keys[i]) { - idx = i; - break; - } - } - else - iwm->default_key = &iwm->keys[idx]; - } else if (idx < 1 || idx > 4) { - return -EINVAL; - } else - idx--; - - if (erq->flags & IW_ENCODE_DISABLED) - remove = 1; - else if (erq->length == 0) { - if (!iwm->keys[idx].in_use) - return -EINVAL; - iwm->default_key = &iwm->keys[idx]; - } - - if (erq->length) { - key = &iwm->keys[idx]; - memset(key, 0, sizeof(struct iwm_key)); - memset(key->hdr.mac, 0xff, ETH_ALEN); - key->hdr.key_idx = idx; - key->hdr.multicast = 1; - key->in_use = !remove; - key->alg = alg; - key->key_len = erq->length; - memcpy(key->key, key_buf, erq->length); - - IWM_DBG_WEXT(iwm, DBG, "Setting key %d, default: %d\n", - idx, !!iwm->default_key); - } - - if (remove) { - if ((erq->flags & IW_ENCODE_NOKEY) || (erq->length == 0)) { - int j; - for (j = 0; j < IWM_NUM_KEYS; j++) - if (iwm->keys[j].in_use) { - struct iwm_key *k = &iwm->keys[j]; - - k->in_use = 0; - ret = iwm_set_key(iwm, remove, 0, k); - if (ret < 0) - return ret; - } - - iwm->umac_profile->sec.ucast_cipher = - UMAC_CIPHER_TYPE_NONE; - iwm->umac_profile->sec.mcast_cipher = - UMAC_CIPHER_TYPE_NONE; - iwm->umac_profile->sec.auth_type = - UMAC_AUTH_TYPE_OPEN; - - return 0; - } else { - key->in_use = 0; - return iwm_set_key(iwm, remove, 0, key); - } - } - - /* - * If we havent set a profile yet, we cant set keys. - * Keys will be pushed after we're associated. - */ - if (!iwm->umac_profile_active) - return 0; - - /* - * If there is a current active profile, but no - * default key, it's not worth trying to associate again. - */ - if (!iwm->default_key) - return 0; - - /* - * Here we have an active profile, but a key setting changed. - * We thus have to invalidate the current profile, and push the - * new one. Keys will be pushed when association takes place. - */ - ret = iwm_invalidate_mlme_profile(iwm); - if (ret < 0) { - IWM_ERR(iwm, "Couldn't invalidate profile\n"); - return ret; - } - - return iwm_send_mlme_profile(iwm); -} - -static int iwm_wext_giwencode(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *erq, char *key) -{ - struct iwm_priv *iwm = ndev_to_iwm(dev); - int idx, i; - - idx = erq->flags & IW_ENCODE_INDEX; - if (idx < 1 || idx > 4) { - idx = -1; - if (!iwm->default_key) { - erq->length = 0; - erq->flags |= IW_ENCODE_NOKEY; - return 0; - } else - for (i = 0; i < IWM_NUM_KEYS; i++) { - if (iwm->default_key == &iwm->keys[i]) { - idx = i; - break; - } - } - if (idx < 0) - return -EINVAL; - } else - idx--; - - erq->flags = idx + 1; - - if (!iwm->keys[idx].in_use) { - erq->length = 0; - erq->flags |= IW_ENCODE_DISABLED; - return 0; - } - - memcpy(key, iwm->keys[idx].key, - min_t(int, erq->length, iwm->keys[idx].key_len)); - erq->length = iwm->keys[idx].key_len; - erq->flags |= IW_ENCODE_ENABLED; - - if (iwm->umac_profile->mode == UMAC_MODE_BSS) { - switch (iwm->umac_profile->sec.auth_type) { - case UMAC_AUTH_TYPE_OPEN: - erq->flags |= IW_ENCODE_OPEN; - break; - default: - erq->flags |= IW_ENCODE_RESTRICTED; - break; - } - } - - return 0; -} - static int iwm_set_wpa_version(struct iwm_priv *iwm, u8 wpa_version) { if (wpa_version & IW_AUTH_WPA_VERSION_WPA2) @@ -481,6 +285,8 @@ static int iwm_set_key_mgt(struct iwm_priv *iwm, u8 key_mgt) { u8 *auth_type = &iwm->umac_profile->sec.auth_type; + IWM_DBG_WEXT(iwm, DBG, "key_mgt: 0x%x\n", key_mgt); + if (key_mgt == IW_AUTH_KEY_MGMT_802_1X) *auth_type = UMAC_AUTH_TYPE_8021X; else if (key_mgt == IW_AUTH_KEY_MGMT_PSK) { @@ -530,6 +336,8 @@ static int iwm_set_auth_alg(struct iwm_priv *iwm, u8 auth_alg) { u8 *auth_type = &iwm->umac_profile->sec.auth_type; + IWM_DBG_WEXT(iwm, DBG, "auth_alg: 0x%x\n", auth_alg); + switch (auth_alg) { case IW_AUTH_ALG_OPEN_SYSTEM: *auth_type = UMAC_AUTH_TYPE_OPEN; @@ -541,6 +349,7 @@ static int iwm_set_auth_alg(struct iwm_priv *iwm, u8 auth_alg) return -EINVAL; *auth_type = UMAC_AUTH_TYPE_RSNA_PSK; } else { + IWM_DBG_WEXT(iwm, DBG, "WEP shared key\n"); *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK; } break; @@ -603,75 +412,6 @@ static int iwm_wext_giwauth(struct net_device *dev, return 0; } -static int iwm_wext_siwencodeext(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *erq, char *extra) -{ - struct iwm_priv *iwm = ndev_to_iwm(dev); - struct iwm_key *key; - struct iw_encode_ext *ext = (struct iw_encode_ext *) extra; - int uninitialized_var(alg), idx, i, remove = 0; - - IWM_DBG_WEXT(iwm, DBG, "alg: 0x%x\n", ext->alg); - IWM_DBG_WEXT(iwm, DBG, "key len: %d\n", ext->key_len); - IWM_DBG_WEXT(iwm, DBG, "ext_flags: 0x%x\n", ext->ext_flags); - IWM_DBG_WEXT(iwm, DBG, "flags: 0x%x\n", erq->flags); - IWM_DBG_WEXT(iwm, DBG, "length: 0x%x\n", erq->length); - - switch (ext->alg) { - case IW_ENCODE_ALG_NONE: - remove = 1; - break; - case IW_ENCODE_ALG_WEP: - if (ext->key_len == WLAN_KEY_LEN_WEP40) - alg = UMAC_CIPHER_TYPE_WEP_40; - else if (ext->key_len == WLAN_KEY_LEN_WEP104) - alg = UMAC_CIPHER_TYPE_WEP_104; - else { - IWM_ERR(iwm, "Invalid key length: %d\n", ext->key_len); - return -EINVAL; - } - - break; - case IW_ENCODE_ALG_TKIP: - alg = UMAC_CIPHER_TYPE_TKIP; - break; - case IW_ENCODE_ALG_CCMP: - alg = UMAC_CIPHER_TYPE_CCMP; - break; - default: - return -EOPNOTSUPP; - } - - idx = erq->flags & IW_ENCODE_INDEX; - - if (idx == 0) { - if (iwm->default_key) - for (i = 0; i < IWM_NUM_KEYS; i++) { - if (iwm->default_key == &iwm->keys[i]) { - idx = i; - break; - } - } - } else if (idx < 1 || idx > 4) { - return -EINVAL; - } else - idx--; - - if (erq->flags & IW_ENCODE_DISABLED) - remove = 1; - else if ((erq->length == 0) || - (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)) { - iwm->default_key = &iwm->keys[idx]; - if (iwm->umac_profile_active && ext->alg == IW_ENCODE_ALG_WEP) - return iwm_set_tx_key(iwm, idx); - } - - key = iwm_key_init(iwm, idx, !remove, ext, alg); - - return iwm_set_key(iwm, remove, !iwm->default_key, key); -} - static const iw_handler iwm_handlers[] = { (iw_handler) NULL, /* SIOCSIWCOMMIT */ @@ -716,8 +456,8 @@ static const iw_handler iwm_handlers[] = (iw_handler) NULL, /* SIOCGIWTXPOW */ (iw_handler) NULL, /* SIOCSIWRETRY */ (iw_handler) NULL, /* SIOCGIWRETRY */ - (iw_handler) iwm_wext_siwencode, /* SIOCSIWENCODE */ - (iw_handler) iwm_wext_giwencode, /* SIOCGIWENCODE */ + (iw_handler) cfg80211_wext_siwencode, /* SIOCSIWENCODE */ + (iw_handler) cfg80211_wext_giwencode, /* SIOCGIWENCODE */ (iw_handler) iwm_wext_siwpower, /* SIOCSIWPOWER */ (iw_handler) iwm_wext_giwpower, /* SIOCGIWPOWER */ (iw_handler) NULL, /* -- hole -- */ @@ -726,7 +466,7 @@ static const iw_handler iwm_handlers[] = (iw_handler) NULL, /* SIOCGIWGENIE */ (iw_handler) iwm_wext_siwauth, /* SIOCSIWAUTH */ (iw_handler) iwm_wext_giwauth, /* SIOCGIWAUTH */ - (iw_handler) iwm_wext_siwencodeext, /* SIOCSIWENCODEEXT */ + (iw_handler) cfg80211_wext_siwencodeext, /* SIOCSIWENCODEEXT */ (iw_handler) NULL, /* SIOCGIWENCODEEXT */ (iw_handler) NULL, /* SIOCSIWPMKSA */ (iw_handler) NULL, /* -- hole -- */ -- cgit v1.2.3 From 191506ecbce03f09f6afa76f1af069574bf99bec Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Mon, 15 Jun 2009 21:59:53 +0200 Subject: iwmc3200wifi: change coexist periodic calibration flag The patch changes coexist periodic calibration priority flag. It also set wireless mode to UMAC and set PM control flag to 0x1. Signed-off-by: Zhu Yi Signed-off-by: Samuel Ortiz Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/commands.c | 13 +++++++++---- drivers/net/wireless/iwmc3200wifi/commands.h | 4 ++-- 2 files changed, 11 insertions(+), 6 deletions(-) (limited to 'drivers/net/wireless/iwmc3200wifi') diff --git a/drivers/net/wireless/iwmc3200wifi/commands.c b/drivers/net/wireless/iwmc3200wifi/commands.c index 145f6f5ae747..0d35afefb61c 100644 --- a/drivers/net/wireless/iwmc3200wifi/commands.c +++ b/drivers/net/wireless/iwmc3200wifi/commands.c @@ -120,7 +120,7 @@ static struct coex_event iwm_sta_cm_prio_tbl[COEX_EVENTS_NUM] = {4, 3, 0, COEX_UNASSOC_MANUAL_SCAN_FLAGS}, {3, 3, 0, COEX_UNASSOC_AUTO_SCAN_FLAGS}, {5, 5, 0, COEX_CALIBRATION_FLAGS}, - {4, 4, 0, COEX_PERIODIC_CALIBRATION_FLAGS}, + {3, 3, 0, COEX_PERIODIC_CALIBRATION_FLAGS}, {5, 4, 0, COEX_CONNECTION_ESTAB_FLAGS}, {4, 4, 0, COEX_ASSOCIATED_IDLE_FLAGS}, {4, 4, 0, COEX_ASSOC_MANUAL_SCAN_FLAGS}, @@ -345,8 +345,7 @@ int iwm_umac_set_config_var(struct iwm_priv *iwm, u16 key, return ret; } -int iwm_send_umac_config(struct iwm_priv *iwm, - __le32 reset_flags) +int iwm_send_umac_config(struct iwm_priv *iwm, __le32 reset_flags) { int ret; @@ -373,6 +372,12 @@ int iwm_send_umac_config(struct iwm_priv *iwm, if (ret < 0) return ret; + ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, + CFG_WIRELESS_MODE, + iwm->conf.wireless_mode); + if (ret < 0) + return ret; + ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, CFG_COEX_MODE, iwm->conf.coexist_mode); if (ret < 0) @@ -415,7 +420,7 @@ int iwm_send_umac_config(struct iwm_priv *iwm, return ret; ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, - CFG_PM_CTRL_FLAGS, 0x30001); + CFG_PM_CTRL_FLAGS, 0x1); if (ret < 0) return ret; diff --git a/drivers/net/wireless/iwmc3200wifi/commands.h b/drivers/net/wireless/iwmc3200wifi/commands.h index 3510df8ff391..e24d5b633997 100644 --- a/drivers/net/wireless/iwmc3200wifi/commands.h +++ b/drivers/net/wireless/iwmc3200wifi/commands.h @@ -106,8 +106,7 @@ enum { CFG_TLC_SPATIAL_STREAM_SUPPORTED, CFG_TLC_RETRY_PER_RATE, CFG_TLC_RETRY_PER_HT_RATE, - CFG_TLC_FIXED_RATE, - CFG_TLC_FIXED_RATE_FLAGS, + CFG_TLC_FIXED_MCS, CFG_TLC_CONTROL_FLAGS, CFG_TLC_SR_MIN_FAIL, CFG_TLC_SR_MIN_PASS, @@ -232,6 +231,7 @@ struct iwm_umac_cmd_get_channel_list { /* Wireless mode */ #define WIRELESS_MODE_11A 0x1 #define WIRELESS_MODE_11G 0x2 +#define WIRELESS_MODE_11N 0x4 #define UMAC_PROFILE_EX_IE_REQUIRED 0x1 #define UMAC_PROFILE_QOS_ALLOWED 0x2 -- cgit v1.2.3 From 3549716484a95fd16f7fcf8b68699bd4c803b382 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Mon, 15 Jun 2009 21:59:54 +0200 Subject: iwmc3200wifi: cache keys when interface is down When the interface is down and one sets a WEP key from userspace, we should be able to simply cache it. Since that implies setting part of the profile's security settings, we now alloc/free the umac_profile at probe/remove time, and no longer at interface bring up/down time. Simply resetting it during the latter is enough. Signed-off-by: Samuel Ortiz Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/cfg80211.c | 12 ++++++++++-- drivers/net/wireless/iwmc3200wifi/main.c | 20 +++----------------- drivers/net/wireless/iwmc3200wifi/netdev.c | 15 +++++++++++++++ 3 files changed, 28 insertions(+), 19 deletions(-) (limited to 'drivers/net/wireless/iwmc3200wifi') diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.c b/drivers/net/wireless/iwmc3200wifi/cfg80211.c index 739bd9b0ddea..0cdd7ef68b78 100644 --- a/drivers/net/wireless/iwmc3200wifi/cfg80211.c +++ b/drivers/net/wireless/iwmc3200wifi/cfg80211.c @@ -271,6 +271,10 @@ static int iwm_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev, if (key_index == iwm->default_key) iwm->default_key = -1; + /* If the interface is down, we just cache this */ + if (!test_bit(IWM_STATUS_READY, &iwm->status)) + return 0; + return iwm_set_key(iwm, 1, key); } @@ -288,12 +292,16 @@ static int iwm_cfg80211_set_default_key(struct wiphy *wiphy, return -EINVAL; } + iwm->default_key = key_index; + + /* If the interface is down, we just cache this */ + if (!test_bit(IWM_STATUS_READY, &iwm->status)) + return 0; + ret = iwm_set_tx_key(iwm, key_index); if (ret < 0) return ret; - iwm->default_key = key_index; - return iwm_reset_profile(iwm); } diff --git a/drivers/net/wireless/iwmc3200wifi/main.c b/drivers/net/wireless/iwmc3200wifi/main.c index 7f56c06a53db..930056b013f3 100644 --- a/drivers/net/wireless/iwmc3200wifi/main.c +++ b/drivers/net/wireless/iwmc3200wifi/main.c @@ -643,19 +643,10 @@ int __iwm_up(struct iwm_priv *iwm) } } - iwm->umac_profile = kmalloc(sizeof(struct iwm_umac_profile), - GFP_KERNEL); - if (!iwm->umac_profile) { - IWM_ERR(iwm, "Couldn't alloc memory for profile\n"); - goto err_fw; - } - - iwm_init_default_profile(iwm, iwm->umac_profile); - ret = iwm_channels_init(iwm); if (ret < 0) { IWM_ERR(iwm, "Couldn't init channels\n"); - goto err_profile; + goto err_fw; } /* Set the READY bit to indicate interface is brought up successfully */ @@ -663,10 +654,6 @@ int __iwm_up(struct iwm_priv *iwm) return 0; - err_profile: - kfree(iwm->umac_profile); - iwm->umac_profile = NULL; - err_fw: iwm_eeprom_exit(iwm); @@ -705,10 +692,9 @@ int __iwm_down(struct iwm_priv *iwm) clear_bit(IWM_STATUS_READY, &iwm->status); iwm_eeprom_exit(iwm); - kfree(iwm->umac_profile); - iwm->umac_profile = NULL; iwm_bss_list_clean(iwm); - + iwm_init_default_profile(iwm, iwm->umac_profile); + iwm->umac_profile_active = false; iwm->default_key = -1; iwm->core_enabled = 0; diff --git a/drivers/net/wireless/iwmc3200wifi/netdev.c b/drivers/net/wireless/iwmc3200wifi/netdev.c index aaa20c6885c8..d4deb4b471e5 100644 --- a/drivers/net/wireless/iwmc3200wifi/netdev.c +++ b/drivers/net/wireless/iwmc3200wifi/netdev.c @@ -48,6 +48,7 @@ #include #include "iwm.h" +#include "commands.h" #include "cfg80211.h" #include "debug.h" @@ -135,8 +136,20 @@ void *iwm_if_alloc(int sizeof_bus, struct device *dev, SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy)); wdev->netdev = ndev; + iwm->umac_profile = kmalloc(sizeof(struct iwm_umac_profile), + GFP_KERNEL); + if (!iwm->umac_profile) { + dev_err(dev, "Couldn't alloc memory for profile\n"); + goto out_profile; + } + + iwm_init_default_profile(iwm, iwm->umac_profile); + return iwm; + out_profile: + free_netdev(ndev); + out_priv: iwm_priv_deinit(iwm); @@ -153,6 +166,8 @@ void iwm_if_free(struct iwm_priv *iwm) free_netdev(iwm_to_ndev(iwm)); iwm_wdev_free(iwm); iwm_priv_deinit(iwm); + kfree(iwm->umac_profile); + iwm->umac_profile = NULL; } int iwm_if_add(struct iwm_priv *iwm) -- cgit v1.2.3 From 257862f3faef397f1a677ae6a5a1828fa00a97b1 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Mon, 15 Jun 2009 21:59:56 +0200 Subject: iwmc3200wifi: rfkill cleanup The patch cleans up the unused rfkill related structures and flags. It also adds wext and cfg80211 handlers for txpower auto and off so that software rfkill could be issued by user space. Signed-off-by: Zhu Yi Signed-off-by: Samuel Ortiz Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/cfg80211.c | 24 ++++++++++++++++++++++++ drivers/net/wireless/iwmc3200wifi/iwm.h | 7 +------ drivers/net/wireless/iwmc3200wifi/netdev.c | 12 ++---------- drivers/net/wireless/iwmc3200wifi/rx.c | 18 +++++++++--------- drivers/net/wireless/iwmc3200wifi/sdio.c | 6 +----- drivers/net/wireless/iwmc3200wifi/wext.c | 4 ++-- 6 files changed, 39 insertions(+), 32 deletions(-) (limited to 'drivers/net/wireless/iwmc3200wifi') diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.c b/drivers/net/wireless/iwmc3200wifi/cfg80211.c index 0cdd7ef68b78..d0629d4757d7 100644 --- a/drivers/net/wireless/iwmc3200wifi/cfg80211.c +++ b/drivers/net/wireless/iwmc3200wifi/cfg80211.c @@ -500,6 +500,28 @@ static int iwm_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) return 0; } +static int iwm_cfg80211_set_txpower(struct wiphy *wiphy, + enum tx_power_setting type, int dbm) +{ + switch (type) { + case TX_POWER_AUTOMATIC: + return 0; + default: + return -EOPNOTSUPP; + } + + return 0; +} + +static int iwm_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm) +{ + struct iwm_priv *iwm = wiphy_to_iwm(wiphy); + + *dbm = iwm->txpower; + + return 0; +} + static struct cfg80211_ops iwm_cfg80211_ops = { .change_virtual_intf = iwm_cfg80211_change_iface, .add_key = iwm_cfg80211_add_key, @@ -510,6 +532,8 @@ static struct cfg80211_ops iwm_cfg80211_ops = { .set_wiphy_params = iwm_cfg80211_set_wiphy_params, .join_ibss = iwm_cfg80211_join_ibss, .leave_ibss = iwm_cfg80211_leave_ibss, + .set_tx_power = iwm_cfg80211_set_txpower, + .get_tx_power = iwm_cfg80211_get_txpower, }; struct wireless_dev *iwm_wdev_alloc(int sizeof_bus, struct device *dev) diff --git a/drivers/net/wireless/iwmc3200wifi/iwm.h b/drivers/net/wireless/iwmc3200wifi/iwm.h index 90b05d999635..4da57f737f27 100644 --- a/drivers/net/wireless/iwmc3200wifi/iwm.h +++ b/drivers/net/wireless/iwmc3200wifi/iwm.h @@ -184,10 +184,6 @@ struct iwm_key { #define IWM_STATUS_ASSOCIATING 3 #define IWM_STATUS_ASSOCIATED 4 -#define IWM_RADIO_RFKILL_OFF 0 -#define IWM_RADIO_RFKILL_HW 1 -#define IWM_RADIO_RFKILL_SW 2 - struct iwm_tx_queue { int id; struct sk_buff_head queue; @@ -221,7 +217,6 @@ struct iwm_priv { struct iwm_conf conf; unsigned long status; - unsigned long radio; struct list_head pending_notif; wait_queue_head_t notif_queue; @@ -240,6 +235,7 @@ struct iwm_priv { u8 bssid[ETH_ALEN]; u8 channel; u16 rate; + u32 txpower; struct iwm_sta_info sta_table[IWM_STA_TABLE_NUM]; struct list_head bss_list; @@ -290,7 +286,6 @@ struct iwm_priv { struct timer_list watchdog; struct work_struct reset_worker; struct mutex mutex; - struct rfkill *rfkill; char private[0] __attribute__((__aligned__(NETDEV_ALIGN))); }; diff --git a/drivers/net/wireless/iwmc3200wifi/netdev.c b/drivers/net/wireless/iwmc3200wifi/netdev.c index d4deb4b471e5..e94e96955b99 100644 --- a/drivers/net/wireless/iwmc3200wifi/netdev.c +++ b/drivers/net/wireless/iwmc3200wifi/netdev.c @@ -55,23 +55,15 @@ static int iwm_open(struct net_device *ndev) { struct iwm_priv *iwm = ndev_to_iwm(ndev); - int ret = 0; - - if (!test_bit(IWM_RADIO_RFKILL_SW, &iwm->radio)) - ret = iwm_up(iwm); - return ret; + return iwm_up(iwm); } static int iwm_stop(struct net_device *ndev) { struct iwm_priv *iwm = ndev_to_iwm(ndev); - int ret = 0; - - if (!test_bit(IWM_RADIO_RFKILL_SW, &iwm->radio)) - ret = iwm_down(iwm); - return ret; + return iwm_down(iwm); } /* diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index 49a8be7c5396..55871da695a9 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c @@ -143,17 +143,18 @@ static int iwm_ntf_init_complete(struct iwm_priv *iwm, u8 *buf, unsigned long buf_size, struct iwm_wifi_cmd *cmd) { + struct wiphy *wiphy = iwm_to_wiphy(iwm); struct iwm_umac_notif_init_complete *init_complete = (struct iwm_umac_notif_init_complete *)(buf); u16 status = le16_to_cpu(init_complete->status); + bool blocked = (status == UMAC_NTFY_INIT_COMPLETE_STATUS_ERR); - if (status == UMAC_NTFY_INIT_COMPLETE_STATUS_ERR) { + if (blocked) IWM_DBG_NTF(iwm, DBG, "Hardware rf kill is on (radio off)\n"); - set_bit(IWM_RADIO_RFKILL_HW, &iwm->radio); - } else { + else IWM_DBG_NTF(iwm, DBG, "Hardware rf kill is off (radio on)\n"); - clear_bit(IWM_RADIO_RFKILL_HW, &iwm->radio); - } + + wiphy_rfkill_set_hw_state(wiphy, blocked); return 0; } @@ -875,6 +876,7 @@ static int iwm_ntf_statistics(struct iwm_priv *iwm, u8 *buf, /* UMAC passes rate info multiplies by 2 */ iwm->rate = max_rate >> 1; } + iwm->txpower = le32_to_cpu(stats->tx_power); wstats->status = 0; @@ -1015,6 +1017,7 @@ static int iwm_ntf_wifi_if_wrapper(struct iwm_priv *iwm, u8 *buf, static int iwm_ntf_card_state(struct iwm_priv *iwm, u8 *buf, unsigned long buf_size, struct iwm_wifi_cmd *cmd) { + struct wiphy *wiphy = iwm_to_wiphy(iwm); struct iwm_lmac_card_state *state = (struct iwm_lmac_card_state *) (buf + sizeof(struct iwm_umac_wifi_in_hdr)); u32 flags = le32_to_cpu(state->flags); @@ -1023,10 +1026,7 @@ static int iwm_ntf_card_state(struct iwm_priv *iwm, u8 *buf, flags & IWM_CARD_STATE_HW_DISABLED ? "ON" : "OFF", flags & IWM_CARD_STATE_CTKILL_DISABLED ? "ON" : "OFF"); - if (flags & IWM_CARD_STATE_HW_DISABLED) - set_bit(IWM_RADIO_RFKILL_HW, &iwm->radio); - else - clear_bit(IWM_RADIO_RFKILL_HW, &iwm->radio); + wiphy_rfkill_set_hw_state(wiphy, flags & IWM_CARD_STATE_HW_DISABLED); return 0; } diff --git a/drivers/net/wireless/iwmc3200wifi/sdio.c b/drivers/net/wireless/iwmc3200wifi/sdio.c index 916681837fd2..b93f620ee4f1 100644 --- a/drivers/net/wireless/iwmc3200wifi/sdio.c +++ b/drivers/net/wireless/iwmc3200wifi/sdio.c @@ -506,11 +506,7 @@ static struct sdio_driver iwm_sdio_driver = { static int __init iwm_sdio_init_module(void) { - int ret; - - ret = sdio_register_driver(&iwm_sdio_driver); - - return ret; + return sdio_register_driver(&iwm_sdio_driver); } static void __exit iwm_sdio_exit_module(void) diff --git a/drivers/net/wireless/iwmc3200wifi/wext.c b/drivers/net/wireless/iwmc3200wifi/wext.c index 3062f37bbe95..973457383c11 100644 --- a/drivers/net/wireless/iwmc3200wifi/wext.c +++ b/drivers/net/wireless/iwmc3200wifi/wext.c @@ -452,8 +452,8 @@ static const iw_handler iwm_handlers[] = (iw_handler) cfg80211_wext_giwrts, /* SIOCGIWRTS */ (iw_handler) cfg80211_wext_siwfrag, /* SIOCSIWFRAG */ (iw_handler) cfg80211_wext_giwfrag, /* SIOCGIWFRAG */ - (iw_handler) NULL, /* SIOCSIWTXPOW */ - (iw_handler) NULL, /* SIOCGIWTXPOW */ + (iw_handler) cfg80211_wext_siwtxpower, /* SIOCSIWTXPOW */ + (iw_handler) cfg80211_wext_giwtxpower, /* SIOCGIWTXPOW */ (iw_handler) NULL, /* SIOCSIWRETRY */ (iw_handler) NULL, /* SIOCGIWRETRY */ (iw_handler) cfg80211_wext_siwencode, /* SIOCSIWENCODE */ -- cgit v1.2.3 From bc92afd92088ab41223383cc6863ab4792533c54 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 1 Jul 2009 21:26:57 +0200 Subject: cfg80211: implement iwpower Just on/off and timeout, and with a hacky cfg80211 method until we figure out what we want, though this is probably sufficient as we want to use pm_qos for wifi everywhere. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/cfg80211.c | 22 +++++++++ drivers/net/wireless/iwmc3200wifi/wext.c | 47 +------------------ include/net/cfg80211.h | 13 ++++++ net/mac80211/Kconfig | 16 ------- net/mac80211/cfg.c | 26 +++++++++++ net/mac80211/mlme.c | 5 -- net/mac80211/wext.c | 70 +--------------------------- net/wireless/Kconfig | 16 +++++++ net/wireless/core.c | 11 ++++- net/wireless/wext-compat.c | 60 ++++++++++++++++++++++++ 10 files changed, 151 insertions(+), 135 deletions(-) (limited to 'drivers/net/wireless/iwmc3200wifi') diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.c b/drivers/net/wireless/iwmc3200wifi/cfg80211.c index d0629d4757d7..54bebba8e27e 100644 --- a/drivers/net/wireless/iwmc3200wifi/cfg80211.c +++ b/drivers/net/wireless/iwmc3200wifi/cfg80211.c @@ -522,6 +522,27 @@ static int iwm_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm) return 0; } +static int iwm_cfg80211_set_power_mgmt(struct wiphy *wiphy, + struct net_device *dev, + bool enabled, int timeout) +{ + struct iwm_priv *iwm = wiphy_to_iwm(wiphy); + u32 power_index; + + if (enabled) + power_index = IWM_POWER_INDEX_DEFAULT; + else + power_index = IWM_POWER_INDEX_MIN; + + if (power_index == iwm->conf.power_index) + return 0; + + iwm->conf.power_index = power_index; + + return iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, + CFG_POWER_INDEX, iwm->conf.power_index); +} + static struct cfg80211_ops iwm_cfg80211_ops = { .change_virtual_intf = iwm_cfg80211_change_iface, .add_key = iwm_cfg80211_add_key, @@ -534,6 +555,7 @@ static struct cfg80211_ops iwm_cfg80211_ops = { .leave_ibss = iwm_cfg80211_leave_ibss, .set_tx_power = iwm_cfg80211_set_txpower, .get_tx_power = iwm_cfg80211_get_txpower, + .set_power_mgmt = iwm_cfg80211_set_power_mgmt, }; struct wireless_dev *iwm_wdev_alloc(int sizeof_bus, struct device *dev) diff --git a/drivers/net/wireless/iwmc3200wifi/wext.c b/drivers/net/wireless/iwmc3200wifi/wext.c index 973457383c11..2e7eaf96cf93 100644 --- a/drivers/net/wireless/iwmc3200wifi/wext.c +++ b/drivers/net/wireless/iwmc3200wifi/wext.c @@ -238,49 +238,6 @@ static int iwm_set_wpa_version(struct iwm_priv *iwm, u8 wpa_version) return 0; } -static int iwm_wext_siwpower(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *wrq, char *extra) -{ - struct iwm_priv *iwm = ndev_to_iwm(dev); - u32 power_index; - - if (wrq->disabled) { - power_index = IWM_POWER_INDEX_MIN; - goto set; - } else - power_index = IWM_POWER_INDEX_DEFAULT; - - switch (wrq->flags & IW_POWER_MODE) { - case IW_POWER_ON: - case IW_POWER_MODE: - case IW_POWER_ALL_R: - break; - default: - return -EINVAL; - } - - set: - if (power_index == iwm->conf.power_index) - return 0; - - iwm->conf.power_index = power_index; - - return iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, - CFG_POWER_INDEX, iwm->conf.power_index); -} - -static int iwm_wext_giwpower(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct iwm_priv *iwm = ndev_to_iwm(dev); - - wrqu->power.disabled = (iwm->conf.power_index == IWM_POWER_INDEX_MIN); - - return 0; -} - static int iwm_set_key_mgt(struct iwm_priv *iwm, u8 key_mgt) { u8 *auth_type = &iwm->umac_profile->sec.auth_type; @@ -458,8 +415,8 @@ static const iw_handler iwm_handlers[] = (iw_handler) NULL, /* SIOCGIWRETRY */ (iw_handler) cfg80211_wext_siwencode, /* SIOCSIWENCODE */ (iw_handler) cfg80211_wext_giwencode, /* SIOCGIWENCODE */ - (iw_handler) iwm_wext_siwpower, /* SIOCSIWPOWER */ - (iw_handler) iwm_wext_giwpower, /* SIOCGIWPOWER */ + (iw_handler) cfg80211_wext_siwpower, /* SIOCSIWPOWER */ + (iw_handler) cfg80211_wext_giwpower, /* SIOCGIWPOWER */ (iw_handler) NULL, /* -- hole -- */ (iw_handler) NULL, /* -- hole -- */ (iw_handler) NULL, /* SIOCSIWGENIE */ diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 07085216532d..82b7d804f6da 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1023,6 +1023,10 @@ struct cfg80211_ops { #ifdef CONFIG_NL80211_TESTMODE int (*testmode_cmd)(struct wiphy *wiphy, void *data, int len); #endif + + /* some temporary stuff to finish wext */ + int (*set_power_mgmt)(struct wiphy *wiphy, struct net_device *dev, + bool enabled, int timeout); }; /* @@ -1262,6 +1266,8 @@ struct wireless_dev { u8 bssid[ETH_ALEN]; u8 ssid[IEEE80211_MAX_SSID_LEN]; s8 default_key, default_mgmt_key; + bool ps; + int ps_timeout; } wext; #endif }; @@ -1606,6 +1612,13 @@ int cfg80211_wext_giwtxpower(struct net_device *dev, struct iw_request_info *info, union iwreq_data *data, char *keybuf); +int cfg80211_wext_siwpower(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *wrq, char *extra); +int cfg80211_wext_giwpower(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *wrq, char *extra); + /* * callbacks for asynchronous cfg80211 methods, notification * functions and BSS handling helpers diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index ba2643a43c73..41a32cd919af 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig @@ -14,22 +14,6 @@ config MAC80211 comment "CFG80211 needs to be enabled for MAC80211" depends on CFG80211=n -config MAC80211_DEFAULT_PS - bool "enable powersave by default" - depends on MAC80211 - default y - help - This option enables powersave mode by default. - - If this causes your applications to misbehave you should fix your - applications instead -- they need to register their network - latency requirement, see Documentation/power/pm_qos_interface.txt. - -config MAC80211_DEFAULT_PS_VALUE - int - default 1 if MAC80211_DEFAULT_PS - default 0 - menu "Rate control algorithm selection" depends on MAC80211 != n diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 03de4024597a..8c7b2cdbeeda 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1388,6 +1388,31 @@ int ieee80211_testmode_cmd(struct wiphy *wiphy, void *data, int len) } #endif +static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, + bool enabled, int timeout) +{ + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_conf *conf = &local->hw.conf; + + if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS)) + return -EOPNOTSUPP; + + if (enabled == sdata->u.mgd.powersave && + timeout == conf->dynamic_ps_timeout) + return 0; + + sdata->u.mgd.powersave = enabled; + conf->dynamic_ps_timeout = timeout; + + if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS) + ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); + + ieee80211_recalc_ps(local, -1); + + return 0; +} + struct cfg80211_ops mac80211_config_ops = { .add_virtual_intf = ieee80211_add_iface, .del_virtual_intf = ieee80211_del_iface, @@ -1431,4 +1456,5 @@ struct cfg80211_ops mac80211_config_ops = { .get_tx_power = ieee80211_get_tx_power, .rfkill_poll = ieee80211_rfkill_poll, CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd) + .set_power_mgmt = ieee80211_set_power_mgmt, }; diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index fbb93a70ddc7..2a7860009f9c 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2360,11 +2360,6 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) ifmgd->flags |= IEEE80211_STA_WMM_ENABLED; hw_flags = sdata->local->hw.flags; - - if (hw_flags & IEEE80211_HW_SUPPORTS_PS) { - ifmgd->powersave = CONFIG_MAC80211_DEFAULT_PS_VALUE; - sdata->local->hw.conf.dynamic_ps_timeout = 500; - } } /* configuration hooks */ diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index d4e61dc903e8..f77929802c7a 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c @@ -255,72 +255,6 @@ static int ieee80211_ioctl_giwrate(struct net_device *dev, return 0; } -static int ieee80211_ioctl_siwpower(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *wrq, - char *extra) -{ - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct ieee80211_conf *conf = &local->hw.conf; - int timeout = 0; - bool ps; - - if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS)) - return -EOPNOTSUPP; - - if (sdata->vif.type != NL80211_IFTYPE_STATION) - return -EINVAL; - - if (wrq->disabled) { - ps = false; - timeout = 0; - goto set; - } - - switch (wrq->flags & IW_POWER_MODE) { - case IW_POWER_ON: /* If not specified */ - case IW_POWER_MODE: /* If set all mask */ - case IW_POWER_ALL_R: /* If explicitely state all */ - ps = true; - break; - default: /* Otherwise we ignore */ - return -EINVAL; - } - - if (wrq->flags & ~(IW_POWER_MODE | IW_POWER_TIMEOUT)) - return -EINVAL; - - if (wrq->flags & IW_POWER_TIMEOUT) - timeout = wrq->value / 1000; - - set: - if (ps == sdata->u.mgd.powersave && timeout == conf->dynamic_ps_timeout) - return 0; - - sdata->u.mgd.powersave = ps; - conf->dynamic_ps_timeout = timeout; - - if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS) - ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); - - ieee80211_recalc_ps(local, -1); - - return 0; -} - -static int ieee80211_ioctl_giwpower(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - - wrqu->power.disabled = !sdata->u.mgd.powersave; - - return 0; -} - /* Get wireless statistics. Called by /proc/net/wireless and by SIOCGIWSTATS */ static struct iw_statistics *ieee80211_get_wireless_stats(struct net_device *dev) { @@ -436,8 +370,8 @@ static const iw_handler ieee80211_handler[] = (iw_handler) cfg80211_wext_giwretry, /* SIOCGIWRETRY */ (iw_handler) cfg80211_wext_siwencode, /* SIOCSIWENCODE */ (iw_handler) cfg80211_wext_giwencode, /* SIOCGIWENCODE */ - (iw_handler) ieee80211_ioctl_siwpower, /* SIOCSIWPOWER */ - (iw_handler) ieee80211_ioctl_giwpower, /* SIOCGIWPOWER */ + (iw_handler) cfg80211_wext_siwpower, /* SIOCSIWPOWER */ + (iw_handler) cfg80211_wext_giwpower, /* SIOCGIWPOWER */ (iw_handler) NULL, /* -- hole -- */ (iw_handler) NULL, /* -- hole -- */ (iw_handler) cfg80211_wext_siwgenie, /* SIOCSIWGENIE */ diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig index 040263118a20..c6031d5b135f 100644 --- a/net/wireless/Kconfig +++ b/net/wireless/Kconfig @@ -26,6 +26,22 @@ config CFG80211_REG_DEBUG If unsure, say N. +config CFG80211_DEFAULT_PS + bool "enable powersave by default" + depends on CFG80211 + default y + help + This option enables powersave mode by default. + + If this causes your applications to misbehave you should fix your + applications instead -- they need to register their network + latency requirement, see Documentation/power/pm_qos_interface.txt. + +config CFG80211_DEFAULT_PS_VALUE + int + default 1 if CFG80211_DEFAULT_PS + default 0 + config CFG80211_DEBUGFS bool "cfg80211 DebugFS entries" depends on CFG80211 && DEBUG_FS diff --git a/net/wireless/core.c b/net/wireless/core.c index e2f80dd0e4a6..413d291d07d7 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -550,12 +550,21 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, } wdev->netdev = dev; wdev->sme_state = CFG80211_SME_IDLE; + mutex_unlock(&rdev->devlist_mtx); #ifdef CONFIG_WIRELESS_EXT wdev->wext.default_key = -1; wdev->wext.default_mgmt_key = -1; wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC; + wdev->wext.ps = CONFIG_CFG80211_DEFAULT_PS_VALUE; + wdev->wext.ps_timeout = 500; + if (rdev->ops->set_power_mgmt) + if (rdev->ops->set_power_mgmt(wdev->wiphy, dev, + wdev->wext.ps, + wdev->wext.ps_timeout)) { + /* assume this means it's off */ + wdev->wext.ps = false; + } #endif - mutex_unlock(&rdev->devlist_mtx); break; case NETDEV_GOING_DOWN: if (!wdev->ssid_len) diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index 02f052fc1808..2e1ab78fb0d7 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c @@ -987,3 +987,63 @@ int cfg80211_wext_giwauth(struct net_device *dev, return -EOPNOTSUPP; } EXPORT_SYMBOL_GPL(cfg80211_wext_giwauth); + +int cfg80211_wext_siwpower(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *wrq, char *extra) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); + bool ps = wdev->wext.ps; + int timeout = wdev->wext.ps_timeout; + int err; + + if (wdev->iftype != NL80211_IFTYPE_STATION) + return -EINVAL; + + if (!rdev->ops->set_power_mgmt) + return -EOPNOTSUPP; + + if (wrq->disabled) { + ps = false; + } else { + switch (wrq->flags & IW_POWER_MODE) { + case IW_POWER_ON: /* If not specified */ + case IW_POWER_MODE: /* If set all mask */ + case IW_POWER_ALL_R: /* If explicitely state all */ + ps = true; + break; + default: /* Otherwise we ignore */ + return -EINVAL; + } + + if (wrq->flags & ~(IW_POWER_MODE | IW_POWER_TIMEOUT)) + return -EINVAL; + + if (wrq->flags & IW_POWER_TIMEOUT) + timeout = wrq->value / 1000; + } + + err = rdev->ops->set_power_mgmt(wdev->wiphy, dev, ps, timeout); + if (err) + return err; + + wdev->wext.ps = ps; + wdev->wext.ps_timeout = timeout; + + return 0; + +} +EXPORT_SYMBOL_GPL(cfg80211_wext_siwpower); + +int cfg80211_wext_giwpower(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *wrq, char *extra) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + + wrq->disabled = !wdev->wext.ps; + + return 0; +} +EXPORT_SYMBOL_GPL(cfg80211_wext_giwpower); -- cgit v1.2.3 From dd13fd649879b6230be5d855e00c286c5e60f354 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Thu, 25 Jun 2009 18:28:30 +0800 Subject: iwmc3200wifi: replace netif_rx with netif_rx_ni The patch uses netif_rx_ni() over netif_rx() to post buffers to upper network code because it is always scheduled in a workqueue. The problem was first observed from a dynamic ticks warning: "NOHZ: local_softirq_pending ..." Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/rx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless/iwmc3200wifi') diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index 55871da695a9..5d2239f59bc3 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c @@ -1373,7 +1373,7 @@ static void iwm_rx_process_packet(struct iwm_priv *iwm, ndev->stats.rx_packets++; ndev->stats.rx_bytes += skb->len; - if (netif_rx(skb) == NET_RX_DROP) { + if (netif_rx_ni(skb) == NET_RX_DROP) { IWM_ERR(iwm, "Packet dropped\n"); ndev->stats.rx_dropped++; } -- cgit v1.2.3 From fd2c7fe0b4dedc34ea0a2a72e00648bd2b8c7c3a Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Thu, 25 Jun 2009 18:28:31 +0800 Subject: iwmc3200wifi: simplify calibration map The patch simplifies calibration map by combining the init_calib_map and periodic_calib_map into one calib_map in struct iwm_conf. Now the initial calibration map is stored in the lower 16 bits of calib_map and the periodic calibration map is stored in the higher 16 bits. Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/fw.c | 19 +++++++++++-------- drivers/net/wireless/iwmc3200wifi/iwm.h | 3 +-- drivers/net/wireless/iwmc3200wifi/lmac.h | 4 ++++ drivers/net/wireless/iwmc3200wifi/main.c | 6 +----- 4 files changed, 17 insertions(+), 15 deletions(-) (limited to 'drivers/net/wireless/iwmc3200wifi') diff --git a/drivers/net/wireless/iwmc3200wifi/fw.c b/drivers/net/wireless/iwmc3200wifi/fw.c index ec1a15a5a0e4..c58f614ce6d8 100644 --- a/drivers/net/wireless/iwmc3200wifi/fw.c +++ b/drivers/net/wireless/iwmc3200wifi/fw.c @@ -275,6 +275,7 @@ static int iwm_load_lmac(struct iwm_priv *iwm, const char *img_name) */ int iwm_load_fw(struct iwm_priv *iwm) { + unsigned long init_calib_map, periodic_calib_map; int ret; /* We first start downloading the UMAC */ @@ -315,23 +316,25 @@ int iwm_load_fw(struct iwm_priv *iwm) return ret; } + init_calib_map = iwm->conf.calib_map & IWM_CALIB_MAP_INIT_MSK; + periodic_calib_map = IWM_CALIB_MAP_PER_LMAC(iwm->conf.calib_map); + #ifdef CONFIG_IWM_B0_HW_SUPPORT if (iwm->conf.hw_b0) { - clear_bit(PHY_CALIBRATE_RX_IQ_CMD, &iwm->conf.init_calib_map); - clear_bit(PHY_CALIBRATE_RX_IQ_CMD, - &iwm->conf.periodic_calib_map); + clear_bit(PHY_CALIBRATE_RX_IQ_CMD, &init_calib_map); + clear_bit(PHY_CALIBRATE_RX_IQ_CMD, &periodic_calib_map); } #endif /* Read RX IQ calibration result from EEPROM */ - if (test_bit(PHY_CALIBRATE_RX_IQ_CMD, &iwm->conf.init_calib_map)) { + if (test_bit(PHY_CALIBRATE_RX_IQ_CMD, &init_calib_map)) { iwm_store_rxiq_calib_result(iwm); set_bit(PHY_CALIBRATE_RX_IQ_CMD, &iwm->calib_done_map); } iwm_send_prio_table(iwm); - iwm_send_init_calib_cfg(iwm, iwm->conf.init_calib_map); + iwm_send_init_calib_cfg(iwm, init_calib_map); - while (iwm->calib_done_map != iwm->conf.init_calib_map) { + while (iwm->calib_done_map != init_calib_map) { ret = iwm_notif_handle(iwm, CALIBRATION_RES_NOTIFICATION, IWM_SRC_LMAC, WAIT_NOTIF_TIMEOUT); if (ret) { @@ -340,7 +343,7 @@ int iwm_load_fw(struct iwm_priv *iwm) } IWM_DBG_FW(iwm, DBG, "Got calibration result. calib_done_map: " "0x%lx, requested calibrations: 0x%lx\n", - iwm->calib_done_map, iwm->conf.init_calib_map); + iwm->calib_done_map, init_calib_map); } /* Handle LMAC CALIBRATION_COMPLETE notification */ @@ -378,7 +381,7 @@ int iwm_load_fw(struct iwm_priv *iwm) iwm_send_prio_table(iwm); iwm_send_calib_results(iwm); - iwm_send_periodic_calib_cfg(iwm, iwm->conf.periodic_calib_map); + iwm_send_periodic_calib_cfg(iwm, periodic_calib_map); return 0; diff --git a/drivers/net/wireless/iwmc3200wifi/iwm.h b/drivers/net/wireless/iwmc3200wifi/iwm.h index 4da57f737f27..1bad78f81350 100644 --- a/drivers/net/wireless/iwmc3200wifi/iwm.h +++ b/drivers/net/wireless/iwmc3200wifi/iwm.h @@ -65,8 +65,7 @@ struct iwm_conf { u32 sdio_ior_timeout; - unsigned long init_calib_map; - unsigned long periodic_calib_map; + unsigned long calib_map; bool reset_on_fatal_err; bool auto_connect; bool wimax_not_present; diff --git a/drivers/net/wireless/iwmc3200wifi/lmac.h b/drivers/net/wireless/iwmc3200wifi/lmac.h index db2e5eea1895..19213e165f5f 100644 --- a/drivers/net/wireless/iwmc3200wifi/lmac.h +++ b/drivers/net/wireless/iwmc3200wifi/lmac.h @@ -396,6 +396,10 @@ enum { CALIBRATION_CMD_NUM, }; +#define IWM_CALIB_MAP_INIT_MSK 0xFFFF +#define IWM_CALIB_MAP_PER_LMAC(m) ((m & 0xFF0000) >> 16) +#define IWM_CALIB_MAP_PER_UMAC(m) ((m & 0xFF000000) >> 24) + struct iwm_lmac_calib_hdr { u8 opcode; u8 first_grp; diff --git a/drivers/net/wireless/iwmc3200wifi/main.c b/drivers/net/wireless/iwmc3200wifi/main.c index 930056b013f3..4fedb45d62b3 100644 --- a/drivers/net/wireless/iwmc3200wifi/main.c +++ b/drivers/net/wireless/iwmc3200wifi/main.c @@ -53,11 +53,7 @@ static struct iwm_conf def_iwm_conf = { .sdio_ior_timeout = 5000, - .init_calib_map = BIT(PHY_CALIBRATE_DC_CMD) | - BIT(PHY_CALIBRATE_LO_CMD) | - BIT(PHY_CALIBRATE_TX_IQ_CMD) | - BIT(PHY_CALIBRATE_RX_IQ_CMD), - .periodic_calib_map = BIT(PHY_CALIBRATE_DC_CMD) | + .calib_map = BIT(PHY_CALIBRATE_DC_CMD) | BIT(PHY_CALIBRATE_LO_CMD) | BIT(PHY_CALIBRATE_TX_IQ_CMD) | BIT(PHY_CALIBRATE_RX_IQ_CMD) | -- cgit v1.2.3 From 19a42803f310ff60ce5a6c02992762068a01394a Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Thu, 25 Jun 2009 18:28:32 +0800 Subject: iwmc3200wifi: remove B0 hardware support The patch removes B0 hardware support. Nobody is using it anyway. Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/eeprom.c | 4 ---- drivers/net/wireless/iwmc3200wifi/fw.c | 6 ------ drivers/net/wireless/iwmc3200wifi/iwm.h | 5 ----- drivers/net/wireless/iwmc3200wifi/main.c | 7 ------- drivers/net/wireless/iwmc3200wifi/rx.c | 7 ------- 5 files changed, 29 deletions(-) (limited to 'drivers/net/wireless/iwmc3200wifi') diff --git a/drivers/net/wireless/iwmc3200wifi/eeprom.c b/drivers/net/wireless/iwmc3200wifi/eeprom.c index 0f34b84fd2eb..365910fbe01e 100644 --- a/drivers/net/wireless/iwmc3200wifi/eeprom.c +++ b/drivers/net/wireless/iwmc3200wifi/eeprom.c @@ -156,10 +156,6 @@ int iwm_eeprom_init(struct iwm_priv *iwm) return -ENOMEM; for (i = IWM_EEPROM_FIRST; i < IWM_EEPROM_LAST; i++) { -#ifdef CONFIG_IWM_B0_HW_SUPPORT - if (iwm->conf.hw_b0 && (i >= IWM_EEPROM_INDIRECT_OFFSET)) - break; -#endif ret = iwm_eeprom_read(iwm, i); if (ret < 0) { IWM_ERR(iwm, "Couldn't read eeprom entry #%d: %s\n", diff --git a/drivers/net/wireless/iwmc3200wifi/fw.c b/drivers/net/wireless/iwmc3200wifi/fw.c index c58f614ce6d8..0f32cab9ced4 100644 --- a/drivers/net/wireless/iwmc3200wifi/fw.c +++ b/drivers/net/wireless/iwmc3200wifi/fw.c @@ -319,12 +319,6 @@ int iwm_load_fw(struct iwm_priv *iwm) init_calib_map = iwm->conf.calib_map & IWM_CALIB_MAP_INIT_MSK; periodic_calib_map = IWM_CALIB_MAP_PER_LMAC(iwm->conf.calib_map); -#ifdef CONFIG_IWM_B0_HW_SUPPORT - if (iwm->conf.hw_b0) { - clear_bit(PHY_CALIBRATE_RX_IQ_CMD, &init_calib_map); - clear_bit(PHY_CALIBRATE_RX_IQ_CMD, &periodic_calib_map); - } -#endif /* Read RX IQ calibration result from EEPROM */ if (test_bit(PHY_CALIBRATE_RX_IQ_CMD, &init_calib_map)) { iwm_store_rxiq_calib_result(iwm); diff --git a/drivers/net/wireless/iwmc3200wifi/iwm.h b/drivers/net/wireless/iwmc3200wifi/iwm.h index 1bad78f81350..79d9d89d47ae 100644 --- a/drivers/net/wireless/iwmc3200wifi/iwm.h +++ b/drivers/net/wireless/iwmc3200wifi/iwm.h @@ -52,8 +52,6 @@ #define IWM_COPYRIGHT "Copyright(c) 2009 Intel Corporation" #define IWM_AUTHOR "" -#define CONFIG_IWM_B0_HW_SUPPORT 1 - #define IWM_SRC_LMAC UMAC_HDI_IN_SOURCE_FHRX #define IWM_SRC_UDMA UMAC_HDI_IN_SOURCE_UDMA #define IWM_SRC_UMAC UMAC_HDI_IN_SOURCE_FW @@ -86,9 +84,6 @@ struct iwm_conf { u8 ibss_channel; u8 mac_addr[ETH_ALEN]; -#ifdef CONFIG_IWM_B0_HW_SUPPORT - bool hw_b0; -#endif }; enum { diff --git a/drivers/net/wireless/iwmc3200wifi/main.c b/drivers/net/wireless/iwmc3200wifi/main.c index 4fedb45d62b3..484f110151b7 100644 --- a/drivers/net/wireless/iwmc3200wifi/main.c +++ b/drivers/net/wireless/iwmc3200wifi/main.c @@ -515,13 +515,6 @@ static int iwm_channels_init(struct iwm_priv *iwm) { int ret; -#ifdef CONFIG_IWM_B0_HW_SUPPORT - if (iwm->conf.hw_b0) { - IWM_INFO(iwm, "Workaround EEPROM channels for B0 hardware\n"); - return 0; - } -#endif - ret = iwm_send_umac_channel_list(iwm); if (ret) { IWM_ERR(iwm, "Send channel list failed\n"); diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index 5d2239f59bc3..3909477fb3bf 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c @@ -924,13 +924,6 @@ static int iwm_ntf_eeprom_proxy(struct iwm_priv *iwm, u8 *buf, if ((hdr_offset + hdr_len) > IWM_EEPROM_LEN) return -EINVAL; -#ifdef CONFIG_IWM_B0_HW_SUPPORT - if (hdr_offset == IWM_EEPROM_SKU_CAP_OFF) { - if (eeprom_proxy->buf[0] == 0xff) - iwm->conf.hw_b0 = 1; - } -#endif - switch (hdr_type) { case IWM_UMAC_CMD_EEPROM_TYPE_READ: memcpy(iwm->eeprom + hdr_offset, eeprom_proxy->buf, hdr_len); -- cgit v1.2.3 From 1cc589b9e7d95888bb8cc806c210d8ab5371d40f Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Thu, 16 Jul 2009 17:34:06 +0800 Subject: iwmc3200wifi: fix UMAC INIT_COMPLETE notification handling The patch fixes the missing UMAC iwm_umac_wifi_in_hdr header in the UMAC INIT_COMPLETE (iwm_umac_notif_init_complete) notification. Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/rx.c | 1 - drivers/net/wireless/iwmc3200wifi/umac.h | 6 ++++++ 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless/iwmc3200wifi') diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index 3909477fb3bf..59ef69ca3ca7 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c @@ -102,7 +102,6 @@ static int iwm_ntf_error(struct iwm_priv *iwm, u8 *buf, error = (struct iwm_umac_notif_error *)buf; fw_err = &error->err; - IWM_ERR(iwm, "%cMAC FW ERROR:\n", (le32_to_cpu(fw_err->category) == UMAC_SYS_ERR_CAT_LMAC) ? 'L' : 'U'); IWM_ERR(iwm, "\tCategory: %d\n", le32_to_cpu(fw_err->category)); diff --git a/drivers/net/wireless/iwmc3200wifi/umac.h b/drivers/net/wireless/iwmc3200wifi/umac.h index 0af2a3c76281..c5a14ae3160a 100644 --- a/drivers/net/wireless/iwmc3200wifi/umac.h +++ b/drivers/net/wireless/iwmc3200wifi/umac.h @@ -615,6 +615,7 @@ struct iwm_umac_notif_alive { } __attribute__ ((packed)); struct iwm_umac_notif_init_complete { + struct iwm_umac_wifi_in_hdr hdr; __le16 status; __le16 reserved; } __attribute__ ((packed)); @@ -643,6 +644,11 @@ struct iwm_fw_error_hdr { __le32 umac_status; __le32 lmac_status; __le32 sdio_status; + __le32 dbm_sample_ctrl; + __le32 dbm_buf_base; + __le32 dbm_buf_end; + __le32 dbm_buf_write_ptr; + __le32 dbm_buf_cycle_cnt; } __attribute__ ((packed)); struct iwm_umac_notif_error { -- cgit v1.2.3 From 3a0e4851c97328ee455a57cb3e4097bb43934a87 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Thu, 16 Jul 2009 17:34:07 +0800 Subject: iwmc3200wifi: hardware does not support IP checksum The iwmc3200wifi hardware doesn't support IP checksum. So mark the skb->ip_summed to CHECKSUM_NONE instead of CHECKSUM_UNNECESSARY. Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/rx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless/iwmc3200wifi') diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index 59ef69ca3ca7..9fb498b514e1 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c @@ -1359,7 +1359,7 @@ static void iwm_rx_process_packet(struct iwm_priv *iwm, skb->dev = iwm_to_ndev(iwm); skb->protocol = eth_type_trans(skb, ndev); - skb->ip_summed = CHECKSUM_UNNECESSARY; + skb->ip_summed = CHECKSUM_NONE; memset(skb->cb, 0, sizeof(skb->cb)); ndev->stats.rx_packets++; -- cgit v1.2.3 From 49b7772776359b8306ce740bfc52d32b344adc83 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Thu, 16 Jul 2009 17:34:08 +0800 Subject: iwmc3200wifi: set cipher_suites before registering wiphy We need to specify all the cipher suites we supported. Otherwise cfg80211_validate_key_settings() will fail when we are setting keys. Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/cfg80211.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers/net/wireless/iwmc3200wifi') diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.c b/drivers/net/wireless/iwmc3200wifi/cfg80211.c index 54bebba8e27e..0aa389564c71 100644 --- a/drivers/net/wireless/iwmc3200wifi/cfg80211.c +++ b/drivers/net/wireless/iwmc3200wifi/cfg80211.c @@ -558,6 +558,13 @@ static struct cfg80211_ops iwm_cfg80211_ops = { .set_power_mgmt = iwm_cfg80211_set_power_mgmt, }; +static const u32 cipher_suites[] = { + WLAN_CIPHER_SUITE_WEP40, + WLAN_CIPHER_SUITE_WEP104, + WLAN_CIPHER_SUITE_TKIP, + WLAN_CIPHER_SUITE_CCMP, +}; + struct wireless_dev *iwm_wdev_alloc(int sizeof_bus, struct device *dev) { int ret = 0; @@ -600,6 +607,9 @@ struct wireless_dev *iwm_wdev_alloc(int sizeof_bus, struct device *dev) wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &iwm_band_5ghz; wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; + wdev->wiphy->cipher_suites = cipher_suites; + wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); + ret = wiphy_register(wdev->wiphy); if (ret < 0) { dev_err(dev, "Couldn't register wiphy device\n"); -- cgit v1.2.3 From 4fdd81f5f2e6fc55b67938f09b3495d679428cd7 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Thu, 16 Jul 2009 17:34:09 +0800 Subject: iwmc3200wifi: use correct debug level This patch uses TX and RX instead of NTF debug levels in some hot paths. Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/rx.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'drivers/net/wireless/iwmc3200wifi') diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index 9fb498b514e1..218933b8800b 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c @@ -218,17 +218,17 @@ static int iwm_ntf_tx(struct iwm_priv *iwm, u8 *buf, (buf + sizeof(struct iwm_umac_wifi_in_hdr)); hdr = (struct iwm_umac_wifi_in_hdr *)buf; - IWM_DBG_NTF(iwm, DBG, "REPLY_TX, buf size: %lu\n", buf_size); - - IWM_DBG_NTF(iwm, DBG, "Seqnum: %d\n", - le16_to_cpu(hdr->sw_hdr.cmd.seq_num)); - IWM_DBG_NTF(iwm, DBG, "\tFrame cnt: %d\n", tx_resp->frame_cnt); - IWM_DBG_NTF(iwm, DBG, "\tRetry cnt: %d\n", - le16_to_cpu(tx_resp->retry_cnt)); - IWM_DBG_NTF(iwm, DBG, "\tSeq ctl: %d\n", le16_to_cpu(tx_resp->seq_ctl)); - IWM_DBG_NTF(iwm, DBG, "\tByte cnt: %d\n", - le16_to_cpu(tx_resp->byte_cnt)); - IWM_DBG_NTF(iwm, DBG, "\tStatus: 0x%x\n", le32_to_cpu(tx_resp->status)); + IWM_DBG_TX(iwm, DBG, "REPLY_TX, buf size: %lu\n", buf_size); + + IWM_DBG_TX(iwm, DBG, "Seqnum: %d\n", + le16_to_cpu(hdr->sw_hdr.cmd.seq_num)); + IWM_DBG_TX(iwm, DBG, "\tFrame cnt: %d\n", tx_resp->frame_cnt); + IWM_DBG_TX(iwm, DBG, "\tRetry cnt: %d\n", + le16_to_cpu(tx_resp->retry_cnt)); + IWM_DBG_TX(iwm, DBG, "\tSeq ctl: %d\n", le16_to_cpu(tx_resp->seq_ctl)); + IWM_DBG_TX(iwm, DBG, "\tByte cnt: %d\n", + le16_to_cpu(tx_resp->byte_cnt)); + IWM_DBG_TX(iwm, DBG, "\tStatus: 0x%x\n", le32_to_cpu(tx_resp->status)); return 0; } @@ -418,8 +418,8 @@ static int iwm_ntf_rx_ticket(struct iwm_priv *iwm, u8 *buf, if (IS_ERR(ticket_node)) return PTR_ERR(ticket_node); - IWM_DBG_NTF(iwm, DBG, "TICKET RELEASE(%d)\n", - ticket->id); + IWM_DBG_RX(iwm, DBG, "TICKET RELEASE(%d)\n", + ticket->id); list_add_tail(&ticket_node->node, &iwm->rx_tickets); /* @@ -454,15 +454,15 @@ static int iwm_ntf_rx_packet(struct iwm_priv *iwm, u8 *buf, u16 id, buf_offset; u32 packet_size; - IWM_DBG_NTF(iwm, DBG, "\n"); + IWM_DBG_RX(iwm, DBG, "\n"); wifi_hdr = (struct iwm_umac_wifi_in_hdr *)buf; id = le16_to_cpu(wifi_hdr->sw_hdr.cmd.seq_num); buf_offset = sizeof(struct iwm_umac_wifi_in_hdr); packet_size = buf_size - sizeof(struct iwm_umac_wifi_in_hdr); - IWM_DBG_NTF(iwm, DBG, "CMD:0x%x, seqnum: %d, packet size: %d\n", - wifi_hdr->sw_hdr.cmd.cmd, id, packet_size); + IWM_DBG_RX(iwm, DBG, "CMD:0x%x, seqnum: %d, packet size: %d\n", + wifi_hdr->sw_hdr.cmd.cmd, id, packet_size); IWM_DBG_RX(iwm, DBG, "Packet id: %d\n", id); IWM_HEXDUMP(iwm, DBG, RX, "PACKET: ", buf + buf_offset, packet_size); -- cgit v1.2.3 From 9967d46aa5ba065650d3352ab5d906f56ba17648 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Thu, 16 Jul 2009 17:34:10 +0800 Subject: iwmc3200wifi: cfg80211 managed mode port This patch ports iwmc3200wifi to the cfg80211 managed mode API. Signed-off-by: Samuel Ortiz Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/cfg80211.c | 195 ++++++++++++++++ drivers/net/wireless/iwmc3200wifi/rx.c | 16 +- drivers/net/wireless/iwmc3200wifi/wext.c | 320 +++------------------------ 3 files changed, 239 insertions(+), 292 deletions(-) (limited to 'drivers/net/wireless/iwmc3200wifi') diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.c b/drivers/net/wireless/iwmc3200wifi/cfg80211.c index 0aa389564c71..ee4031764389 100644 --- a/drivers/net/wireless/iwmc3200wifi/cfg80211.c +++ b/drivers/net/wireless/iwmc3200wifi/cfg80211.c @@ -305,6 +305,25 @@ static int iwm_cfg80211_set_default_key(struct wiphy *wiphy, return iwm_reset_profile(iwm); } +int iwm_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, + u8 *mac, struct station_info *sinfo) +{ + struct iwm_priv *iwm = ndev_to_iwm(ndev); + + if (memcmp(mac, iwm->bssid, ETH_ALEN)) + return -ENOENT; + + sinfo->filled |= STATION_INFO_TX_BITRATE; + sinfo->txrate.legacy = iwm->rate * 10; + + if (test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) { + sinfo->filled |= STATION_INFO_SIGNAL; + sinfo->signal = iwm->wstats.qual.level; + } + + return 0; +} + int iwm_cfg80211_inform_bss(struct iwm_priv *iwm) { @@ -500,6 +519,179 @@ static int iwm_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) return 0; } +static int iwm_set_auth_type(struct iwm_priv *iwm, + enum nl80211_auth_type sme_auth_type) +{ + u8 *auth_type = &iwm->umac_profile->sec.auth_type; + + switch (sme_auth_type) { + case NL80211_AUTHTYPE_AUTOMATIC: + case NL80211_AUTHTYPE_OPEN_SYSTEM: + IWM_DBG_WEXT(iwm, DBG, "OPEN auth\n"); + *auth_type = UMAC_AUTH_TYPE_OPEN; + break; + case NL80211_AUTHTYPE_SHARED_KEY: + if (iwm->umac_profile->sec.flags & + (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) { + IWM_DBG_WEXT(iwm, DBG, "WPA auth alg\n"); + *auth_type = UMAC_AUTH_TYPE_RSNA_PSK; + } else { + IWM_DBG_WEXT(iwm, DBG, "WEP shared key auth alg\n"); + *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK; + } + + break; + default: + IWM_ERR(iwm, "Unsupported auth alg: 0x%x\n", sme_auth_type); + return -ENOTSUPP; + } + + return 0; +} + +static int iwm_set_wpa_version(struct iwm_priv *iwm, u32 wpa_version) +{ + if (!wpa_version) { + iwm->umac_profile->sec.flags = UMAC_SEC_FLG_LEGACY_PROFILE; + return 0; + } + + if (wpa_version & NL80211_WPA_VERSION_2) + iwm->umac_profile->sec.flags = UMAC_SEC_FLG_RSNA_ON_MSK; + + if (wpa_version & NL80211_WPA_VERSION_1) + iwm->umac_profile->sec.flags |= UMAC_SEC_FLG_WPA_ON_MSK; + + return 0; +} + +static int iwm_set_cipher(struct iwm_priv *iwm, u32 cipher, bool ucast) +{ + u8 *profile_cipher = ucast ? &iwm->umac_profile->sec.ucast_cipher : + &iwm->umac_profile->sec.mcast_cipher; + + if (!cipher) { + *profile_cipher = UMAC_CIPHER_TYPE_NONE; + return 0; + } + + switch (cipher) { + case IW_AUTH_CIPHER_NONE: + *profile_cipher = UMAC_CIPHER_TYPE_NONE; + break; + case WLAN_CIPHER_SUITE_WEP40: + *profile_cipher = UMAC_CIPHER_TYPE_WEP_40; + break; + case WLAN_CIPHER_SUITE_WEP104: + *profile_cipher = UMAC_CIPHER_TYPE_WEP_104; + break; + case WLAN_CIPHER_SUITE_TKIP: + *profile_cipher = UMAC_CIPHER_TYPE_TKIP; + break; + case WLAN_CIPHER_SUITE_CCMP: + *profile_cipher = UMAC_CIPHER_TYPE_CCMP; + break; + default: + IWM_ERR(iwm, "Unsupported cipher: 0x%x\n", cipher); + return -ENOTSUPP; + } + + return 0; +} + +static int iwm_set_key_mgt(struct iwm_priv *iwm, u32 key_mgt) +{ + u8 *auth_type = &iwm->umac_profile->sec.auth_type; + + IWM_DBG_WEXT(iwm, DBG, "key_mgt: 0x%x\n", key_mgt); + + if (key_mgt == WLAN_AKM_SUITE_8021X) + *auth_type = UMAC_AUTH_TYPE_8021X; + else if (key_mgt == WLAN_AKM_SUITE_PSK) { + if (iwm->umac_profile->sec.flags & + (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) + *auth_type = UMAC_AUTH_TYPE_RSNA_PSK; + else + *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK; + } else { + IWM_ERR(iwm, "Invalid key mgt: 0x%x\n", key_mgt); + return -EINVAL; + } + + return 0; +} + + +static int iwm_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_connect_params *sme) +{ + struct iwm_priv *iwm = wiphy_to_iwm(wiphy); + struct ieee80211_channel *chan = sme->channel; + int ret; + + if (!test_bit(IWM_STATUS_READY, &iwm->status)) + return -EIO; + + if (!sme->ssid) + return -EINVAL; + + if (chan) + iwm->channel = + ieee80211_frequency_to_channel(chan->center_freq); + + iwm->umac_profile->ssid.ssid_len = sme->ssid_len; + memcpy(iwm->umac_profile->ssid.ssid, sme->ssid, sme->ssid_len); + + if (sme->bssid) { + IWM_DBG_WEXT(iwm, DBG, "BSSID: %pM\n", sme->bssid); + memcpy(&iwm->umac_profile->bssid[0], sme->bssid, ETH_ALEN); + iwm->umac_profile->bss_num = 1; + } else { + memset(&iwm->umac_profile->bssid[0], 0, ETH_ALEN); + iwm->umac_profile->bss_num = 0; + } + + ret = iwm_set_auth_type(iwm, sme->auth_type); + if (ret < 0) + return ret; + + ret = iwm_set_wpa_version(iwm, sme->crypto.wpa_versions); + if (ret < 0) + return ret; + + if (sme->crypto.n_ciphers_pairwise) { + ret = iwm_set_cipher(iwm, sme->crypto.ciphers_pairwise[0], + true); + if (ret < 0) + return ret; + } + + ret = iwm_set_cipher(iwm, sme->crypto.cipher_group, false); + if (ret < 0) + return ret; + + if (sme->crypto.n_akm_suites) { + ret = iwm_set_key_mgt(iwm, sme->crypto.akm_suites[0]); + if (ret < 0) + return ret; + } + + return iwm_send_mlme_profile(iwm); +} + +static int iwm_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, + u16 reason_code) +{ + struct iwm_priv *iwm = wiphy_to_iwm(wiphy); + + IWM_DBG_WEXT(iwm, DBG, "Active: %d\n", iwm->umac_profile_active); + + if (iwm->umac_profile_active) + return iwm_invalidate_mlme_profile(iwm); + + return 0; +} + static int iwm_cfg80211_set_txpower(struct wiphy *wiphy, enum tx_power_setting type, int dbm) { @@ -549,8 +741,11 @@ static struct cfg80211_ops iwm_cfg80211_ops = { .get_key = iwm_cfg80211_get_key, .del_key = iwm_cfg80211_del_key, .set_default_key = iwm_cfg80211_set_default_key, + .get_station = iwm_cfg80211_get_station, .scan = iwm_cfg80211_scan, .set_wiphy_params = iwm_cfg80211_set_wiphy_params, + .connect = iwm_cfg80211_connect, + .disconnect = iwm_cfg80211_disconnect, .join_ibss = iwm_cfg80211_join_ibss, .leave_ibss = iwm_cfg80211_leave_ibss, .set_tx_power = iwm_cfg80211_set_txpower, diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index 218933b8800b..82b572a6fc0b 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c @@ -503,13 +503,10 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf, { struct iwm_umac_notif_assoc_complete *complete = (struct iwm_umac_notif_assoc_complete *)buf; - union iwreq_data wrqu; IWM_DBG_MLME(iwm, INFO, "Association with %pM completed, status: %d\n", complete->bssid, complete->status); - memset(&wrqu, 0, sizeof(wrqu)); - clear_bit(IWM_STATUS_ASSOCIATING, &iwm->status); switch (le32_to_cpu(complete->status)) { @@ -520,7 +517,10 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf, iwm_link_on(iwm); - memcpy(wrqu.ap_addr.sa_data, complete->bssid, ETH_ALEN); + cfg80211_connect_result(iwm_to_ndev(iwm), + complete->bssid, + NULL, 0, NULL, 0, + WLAN_STATUS_SUCCESS, GFP_KERNEL); break; case UMAC_ASSOC_COMPLETE_FAILURE: clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status); @@ -528,6 +528,11 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf, iwm->channel = 0; iwm_link_off(iwm); + + cfg80211_connect_result(iwm_to_ndev(iwm), complete->bssid, + NULL, 0, NULL, 0, + WLAN_STATUS_UNSPECIFIED_FAILURE, + GFP_KERNEL); default: break; } @@ -537,9 +542,6 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf, return 0; } - wrqu.ap_addr.sa_family = ARPHRD_ETHER; - wireless_send_event(iwm_to_ndev(iwm), SIOCGIWAP, &wrqu, NULL); - return 0; } diff --git a/drivers/net/wireless/iwmc3200wifi/wext.c b/drivers/net/wireless/iwmc3200wifi/wext.c index 2e7eaf96cf93..c3c90d5963bf 100644 --- a/drivers/net/wireless/iwmc3200wifi/wext.c +++ b/drivers/net/wireless/iwmc3200wifi/wext.c @@ -21,31 +21,11 @@ * */ -#include -#include #include -#include -#include #include -#include #include "iwm.h" -#include "umac.h" #include "commands.h" -#include "debug.h" - -static struct iw_statistics *iwm_get_wireless_stats(struct net_device *dev) -{ - struct iwm_priv *iwm = ndev_to_iwm(dev); - struct iw_statistics *wstats = &iwm->wstats; - - if (!test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) { - memset(wstats, 0, sizeof(struct iw_statistics)); - wstats->qual.updated = IW_QUAL_ALL_INVALID; - } - - return wstats; -} static int iwm_wext_siwfreq(struct net_device *dev, struct iw_request_info *info, @@ -53,14 +33,12 @@ static int iwm_wext_siwfreq(struct net_device *dev, { struct iwm_priv *iwm = ndev_to_iwm(dev); - if (freq->flags == IW_FREQ_AUTO) - return 0; - - /* frequency/channel can only be set in IBSS mode */ - if (iwm->conf.mode != UMAC_MODE_IBSS) + switch (iwm->conf.mode) { + case UMAC_MODE_IBSS: + return cfg80211_ibss_wext_siwfreq(dev, info, freq, extra); + default: return -EOPNOTSUPP; - - return cfg80211_ibss_wext_siwfreq(dev, info, freq, extra); + } } static int iwm_wext_giwfreq(struct net_device *dev, @@ -69,69 +47,29 @@ static int iwm_wext_giwfreq(struct net_device *dev, { struct iwm_priv *iwm = ndev_to_iwm(dev); - if (iwm->conf.mode == UMAC_MODE_IBSS) + switch (iwm->conf.mode) { + case UMAC_MODE_IBSS: return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra); - - freq->e = 0; - freq->m = iwm->channel; - - return 0; + case UMAC_MODE_BSS: + return cfg80211_mgd_wext_giwfreq(dev, info, freq, extra); + default: + return -EOPNOTSUPP; + } } static int iwm_wext_siwap(struct net_device *dev, struct iw_request_info *info, struct sockaddr *ap_addr, char *extra) { struct iwm_priv *iwm = ndev_to_iwm(dev); - int ret; - - IWM_DBG_WEXT(iwm, DBG, "Set BSSID: %pM\n", ap_addr->sa_data); - if (iwm->conf.mode == UMAC_MODE_IBSS) + switch (iwm->conf.mode) { + case UMAC_MODE_IBSS: return cfg80211_ibss_wext_siwap(dev, info, ap_addr, extra); - - if (!test_bit(IWM_STATUS_READY, &iwm->status)) - return -EIO; - - if (is_zero_ether_addr(ap_addr->sa_data) || - is_broadcast_ether_addr(ap_addr->sa_data)) { - IWM_DBG_WEXT(iwm, DBG, "clear mandatory bssid %pM\n", - iwm->umac_profile->bssid[0]); - memset(&iwm->umac_profile->bssid[0], 0, ETH_ALEN); - iwm->umac_profile->bss_num = 0; - } else { - IWM_DBG_WEXT(iwm, DBG, "add mandatory bssid %pM\n", - ap_addr->sa_data); - memcpy(&iwm->umac_profile->bssid[0], ap_addr->sa_data, - ETH_ALEN); - iwm->umac_profile->bss_num = 1; - } - - if (iwm->umac_profile_active) { - int i; - - if (!memcmp(&iwm->umac_profile->bssid[0], iwm->bssid, ETH_ALEN)) - return 0; - - /* - * If we're clearing the BSSID, and we're associated, - * we have to clear the keys as they're no longer valid. - */ - if (is_zero_ether_addr(ap_addr->sa_data)) { - for (i = 0; i < IWM_NUM_KEYS; i++) - iwm->keys[i].key_len = 0; - } - - ret = iwm_invalidate_mlme_profile(iwm); - if (ret < 0) { - IWM_ERR(iwm, "Couldn't invalidate profile\n"); - return ret; - } + case UMAC_MODE_BSS: + return cfg80211_mgd_wext_siwap(dev, info, ap_addr, extra); + default: + return -EOPNOTSUPP; } - - if (iwm->umac_profile->ssid.ssid_len) - return iwm_send_mlme_profile(iwm); - - return 0; } static int iwm_wext_giwap(struct net_device *dev, struct iw_request_info *info, @@ -143,17 +81,10 @@ static int iwm_wext_giwap(struct net_device *dev, struct iw_request_info *info, case UMAC_MODE_IBSS: return cfg80211_ibss_wext_giwap(dev, info, ap_addr, extra); case UMAC_MODE_BSS: - if (test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) { - ap_addr->sa_family = ARPHRD_ETHER; - memcpy(&ap_addr->sa_data, iwm->bssid, ETH_ALEN); - } else - memset(&ap_addr->sa_data, 0, ETH_ALEN); - break; + return cfg80211_mgd_wext_giwap(dev, info, ap_addr, extra); default: return -EOPNOTSUPP; } - - return 0; } static int iwm_wext_siwessid(struct net_device *dev, @@ -161,36 +92,15 @@ static int iwm_wext_siwessid(struct net_device *dev, struct iw_point *data, char *ssid) { struct iwm_priv *iwm = ndev_to_iwm(dev); - size_t len = data->length; - int ret; - - IWM_DBG_WEXT(iwm, DBG, "Set ESSID: >%s<\n", ssid); - if (iwm->conf.mode == UMAC_MODE_IBSS) + switch (iwm->conf.mode) { + case UMAC_MODE_IBSS: return cfg80211_ibss_wext_siwessid(dev, info, data, ssid); - - if (!test_bit(IWM_STATUS_READY, &iwm->status)) - return -EIO; - - if (len > 0 && ssid[len - 1] == '\0') - len--; - - if (iwm->umac_profile_active) { - if (iwm->umac_profile->ssid.ssid_len == len && - !memcmp(iwm->umac_profile->ssid.ssid, ssid, len)) - return 0; - - ret = iwm_invalidate_mlme_profile(iwm); - if (ret < 0) { - IWM_ERR(iwm, "Couldn't invalidate profile\n"); - return ret; - } + case UMAC_MODE_BSS: + return cfg80211_mgd_wext_siwessid(dev, info, data, ssid); + default: + return -EOPNOTSUPP; } - - iwm->umac_profile->ssid.ssid_len = len; - memcpy(iwm->umac_profile->ssid.ssid, ssid, len); - - return iwm_send_mlme_profile(iwm); } static int iwm_wext_giwessid(struct net_device *dev, @@ -199,174 +109,14 @@ static int iwm_wext_giwessid(struct net_device *dev, { struct iwm_priv *iwm = ndev_to_iwm(dev); - if (iwm->conf.mode == UMAC_MODE_IBSS) + switch (iwm->conf.mode) { + case UMAC_MODE_IBSS: return cfg80211_ibss_wext_giwessid(dev, info, data, ssid); - - if (!test_bit(IWM_STATUS_READY, &iwm->status)) - return -EIO; - - data->length = iwm->umac_profile->ssid.ssid_len; - if (data->length) { - memcpy(ssid, iwm->umac_profile->ssid.ssid, data->length); - data->flags = 1; - } else - data->flags = 0; - - return 0; -} - -static int iwm_wext_giwrate(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rate, char *extra) -{ - struct iwm_priv *iwm = ndev_to_iwm(dev); - - rate->value = iwm->rate * 1000000; - - return 0; -} - -static int iwm_set_wpa_version(struct iwm_priv *iwm, u8 wpa_version) -{ - if (wpa_version & IW_AUTH_WPA_VERSION_WPA2) - iwm->umac_profile->sec.flags = UMAC_SEC_FLG_RSNA_ON_MSK; - else if (wpa_version & IW_AUTH_WPA_VERSION_WPA) - iwm->umac_profile->sec.flags = UMAC_SEC_FLG_WPA_ON_MSK; - else - iwm->umac_profile->sec.flags = UMAC_SEC_FLG_LEGACY_PROFILE; - - return 0; -} - -static int iwm_set_key_mgt(struct iwm_priv *iwm, u8 key_mgt) -{ - u8 *auth_type = &iwm->umac_profile->sec.auth_type; - - IWM_DBG_WEXT(iwm, DBG, "key_mgt: 0x%x\n", key_mgt); - - if (key_mgt == IW_AUTH_KEY_MGMT_802_1X) - *auth_type = UMAC_AUTH_TYPE_8021X; - else if (key_mgt == IW_AUTH_KEY_MGMT_PSK) { - if (iwm->umac_profile->sec.flags & - (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) - *auth_type = UMAC_AUTH_TYPE_RSNA_PSK; - else - *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK; - } else { - IWM_ERR(iwm, "Invalid key mgt: 0x%x\n", key_mgt); - return -EINVAL; - } - - return 0; -} - -static int iwm_set_cipher(struct iwm_priv *iwm, u8 cipher, u8 ucast) -{ - u8 *profile_cipher = ucast ? &iwm->umac_profile->sec.ucast_cipher : - &iwm->umac_profile->sec.mcast_cipher; - - switch (cipher) { - case IW_AUTH_CIPHER_NONE: - *profile_cipher = UMAC_CIPHER_TYPE_NONE; - break; - case IW_AUTH_CIPHER_WEP40: - *profile_cipher = UMAC_CIPHER_TYPE_WEP_40; - break; - case IW_AUTH_CIPHER_TKIP: - *profile_cipher = UMAC_CIPHER_TYPE_TKIP; - break; - case IW_AUTH_CIPHER_CCMP: - *profile_cipher = UMAC_CIPHER_TYPE_CCMP; - break; - case IW_AUTH_CIPHER_WEP104: - *profile_cipher = UMAC_CIPHER_TYPE_WEP_104; - break; - default: - IWM_ERR(iwm, "Unsupported cipher: 0x%x\n", cipher); - return -ENOTSUPP; - } - - return 0; -} - -static int iwm_set_auth_alg(struct iwm_priv *iwm, u8 auth_alg) -{ - u8 *auth_type = &iwm->umac_profile->sec.auth_type; - - IWM_DBG_WEXT(iwm, DBG, "auth_alg: 0x%x\n", auth_alg); - - switch (auth_alg) { - case IW_AUTH_ALG_OPEN_SYSTEM: - *auth_type = UMAC_AUTH_TYPE_OPEN; - break; - case IW_AUTH_ALG_SHARED_KEY: - if (iwm->umac_profile->sec.flags & - (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) { - if (*auth_type == UMAC_AUTH_TYPE_8021X) - return -EINVAL; - *auth_type = UMAC_AUTH_TYPE_RSNA_PSK; - } else { - IWM_DBG_WEXT(iwm, DBG, "WEP shared key\n"); - *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK; - } - break; - case IW_AUTH_ALG_LEAP: - default: - IWM_ERR(iwm, "Unsupported auth alg: 0x%x\n", auth_alg); - return -ENOTSUPP; - } - - return 0; -} - -static int iwm_wext_siwauth(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *data, char *extra) -{ - struct iwm_priv *iwm = ndev_to_iwm(dev); - int ret; - - if ((data->flags) & - (IW_AUTH_WPA_VERSION | IW_AUTH_KEY_MGMT | - IW_AUTH_WPA_ENABLED | IW_AUTH_80211_AUTH_ALG)) { - /* We need to invalidate the current profile */ - if (iwm->umac_profile_active) { - ret = iwm_invalidate_mlme_profile(iwm); - if (ret < 0) { - IWM_ERR(iwm, "Couldn't invalidate profile\n"); - return ret; - } - } - } - - switch (data->flags & IW_AUTH_INDEX) { - case IW_AUTH_WPA_VERSION: - return iwm_set_wpa_version(iwm, data->value); - break; - case IW_AUTH_CIPHER_PAIRWISE: - return iwm_set_cipher(iwm, data->value, 1); - break; - case IW_AUTH_CIPHER_GROUP: - return iwm_set_cipher(iwm, data->value, 0); - break; - case IW_AUTH_KEY_MGMT: - return iwm_set_key_mgt(iwm, data->value); - break; - case IW_AUTH_80211_AUTH_ALG: - return iwm_set_auth_alg(iwm, data->value); - break; + case UMAC_MODE_BSS: + return cfg80211_mgd_wext_giwessid(dev, info, data, ssid); default: - return -ENOTSUPP; + return -EOPNOTSUPP; } - - return 0; -} - -static int iwm_wext_giwauth(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *data, char *extra) -{ - return 0; } static const iw_handler iwm_handlers[] = @@ -404,7 +154,7 @@ static const iw_handler iwm_handlers[] = (iw_handler) NULL, /* -- hole -- */ (iw_handler) NULL, /* -- hole -- */ (iw_handler) NULL, /* SIOCSIWRATE */ - (iw_handler) iwm_wext_giwrate, /* SIOCGIWRATE */ + (iw_handler) cfg80211_wext_giwrate, /* SIOCGIWRATE */ (iw_handler) cfg80211_wext_siwrts, /* SIOCSIWRTS */ (iw_handler) cfg80211_wext_giwrts, /* SIOCGIWRTS */ (iw_handler) cfg80211_wext_siwfrag, /* SIOCSIWFRAG */ @@ -419,10 +169,10 @@ static const iw_handler iwm_handlers[] = (iw_handler) cfg80211_wext_giwpower, /* SIOCGIWPOWER */ (iw_handler) NULL, /* -- hole -- */ (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* SIOCSIWGENIE */ + (iw_handler) cfg80211_wext_siwgenie, /* SIOCSIWGENIE */ (iw_handler) NULL, /* SIOCGIWGENIE */ - (iw_handler) iwm_wext_siwauth, /* SIOCSIWAUTH */ - (iw_handler) iwm_wext_giwauth, /* SIOCGIWAUTH */ + (iw_handler) cfg80211_wext_siwauth, /* SIOCSIWAUTH */ + (iw_handler) cfg80211_wext_giwauth, /* SIOCGIWAUTH */ (iw_handler) cfg80211_wext_siwencodeext, /* SIOCSIWENCODEEXT */ (iw_handler) NULL, /* SIOCGIWENCODEEXT */ (iw_handler) NULL, /* SIOCSIWPMKSA */ @@ -432,6 +182,6 @@ static const iw_handler iwm_handlers[] = const struct iw_handler_def iwm_iw_handler_def = { .num_standard = ARRAY_SIZE(iwm_handlers), .standard = (iw_handler *) iwm_handlers, - .get_wireless_stats = iwm_get_wireless_stats, + .get_wireless_stats = cfg80211_wireless_stats, }; -- cgit v1.2.3 From 0e371f1a0c0acd4abfa052b01e7b1f4a71ef6590 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Thu, 16 Jul 2009 17:34:11 +0800 Subject: iwmc3200wifi: remove setting WEP keys before setting essid support The recent cfg80211 "rework key operation" patch from Johannes Berg makes sure keys are set only after the connection has been established. So we can remove the setting WEP keys before essid support from the driver. Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/cfg80211.c | 26 -------------------------- 1 file changed, 26 deletions(-) (limited to 'drivers/net/wireless/iwmc3200wifi') diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.c b/drivers/net/wireless/iwmc3200wifi/cfg80211.c index ee4031764389..0372658bac99 100644 --- a/drivers/net/wireless/iwmc3200wifi/cfg80211.c +++ b/drivers/net/wireless/iwmc3200wifi/cfg80211.c @@ -203,32 +203,6 @@ static int iwm_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, return ret; } - /* - * The WEP keys can be set before or after setting the essid. - * We need to handle both cases by simply pushing the keys after - * we send the profile. - * If the profile is not set yet (i.e. we're pushing keys before - * the essid), we set the cipher appropriately. - * If the profile is set, we havent associated yet because our - * cipher was incorrectly set. So we invalidate and send the - * profile again. - */ - if (key->cipher == WLAN_CIPHER_SUITE_WEP40 || - key->cipher == WLAN_CIPHER_SUITE_WEP104) { - u8 *ucast_cipher = &iwm->umac_profile->sec.ucast_cipher; - u8 *mcast_cipher = &iwm->umac_profile->sec.mcast_cipher; - - IWM_DBG_WEXT(iwm, DBG, "WEP key\n"); - - if (key->cipher == WLAN_CIPHER_SUITE_WEP40) - *ucast_cipher = *mcast_cipher = UMAC_CIPHER_TYPE_WEP_40; - if (key->cipher == WLAN_CIPHER_SUITE_WEP104) - *ucast_cipher = *mcast_cipher = - UMAC_CIPHER_TYPE_WEP_104; - - return iwm_reset_profile(iwm); - } - return iwm_set_key(iwm, 0, key); } -- cgit v1.2.3 From b6c321718e1376b1a55afc63cce090a2c4573417 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Thu, 16 Jul 2009 17:34:12 +0800 Subject: iwmc3200wifi: make iwm_send_wifi_if_cmd return 0 on success We used to return the result of wait_event_interruptible_timeout() which is the remaining timeout on success. But this information is not used by any of its callers. So we just return 0 on success. This fixed a erroneous return value bug for iwm_set_key(). Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/commands.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) (limited to 'drivers/net/wireless/iwmc3200wifi') diff --git a/drivers/net/wireless/iwmc3200wifi/commands.c b/drivers/net/wireless/iwmc3200wifi/commands.c index 0d35afefb61c..e6be29704a1d 100644 --- a/drivers/net/wireless/iwmc3200wifi/commands.c +++ b/drivers/net/wireless/iwmc3200wifi/commands.c @@ -87,8 +87,7 @@ int iwm_send_wifi_if_cmd(struct iwm_priv *iwm, void *payload, u16 payload_size, test_and_clear_bit(oid, &iwm->wifi_ntfy[0]), 3 * HZ); - if (!ret) - ret = -EBUSY; + return ret ? 0 : -EBUSY; } return ret; @@ -480,8 +479,10 @@ static int iwm_target_read(struct iwm_priv *iwm, __le32 address, target_cmd.eop = 1; ret = iwm_hal_send_target_cmd(iwm, &target_cmd, NULL); - if (ret < 0) + if (ret < 0) { IWM_ERR(iwm, "Couldn't send READ command\n"); + return ret; + } /* When succeding, the send_target routine returns the seq number */ seq_num = ret; @@ -501,7 +502,7 @@ static int iwm_target_read(struct iwm_priv *iwm, __le32 address, kfree(cmd); - return ret; + return 0; } int iwm_read_mac(struct iwm_priv *iwm, u8 *mac) @@ -511,7 +512,7 @@ int iwm_read_mac(struct iwm_priv *iwm, u8 *mac) ret = iwm_target_read(iwm, cpu_to_le32(WICO_MAC_ADDRESS_ADDR), mac_align, sizeof(mac_align)); - if (ret < 0) + if (ret) return ret; if (is_valid_ether_addr(mac_align)) @@ -714,7 +715,7 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, struct iwm_key *key) ret = iwm_send_wifi_if_cmd(iwm, &key_remove, sizeof(struct iwm_umac_key_remove), 1); - if (ret < 0) + if (ret) return ret; iwm->keys[key_idx].key_len = 0; @@ -736,7 +737,7 @@ int iwm_send_mlme_profile(struct iwm_priv *iwm) sizeof(struct iwm_umac_wifi_if)); ret = iwm_send_wifi_if_cmd(iwm, &profile, sizeof(profile), 1); - if (ret < 0) { + if (ret) { IWM_ERR(iwm, "Send profile command failed\n"); return ret; } @@ -752,12 +753,12 @@ int iwm_send_mlme_profile(struct iwm_priv *iwm) 3 * HZ); ret = iwm_set_key(iwm, 0, key); - if (ret < 0) + if (ret) return ret; if (iwm->default_key == i) { ret = iwm_set_tx_key(iwm, i); - if (ret < 0) + if (ret) return ret; } } @@ -778,15 +779,13 @@ int iwm_invalidate_mlme_profile(struct iwm_priv *iwm) invalid.reason = WLAN_REASON_UNSPECIFIED; ret = iwm_send_wifi_if_cmd(iwm, &invalid, sizeof(invalid), 1); - if (ret < 0) + if (ret) return ret; ret = wait_event_interruptible_timeout(iwm->mlme_queue, (iwm->umac_profile_active == 0), 2 * HZ); - if (!ret) - return -EBUSY; - return 0; + return ret ? 0 : -EBUSY; } int iwm_send_umac_stats_req(struct iwm_priv *iwm, u32 flags) @@ -869,7 +868,7 @@ int iwm_scan_ssids(struct iwm_priv *iwm, struct cfg80211_ssid *ssids, } ret = iwm_send_wifi_if_cmd(iwm, &req, sizeof(req), 0); - if (ret < 0) { + if (ret) { IWM_ERR(iwm, "Couldn't send scan request\n"); return ret; } -- cgit v1.2.3 From 6e5db0a8454b44bf88fa74cf437a507ec08f436d Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Thu, 16 Jul 2009 17:34:13 +0800 Subject: iwmc3200wifi: remove key caches in driver cfg80211 now guarantees keys are set after connecting. We can remove the key cache code from the driver now. Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/cfg80211.c | 43 +--------------------------- drivers/net/wireless/iwmc3200wifi/commands.c | 29 +------------------ 2 files changed, 2 insertions(+), 70 deletions(-) (limited to 'drivers/net/wireless/iwmc3200wifi') diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.c b/drivers/net/wireless/iwmc3200wifi/cfg80211.c index 0372658bac99..3f5a08fa401f 100644 --- a/drivers/net/wireless/iwmc3200wifi/cfg80211.c +++ b/drivers/net/wireless/iwmc3200wifi/cfg80211.c @@ -158,34 +158,6 @@ static int iwm_key_init(struct iwm_key *key, u8 key_index, return 0; } -static int iwm_reset_profile(struct iwm_priv *iwm) -{ - int ret; - - if (!iwm->umac_profile_active) - return 0; - - /* - * If there is a current active profile, but no - * default key, it's not worth trying to associate again. - */ - if (iwm->default_key < 0) - return 0; - - /* - * Here we have an active profile, but a key setting changed. - * We thus have to invalidate the current profile, and push the - * new one. Keys will be pushed when association takes place. - */ - ret = iwm_invalidate_mlme_profile(iwm); - if (ret < 0) { - IWM_ERR(iwm, "Couldn't invalidate profile\n"); - return ret; - } - - return iwm_send_mlme_profile(iwm); -} - static int iwm_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, u8 key_index, const u8 *mac_addr, struct key_params *params) @@ -245,10 +217,6 @@ static int iwm_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev, if (key_index == iwm->default_key) iwm->default_key = -1; - /* If the interface is down, we just cache this */ - if (!test_bit(IWM_STATUS_READY, &iwm->status)) - return 0; - return iwm_set_key(iwm, 1, key); } @@ -257,7 +225,6 @@ static int iwm_cfg80211_set_default_key(struct wiphy *wiphy, u8 key_index) { struct iwm_priv *iwm = ndev_to_iwm(ndev); - int ret; IWM_DBG_WEXT(iwm, DBG, "Default key index is: %d\n", key_index); @@ -268,15 +235,7 @@ static int iwm_cfg80211_set_default_key(struct wiphy *wiphy, iwm->default_key = key_index; - /* If the interface is down, we just cache this */ - if (!test_bit(IWM_STATUS_READY, &iwm->status)) - return 0; - - ret = iwm_set_tx_key(iwm, key_index); - if (ret < 0) - return ret; - - return iwm_reset_profile(iwm); + return iwm_set_tx_key(iwm, key_index); } int iwm_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, diff --git a/drivers/net/wireless/iwmc3200wifi/commands.c b/drivers/net/wireless/iwmc3200wifi/commands.c index e6be29704a1d..0d6637005f42 100644 --- a/drivers/net/wireless/iwmc3200wifi/commands.c +++ b/drivers/net/wireless/iwmc3200wifi/commands.c @@ -584,12 +584,6 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, struct iwm_key *key) struct iwm_umac_key_tkip *tkip = (struct iwm_umac_key_tkip *)cmd; struct iwm_umac_key_ccmp *ccmp = (struct iwm_umac_key_ccmp *)cmd; - /* - * We check if our current profile is valid. - * If not, we dont push the key, we just cache them, - * so that with the next siwsessid call, the keys - * will be actually pushed. - */ if (!remove) { ret = iwm_check_profile(iwm); if (ret < 0) @@ -727,7 +721,7 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, struct iwm_key *key) int iwm_send_mlme_profile(struct iwm_priv *iwm) { - int ret, i; + int ret; struct iwm_umac_profile profile; memcpy(&profile, iwm->umac_profile, sizeof(profile)); @@ -742,27 +736,6 @@ int iwm_send_mlme_profile(struct iwm_priv *iwm) return ret; } - for (i = 0; i < IWM_NUM_KEYS; i++) - if (iwm->keys[i].key_len) { - struct iwm_key *key = &iwm->keys[i]; - - /* Wait for the profile before sending the keys */ - wait_event_interruptible_timeout(iwm->mlme_queue, - (test_bit(IWM_STATUS_ASSOCIATING, &iwm->status) || - test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)), - 3 * HZ); - - ret = iwm_set_key(iwm, 0, key); - if (ret) - return ret; - - if (iwm->default_key == i) { - ret = iwm_set_tx_key(iwm, i); - if (ret) - return ret; - } - } - return 0; } -- cgit v1.2.3 From b68518fcbc6e0fe8c06a218cd2b92f62f3730cf9 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Mon, 20 Jul 2009 11:47:45 +0800 Subject: iwmc3200wifi: use cfg80211_connect_result to send req/resp IE cfg80211_connect_result() let us specify associate request and response IEs as parameters after we are connected. We use this capability instead of doing it ourselves with WEXT. Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/iwm.h | 5 +++++ drivers/net/wireless/iwmc3200wifi/main.c | 7 +++++++ drivers/net/wireless/iwmc3200wifi/rx.c | 36 ++++++++++++++++++++------------ 3 files changed, 35 insertions(+), 13 deletions(-) (limited to 'drivers/net/wireless/iwmc3200wifi') diff --git a/drivers/net/wireless/iwmc3200wifi/iwm.h b/drivers/net/wireless/iwmc3200wifi/iwm.h index 79d9d89d47ae..2175a481d2f4 100644 --- a/drivers/net/wireless/iwmc3200wifi/iwm.h +++ b/drivers/net/wireless/iwmc3200wifi/iwm.h @@ -281,6 +281,11 @@ struct iwm_priv { struct work_struct reset_worker; struct mutex mutex; + u8 *req_ie; + int req_ie_len; + u8 *resp_ie; + int resp_ie_len; + char private[0] __attribute__((__aligned__(NETDEV_ALIGN))); }; diff --git a/drivers/net/wireless/iwmc3200wifi/main.c b/drivers/net/wireless/iwmc3200wifi/main.c index 484f110151b7..cf2574442b57 100644 --- a/drivers/net/wireless/iwmc3200wifi/main.c +++ b/drivers/net/wireless/iwmc3200wifi/main.c @@ -497,6 +497,13 @@ void iwm_link_off(struct iwm_priv *iwm) memset(wstats, 0, sizeof(struct iw_statistics)); wstats->qual.updated = IW_QUAL_ALL_INVALID; + kfree(iwm->req_ie); + iwm->req_ie = NULL; + iwm->req_ie_len = 0; + kfree(iwm->resp_ie); + iwm->resp_ie = NULL; + iwm->resp_ie_len = 0; + del_timer_sync(&iwm->watchdog); } diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index 82b572a6fc0b..6743391a45be 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c @@ -519,7 +519,8 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf, cfg80211_connect_result(iwm_to_ndev(iwm), complete->bssid, - NULL, 0, NULL, 0, + iwm->req_ie, iwm->req_ie_len, + iwm->resp_ie, iwm->resp_ie_len, WLAN_STATUS_SUCCESS, GFP_KERNEL); break; case UMAC_ASSOC_COMPLETE_FAILURE: @@ -771,37 +772,46 @@ static int iwm_mlme_mgt_frame(struct iwm_priv *iwm, u8 *buf, unsigned long buf_size, struct iwm_wifi_cmd *cmd) { struct iwm_umac_notif_mgt_frame *mgt_frame = - (struct iwm_umac_notif_mgt_frame *)buf; + (struct iwm_umac_notif_mgt_frame *)buf; struct ieee80211_mgmt *mgt = (struct ieee80211_mgmt *)mgt_frame->frame; u8 *ie; - unsigned int event; - union iwreq_data wrqu; IWM_HEXDUMP(iwm, DBG, MLME, "MGT: ", mgt_frame->frame, le16_to_cpu(mgt_frame->len)); if (ieee80211_is_assoc_req(mgt->frame_control)) { ie = mgt->u.assoc_req.variable;; - event = IWEVASSOCREQIE; + iwm->req_ie_len = + le16_to_cpu(mgt_frame->len) - (ie - (u8 *)mgt); + kfree(iwm->req_ie); + iwm->req_ie = kmemdup(mgt->u.assoc_req.variable, + iwm->req_ie_len, GFP_KERNEL); } else if (ieee80211_is_reassoc_req(mgt->frame_control)) { ie = mgt->u.reassoc_req.variable;; - event = IWEVASSOCREQIE; + iwm->req_ie_len = + le16_to_cpu(mgt_frame->len) - (ie - (u8 *)mgt); + kfree(iwm->req_ie); + iwm->req_ie = kmemdup(mgt->u.reassoc_req.variable, + iwm->req_ie_len, GFP_KERNEL); } else if (ieee80211_is_assoc_resp(mgt->frame_control)) { ie = mgt->u.assoc_resp.variable;; - event = IWEVASSOCRESPIE; + iwm->resp_ie_len = + le16_to_cpu(mgt_frame->len) - (ie - (u8 *)mgt); + kfree(iwm->resp_ie); + iwm->resp_ie = kmemdup(mgt->u.assoc_resp.variable, + iwm->resp_ie_len, GFP_KERNEL); } else if (ieee80211_is_reassoc_resp(mgt->frame_control)) { ie = mgt->u.reassoc_resp.variable;; - event = IWEVASSOCRESPIE; + iwm->resp_ie_len = + le16_to_cpu(mgt_frame->len) - (ie - (u8 *)mgt); + kfree(iwm->resp_ie); + iwm->resp_ie = kmemdup(mgt->u.reassoc_resp.variable, + iwm->resp_ie_len, GFP_KERNEL); } else { IWM_ERR(iwm, "Unsupported management frame"); return 0; } - wrqu.data.length = le16_to_cpu(mgt_frame->len) - (ie - (u8 *)mgt); - - IWM_HEXDUMP(iwm, DBG, MLME, "EVT: ", ie, wrqu.data.length); - wireless_send_event(iwm_to_ndev(iwm), event, &wrqu, ie); - return 0; } -- cgit v1.2.3 From 9c7c0cdd24e64f9aed39453a1bffc3b3fd16ef99 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Mon, 20 Jul 2009 11:47:46 +0800 Subject: iwmc3200wifi: fix cfg80211_connect_result is called in IBSS Avoid calling cfg80211_connect_result() in IBSS mode. Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/rx.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'drivers/net/wireless/iwmc3200wifi') diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index 6743391a45be..86079a187eef 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c @@ -517,6 +517,9 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf, iwm_link_on(iwm); + if (iwm->conf.mode == UMAC_MODE_IBSS) + goto ibss; + cfg80211_connect_result(iwm_to_ndev(iwm), complete->bssid, iwm->req_ie, iwm->req_ie_len, @@ -530,6 +533,9 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf, iwm_link_off(iwm); + if (iwm->conf.mode == UMAC_MODE_IBSS) + goto ibss; + cfg80211_connect_result(iwm_to_ndev(iwm), complete->bssid, NULL, 0, NULL, 0, WLAN_STATUS_UNSPECIFIED_FAILURE, @@ -538,11 +544,10 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf, break; } - if (iwm->conf.mode == UMAC_MODE_IBSS) { - cfg80211_ibss_joined(iwm_to_ndev(iwm), iwm->bssid, GFP_KERNEL); - return 0; - } + return 0; + ibss: + cfg80211_ibss_joined(iwm_to_ndev(iwm), iwm->bssid, GFP_KERNEL); return 0; } -- cgit v1.2.3 From 971ad01169398170976951d3a9479a29d231c734 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Mon, 20 Jul 2009 11:47:47 +0800 Subject: iwmc3200wifi: fix a use-after-free bug The patch fixes a use-after-free bug for cmd->seq_num; Reported-by: Dan Carpenter Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/hal.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'drivers/net/wireless/iwmc3200wifi') diff --git a/drivers/net/wireless/iwmc3200wifi/hal.c b/drivers/net/wireless/iwmc3200wifi/hal.c index ee127fe4f43f..c430418248b4 100644 --- a/drivers/net/wireless/iwmc3200wifi/hal.c +++ b/drivers/net/wireless/iwmc3200wifi/hal.c @@ -105,9 +105,9 @@ #include "umac.h" #include "debug.h" -static void iwm_nonwifi_cmd_init(struct iwm_priv *iwm, - struct iwm_nonwifi_cmd *cmd, - struct iwm_udma_nonwifi_cmd *udma_cmd) +static int iwm_nonwifi_cmd_init(struct iwm_priv *iwm, + struct iwm_nonwifi_cmd *cmd, + struct iwm_udma_nonwifi_cmd *udma_cmd) { INIT_LIST_HEAD(&cmd->pending); @@ -118,7 +118,7 @@ static void iwm_nonwifi_cmd_init(struct iwm_priv *iwm, cmd->seq_num = iwm->nonwifi_seq_num; udma_cmd->seq_num = cpu_to_le16(cmd->seq_num); - cmd->seq_num = iwm->nonwifi_seq_num++; + iwm->nonwifi_seq_num++; iwm->nonwifi_seq_num %= UMAC_NONWIFI_SEQ_NUM_MAX; if (udma_cmd->resp) @@ -130,6 +130,8 @@ static void iwm_nonwifi_cmd_init(struct iwm_priv *iwm, cmd->buf.len = 0; memcpy(&cmd->udma_cmd, udma_cmd, sizeof(*udma_cmd)); + + return cmd->seq_num; } u16 iwm_alloc_wifi_cmd_seq(struct iwm_priv *iwm) @@ -369,7 +371,7 @@ int iwm_hal_send_target_cmd(struct iwm_priv *iwm, const void *payload) { struct iwm_nonwifi_cmd *cmd; - int ret; + int ret, seq_num; cmd = kzalloc(sizeof(struct iwm_nonwifi_cmd), GFP_KERNEL); if (!cmd) { @@ -377,7 +379,7 @@ int iwm_hal_send_target_cmd(struct iwm_priv *iwm, return -ENOMEM; } - iwm_nonwifi_cmd_init(iwm, cmd, udma_cmd); + seq_num = iwm_nonwifi_cmd_init(iwm, cmd, udma_cmd); if (cmd->udma_cmd.opcode == UMAC_HDI_OUT_OPCODE_WRITE || cmd->udma_cmd.opcode == UMAC_HDI_OUT_OPCODE_WRITE_PERSISTENT) { @@ -393,7 +395,7 @@ int iwm_hal_send_target_cmd(struct iwm_priv *iwm, if (ret < 0) return ret; - return cmd->seq_num; + return seq_num; } static void iwm_build_lmac_hdr(struct iwm_priv *iwm, struct iwm_lmac_hdr *hdr, -- cgit v1.2.3 From 51def0bea92629dff02ff1de40603eb90c609c55 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 22 Jul 2009 14:06:56 +0000 Subject: imwc3200: move iwmc3200 SDIO ids to sdio_ids.h 1. add intel's sdio vendor id to sdio_ids.h 2. move iwmc3200 sdio devices' ids to sdio_ids.h Signed-off-by: Tomas Winkler Signed-off-by: David S. Miller --- drivers/net/wimax/i2400m/sdio.c | 12 +++++------- drivers/net/wireless/iwmc3200wifi/sdio.c | 4 +++- drivers/net/wireless/iwmc3200wifi/sdio.h | 3 --- include/linux/mmc/sdio_ids.h | 6 ++++++ 4 files changed, 14 insertions(+), 11 deletions(-) (limited to 'drivers/net/wireless/iwmc3200wifi') diff --git a/drivers/net/wimax/i2400m/sdio.c b/drivers/net/wimax/i2400m/sdio.c index 2538825d1c66..ea7b29034aab 100644 --- a/drivers/net/wimax/i2400m/sdio.c +++ b/drivers/net/wimax/i2400m/sdio.c @@ -58,6 +58,7 @@ */ #include +#include #include #include #include "i2400m-sdio.h" @@ -501,15 +502,12 @@ void i2400ms_remove(struct sdio_func *func) d_fnend(3, dev, "SDIO func %p\n", func); } -enum { - I2400MS_INTEL_VID = 0x89, -}; - static const struct sdio_device_id i2400ms_sdio_ids[] = { - /* Intel: i2400m WiMAX over SDIO */ - { SDIO_DEVICE(I2400MS_INTEL_VID, 0x1402) }, - { }, /* end: all zeroes */ + /* Intel: i2400m WiMAX (iwmc3200) over SDIO */ + { SDIO_DEVICE(SDIO_VENDOR_ID_INTEL, + SDIO_DEVICE_ID_INTEL_IWMC3200WIMAX) }, + { /* end: all zeroes */ }, }; MODULE_DEVICE_TABLE(sdio, i2400ms_sdio_ids); diff --git a/drivers/net/wireless/iwmc3200wifi/sdio.c b/drivers/net/wireless/iwmc3200wifi/sdio.c index b93f620ee4f1..8b1de84003ca 100644 --- a/drivers/net/wireless/iwmc3200wifi/sdio.c +++ b/drivers/net/wireless/iwmc3200wifi/sdio.c @@ -65,6 +65,7 @@ #include #include #include +#include #include #include @@ -492,7 +493,8 @@ static void iwm_sdio_remove(struct sdio_func *func) } static const struct sdio_device_id iwm_sdio_ids[] = { - { SDIO_DEVICE(SDIO_VENDOR_ID_INTEL, SDIO_DEVICE_ID_IWM) }, + { SDIO_DEVICE(SDIO_VENDOR_ID_INTEL, + SDIO_DEVICE_ID_INTEL_IWMC3200WIFI) }, { /* end: all zeroes */ }, }; MODULE_DEVICE_TABLE(sdio, iwm_sdio_ids); diff --git a/drivers/net/wireless/iwmc3200wifi/sdio.h b/drivers/net/wireless/iwmc3200wifi/sdio.h index b3c156b08dda..aab6b6892e45 100644 --- a/drivers/net/wireless/iwmc3200wifi/sdio.h +++ b/drivers/net/wireless/iwmc3200wifi/sdio.h @@ -39,9 +39,6 @@ #ifndef __IWM_SDIO_H__ #define __IWM_SDIO_H__ -#define SDIO_VENDOR_ID_INTEL 0x89 -#define SDIO_DEVICE_ID_IWM 0x1403 - #define IWM_SDIO_DATA_ADDR 0x0 #define IWM_SDIO_INTR_ENABLE_ADDR 0x14 #define IWM_SDIO_INTR_STATUS_ADDR 0x13 diff --git a/include/linux/mmc/sdio_ids.h b/include/linux/mmc/sdio_ids.h index 39751c8cde9c..2dbfb5a05994 100644 --- a/include/linux/mmc/sdio_ids.h +++ b/include/linux/mmc/sdio_ids.h @@ -22,6 +22,12 @@ /* * Vendors and devices. Sort key: vendor first, device next. */ +#define SDIO_VENDOR_ID_INTEL 0x0089 +#define SDIO_DEVICE_ID_INTEL_IWMC3200WIMAX 0x1402 +#define SDIO_DEVICE_ID_INTEL_IWMC3200WIFI 0x1403 +#define SDIO_DEVICE_ID_INTEL_IWMC3200TOP 0x1404 +#define SDIO_DEVICE_ID_INTEL_IWMC3200GPS 0x1405 +#define SDIO_DEVICE_ID_INTEL_IWMC3200BT 0x1406 #define SDIO_VENDOR_ID_MARVELL 0x02df #define SDIO_DEVICE_ID_MARVELL_LIBERTAS 0x9103 -- cgit v1.2.3 From 0e82ffe3b90bcad72cfe80e4379946b8fb0691ca Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 27 Jul 2009 12:01:50 +0200 Subject: cfg80211: combine iwfreq implementations Until now we implemented iwfreq for managed mode, we needed to keep the implementations separate, but now that we have all versions implemented we can combine them and export just one handler. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/wext.c | 34 +-------------- include/net/cfg80211.h | 20 +++------ net/mac80211/wext.c | 73 +------------------------------- net/wireless/core.h | 3 ++ net/wireless/ibss.c | 5 +-- net/wireless/nl80211.c | 2 + net/wireless/wext-compat.c | 54 ++++++++++++++++++++++- net/wireless/wext-compat.h | 21 +++++++++ net/wireless/wext-sme.c | 5 +-- 9 files changed, 91 insertions(+), 126 deletions(-) create mode 100644 net/wireless/wext-compat.h (limited to 'drivers/net/wireless/iwmc3200wifi') diff --git a/drivers/net/wireless/iwmc3200wifi/wext.c b/drivers/net/wireless/iwmc3200wifi/wext.c index c3c90d5963bf..8058e9991c30 100644 --- a/drivers/net/wireless/iwmc3200wifi/wext.c +++ b/drivers/net/wireless/iwmc3200wifi/wext.c @@ -27,36 +27,6 @@ #include "iwm.h" #include "commands.h" -static int iwm_wext_siwfreq(struct net_device *dev, - struct iw_request_info *info, - struct iw_freq *freq, char *extra) -{ - struct iwm_priv *iwm = ndev_to_iwm(dev); - - switch (iwm->conf.mode) { - case UMAC_MODE_IBSS: - return cfg80211_ibss_wext_siwfreq(dev, info, freq, extra); - default: - return -EOPNOTSUPP; - } -} - -static int iwm_wext_giwfreq(struct net_device *dev, - struct iw_request_info *info, - struct iw_freq *freq, char *extra) -{ - struct iwm_priv *iwm = ndev_to_iwm(dev); - - switch (iwm->conf.mode) { - case UMAC_MODE_IBSS: - return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra); - case UMAC_MODE_BSS: - return cfg80211_mgd_wext_giwfreq(dev, info, freq, extra); - default: - return -EOPNOTSUPP; - } -} - static int iwm_wext_siwap(struct net_device *dev, struct iw_request_info *info, struct sockaddr *ap_addr, char *extra) { @@ -125,8 +95,8 @@ static const iw_handler iwm_handlers[] = (iw_handler) cfg80211_wext_giwname, /* SIOCGIWNAME */ (iw_handler) NULL, /* SIOCSIWNWID */ (iw_handler) NULL, /* SIOCGIWNWID */ - (iw_handler) iwm_wext_siwfreq, /* SIOCSIWFREQ */ - (iw_handler) iwm_wext_giwfreq, /* SIOCGIWFREQ */ + (iw_handler) cfg80211_wext_siwfreq, /* SIOCSIWFREQ */ + (iw_handler) cfg80211_wext_giwfreq, /* SIOCGIWFREQ */ (iw_handler) cfg80211_wext_siwmode, /* SIOCSIWMODE */ (iw_handler) cfg80211_wext_giwmode, /* SIOCGIWMODE */ (iw_handler) NULL, /* SIOCSIWSENS */ diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 0d278777e39c..5d249c4bf225 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1595,12 +1595,6 @@ int cfg80211_wext_siwmlme(struct net_device *dev, int cfg80211_wext_giwrange(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra); -int cfg80211_ibss_wext_siwfreq(struct net_device *dev, - struct iw_request_info *info, - struct iw_freq *freq, char *extra); -int cfg80211_ibss_wext_giwfreq(struct net_device *dev, - struct iw_request_info *info, - struct iw_freq *freq, char *extra); int cfg80211_ibss_wext_siwessid(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *ssid); @@ -1614,12 +1608,6 @@ int cfg80211_ibss_wext_giwap(struct net_device *dev, struct iw_request_info *info, struct sockaddr *ap_addr, char *extra); -int cfg80211_mgd_wext_siwfreq(struct net_device *dev, - struct iw_request_info *info, - struct iw_freq *freq, char *extra); -int cfg80211_mgd_wext_giwfreq(struct net_device *dev, - struct iw_request_info *info, - struct iw_freq *freq, char *extra); int cfg80211_mgd_wext_siwessid(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *ssid); @@ -1642,8 +1630,12 @@ int cfg80211_wext_giwauth(struct net_device *dev, struct iw_request_info *info, struct iw_param *data, char *extra); -struct ieee80211_channel *cfg80211_wext_freq(struct wiphy *wiphy, - struct iw_freq *freq); +int cfg80211_wext_siwfreq(struct net_device *dev, + struct iw_request_info *info, + struct iw_freq *freq, char *extra); +int cfg80211_wext_giwfreq(struct net_device *dev, + struct iw_request_info *info, + struct iw_freq *freq, char *extra); int cfg80211_wext_siwrate(struct net_device *dev, struct iw_request_info *info, diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 5acb8140ee58..7cd9aa79ef52 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c @@ -27,75 +27,6 @@ #include "aes_ccm.h" -static int ieee80211_ioctl_siwfreq(struct net_device *dev, - struct iw_request_info *info, - struct iw_freq *freq, char *extra) -{ - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - struct ieee80211_local *local = sdata->local; - struct ieee80211_channel *chan; - - if (sdata->vif.type == NL80211_IFTYPE_ADHOC) - return cfg80211_ibss_wext_siwfreq(dev, info, freq, extra); - else if (sdata->vif.type == NL80211_IFTYPE_STATION) - return cfg80211_mgd_wext_siwfreq(dev, info, freq, extra); - - /* freq->e == 0: freq->m = channel; otherwise freq = m * 10^e */ - if (freq->e == 0) { - if (freq->m < 0) - return -EINVAL; - else - chan = ieee80211_get_channel(local->hw.wiphy, - ieee80211_channel_to_frequency(freq->m)); - } else { - int i, div = 1000000; - for (i = 0; i < freq->e; i++) - div /= 10; - if (div <= 0) - return -EINVAL; - chan = ieee80211_get_channel(local->hw.wiphy, freq->m / div); - } - - if (!chan) - return -EINVAL; - - if (chan->flags & IEEE80211_CHAN_DISABLED) - return -EINVAL; - - /* - * no change except maybe auto -> fixed, ignore the HT - * setting so you can fix a channel you're on already - */ - if (local->oper_channel == chan) - return 0; - - local->oper_channel = chan; - local->oper_channel_type = NL80211_CHAN_NO_HT; - ieee80211_hw_config(local, 0); - - return 0; -} - - -static int ieee80211_ioctl_giwfreq(struct net_device *dev, - struct iw_request_info *info, - struct iw_freq *freq, char *extra) -{ - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - - if (sdata->vif.type == NL80211_IFTYPE_ADHOC) - return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra); - else if (sdata->vif.type == NL80211_IFTYPE_STATION) - return cfg80211_mgd_wext_giwfreq(dev, info, freq, extra); - - freq->m = local->oper_channel->center_freq; - freq->e = 6; - - return 0; -} - - static int ieee80211_ioctl_siwessid(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *ssid) @@ -173,8 +104,8 @@ static const iw_handler ieee80211_handler[] = (iw_handler) cfg80211_wext_giwname, /* SIOCGIWNAME */ (iw_handler) NULL, /* SIOCSIWNWID */ (iw_handler) NULL, /* SIOCGIWNWID */ - (iw_handler) ieee80211_ioctl_siwfreq, /* SIOCSIWFREQ */ - (iw_handler) ieee80211_ioctl_giwfreq, /* SIOCGIWFREQ */ + (iw_handler) cfg80211_wext_siwfreq, /* SIOCSIWFREQ */ + (iw_handler) cfg80211_wext_giwfreq, /* SIOCGIWFREQ */ (iw_handler) cfg80211_wext_siwmode, /* SIOCSIWMODE */ (iw_handler) cfg80211_wext_giwmode, /* SIOCGIWMODE */ (iw_handler) NULL, /* SIOCSIWSENS */ diff --git a/net/wireless/core.h b/net/wireless/core.h index 4276b70cd975..6d903c1d721d 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -66,6 +66,9 @@ struct cfg80211_registered_device { struct work_struct conn_work; struct work_struct event_work; + /* current channel */ + struct ieee80211_channel *channel; + #ifdef CONFIG_CFG80211_DEBUGFS /* Debugfs entries */ struct wiphy_debugfsdentries { diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c index 8b65e212ae49..de9ac49cd907 100644 --- a/net/wireless/ibss.c +++ b/net/wireless/ibss.c @@ -7,6 +7,7 @@ #include #include #include +#include "wext-compat.h" #include "nl80211.h" @@ -312,8 +313,6 @@ int cfg80211_ibss_wext_siwfreq(struct net_device *dev, return err; } -/* temporary symbol - mark GPL - in the future the handler won't be */ -EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_siwfreq); int cfg80211_ibss_wext_giwfreq(struct net_device *dev, struct iw_request_info *info, @@ -342,8 +341,6 @@ int cfg80211_ibss_wext_giwfreq(struct net_device *dev, /* no channel if not joining */ return -EINVAL; } -/* temporary symbol - mark GPL - in the future the handler won't be */ -EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_giwfreq); int cfg80211_ibss_wext_siwessid(struct net_device *dev, struct iw_request_info *info, diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index c951eb2b07d5..0cd548267d4a 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -757,6 +757,8 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) channel_type); if (result) goto bad_res; + + rdev->channel = chan; } changed = 0; diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index c7351a98e660..fc2e7768967d 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c @@ -14,6 +14,7 @@ #include #include #include +#include "wext-compat.h" #include "core.h" int cfg80211_wext_giwname(struct net_device *dev, @@ -300,7 +301,6 @@ struct ieee80211_channel *cfg80211_wext_freq(struct wiphy *wiphy, return ERR_PTR(-EINVAL); return chan; } -EXPORT_SYMBOL_GPL(cfg80211_wext_freq); int cfg80211_wext_siwrts(struct net_device *dev, struct iw_request_info *info, @@ -759,6 +759,58 @@ int cfg80211_wext_giwencode(struct net_device *dev, } EXPORT_SYMBOL_GPL(cfg80211_wext_giwencode); +int cfg80211_wext_siwfreq(struct net_device *dev, + struct iw_request_info *info, + struct iw_freq *freq, char *extra) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); + struct ieee80211_channel *chan; + int err; + + switch (wdev->iftype) { + case NL80211_IFTYPE_STATION: + return cfg80211_mgd_wext_siwfreq(dev, info, freq, extra); + case NL80211_IFTYPE_ADHOC: + return cfg80211_ibss_wext_siwfreq(dev, info, freq, extra); + default: + chan = cfg80211_wext_freq(wdev->wiphy, freq); + if (!chan) + return -EINVAL; + if (IS_ERR(chan)) + return PTR_ERR(chan); + err = rdev->ops->set_channel(wdev->wiphy, chan, + NL80211_CHAN_NO_HT); + if (err) + return err; + rdev->channel = chan; + return 0; + } +} +EXPORT_SYMBOL_GPL(cfg80211_wext_siwfreq); + +int cfg80211_wext_giwfreq(struct net_device *dev, + struct iw_request_info *info, + struct iw_freq *freq, char *extra) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); + + switch (wdev->iftype) { + case NL80211_IFTYPE_STATION: + return cfg80211_mgd_wext_giwfreq(dev, info, freq, extra); + case NL80211_IFTYPE_ADHOC: + return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra); + default: + if (!rdev->channel) + return -EINVAL; + freq->m = rdev->channel->center_freq; + freq->e = 6; + return 0; + } +} +EXPORT_SYMBOL_GPL(cfg80211_wext_giwfreq); + int cfg80211_wext_siwtxpower(struct net_device *dev, struct iw_request_info *info, union iwreq_data *data, char *extra) diff --git a/net/wireless/wext-compat.h b/net/wireless/wext-compat.h new file mode 100644 index 000000000000..23a6b5a83f2d --- /dev/null +++ b/net/wireless/wext-compat.h @@ -0,0 +1,21 @@ +#ifndef __WEXT_COMPAT +#define __WEXT_COMPAT + +int cfg80211_ibss_wext_siwfreq(struct net_device *dev, + struct iw_request_info *info, + struct iw_freq *freq, char *extra); +int cfg80211_ibss_wext_giwfreq(struct net_device *dev, + struct iw_request_info *info, + struct iw_freq *freq, char *extra); + +int cfg80211_mgd_wext_siwfreq(struct net_device *dev, + struct iw_request_info *info, + struct iw_freq *freq, char *extra); +int cfg80211_mgd_wext_giwfreq(struct net_device *dev, + struct iw_request_info *info, + struct iw_freq *freq, char *extra); + +struct ieee80211_channel *cfg80211_wext_freq(struct wiphy *wiphy, + struct iw_freq *freq); + +#endif /* __WEXT_COMPAT */ diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c index 4c689fd865b0..509279a1cfb2 100644 --- a/net/wireless/wext-sme.c +++ b/net/wireless/wext-sme.c @@ -8,6 +8,7 @@ #include #include #include +#include "wext-compat.h" #include "nl80211.h" int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev, @@ -108,8 +109,6 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev, cfg80211_unlock_rdev(rdev); return err; } -/* temporary symbol - mark GPL - in the future the handler won't be */ -EXPORT_SYMBOL_GPL(cfg80211_mgd_wext_siwfreq); int cfg80211_mgd_wext_giwfreq(struct net_device *dev, struct iw_request_info *info, @@ -138,8 +137,6 @@ int cfg80211_mgd_wext_giwfreq(struct net_device *dev, /* no channel if not joining */ return -EINVAL; } -/* temporary symbol - mark GPL - in the future the handler won't be */ -EXPORT_SYMBOL_GPL(cfg80211_mgd_wext_giwfreq); int cfg80211_mgd_wext_siwessid(struct net_device *dev, struct iw_request_info *info, -- cgit v1.2.3 From 562e482265ac4d660d9f0114419591d62f44361d Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 27 Jul 2009 12:01:51 +0200 Subject: cfg80211: combine IWAP handlers Since we now have IWAP handlers for all modes, we can combine them into one. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/wext.c | 34 ++------------------- include/net/cfg80211.h | 24 ++++----------- net/mac80211/wext.c | 41 ++----------------------- net/wireless/ibss.c | 4 --- net/wireless/wext-compat.c | 52 +++++++++++++++++++++++++++----- net/wireless/wext-compat.h | 12 ++++++++ net/wireless/wext-sme.c | 4 --- 7 files changed, 66 insertions(+), 105 deletions(-) (limited to 'drivers/net/wireless/iwmc3200wifi') diff --git a/drivers/net/wireless/iwmc3200wifi/wext.c b/drivers/net/wireless/iwmc3200wifi/wext.c index 8058e9991c30..5319b16474e3 100644 --- a/drivers/net/wireless/iwmc3200wifi/wext.c +++ b/drivers/net/wireless/iwmc3200wifi/wext.c @@ -27,36 +27,6 @@ #include "iwm.h" #include "commands.h" -static int iwm_wext_siwap(struct net_device *dev, struct iw_request_info *info, - struct sockaddr *ap_addr, char *extra) -{ - struct iwm_priv *iwm = ndev_to_iwm(dev); - - switch (iwm->conf.mode) { - case UMAC_MODE_IBSS: - return cfg80211_ibss_wext_siwap(dev, info, ap_addr, extra); - case UMAC_MODE_BSS: - return cfg80211_mgd_wext_siwap(dev, info, ap_addr, extra); - default: - return -EOPNOTSUPP; - } -} - -static int iwm_wext_giwap(struct net_device *dev, struct iw_request_info *info, - struct sockaddr *ap_addr, char *extra) -{ - struct iwm_priv *iwm = ndev_to_iwm(dev); - - switch (iwm->conf.mode) { - case UMAC_MODE_IBSS: - return cfg80211_ibss_wext_giwap(dev, info, ap_addr, extra); - case UMAC_MODE_BSS: - return cfg80211_mgd_wext_giwap(dev, info, ap_addr, extra); - default: - return -EOPNOTSUPP; - } -} - static int iwm_wext_siwessid(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *ssid) @@ -111,8 +81,8 @@ static const iw_handler iwm_handlers[] = (iw_handler) NULL, /* SIOCGIWSPY */ (iw_handler) NULL, /* SIOCSIWTHRSPY */ (iw_handler) NULL, /* SIOCGIWTHRSPY */ - (iw_handler) iwm_wext_siwap, /* SIOCSIWAP */ - (iw_handler) iwm_wext_giwap, /* SIOCGIWAP */ + (iw_handler) cfg80211_wext_siwap, /* SIOCSIWAP */ + (iw_handler) cfg80211_wext_giwap, /* SIOCGIWAP */ (iw_handler) NULL, /* SIOCSIWMLME */ (iw_handler) NULL, /* SIOCGIWAPLIST */ (iw_handler) cfg80211_wext_siwscan, /* SIOCSIWSCAN */ diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 5d249c4bf225..3348c16e1f35 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1601,12 +1601,6 @@ int cfg80211_ibss_wext_siwessid(struct net_device *dev, int cfg80211_ibss_wext_giwessid(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *ssid); -int cfg80211_ibss_wext_siwap(struct net_device *dev, - struct iw_request_info *info, - struct sockaddr *ap_addr, char *extra); -int cfg80211_ibss_wext_giwap(struct net_device *dev, - struct iw_request_info *info, - struct sockaddr *ap_addr, char *extra); int cfg80211_mgd_wext_siwessid(struct net_device *dev, struct iw_request_info *info, @@ -1614,12 +1608,6 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev, int cfg80211_mgd_wext_giwessid(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *ssid); -int cfg80211_mgd_wext_siwap(struct net_device *dev, - struct iw_request_info *info, - struct sockaddr *ap_addr, char *extra); -int cfg80211_mgd_wext_giwap(struct net_device *dev, - struct iw_request_info *info, - struct sockaddr *ap_addr, char *extra); int cfg80211_wext_siwgenie(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra); @@ -1686,12 +1674,12 @@ int cfg80211_wext_giwpower(struct net_device *dev, struct iw_request_info *info, struct iw_param *wrq, char *extra); -int cfg80211_wds_wext_siwap(struct net_device *dev, - struct iw_request_info *info, - struct sockaddr *addr, char *extra); -int cfg80211_wds_wext_giwap(struct net_device *dev, - struct iw_request_info *info, - struct sockaddr *addr, char *extra); +int cfg80211_wext_siwap(struct net_device *dev, + struct iw_request_info *info, + struct sockaddr *ap_addr, char *extra); +int cfg80211_wext_giwap(struct net_device *dev, + struct iw_request_info *info, + struct sockaddr *ap_addr, char *extra); /* * callbacks for asynchronous cfg80211 methods, notification diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 7cd9aa79ef52..72866c8b8c3d 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c @@ -59,43 +59,6 @@ static int ieee80211_ioctl_giwessid(struct net_device *dev, } -static int ieee80211_ioctl_siwap(struct net_device *dev, - struct iw_request_info *info, - struct sockaddr *ap_addr, char *extra) -{ - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - - if (sdata->vif.type == NL80211_IFTYPE_ADHOC) - return cfg80211_ibss_wext_siwap(dev, info, ap_addr, extra); - - if (sdata->vif.type == NL80211_IFTYPE_STATION) - return cfg80211_mgd_wext_siwap(dev, info, ap_addr, extra); - - if (sdata->vif.type == NL80211_IFTYPE_WDS) - return cfg80211_wds_wext_siwap(dev, info, ap_addr, extra); - return -EOPNOTSUPP; -} - - -static int ieee80211_ioctl_giwap(struct net_device *dev, - struct iw_request_info *info, - struct sockaddr *ap_addr, char *extra) -{ - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - - if (sdata->vif.type == NL80211_IFTYPE_ADHOC) - return cfg80211_ibss_wext_giwap(dev, info, ap_addr, extra); - - if (sdata->vif.type == NL80211_IFTYPE_STATION) - return cfg80211_mgd_wext_giwap(dev, info, ap_addr, extra); - - if (sdata->vif.type == NL80211_IFTYPE_WDS) - return cfg80211_wds_wext_giwap(dev, info, ap_addr, extra); - - return -EOPNOTSUPP; -} - - /* Structures to export the Wireless Handlers */ static const iw_handler ieee80211_handler[] = @@ -120,8 +83,8 @@ static const iw_handler ieee80211_handler[] = (iw_handler) NULL, /* SIOCGIWSPY */ (iw_handler) NULL, /* SIOCSIWTHRSPY */ (iw_handler) NULL, /* SIOCGIWTHRSPY */ - (iw_handler) ieee80211_ioctl_siwap, /* SIOCSIWAP */ - (iw_handler) ieee80211_ioctl_giwap, /* SIOCGIWAP */ + (iw_handler) cfg80211_wext_siwap, /* SIOCSIWAP */ + (iw_handler) cfg80211_wext_giwap, /* SIOCGIWAP */ (iw_handler) cfg80211_wext_siwmlme, /* SIOCSIWMLME */ (iw_handler) NULL, /* SIOCGIWAPLIST */ (iw_handler) cfg80211_wext_siwscan, /* SIOCSIWSCAN */ diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c index de9ac49cd907..f955225ed911 100644 --- a/net/wireless/ibss.c +++ b/net/wireless/ibss.c @@ -466,8 +466,6 @@ int cfg80211_ibss_wext_siwap(struct net_device *dev, return err; } -/* temporary symbol - mark GPL - in the future the handler won't be */ -EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_siwap); int cfg80211_ibss_wext_giwap(struct net_device *dev, struct iw_request_info *info, @@ -493,6 +491,4 @@ int cfg80211_ibss_wext_giwap(struct net_device *dev, return 0; } -/* temporary symbol - mark GPL - in the future the handler won't be */ -EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_giwap); #endif diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index fc2e7768967d..c27774bd0107 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c @@ -1149,9 +1149,9 @@ int cfg80211_wext_giwpower(struct net_device *dev, } EXPORT_SYMBOL_GPL(cfg80211_wext_giwpower); -int cfg80211_wds_wext_siwap(struct net_device *dev, - struct iw_request_info *info, - struct sockaddr *addr, char *extra) +static int cfg80211_wds_wext_siwap(struct net_device *dev, + struct iw_request_info *info, + struct sockaddr *addr, char *extra) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); @@ -1177,11 +1177,10 @@ int cfg80211_wds_wext_siwap(struct net_device *dev, return 0; } -EXPORT_SYMBOL_GPL(cfg80211_wds_wext_siwap); -int cfg80211_wds_wext_giwap(struct net_device *dev, - struct iw_request_info *info, - struct sockaddr *addr, char *extra) +static int cfg80211_wds_wext_giwap(struct net_device *dev, + struct iw_request_info *info, + struct sockaddr *addr, char *extra) { struct wireless_dev *wdev = dev->ieee80211_ptr; @@ -1193,7 +1192,6 @@ int cfg80211_wds_wext_giwap(struct net_device *dev, return 0; } -EXPORT_SYMBOL_GPL(cfg80211_wds_wext_giwap); int cfg80211_wext_siwrate(struct net_device *dev, struct iw_request_info *info, @@ -1327,3 +1325,41 @@ struct iw_statistics *cfg80211_wireless_stats(struct net_device *dev) return &wstats; } EXPORT_SYMBOL_GPL(cfg80211_wireless_stats); + +int cfg80211_wext_siwap(struct net_device *dev, + struct iw_request_info *info, + struct sockaddr *ap_addr, char *extra) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + + switch (wdev->iftype) { + case NL80211_IFTYPE_ADHOC: + return cfg80211_ibss_wext_siwap(dev, info, ap_addr, extra); + case NL80211_IFTYPE_STATION: + return cfg80211_mgd_wext_siwap(dev, info, ap_addr, extra); + case NL80211_IFTYPE_WDS: + return cfg80211_wds_wext_siwap(dev, info, ap_addr, extra); + default: + return -EOPNOTSUPP; + } +} +EXPORT_SYMBOL_GPL(cfg80211_wext_siwap); + +int cfg80211_wext_giwap(struct net_device *dev, + struct iw_request_info *info, + struct sockaddr *ap_addr, char *extra) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + + switch (wdev->iftype) { + case NL80211_IFTYPE_ADHOC: + return cfg80211_ibss_wext_giwap(dev, info, ap_addr, extra); + case NL80211_IFTYPE_STATION: + return cfg80211_mgd_wext_giwap(dev, info, ap_addr, extra); + case NL80211_IFTYPE_WDS: + return cfg80211_wds_wext_giwap(dev, info, ap_addr, extra); + default: + return -EOPNOTSUPP; + } +} +EXPORT_SYMBOL_GPL(cfg80211_wext_giwap); diff --git a/net/wireless/wext-compat.h b/net/wireless/wext-compat.h index 23a6b5a83f2d..51028ebf19ae 100644 --- a/net/wireless/wext-compat.h +++ b/net/wireless/wext-compat.h @@ -7,6 +7,12 @@ int cfg80211_ibss_wext_siwfreq(struct net_device *dev, int cfg80211_ibss_wext_giwfreq(struct net_device *dev, struct iw_request_info *info, struct iw_freq *freq, char *extra); +int cfg80211_ibss_wext_siwap(struct net_device *dev, + struct iw_request_info *info, + struct sockaddr *ap_addr, char *extra); +int cfg80211_ibss_wext_giwap(struct net_device *dev, + struct iw_request_info *info, + struct sockaddr *ap_addr, char *extra); int cfg80211_mgd_wext_siwfreq(struct net_device *dev, struct iw_request_info *info, @@ -14,6 +20,12 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev, int cfg80211_mgd_wext_giwfreq(struct net_device *dev, struct iw_request_info *info, struct iw_freq *freq, char *extra); +int cfg80211_mgd_wext_siwap(struct net_device *dev, + struct iw_request_info *info, + struct sockaddr *ap_addr, char *extra); +int cfg80211_mgd_wext_giwap(struct net_device *dev, + struct iw_request_info *info, + struct sockaddr *ap_addr, char *extra); struct ieee80211_channel *cfg80211_wext_freq(struct wiphy *wiphy, struct iw_freq *freq); diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c index 509279a1cfb2..1aa31cc55113 100644 --- a/net/wireless/wext-sme.c +++ b/net/wireless/wext-sme.c @@ -273,8 +273,6 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev, cfg80211_unlock_rdev(wiphy_to_dev(wdev->wiphy)); return err; } -/* temporary symbol - mark GPL - in the future the handler won't be */ -EXPORT_SYMBOL_GPL(cfg80211_mgd_wext_siwap); int cfg80211_mgd_wext_giwap(struct net_device *dev, struct iw_request_info *info, @@ -299,8 +297,6 @@ int cfg80211_mgd_wext_giwap(struct net_device *dev, return 0; } -/* temporary symbol - mark GPL - in the future the handler won't be */ -EXPORT_SYMBOL_GPL(cfg80211_mgd_wext_giwap); int cfg80211_wext_siwgenie(struct net_device *dev, struct iw_request_info *info, -- cgit v1.2.3 From 1f9298f96082692bdfe73af6fc2167f627f21647 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 27 Jul 2009 12:01:52 +0200 Subject: cfg80211: combine IWESSID handlers Since we now have handlers IWESSID for all modes, we can combine them into one. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/wext.c | 36 ++------------------------------ include/net/cfg80211.h | 20 ++++++------------ net/mac80211/wext.c | 35 ++----------------------------- net/wireless/ibss.c | 4 ---- net/wireless/wext-compat.c | 34 ++++++++++++++++++++++++++++++ net/wireless/wext-compat.h | 12 +++++++++++ net/wireless/wext-sme.c | 4 ---- 7 files changed, 56 insertions(+), 89 deletions(-) (limited to 'drivers/net/wireless/iwmc3200wifi') diff --git a/drivers/net/wireless/iwmc3200wifi/wext.c b/drivers/net/wireless/iwmc3200wifi/wext.c index 5319b16474e3..9196024a2890 100644 --- a/drivers/net/wireless/iwmc3200wifi/wext.c +++ b/drivers/net/wireless/iwmc3200wifi/wext.c @@ -27,38 +27,6 @@ #include "iwm.h" #include "commands.h" -static int iwm_wext_siwessid(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *ssid) -{ - struct iwm_priv *iwm = ndev_to_iwm(dev); - - switch (iwm->conf.mode) { - case UMAC_MODE_IBSS: - return cfg80211_ibss_wext_siwessid(dev, info, data, ssid); - case UMAC_MODE_BSS: - return cfg80211_mgd_wext_siwessid(dev, info, data, ssid); - default: - return -EOPNOTSUPP; - } -} - -static int iwm_wext_giwessid(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *ssid) -{ - struct iwm_priv *iwm = ndev_to_iwm(dev); - - switch (iwm->conf.mode) { - case UMAC_MODE_IBSS: - return cfg80211_ibss_wext_giwessid(dev, info, data, ssid); - case UMAC_MODE_BSS: - return cfg80211_mgd_wext_giwessid(dev, info, data, ssid); - default: - return -EOPNOTSUPP; - } -} - static const iw_handler iwm_handlers[] = { (iw_handler) NULL, /* SIOCSIWCOMMIT */ @@ -87,8 +55,8 @@ static const iw_handler iwm_handlers[] = (iw_handler) NULL, /* SIOCGIWAPLIST */ (iw_handler) cfg80211_wext_siwscan, /* SIOCSIWSCAN */ (iw_handler) cfg80211_wext_giwscan, /* SIOCGIWSCAN */ - (iw_handler) iwm_wext_siwessid, /* SIOCSIWESSID */ - (iw_handler) iwm_wext_giwessid, /* SIOCGIWESSID */ + (iw_handler) cfg80211_wext_siwessid, /* SIOCSIWESSID */ + (iw_handler) cfg80211_wext_giwessid, /* SIOCGIWESSID */ (iw_handler) NULL, /* SIOCSIWNICKN */ (iw_handler) NULL, /* SIOCGIWNICKN */ (iw_handler) NULL, /* -- hole -- */ diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 3348c16e1f35..e1b92358242b 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1595,19 +1595,6 @@ int cfg80211_wext_siwmlme(struct net_device *dev, int cfg80211_wext_giwrange(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra); -int cfg80211_ibss_wext_siwessid(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *ssid); -int cfg80211_ibss_wext_giwessid(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *ssid); - -int cfg80211_mgd_wext_siwessid(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *ssid); -int cfg80211_mgd_wext_giwessid(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *ssid); int cfg80211_wext_siwgenie(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *extra); @@ -1624,7 +1611,12 @@ int cfg80211_wext_siwfreq(struct net_device *dev, int cfg80211_wext_giwfreq(struct net_device *dev, struct iw_request_info *info, struct iw_freq *freq, char *extra); - +int cfg80211_wext_siwessid(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *data, char *ssid); +int cfg80211_wext_giwessid(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *data, char *ssid); int cfg80211_wext_siwrate(struct net_device *dev, struct iw_request_info *info, struct iw_param *rate, char *extra); diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 72866c8b8c3d..aa250c3e8fda 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c @@ -27,37 +27,6 @@ #include "aes_ccm.h" -static int ieee80211_ioctl_siwessid(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *ssid) -{ - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - - if (sdata->vif.type == NL80211_IFTYPE_ADHOC) - return cfg80211_ibss_wext_siwessid(dev, info, data, ssid); - else if (sdata->vif.type == NL80211_IFTYPE_STATION) - return cfg80211_mgd_wext_siwessid(dev, info, data, ssid); - - return -EOPNOTSUPP; -} - - -static int ieee80211_ioctl_giwessid(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *ssid) -{ - struct ieee80211_sub_if_data *sdata; - - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - - if (sdata->vif.type == NL80211_IFTYPE_ADHOC) - return cfg80211_ibss_wext_giwessid(dev, info, data, ssid); - else if (sdata->vif.type == NL80211_IFTYPE_STATION) - return cfg80211_mgd_wext_giwessid(dev, info, data, ssid); - - return -EOPNOTSUPP; -} - /* Structures to export the Wireless Handlers */ @@ -89,8 +58,8 @@ static const iw_handler ieee80211_handler[] = (iw_handler) NULL, /* SIOCGIWAPLIST */ (iw_handler) cfg80211_wext_siwscan, /* SIOCSIWSCAN */ (iw_handler) cfg80211_wext_giwscan, /* SIOCGIWSCAN */ - (iw_handler) ieee80211_ioctl_siwessid, /* SIOCSIWESSID */ - (iw_handler) ieee80211_ioctl_giwessid, /* SIOCGIWESSID */ + (iw_handler) cfg80211_wext_siwessid, /* SIOCSIWESSID */ + (iw_handler) cfg80211_wext_giwessid, /* SIOCGIWESSID */ (iw_handler) NULL, /* SIOCSIWNICKN */ (iw_handler) NULL, /* SIOCGIWNICKN */ (iw_handler) NULL, /* -- hole -- */ diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c index f955225ed911..4d7a084b35e2 100644 --- a/net/wireless/ibss.c +++ b/net/wireless/ibss.c @@ -381,8 +381,6 @@ int cfg80211_ibss_wext_siwessid(struct net_device *dev, return err; } -/* temporary symbol - mark GPL - in the future the handler won't be */ -EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_siwessid); int cfg80211_ibss_wext_giwessid(struct net_device *dev, struct iw_request_info *info, @@ -410,8 +408,6 @@ int cfg80211_ibss_wext_giwessid(struct net_device *dev, return 0; } -/* temporary symbol - mark GPL - in the future the handler won't be */ -EXPORT_SYMBOL_GPL(cfg80211_ibss_wext_giwessid); int cfg80211_ibss_wext_siwap(struct net_device *dev, struct iw_request_info *info, diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index c27774bd0107..083e4c33d95d 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c @@ -1363,3 +1363,37 @@ int cfg80211_wext_giwap(struct net_device *dev, } } EXPORT_SYMBOL_GPL(cfg80211_wext_giwap); + +int cfg80211_wext_siwessid(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *data, char *ssid) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + + switch (wdev->iftype) { + case NL80211_IFTYPE_ADHOC: + return cfg80211_ibss_wext_siwessid(dev, info, data, ssid); + case NL80211_IFTYPE_STATION: + return cfg80211_mgd_wext_siwessid(dev, info, data, ssid); + default: + return -EOPNOTSUPP; + } +} +EXPORT_SYMBOL_GPL(cfg80211_wext_siwessid); + +int cfg80211_wext_giwessid(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *data, char *ssid) +{ + struct wireless_dev *wdev = dev->ieee80211_ptr; + + switch (wdev->iftype) { + case NL80211_IFTYPE_ADHOC: + return cfg80211_ibss_wext_giwessid(dev, info, data, ssid); + case NL80211_IFTYPE_STATION: + return cfg80211_mgd_wext_giwessid(dev, info, data, ssid); + default: + return -EOPNOTSUPP; + } +} +EXPORT_SYMBOL_GPL(cfg80211_wext_giwessid); diff --git a/net/wireless/wext-compat.h b/net/wireless/wext-compat.h index 51028ebf19ae..c0310d93c2e5 100644 --- a/net/wireless/wext-compat.h +++ b/net/wireless/wext-compat.h @@ -13,6 +13,12 @@ int cfg80211_ibss_wext_siwap(struct net_device *dev, int cfg80211_ibss_wext_giwap(struct net_device *dev, struct iw_request_info *info, struct sockaddr *ap_addr, char *extra); +int cfg80211_ibss_wext_siwessid(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *data, char *ssid); +int cfg80211_ibss_wext_giwessid(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *data, char *ssid); int cfg80211_mgd_wext_siwfreq(struct net_device *dev, struct iw_request_info *info, @@ -26,6 +32,12 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev, int cfg80211_mgd_wext_giwap(struct net_device *dev, struct iw_request_info *info, struct sockaddr *ap_addr, char *extra); +int cfg80211_mgd_wext_siwessid(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *data, char *ssid); +int cfg80211_mgd_wext_giwessid(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *data, char *ssid); struct ieee80211_channel *cfg80211_wext_freq(struct wiphy *wiphy, struct iw_freq *freq); diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c index 1aa31cc55113..7bacbd1c2af6 100644 --- a/net/wireless/wext-sme.c +++ b/net/wireless/wext-sme.c @@ -192,8 +192,6 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev, cfg80211_unlock_rdev(wiphy_to_dev(wdev->wiphy)); return err; } -/* temporary symbol - mark GPL - in the future the handler won't be */ -EXPORT_SYMBOL_GPL(cfg80211_mgd_wext_siwessid); int cfg80211_mgd_wext_giwessid(struct net_device *dev, struct iw_request_info *info, @@ -218,8 +216,6 @@ int cfg80211_mgd_wext_giwessid(struct net_device *dev, return 0; } -/* temporary symbol - mark GPL - in the future the handler won't be */ -EXPORT_SYMBOL_GPL(cfg80211_mgd_wext_giwessid); int cfg80211_mgd_wext_siwap(struct net_device *dev, struct iw_request_info *info, -- cgit v1.2.3 From a9a11622c5c742c115fad371c0397ae86dd3bb67 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 27 Jul 2009 12:01:53 +0200 Subject: cfg80211: self-contained wext handling where possible Finally! This is what you've all been waiting for! This patch makes cfg80211 take care of wext emulation _completely_ by itself, drivers that don't need things cfg80211 doesn't do yet don't even need to be aware of wireless extensions. This means we can also clean up mac80211's and iwm's Kconfig and make it possible to build them w/o wext now! RIP wext. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/Kconfig | 1 - drivers/net/wireless/iwmc3200wifi/Makefile | 2 +- drivers/net/wireless/iwmc3200wifi/iwm.h | 2 - drivers/net/wireless/iwmc3200wifi/netdev.c | 1 - drivers/net/wireless/iwmc3200wifi/wext.c | 95 ----------------------------- net/mac80211/Kconfig | 1 - net/mac80211/Makefile | 1 - net/mac80211/ieee80211_i.h | 4 -- net/mac80211/iface.c | 1 - net/mac80211/scan.c | 1 - net/mac80211/wext.c | 98 ------------------------------ net/wireless/core.c | 3 + net/wireless/mlme.c | 2 + net/wireless/scan.c | 1 + net/wireless/sme.c | 2 + net/wireless/wext-compat.c | 40 ++++++++++++ net/wireless/wext-compat.h | 5 ++ 17 files changed, 54 insertions(+), 206 deletions(-) delete mode 100644 drivers/net/wireless/iwmc3200wifi/wext.c delete mode 100644 net/mac80211/wext.c (limited to 'drivers/net/wireless/iwmc3200wifi') diff --git a/drivers/net/wireless/iwmc3200wifi/Kconfig b/drivers/net/wireless/iwmc3200wifi/Kconfig index 030401d367d3..c62da435285a 100644 --- a/drivers/net/wireless/iwmc3200wifi/Kconfig +++ b/drivers/net/wireless/iwmc3200wifi/Kconfig @@ -2,7 +2,6 @@ config IWM tristate "Intel Wireless Multicomm 3200 WiFi driver" depends on MMC && WLAN_80211 && EXPERIMENTAL depends on CFG80211 - select WIRELESS_EXT select FW_LOADER help The Intel Wireless Multicomm 3200 hardware is a combo diff --git a/drivers/net/wireless/iwmc3200wifi/Makefile b/drivers/net/wireless/iwmc3200wifi/Makefile index 927f022545c1..d34291b652d3 100644 --- a/drivers/net/wireless/iwmc3200wifi/Makefile +++ b/drivers/net/wireless/iwmc3200wifi/Makefile @@ -1,5 +1,5 @@ obj-$(CONFIG_IWM) := iwmc3200wifi.o iwmc3200wifi-objs += main.o netdev.o rx.o tx.o sdio.o hal.o fw.o -iwmc3200wifi-objs += commands.o wext.o cfg80211.o eeprom.o +iwmc3200wifi-objs += commands.o cfg80211.o eeprom.o iwmc3200wifi-$(CONFIG_IWM_DEBUG) += debugfs.o diff --git a/drivers/net/wireless/iwmc3200wifi/iwm.h b/drivers/net/wireless/iwmc3200wifi/iwm.h index 2175a481d2f4..7a51bc340fda 100644 --- a/drivers/net/wireless/iwmc3200wifi/iwm.h +++ b/drivers/net/wireless/iwmc3200wifi/iwm.h @@ -306,8 +306,6 @@ static inline void *iwm_private(struct iwm_priv *iwm) #define skb_to_rx_info(s) ((struct iwm_rx_info *)(s->cb)) #define skb_to_tx_info(s) ((struct iwm_tx_info *)s->cb) -extern const struct iw_handler_def iwm_iw_handler_def; - void *iwm_if_alloc(int sizeof_bus, struct device *dev, struct iwm_if_ops *if_ops); void iwm_if_free(struct iwm_priv *iwm); diff --git a/drivers/net/wireless/iwmc3200wifi/netdev.c b/drivers/net/wireless/iwmc3200wifi/netdev.c index 092d28ae56a0..30116d1b4489 100644 --- a/drivers/net/wireless/iwmc3200wifi/netdev.c +++ b/drivers/net/wireless/iwmc3200wifi/netdev.c @@ -123,7 +123,6 @@ void *iwm_if_alloc(int sizeof_bus, struct device *dev, } ndev->netdev_ops = &iwm_netdev_ops; - ndev->wireless_handlers = &iwm_iw_handler_def; ndev->ieee80211_ptr = wdev; SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy)); wdev->netdev = ndev; diff --git a/drivers/net/wireless/iwmc3200wifi/wext.c b/drivers/net/wireless/iwmc3200wifi/wext.c deleted file mode 100644 index 9196024a2890..000000000000 --- a/drivers/net/wireless/iwmc3200wifi/wext.c +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Intel Wireless Multicomm 3200 WiFi driver - * - * Copyright (C) 2009 Intel Corporation - * Samuel Ortiz - * Zhu Yi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version - * 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - */ - -#include -#include - -#include "iwm.h" -#include "commands.h" - -static const iw_handler iwm_handlers[] = -{ - (iw_handler) NULL, /* SIOCSIWCOMMIT */ - (iw_handler) cfg80211_wext_giwname, /* SIOCGIWNAME */ - (iw_handler) NULL, /* SIOCSIWNWID */ - (iw_handler) NULL, /* SIOCGIWNWID */ - (iw_handler) cfg80211_wext_siwfreq, /* SIOCSIWFREQ */ - (iw_handler) cfg80211_wext_giwfreq, /* SIOCGIWFREQ */ - (iw_handler) cfg80211_wext_siwmode, /* SIOCSIWMODE */ - (iw_handler) cfg80211_wext_giwmode, /* SIOCGIWMODE */ - (iw_handler) NULL, /* SIOCSIWSENS */ - (iw_handler) NULL, /* SIOCGIWSENS */ - (iw_handler) NULL /* not used */, /* SIOCSIWRANGE */ - (iw_handler) cfg80211_wext_giwrange, /* SIOCGIWRANGE */ - (iw_handler) NULL /* not used */, /* SIOCSIWPRIV */ - (iw_handler) NULL /* kernel code */, /* SIOCGIWPRIV */ - (iw_handler) NULL /* not used */, /* SIOCSIWSTATS */ - (iw_handler) NULL /* kernel code */, /* SIOCGIWSTATS */ - (iw_handler) NULL, /* SIOCSIWSPY */ - (iw_handler) NULL, /* SIOCGIWSPY */ - (iw_handler) NULL, /* SIOCSIWTHRSPY */ - (iw_handler) NULL, /* SIOCGIWTHRSPY */ - (iw_handler) cfg80211_wext_siwap, /* SIOCSIWAP */ - (iw_handler) cfg80211_wext_giwap, /* SIOCGIWAP */ - (iw_handler) NULL, /* SIOCSIWMLME */ - (iw_handler) NULL, /* SIOCGIWAPLIST */ - (iw_handler) cfg80211_wext_siwscan, /* SIOCSIWSCAN */ - (iw_handler) cfg80211_wext_giwscan, /* SIOCGIWSCAN */ - (iw_handler) cfg80211_wext_siwessid, /* SIOCSIWESSID */ - (iw_handler) cfg80211_wext_giwessid, /* SIOCGIWESSID */ - (iw_handler) NULL, /* SIOCSIWNICKN */ - (iw_handler) NULL, /* SIOCGIWNICKN */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* SIOCSIWRATE */ - (iw_handler) cfg80211_wext_giwrate, /* SIOCGIWRATE */ - (iw_handler) cfg80211_wext_siwrts, /* SIOCSIWRTS */ - (iw_handler) cfg80211_wext_giwrts, /* SIOCGIWRTS */ - (iw_handler) cfg80211_wext_siwfrag, /* SIOCSIWFRAG */ - (iw_handler) cfg80211_wext_giwfrag, /* SIOCGIWFRAG */ - (iw_handler) cfg80211_wext_siwtxpower, /* SIOCSIWTXPOW */ - (iw_handler) cfg80211_wext_giwtxpower, /* SIOCGIWTXPOW */ - (iw_handler) NULL, /* SIOCSIWRETRY */ - (iw_handler) NULL, /* SIOCGIWRETRY */ - (iw_handler) cfg80211_wext_siwencode, /* SIOCSIWENCODE */ - (iw_handler) cfg80211_wext_giwencode, /* SIOCGIWENCODE */ - (iw_handler) cfg80211_wext_siwpower, /* SIOCSIWPOWER */ - (iw_handler) cfg80211_wext_giwpower, /* SIOCGIWPOWER */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) cfg80211_wext_siwgenie, /* SIOCSIWGENIE */ - (iw_handler) NULL, /* SIOCGIWGENIE */ - (iw_handler) cfg80211_wext_siwauth, /* SIOCSIWAUTH */ - (iw_handler) cfg80211_wext_giwauth, /* SIOCGIWAUTH */ - (iw_handler) cfg80211_wext_siwencodeext, /* SIOCSIWENCODEEXT */ - (iw_handler) NULL, /* SIOCGIWENCODEEXT */ - (iw_handler) NULL, /* SIOCSIWPMKSA */ - (iw_handler) NULL, /* -- hole -- */ -}; - -const struct iw_handler_def iwm_iw_handler_def = { - .num_standard = ARRAY_SIZE(iwm_handlers), - .standard = (iw_handler *) iwm_handlers, - .get_wireless_stats = cfg80211_wireless_stats, -}; - diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index 19a4c66e143e..7dd77b6d4c9a 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig @@ -6,7 +6,6 @@ config MAC80211 select CRYPTO_ARC4 select CRYPTO_AES select CRC32 - select WIRELESS_EXT ---help--- This option enables the hardware independent IEEE 802.11 networking stack. diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile index 91284a74ff91..9f3cf7129324 100644 --- a/net/mac80211/Makefile +++ b/net/mac80211/Makefile @@ -3,7 +3,6 @@ obj-$(CONFIG_MAC80211) += mac80211.o # mac80211 objects mac80211-y := \ main.o \ - wext.o \ sta_info.o \ wep.o \ wpa.o \ diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index c6b25cb73284..aec6853cb435 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -24,7 +24,6 @@ #include #include #include -#include #include #include "key.h" #include "sta_info.h" @@ -951,9 +950,6 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, void ieee80211_configure_filter(struct ieee80211_local *local); u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata); -/* wireless extensions */ -extern const struct iw_handler_def ieee80211_iw_handler_def; - /* STA code */ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata); int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index d79a21105042..6c655b6547fb 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -684,7 +684,6 @@ static void ieee80211_if_setup(struct net_device *dev) { ether_setup(dev); dev->netdev_ops = &ieee80211_dataif_ops; - dev->wireless_handlers = &ieee80211_iw_handler_def; dev->destructor = free_netdev; } diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 147772a2977c..45731000eb8d 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -18,7 +18,6 @@ #include #include #include -#include #include "ieee80211_i.h" #include "driver-ops.h" diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c deleted file mode 100644 index aa250c3e8fda..000000000000 --- a/net/mac80211/wext.c +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright 2002-2005, Instant802 Networks, Inc. - * Copyright 2005-2006, Devicescape Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include "ieee80211_i.h" -#include "led.h" -#include "rate.h" -#include "wpa.h" -#include "aes_ccm.h" - - - -/* Structures to export the Wireless Handlers */ - -static const iw_handler ieee80211_handler[] = -{ - (iw_handler) NULL, /* SIOCSIWCOMMIT */ - (iw_handler) cfg80211_wext_giwname, /* SIOCGIWNAME */ - (iw_handler) NULL, /* SIOCSIWNWID */ - (iw_handler) NULL, /* SIOCGIWNWID */ - (iw_handler) cfg80211_wext_siwfreq, /* SIOCSIWFREQ */ - (iw_handler) cfg80211_wext_giwfreq, /* SIOCGIWFREQ */ - (iw_handler) cfg80211_wext_siwmode, /* SIOCSIWMODE */ - (iw_handler) cfg80211_wext_giwmode, /* SIOCGIWMODE */ - (iw_handler) NULL, /* SIOCSIWSENS */ - (iw_handler) NULL, /* SIOCGIWSENS */ - (iw_handler) NULL /* not used */, /* SIOCSIWRANGE */ - (iw_handler) cfg80211_wext_giwrange, /* SIOCGIWRANGE */ - (iw_handler) NULL /* not used */, /* SIOCSIWPRIV */ - (iw_handler) NULL /* kernel code */, /* SIOCGIWPRIV */ - (iw_handler) NULL /* not used */, /* SIOCSIWSTATS */ - (iw_handler) NULL /* kernel code */, /* SIOCGIWSTATS */ - (iw_handler) NULL, /* SIOCSIWSPY */ - (iw_handler) NULL, /* SIOCGIWSPY */ - (iw_handler) NULL, /* SIOCSIWTHRSPY */ - (iw_handler) NULL, /* SIOCGIWTHRSPY */ - (iw_handler) cfg80211_wext_siwap, /* SIOCSIWAP */ - (iw_handler) cfg80211_wext_giwap, /* SIOCGIWAP */ - (iw_handler) cfg80211_wext_siwmlme, /* SIOCSIWMLME */ - (iw_handler) NULL, /* SIOCGIWAPLIST */ - (iw_handler) cfg80211_wext_siwscan, /* SIOCSIWSCAN */ - (iw_handler) cfg80211_wext_giwscan, /* SIOCGIWSCAN */ - (iw_handler) cfg80211_wext_siwessid, /* SIOCSIWESSID */ - (iw_handler) cfg80211_wext_giwessid, /* SIOCGIWESSID */ - (iw_handler) NULL, /* SIOCSIWNICKN */ - (iw_handler) NULL, /* SIOCGIWNICKN */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) cfg80211_wext_siwrate, /* SIOCSIWRATE */ - (iw_handler) cfg80211_wext_giwrate, /* SIOCGIWRATE */ - (iw_handler) cfg80211_wext_siwrts, /* SIOCSIWRTS */ - (iw_handler) cfg80211_wext_giwrts, /* SIOCGIWRTS */ - (iw_handler) cfg80211_wext_siwfrag, /* SIOCSIWFRAG */ - (iw_handler) cfg80211_wext_giwfrag, /* SIOCGIWFRAG */ - (iw_handler) cfg80211_wext_siwtxpower, /* SIOCSIWTXPOW */ - (iw_handler) cfg80211_wext_giwtxpower, /* SIOCGIWTXPOW */ - (iw_handler) cfg80211_wext_siwretry, /* SIOCSIWRETRY */ - (iw_handler) cfg80211_wext_giwretry, /* SIOCGIWRETRY */ - (iw_handler) cfg80211_wext_siwencode, /* SIOCSIWENCODE */ - (iw_handler) cfg80211_wext_giwencode, /* SIOCGIWENCODE */ - (iw_handler) cfg80211_wext_siwpower, /* SIOCSIWPOWER */ - (iw_handler) cfg80211_wext_giwpower, /* SIOCGIWPOWER */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) cfg80211_wext_siwgenie, /* SIOCSIWGENIE */ - (iw_handler) NULL, /* SIOCGIWGENIE */ - (iw_handler) cfg80211_wext_siwauth, /* SIOCSIWAUTH */ - (iw_handler) cfg80211_wext_giwauth, /* SIOCGIWAUTH */ - (iw_handler) cfg80211_wext_siwencodeext, /* SIOCSIWENCODEEXT */ - (iw_handler) NULL, /* SIOCGIWENCODEEXT */ - (iw_handler) NULL, /* SIOCSIWPMKSA */ - (iw_handler) NULL, /* -- hole -- */ -}; - -const struct iw_handler_def ieee80211_iw_handler_def = -{ - .num_standard = ARRAY_SIZE(ieee80211_handler), - .standard = (iw_handler *) ieee80211_handler, - .get_wireless_stats = cfg80211_wireless_stats, -}; diff --git a/net/wireless/core.c b/net/wireless/core.c index 442c9f389799..f9fee65dc06a 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -19,6 +19,7 @@ #include "core.h" #include "sysfs.h" #include "debugfs.h" +#include "wext-compat.h" /* name for sysfs, %d is appended */ #define PHY_NAME "phy" @@ -665,6 +666,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, wdev->sme_state = CFG80211_SME_IDLE; mutex_unlock(&rdev->devlist_mtx); #ifdef CONFIG_WIRELESS_EXT + if (!dev->wireless_handlers) + dev->wireless_handlers = &cfg80211_wext_handler; wdev->wext.default_key = -1; wdev->wext.default_mgmt_key = -1; wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC; diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 30058a80d7af..097a87d7bae1 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c @@ -8,7 +8,9 @@ #include #include #include +#include #include +#include #include "core.h" #include "nl80211.h" diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 2a2683f6c04a..67714d7ed5b4 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -14,6 +14,7 @@ #include #include "core.h" #include "nl80211.h" +#include "wext-compat.h" #define IEEE80211_SCAN_RESULT_EXPIRE (15 * HZ) diff --git a/net/wireless/sme.c b/net/wireless/sme.c index a19741097989..d2b5d4ce0a00 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c @@ -8,6 +8,8 @@ #include #include #include +#include +#include #include #include #include "nl80211.h" diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index 083e4c33d95d..e4e90e249bab 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c @@ -1397,3 +1397,43 @@ int cfg80211_wext_giwessid(struct net_device *dev, } } EXPORT_SYMBOL_GPL(cfg80211_wext_giwessid); + +static const iw_handler cfg80211_handlers[] = { + [IW_IOCTL_IDX(SIOCGIWNAME)] = (iw_handler) cfg80211_wext_giwname, + [IW_IOCTL_IDX(SIOCSIWFREQ)] = (iw_handler) cfg80211_wext_siwfreq, + [IW_IOCTL_IDX(SIOCGIWFREQ)] = (iw_handler) cfg80211_wext_giwfreq, + [IW_IOCTL_IDX(SIOCSIWMODE)] = (iw_handler) cfg80211_wext_siwmode, + [IW_IOCTL_IDX(SIOCGIWMODE)] = (iw_handler) cfg80211_wext_giwmode, + [IW_IOCTL_IDX(SIOCGIWRANGE)] = (iw_handler) cfg80211_wext_giwrange, + [IW_IOCTL_IDX(SIOCSIWAP)] = (iw_handler) cfg80211_wext_siwap, + [IW_IOCTL_IDX(SIOCGIWAP)] = (iw_handler) cfg80211_wext_giwap, + [IW_IOCTL_IDX(SIOCSIWMLME)] = (iw_handler) cfg80211_wext_siwmlme, + [IW_IOCTL_IDX(SIOCSIWSCAN)] = (iw_handler) cfg80211_wext_siwscan, + [IW_IOCTL_IDX(SIOCGIWSCAN)] = (iw_handler) cfg80211_wext_giwscan, + [IW_IOCTL_IDX(SIOCSIWESSID)] = (iw_handler) cfg80211_wext_siwessid, + [IW_IOCTL_IDX(SIOCGIWESSID)] = (iw_handler) cfg80211_wext_giwessid, + [IW_IOCTL_IDX(SIOCSIWRATE)] = (iw_handler) cfg80211_wext_siwrate, + [IW_IOCTL_IDX(SIOCGIWRATE)] = (iw_handler) cfg80211_wext_giwrate, + [IW_IOCTL_IDX(SIOCSIWRTS)] = (iw_handler) cfg80211_wext_siwrts, + [IW_IOCTL_IDX(SIOCGIWRTS)] = (iw_handler) cfg80211_wext_giwrts, + [IW_IOCTL_IDX(SIOCSIWFRAG)] = (iw_handler) cfg80211_wext_siwfrag, + [IW_IOCTL_IDX(SIOCGIWFRAG)] = (iw_handler) cfg80211_wext_giwfrag, + [IW_IOCTL_IDX(SIOCSIWTXPOW)] = (iw_handler) cfg80211_wext_siwtxpower, + [IW_IOCTL_IDX(SIOCGIWTXPOW)] = (iw_handler) cfg80211_wext_giwtxpower, + [IW_IOCTL_IDX(SIOCSIWRETRY)] = (iw_handler) cfg80211_wext_siwretry, + [IW_IOCTL_IDX(SIOCGIWRETRY)] = (iw_handler) cfg80211_wext_giwretry, + [IW_IOCTL_IDX(SIOCSIWENCODE)] = (iw_handler) cfg80211_wext_siwencode, + [IW_IOCTL_IDX(SIOCGIWENCODE)] = (iw_handler) cfg80211_wext_giwencode, + [IW_IOCTL_IDX(SIOCSIWPOWER)] = (iw_handler) cfg80211_wext_siwpower, + [IW_IOCTL_IDX(SIOCGIWPOWER)] = (iw_handler) cfg80211_wext_giwpower, + [IW_IOCTL_IDX(SIOCSIWGENIE)] = (iw_handler) cfg80211_wext_siwgenie, + [IW_IOCTL_IDX(SIOCSIWAUTH)] = (iw_handler) cfg80211_wext_siwauth, + [IW_IOCTL_IDX(SIOCGIWAUTH)] = (iw_handler) cfg80211_wext_giwauth, + [IW_IOCTL_IDX(SIOCSIWENCODEEXT)]= (iw_handler) cfg80211_wext_siwencodeext, +}; + +const struct iw_handler_def cfg80211_wext_handler = { + .num_standard = ARRAY_SIZE(cfg80211_handlers), + .standard = cfg80211_handlers, + .get_wireless_stats = cfg80211_wireless_stats, +}; diff --git a/net/wireless/wext-compat.h b/net/wireless/wext-compat.h index c0310d93c2e5..9a3774749589 100644 --- a/net/wireless/wext-compat.h +++ b/net/wireless/wext-compat.h @@ -1,6 +1,9 @@ #ifndef __WEXT_COMPAT #define __WEXT_COMPAT +#include +#include + int cfg80211_ibss_wext_siwfreq(struct net_device *dev, struct iw_request_info *info, struct iw_freq *freq, char *extra); @@ -42,4 +45,6 @@ int cfg80211_mgd_wext_giwessid(struct net_device *dev, struct ieee80211_channel *cfg80211_wext_freq(struct wiphy *wiphy, struct iw_freq *freq); + +extern const struct iw_handler_def cfg80211_wext_handler; #endif /* __WEXT_COMPAT */ -- cgit v1.2.3 From 554503f8c9e11cbea92b7cf1e31f7e4d93ad4492 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Mon, 3 Aug 2009 14:37:01 +0800 Subject: iwmc3200wifi: fix set_wpa_version and set_auth_type order iwm->umac_profile->sec.flags is set by iwm_set_wpa_version and checked by iwm_set_auth_type. The patch changes the order to make the flag used correctly. Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/cfg80211.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless/iwmc3200wifi') diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.c b/drivers/net/wireless/iwmc3200wifi/cfg80211.c index 3f5a08fa401f..a6e852f4f92c 100644 --- a/drivers/net/wireless/iwmc3200wifi/cfg80211.c +++ b/drivers/net/wireless/iwmc3200wifi/cfg80211.c @@ -484,6 +484,8 @@ static int iwm_set_auth_type(struct iwm_priv *iwm, static int iwm_set_wpa_version(struct iwm_priv *iwm, u32 wpa_version) { + IWM_DBG_WEXT(iwm, DBG, "wpa_version: %d\n", wpa_version); + if (!wpa_version) { iwm->umac_profile->sec.flags = UMAC_SEC_FLG_LEGACY_PROFILE; return 0; @@ -508,6 +510,9 @@ static int iwm_set_cipher(struct iwm_priv *iwm, u32 cipher, bool ucast) return 0; } + IWM_DBG_WEXT(iwm, DBG, "%ccast cipher is 0x%x\n", ucast ? 'u' : 'm', + cipher); + switch (cipher) { case IW_AUTH_CIPHER_NONE: *profile_cipher = UMAC_CIPHER_TYPE_NONE; @@ -584,11 +589,11 @@ static int iwm_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, iwm->umac_profile->bss_num = 0; } - ret = iwm_set_auth_type(iwm, sme->auth_type); + ret = iwm_set_wpa_version(iwm, sme->crypto.wpa_versions); if (ret < 0) return ret; - ret = iwm_set_wpa_version(iwm, sme->crypto.wpa_versions); + ret = iwm_set_auth_type(iwm, sme->auth_type); if (ret < 0) return ret; -- cgit v1.2.3 From beda278d987cf7091302cf730c5b226d88e01c5b Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Mon, 3 Aug 2009 14:37:02 +0800 Subject: iwmc3200wifi: set WEP key static flag correctly We should only set the static_key flag for open and legacy authentication types. It should not be set for 802.1X and TKIP. Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/commands.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless/iwmc3200wifi') diff --git a/drivers/net/wireless/iwmc3200wifi/commands.c b/drivers/net/wireless/iwmc3200wifi/commands.c index 0d6637005f42..6b3626013fd2 100644 --- a/drivers/net/wireless/iwmc3200wifi/commands.c +++ b/drivers/net/wireless/iwmc3200wifi/commands.c @@ -596,6 +596,8 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, struct iwm_key *key) key_idx = key->hdr.key_idx; if (!remove) { + u8 auth_type = iwm->umac_profile->sec.auth_type; + IWM_DBG_WEXT(iwm, DBG, "key_idx:%d\n", key_idx); IWM_DBG_WEXT(iwm, DBG, "key_len:%d\n", key_len); IWM_DBG_WEXT(iwm, DBG, "MAC:%pM, idx:%d, multicast:%d\n", @@ -618,7 +620,9 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, struct iwm_key *key) memcpy(&wep40->key_hdr, key_hdr, sizeof(struct iwm_umac_key_hdr)); memcpy(wep40->key, key_data, key_len); - wep40->static_key = 1; + wep40->static_key = + !!((auth_type != UMAC_AUTH_TYPE_8021X) && + (auth_type != UMAC_AUTH_TYPE_RSNA_PSK)); cmd_size = sizeof(struct iwm_umac_key_wep40); break; @@ -632,7 +636,9 @@ int iwm_set_key(struct iwm_priv *iwm, bool remove, struct iwm_key *key) memcpy(&wep104->key_hdr, key_hdr, sizeof(struct iwm_umac_key_hdr)); memcpy(wep104->key, key_data, key_len); - wep104->static_key = 1; + wep104->static_key = + !!((auth_type != UMAC_AUTH_TYPE_8021X) && + (auth_type != UMAC_AUTH_TYPE_RSNA_PSK)); cmd_size = sizeof(struct iwm_umac_key_wep104); break; -- cgit v1.2.3 From 847c1e130092240c225a7be08607a7bf4e296fbd Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Mon, 3 Aug 2009 14:37:03 +0800 Subject: iwmc3200wifi: avoid setting default key for 802.1X and RSNA UMAC only allows us to set default key for WEP and auth type is not 802.1X or RSNA. This patch fixes iwmc3200wifi for 802.1X with WEP104. Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/commands.c | 39 ++++++++++++++++++---------- 1 file changed, 26 insertions(+), 13 deletions(-) (limited to 'drivers/net/wireless/iwmc3200wifi') diff --git a/drivers/net/wireless/iwmc3200wifi/commands.c b/drivers/net/wireless/iwmc3200wifi/commands.c index 6b3626013fd2..f0c8acdb71a4 100644 --- a/drivers/net/wireless/iwmc3200wifi/commands.c +++ b/drivers/net/wireless/iwmc3200wifi/commands.c @@ -526,19 +526,6 @@ int iwm_read_mac(struct iwm_priv *iwm, u8 *mac) return 0; } -int iwm_set_tx_key(struct iwm_priv *iwm, u8 key_idx) -{ - struct iwm_umac_tx_key_id tx_key_id; - - tx_key_id.hdr.oid = UMAC_WIFI_IF_CMD_GLOBAL_TX_KEY_ID; - tx_key_id.hdr.buf_size = cpu_to_le16(sizeof(struct iwm_umac_tx_key_id) - - sizeof(struct iwm_umac_wifi_if)); - - tx_key_id.key_idx = key_idx; - - return iwm_send_wifi_if_cmd(iwm, &tx_key_id, sizeof(tx_key_id), 1); -} - static int iwm_check_profile(struct iwm_priv *iwm) { if (!iwm->umac_profile_active) @@ -572,6 +559,32 @@ static int iwm_check_profile(struct iwm_priv *iwm) return 0; } +int iwm_set_tx_key(struct iwm_priv *iwm, u8 key_idx) +{ + struct iwm_umac_tx_key_id tx_key_id; + int ret; + + ret = iwm_check_profile(iwm); + if (ret < 0) + return ret; + + /* UMAC only allows to set default key for WEP and auth type is + * NOT 802.1X or RSNA. */ + if ((iwm->umac_profile->sec.ucast_cipher != UMAC_CIPHER_TYPE_WEP_40 && + iwm->umac_profile->sec.ucast_cipher != UMAC_CIPHER_TYPE_WEP_104) || + iwm->umac_profile->sec.auth_type == UMAC_AUTH_TYPE_8021X || + iwm->umac_profile->sec.auth_type == UMAC_AUTH_TYPE_RSNA_PSK) + return 0; + + tx_key_id.hdr.oid = UMAC_WIFI_IF_CMD_GLOBAL_TX_KEY_ID; + tx_key_id.hdr.buf_size = cpu_to_le16(sizeof(struct iwm_umac_tx_key_id) - + sizeof(struct iwm_umac_wifi_if)); + + tx_key_id.key_idx = key_idx; + + return iwm_send_wifi_if_cmd(iwm, &tx_key_id, sizeof(tx_key_id), 1); +} + int iwm_set_key(struct iwm_priv *iwm, bool remove, struct iwm_key *key) { int ret = 0; -- cgit v1.2.3 From ae73abf2350de7cbfc5c46a936f4d2a532b36679 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Tue, 1 Sep 2009 15:13:58 +0200 Subject: iwmc3200wifi: invalidate profile when necessary before connect If cfg80211 requests to connect when we have already had an active profile, invalidate the current profile first before sending a new profile to UMAC. Signed-off-by: Zhu Yi Signed-off-by: Samuel Ortiz Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/cfg80211.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers/net/wireless/iwmc3200wifi') diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.c b/drivers/net/wireless/iwmc3200wifi/cfg80211.c index a6e852f4f92c..789ef5ca88ba 100644 --- a/drivers/net/wireless/iwmc3200wifi/cfg80211.c +++ b/drivers/net/wireless/iwmc3200wifi/cfg80211.c @@ -326,11 +326,8 @@ static int iwm_cfg80211_change_iface(struct wiphy *wiphy, iwm->umac_profile->mode = cpu_to_le32(iwm->conf.mode); - if (iwm->umac_profile_active) { - int ret = iwm_invalidate_mlme_profile(iwm); - if (ret < 0) - IWM_ERR(iwm, "Couldn't invalidate profile\n"); - } + if (iwm->umac_profile_active) + iwm_invalidate_mlme_profile(iwm); return 0; } @@ -573,6 +570,14 @@ static int iwm_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, if (!sme->ssid) return -EINVAL; + if (iwm->umac_profile_active) { + ret = iwm_invalidate_mlme_profile(iwm); + if (ret) { + IWM_ERR(iwm, "Couldn't invalidate profile\n"); + return ret; + } + } + if (chan) iwm->channel = ieee80211_frequency_to_channel(chan->center_freq); -- cgit v1.2.3 From b90a5c9561d3f75f906a84613cc0071121143fb6 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Tue, 1 Sep 2009 15:13:59 +0200 Subject: iwmc3200wifi: Set WEP key from connect When connect is called with the LEGACY_PSK authentication type set, and a proper sme->key, we need to set the WEP key straight after setting the profile otherwise the authentication will never start. Signed-off-by: Samuel Ortiz Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/cfg80211.c | 44 +++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless/iwmc3200wifi') diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.c b/drivers/net/wireless/iwmc3200wifi/cfg80211.c index 789ef5ca88ba..d8bb723d88d9 100644 --- a/drivers/net/wireless/iwmc3200wifi/cfg80211.c +++ b/drivers/net/wireless/iwmc3200wifi/cfg80211.c @@ -562,6 +562,7 @@ static int iwm_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, { struct iwm_priv *iwm = wiphy_to_iwm(wiphy); struct ieee80211_channel *chan = sme->channel; + struct key_params key_param; int ret; if (!test_bit(IWM_STATUS_READY, &iwm->status)) @@ -619,7 +620,48 @@ static int iwm_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, return ret; } - return iwm_send_mlme_profile(iwm); + /* + * We save the WEP key in case we want to do shared authentication. + * We have to do it so because UMAC will assert whenever it gets a + * key before a profile. + */ + if (sme->key) { + key_param.key = kmemdup(sme->key, sme->key_len, GFP_KERNEL); + if (key_param.key == NULL) + return -ENOMEM; + key_param.key_len = sme->key_len; + key_param.seq_len = 0; + key_param.cipher = sme->crypto.ciphers_pairwise[0]; + + ret = iwm_key_init(&iwm->keys[sme->key_idx], sme->key_idx, + NULL, &key_param); + kfree(key_param.key); + if (ret < 0) { + IWM_ERR(iwm, "Invalid key_params\n"); + return ret; + } + + iwm->default_key = sme->key_idx; + } + + ret = iwm_send_mlme_profile(iwm); + + if (iwm->umac_profile->sec.auth_type != UMAC_AUTH_TYPE_LEGACY_PSK || + sme->key == NULL) + return ret; + + /* + * We want to do shared auth. + * We need to actually set the key we previously cached, + * and then tell the UMAC it's the default one. + * That will trigger the auth+assoc UMAC machinery, and again, + * this must be done after setting the profile. + */ + ret = iwm_set_key(iwm, 0, &iwm->keys[sme->key_idx]); + if (ret < 0) + return ret; + + return iwm_set_tx_key(iwm, iwm->default_key); } static int iwm_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, -- cgit v1.2.3 From d041811d931d4f515fd58e222757cbc7d6375db4 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Tue, 1 Sep 2009 15:14:00 +0200 Subject: iwmc3200wifi: Fix sparse warning iwm_cfg80211_get_station() should be static. Signed-off-by: Samuel Ortiz Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/cfg80211.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless/iwmc3200wifi') diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.c b/drivers/net/wireless/iwmc3200wifi/cfg80211.c index d8bb723d88d9..2784b089f491 100644 --- a/drivers/net/wireless/iwmc3200wifi/cfg80211.c +++ b/drivers/net/wireless/iwmc3200wifi/cfg80211.c @@ -238,8 +238,9 @@ static int iwm_cfg80211_set_default_key(struct wiphy *wiphy, return iwm_set_tx_key(iwm, key_index); } -int iwm_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, - u8 *mac, struct station_info *sinfo) +static int iwm_cfg80211_get_station(struct wiphy *wiphy, + struct net_device *ndev, + u8 *mac, struct station_info *sinfo) { struct iwm_priv *iwm = ndev_to_iwm(ndev); -- cgit v1.2.3 From de15fd31fcabb4b81a556736dd67ec4f71462f07 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Tue, 1 Sep 2009 15:14:01 +0200 Subject: iwmc3200wifi: use cfg80211_roamed to send roam event The device sends connection terminated and [re]association success (or failure) events when roaming occours. The patch uses cfg80211_roamed instead of cfg80211_connect_result to notify SME for roaming. Signed-off-by: Zhu Yi Signed-off-by: Samuel Ortiz Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/cfg80211.c | 2 +- drivers/net/wireless/iwmc3200wifi/commands.c | 1 + drivers/net/wireless/iwmc3200wifi/iwm.h | 2 +- drivers/net/wireless/iwmc3200wifi/rx.c | 26 ++++++++++++++++++++------ 4 files changed, 23 insertions(+), 8 deletions(-) (limited to 'drivers/net/wireless/iwmc3200wifi') diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.c b/drivers/net/wireless/iwmc3200wifi/cfg80211.c index 2784b089f491..a56a2b0ac99a 100644 --- a/drivers/net/wireless/iwmc3200wifi/cfg80211.c +++ b/drivers/net/wireless/iwmc3200wifi/cfg80211.c @@ -673,7 +673,7 @@ static int iwm_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, IWM_DBG_WEXT(iwm, DBG, "Active: %d\n", iwm->umac_profile_active); if (iwm->umac_profile_active) - return iwm_invalidate_mlme_profile(iwm); + iwm_invalidate_mlme_profile(iwm); return 0; } diff --git a/drivers/net/wireless/iwmc3200wifi/commands.c b/drivers/net/wireless/iwmc3200wifi/commands.c index a68a2aff3c1e..23b52fa2605f 100644 --- a/drivers/net/wireless/iwmc3200wifi/commands.c +++ b/drivers/net/wireless/iwmc3200wifi/commands.c @@ -756,6 +756,7 @@ int iwm_send_mlme_profile(struct iwm_priv *iwm) return ret; } + set_bit(IWM_STATUS_SME_CONNECTING, &iwm->status); return 0; } diff --git a/drivers/net/wireless/iwmc3200wifi/iwm.h b/drivers/net/wireless/iwmc3200wifi/iwm.h index 7a51bc340fda..f054cc828d8d 100644 --- a/drivers/net/wireless/iwmc3200wifi/iwm.h +++ b/drivers/net/wireless/iwmc3200wifi/iwm.h @@ -175,7 +175,7 @@ struct iwm_key { #define IWM_STATUS_READY 0 #define IWM_STATUS_SCANNING 1 #define IWM_STATUS_SCAN_ABORTING 2 -#define IWM_STATUS_ASSOCIATING 3 +#define IWM_STATUS_SME_CONNECTING 3 #define IWM_STATUS_ASSOCIATED 4 struct iwm_tx_queue { diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index 86079a187eef..9e6f2cd38d60 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c @@ -487,8 +487,6 @@ static int iwm_mlme_assoc_start(struct iwm_priv *iwm, u8 *buf, start = (struct iwm_umac_notif_assoc_start *)buf; - set_bit(IWM_STATUS_ASSOCIATING, &iwm->status); - IWM_DBG_MLME(iwm, INFO, "Association with %pM Started, reason: %d\n", start->bssid, le32_to_cpu(start->roam_reason)); @@ -507,14 +505,23 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf, IWM_DBG_MLME(iwm, INFO, "Association with %pM completed, status: %d\n", complete->bssid, complete->status); - clear_bit(IWM_STATUS_ASSOCIATING, &iwm->status); - switch (le32_to_cpu(complete->status)) { case UMAC_ASSOC_COMPLETE_SUCCESS: set_bit(IWM_STATUS_ASSOCIATED, &iwm->status); memcpy(iwm->bssid, complete->bssid, ETH_ALEN); iwm->channel = complete->channel; + /* Internal roaming state, avoid notifying SME. */ + if (!test_and_clear_bit(IWM_STATUS_SME_CONNECTING, &iwm->status) + && iwm->conf.mode == UMAC_MODE_BSS) { + cfg80211_roamed(iwm_to_ndev(iwm), + complete->bssid, + iwm->req_ie, iwm->req_ie_len, + iwm->resp_ie, iwm->resp_ie_len, + GFP_KERNEL); + break; + } + iwm_link_on(iwm); if (iwm->conf.mode == UMAC_MODE_IBSS) @@ -531,6 +538,11 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf, memset(iwm->bssid, 0, ETH_ALEN); iwm->channel = 0; + /* Internal roaming state, avoid notifying SME. */ + if (!test_and_clear_bit(IWM_STATUS_SME_CONNECTING, &iwm->status) + && iwm->conf.mode == UMAC_MODE_BSS) + break; + iwm_link_off(iwm); if (iwm->conf.mode == UMAC_MODE_IBSS) @@ -540,6 +552,7 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf, NULL, 0, NULL, 0, WLAN_STATUS_UNSPECIFIED_FAILURE, GFP_KERNEL); + break; default: break; } @@ -562,7 +575,7 @@ static int iwm_mlme_profile_invalidate(struct iwm_priv *iwm, u8 *buf, IWM_DBG_MLME(iwm, INFO, "Profile Invalidated. Reason: %d\n", le32_to_cpu(invalid->reason)); - clear_bit(IWM_STATUS_ASSOCIATING, &iwm->status); + clear_bit(IWM_STATUS_SME_CONNECTING, &iwm->status); clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status); iwm->umac_profile_active = 0; @@ -813,7 +826,8 @@ static int iwm_mlme_mgt_frame(struct iwm_priv *iwm, u8 *buf, iwm->resp_ie = kmemdup(mgt->u.reassoc_resp.variable, iwm->resp_ie_len, GFP_KERNEL); } else { - IWM_ERR(iwm, "Unsupported management frame"); + IWM_ERR(iwm, "Unsupported management frame: 0x%x", + cpu_to_le16(mgt->frame_control)); return 0; } -- cgit v1.2.3 From c7436273889e0ce511b317041f35344e92344885 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Tue, 1 Sep 2009 15:14:02 +0200 Subject: iwmc3200wifi: add disconnect work When the driver receives "connection terminated" event from device, it could be caused by 2 reasons: the firmware is roaming or the connection is lost (AP disappears). For the former, an association complete event is supposed to come within 3 seconds. For the latter, the driver won't receive any event except the connection terminated. So we kick a delayed work (5*HZ) when we receive the connection terminated event. It will be canceled if it turns out to be a roaming event later. Otherwise we notify SME and userspace the disconnection. Signed-off-by: Zhu Yi Signed-off-by: Samuel Ortiz Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/iwm.h | 1 + drivers/net/wireless/iwmc3200wifi/main.c | 21 +++++++++++++++++++++ drivers/net/wireless/iwmc3200wifi/rx.c | 32 +++++++++++++++++++++++++++----- 3 files changed, 49 insertions(+), 5 deletions(-) (limited to 'drivers/net/wireless/iwmc3200wifi') diff --git a/drivers/net/wireless/iwmc3200wifi/iwm.h b/drivers/net/wireless/iwmc3200wifi/iwm.h index f054cc828d8d..da49df6f4020 100644 --- a/drivers/net/wireless/iwmc3200wifi/iwm.h +++ b/drivers/net/wireless/iwmc3200wifi/iwm.h @@ -273,6 +273,7 @@ struct iwm_priv { struct iw_statistics wstats; struct delayed_work stats_request; + struct delayed_work disconnect; struct iwm_debugfs dbg; diff --git a/drivers/net/wireless/iwmc3200wifi/main.c b/drivers/net/wireless/iwmc3200wifi/main.c index cf2574442b57..c41fa8c5fa11 100644 --- a/drivers/net/wireless/iwmc3200wifi/main.c +++ b/drivers/net/wireless/iwmc3200wifi/main.c @@ -108,6 +108,26 @@ static void iwm_statistics_request(struct work_struct *work) iwm_send_umac_stats_req(iwm, 0); } +static void iwm_disconnect_work(struct work_struct *work) +{ + struct iwm_priv *iwm = + container_of(work, struct iwm_priv, disconnect.work); + + if (iwm->umac_profile_active) + iwm_invalidate_mlme_profile(iwm); + + clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status); + iwm->umac_profile_active = 0; + memset(iwm->bssid, 0, ETH_ALEN); + iwm->channel = 0; + + iwm_link_off(iwm); + + wake_up_interruptible(&iwm->mlme_queue); + + cfg80211_disconnected(iwm_to_ndev(iwm), 0, NULL, 0, GFP_KERNEL); +} + int __iwm_up(struct iwm_priv *iwm); int __iwm_down(struct iwm_priv *iwm); @@ -198,6 +218,7 @@ int iwm_priv_init(struct iwm_priv *iwm) spin_lock_init(&iwm->cmd_lock); iwm->scan_id = 1; INIT_DELAYED_WORK(&iwm->stats_request, iwm_statistics_request); + INIT_DELAYED_WORK(&iwm->disconnect, iwm_disconnect_work); INIT_WORK(&iwm->reset_worker, iwm_reset_worker); INIT_LIST_HEAD(&iwm->bss_list); diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index 9e6f2cd38d60..4d9793e68650 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c @@ -514,6 +514,7 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf, /* Internal roaming state, avoid notifying SME. */ if (!test_and_clear_bit(IWM_STATUS_SME_CONNECTING, &iwm->status) && iwm->conf.mode == UMAC_MODE_BSS) { + cancel_delayed_work(&iwm->disconnect); cfg80211_roamed(iwm_to_ndev(iwm), complete->bssid, iwm->req_ie, iwm->req_ie_len, @@ -540,8 +541,10 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf, /* Internal roaming state, avoid notifying SME. */ if (!test_and_clear_bit(IWM_STATUS_SME_CONNECTING, &iwm->status) - && iwm->conf.mode == UMAC_MODE_BSS) + && iwm->conf.mode == UMAC_MODE_BSS) { + cancel_delayed_work(&iwm->disconnect); break; + } iwm_link_off(iwm); @@ -569,11 +572,18 @@ static int iwm_mlme_profile_invalidate(struct iwm_priv *iwm, u8 *buf, struct iwm_wifi_cmd *cmd) { struct iwm_umac_notif_profile_invalidate *invalid; + u32 reason; invalid = (struct iwm_umac_notif_profile_invalidate *)buf; + reason = le32_to_cpu(invalid->reason); + + IWM_DBG_MLME(iwm, INFO, "Profile Invalidated. Reason: %d\n", reason); - IWM_DBG_MLME(iwm, INFO, "Profile Invalidated. Reason: %d\n", - le32_to_cpu(invalid->reason)); + if (reason != UMAC_PROFILE_INVALID_REQUEST && + test_bit(IWM_STATUS_SME_CONNECTING, &iwm->status)) + cfg80211_connect_result(iwm_to_ndev(iwm), NULL, NULL, 0, NULL, + 0, WLAN_STATUS_UNSPECIFIED_FAILURE, + GFP_KERNEL); clear_bit(IWM_STATUS_SME_CONNECTING, &iwm->status); clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status); @@ -589,6 +599,19 @@ static int iwm_mlme_profile_invalidate(struct iwm_priv *iwm, u8 *buf, return 0; } +#define IWM_DISCONNECT_INTERVAL (5 * HZ) + +static int iwm_mlme_connection_terminated(struct iwm_priv *iwm, u8 *buf, + unsigned long buf_size, + struct iwm_wifi_cmd *cmd) +{ + IWM_DBG_MLME(iwm, DBG, "Connection terminated\n"); + + schedule_delayed_work(&iwm->disconnect, IWM_DISCONNECT_INTERVAL); + + return 0; +} + static int iwm_mlme_scan_complete(struct iwm_priv *iwm, u8 *buf, unsigned long buf_size, struct iwm_wifi_cmd *cmd) @@ -848,8 +871,7 @@ static int iwm_ntf_mlme(struct iwm_priv *iwm, u8 *buf, case WIFI_IF_NTFY_PROFILE_INVALIDATE_COMPLETE: return iwm_mlme_profile_invalidate(iwm, buf, buf_size, cmd); case WIFI_IF_NTFY_CONNECTION_TERMINATED: - IWM_DBG_MLME(iwm, DBG, "Connection terminated\n"); - break; + return iwm_mlme_connection_terminated(iwm, buf, buf_size, cmd); case WIFI_IF_NTFY_SCAN_COMPLETE: return iwm_mlme_scan_complete(iwm, buf, buf_size, cmd); case WIFI_IF_NTFY_STA_TABLE_CHANGE: -- cgit v1.2.3 From 31452420ca956f2cf37f705c869e265c33894f07 Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Tue, 1 Sep 2009 15:14:03 +0200 Subject: iwmc3200wifi: fix misuse of le16_to_cpu Also mark some functions static. Signed-off-by: Zhu Yi Signed-off-by: Samuel Ortiz Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/main.c | 8 ++++---- drivers/net/wireless/iwmc3200wifi/rx.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/net/wireless/iwmc3200wifi') diff --git a/drivers/net/wireless/iwmc3200wifi/main.c b/drivers/net/wireless/iwmc3200wifi/main.c index c41fa8c5fa11..6cf2f0c0911e 100644 --- a/drivers/net/wireless/iwmc3200wifi/main.c +++ b/drivers/net/wireless/iwmc3200wifi/main.c @@ -128,8 +128,8 @@ static void iwm_disconnect_work(struct work_struct *work) cfg80211_disconnected(iwm_to_ndev(iwm), 0, NULL, 0, GFP_KERNEL); } -int __iwm_up(struct iwm_priv *iwm); -int __iwm_down(struct iwm_priv *iwm); +static int __iwm_up(struct iwm_priv *iwm); +static int __iwm_down(struct iwm_priv *iwm); static void iwm_reset_worker(struct work_struct *work) { @@ -559,7 +559,7 @@ static int iwm_channels_init(struct iwm_priv *iwm) return 0; } -int __iwm_up(struct iwm_priv *iwm) +static int __iwm_up(struct iwm_priv *iwm) { int ret; struct iwm_notif *notif_reboot, *notif_ack = NULL; @@ -693,7 +693,7 @@ int iwm_up(struct iwm_priv *iwm) return ret; } -int __iwm_down(struct iwm_priv *iwm) +static int __iwm_down(struct iwm_priv *iwm) { int ret; diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index 4d9793e68650..2daa58633e6f 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c @@ -850,7 +850,7 @@ static int iwm_mlme_mgt_frame(struct iwm_priv *iwm, u8 *buf, iwm->resp_ie_len, GFP_KERNEL); } else { IWM_ERR(iwm, "Unsupported management frame: 0x%x", - cpu_to_le16(mgt->frame_control)); + le16_to_cpu(mgt->frame_control)); return 0; } -- cgit v1.2.3 From d04bd6283cf7433d56f3d8f648f1d6963fda4fdc Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Tue, 1 Sep 2009 15:14:04 +0200 Subject: iwmc3200wifi: New initial LMAC calibration The LMAC calibration API got broken mostly by having a configuration bitmap being different than the result one. This patch tries to address that issue by correctly running calibrations with the newest firmwares, and keeping a backward compatibility fallback path for older firmwares, where the configuration and result bitmaps were identical. Signed-off-by: Samuel Ortiz Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/fw.c | 56 ++++++++++++++++++++++---------- drivers/net/wireless/iwmc3200wifi/iwm.h | 1 + drivers/net/wireless/iwmc3200wifi/lmac.h | 15 +++++++++ drivers/net/wireless/iwmc3200wifi/main.c | 7 +++- 4 files changed, 61 insertions(+), 18 deletions(-) (limited to 'drivers/net/wireless/iwmc3200wifi') diff --git a/drivers/net/wireless/iwmc3200wifi/fw.c b/drivers/net/wireless/iwmc3200wifi/fw.c index 0f32cab9ced4..6b0bcad758ca 100644 --- a/drivers/net/wireless/iwmc3200wifi/fw.c +++ b/drivers/net/wireless/iwmc3200wifi/fw.c @@ -261,6 +261,33 @@ static int iwm_load_lmac(struct iwm_priv *iwm, const char *img_name) cpu_to_le32(UMAC_RST_CTRL_FLG_LARC_CLK_EN), 0); } +static int iwm_init_calib(struct iwm_priv *iwm, unsigned long cfg_bitmap, + unsigned long expected_bitmap, u8 rx_iq_cmd) +{ + /* Read RX IQ calibration result from EEPROM */ + if (test_bit(rx_iq_cmd, &cfg_bitmap)) { + iwm_store_rxiq_calib_result(iwm); + set_bit(PHY_CALIBRATE_RX_IQ_CMD, &iwm->calib_done_map); + } + + iwm_send_prio_table(iwm); + iwm_send_init_calib_cfg(iwm, cfg_bitmap); + + while (iwm->calib_done_map != expected_bitmap) { + if (iwm_notif_handle(iwm, CALIBRATION_RES_NOTIFICATION, + IWM_SRC_LMAC, WAIT_NOTIF_TIMEOUT)) { + IWM_DBG_FW(iwm, DBG, "Initial calibration timeout\n"); + return -ETIMEDOUT; + } + + IWM_DBG_FW(iwm, DBG, "Got calibration result. calib_done_map: " + "0x%lx, expected calibrations: 0x%lx\n", + iwm->calib_done_map, expected_bitmap); + } + + return 0; +} + /* * We currently have to load 3 FWs: * 1) The UMAC (Upper MAC). @@ -276,6 +303,7 @@ static int iwm_load_lmac(struct iwm_priv *iwm, const char *img_name) int iwm_load_fw(struct iwm_priv *iwm) { unsigned long init_calib_map, periodic_calib_map; + unsigned long expected_calib_map; int ret; /* We first start downloading the UMAC */ @@ -317,27 +345,21 @@ int iwm_load_fw(struct iwm_priv *iwm) } init_calib_map = iwm->conf.calib_map & IWM_CALIB_MAP_INIT_MSK; + expected_calib_map = iwm->conf.expected_calib_map & + IWM_CALIB_MAP_INIT_MSK; periodic_calib_map = IWM_CALIB_MAP_PER_LMAC(iwm->conf.calib_map); - /* Read RX IQ calibration result from EEPROM */ - if (test_bit(PHY_CALIBRATE_RX_IQ_CMD, &init_calib_map)) { - iwm_store_rxiq_calib_result(iwm); - set_bit(PHY_CALIBRATE_RX_IQ_CMD, &iwm->calib_done_map); - } - - iwm_send_prio_table(iwm); - iwm_send_init_calib_cfg(iwm, init_calib_map); - - while (iwm->calib_done_map != init_calib_map) { - ret = iwm_notif_handle(iwm, CALIBRATION_RES_NOTIFICATION, - IWM_SRC_LMAC, WAIT_NOTIF_TIMEOUT); - if (ret) { - IWM_ERR(iwm, "Wait for calibration result timeout\n"); + ret = iwm_init_calib(iwm, init_calib_map, expected_calib_map, + CALIB_CFG_RX_IQ_IDX); + if (ret < 0) { + /* Let's try the old way */ + ret = iwm_init_calib(iwm, expected_calib_map, + expected_calib_map, + PHY_CALIBRATE_RX_IQ_CMD); + if (ret < 0) { + IWM_ERR(iwm, "Calibration result timeout\n"); goto out; } - IWM_DBG_FW(iwm, DBG, "Got calibration result. calib_done_map: " - "0x%lx, requested calibrations: 0x%lx\n", - iwm->calib_done_map, init_calib_map); } /* Handle LMAC CALIBRATION_COMPLETE notification */ diff --git a/drivers/net/wireless/iwmc3200wifi/iwm.h b/drivers/net/wireless/iwmc3200wifi/iwm.h index da49df6f4020..74964ee93bb7 100644 --- a/drivers/net/wireless/iwmc3200wifi/iwm.h +++ b/drivers/net/wireless/iwmc3200wifi/iwm.h @@ -64,6 +64,7 @@ struct iwm_conf { u32 sdio_ior_timeout; unsigned long calib_map; + unsigned long expected_calib_map; bool reset_on_fatal_err; bool auto_connect; bool wimax_not_present; diff --git a/drivers/net/wireless/iwmc3200wifi/lmac.h b/drivers/net/wireless/iwmc3200wifi/lmac.h index 19213e165f5f..6c1a14c4480f 100644 --- a/drivers/net/wireless/iwmc3200wifi/lmac.h +++ b/drivers/net/wireless/iwmc3200wifi/lmac.h @@ -396,9 +396,24 @@ enum { CALIBRATION_CMD_NUM, }; +enum { + CALIB_CFG_RX_BB_IDX = 0, + CALIB_CFG_DC_IDX = 1, + CALIB_CFG_LO_IDX = 2, + CALIB_CFG_TX_IQ_IDX = 3, + CALIB_CFG_RX_IQ_IDX = 4, + CALIB_CFG_NOISE_IDX = 5, + CALIB_CFG_CRYSTAL_IDX = 6, + CALIB_CFG_TEMPERATURE_IDX = 7, + CALIB_CFG_PAPD_IDX = 8, + CALIB_CFG_LAST_IDX = CALIB_CFG_PAPD_IDX, + CALIB_CFG_MODULE_NUM, +}; + #define IWM_CALIB_MAP_INIT_MSK 0xFFFF #define IWM_CALIB_MAP_PER_LMAC(m) ((m & 0xFF0000) >> 16) #define IWM_CALIB_MAP_PER_UMAC(m) ((m & 0xFF000000) >> 24) +#define IWM_CALIB_OPCODE_TO_INDEX(op) (op - PHY_CALIBRATE_OPCODES_NUM) struct iwm_lmac_calib_hdr { u8 opcode; diff --git a/drivers/net/wireless/iwmc3200wifi/main.c b/drivers/net/wireless/iwmc3200wifi/main.c index 6cf2f0c0911e..fc7fce44a9d7 100644 --- a/drivers/net/wireless/iwmc3200wifi/main.c +++ b/drivers/net/wireless/iwmc3200wifi/main.c @@ -53,7 +53,12 @@ static struct iwm_conf def_iwm_conf = { .sdio_ior_timeout = 5000, - .calib_map = BIT(PHY_CALIBRATE_DC_CMD) | + .calib_map = BIT(CALIB_CFG_DC_IDX) | + BIT(CALIB_CFG_LO_IDX) | + BIT(CALIB_CFG_TX_IQ_IDX) | + BIT(CALIB_CFG_RX_IQ_IDX) | + BIT(SHILOH_PHY_CALIBRATE_BASE_BAND_CMD), + .expected_calib_map = BIT(PHY_CALIBRATE_DC_CMD) | BIT(PHY_CALIBRATE_LO_CMD) | BIT(PHY_CALIBRATE_TX_IQ_CMD) | BIT(PHY_CALIBRATE_RX_IQ_CMD) | -- cgit v1.2.3 From d210176eaaed0c7883caba52665bcfb5d420c660 Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Tue, 1 Sep 2009 15:14:05 +0200 Subject: iwmc3200wifi: Handle UMAC stalls and UMAC assert properly When UMAC stalls or asserts, we want to reset the device. But when we're associated, the current reset worker will end up calling cfg80211_connect_result() with the cfg80211 sme layer knowing that we're reassociating. That ends up with some ugly warnings. With this patch we're telling the upper layer that we've roamed if reassociation succeeds, and that we're disconnected if it fails. Signed-off-by: Samuel Ortiz Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/iwm.h | 2 ++ drivers/net/wireless/iwmc3200wifi/main.c | 18 +++++++++++++++--- drivers/net/wireless/iwmc3200wifi/rx.c | 29 +++++++++++++++++++++++------ 3 files changed, 40 insertions(+), 9 deletions(-) (limited to 'drivers/net/wireless/iwmc3200wifi') diff --git a/drivers/net/wireless/iwmc3200wifi/iwm.h b/drivers/net/wireless/iwmc3200wifi/iwm.h index 74964ee93bb7..f5c2d6f3fd43 100644 --- a/drivers/net/wireless/iwmc3200wifi/iwm.h +++ b/drivers/net/wireless/iwmc3200wifi/iwm.h @@ -178,6 +178,7 @@ struct iwm_key { #define IWM_STATUS_SCAN_ABORTING 2 #define IWM_STATUS_SME_CONNECTING 3 #define IWM_STATUS_ASSOCIATED 4 +#define IWM_STATUS_RESETTING 5 struct iwm_tx_queue { int id; @@ -317,6 +318,7 @@ int iwm_mode_to_nl80211_iftype(int mode); int iwm_priv_init(struct iwm_priv *iwm); void iwm_priv_deinit(struct iwm_priv *iwm); void iwm_reset(struct iwm_priv *iwm); +void iwm_resetting(struct iwm_priv *iwm); void iwm_tx_credit_init_pools(struct iwm_priv *iwm, struct iwm_umac_notif_alive *alive); int iwm_tx_credit_alloc(struct iwm_priv *iwm, int id, int nb); diff --git a/drivers/net/wireless/iwmc3200wifi/main.c b/drivers/net/wireless/iwmc3200wifi/main.c index fc7fce44a9d7..6a5b76acb645 100644 --- a/drivers/net/wireless/iwmc3200wifi/main.c +++ b/drivers/net/wireless/iwmc3200wifi/main.c @@ -187,7 +187,8 @@ static void iwm_reset_worker(struct work_struct *work) memcpy(iwm->umac_profile, profile, sizeof(*profile)); iwm_send_mlme_profile(iwm); kfree(profile); - } + } else + clear_bit(IWM_STATUS_RESETTING, &iwm->status); out: mutex_unlock(&iwm->mutex); @@ -200,7 +201,7 @@ static void iwm_watchdog(unsigned long data) IWM_WARN(iwm, "Watchdog expired: UMAC stalls!\n"); if (modparam_reset) - schedule_work(&iwm->reset_worker); + iwm_resetting(iwm); } int iwm_priv_init(struct iwm_priv *iwm) @@ -284,7 +285,11 @@ void iwm_reset(struct iwm_priv *iwm) if (test_bit(IWM_STATUS_READY, &iwm->status)) iwm_target_reset(iwm); - iwm->status = 0; + if (test_bit(IWM_STATUS_RESETTING, &iwm->status)) { + iwm->status = 0; + set_bit(IWM_STATUS_RESETTING, &iwm->status); + } else + iwm->status = 0; iwm->scan_id = 1; list_for_each_entry_safe(notif, next, &iwm->pending_notif, pending) { @@ -300,6 +305,13 @@ void iwm_reset(struct iwm_priv *iwm) iwm_link_off(iwm); } +void iwm_resetting(struct iwm_priv *iwm) +{ + set_bit(IWM_STATUS_RESETTING, &iwm->status); + + schedule_work(&iwm->reset_worker); +} + /* * Notification code: * diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index 2daa58633e6f..14950b147f91 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c @@ -118,6 +118,8 @@ static int iwm_ntf_error(struct iwm_priv *iwm, u8 *buf, IWM_ERR(iwm, "\tLMAC status: 0x%x\n", le32_to_cpu(fw_err->lmac_status)); IWM_ERR(iwm, "\tSDIO status: 0x%x\n", le32_to_cpu(fw_err->sdio_status)); + iwm_resetting(iwm); + return 0; } @@ -528,11 +530,19 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf, if (iwm->conf.mode == UMAC_MODE_IBSS) goto ibss; - cfg80211_connect_result(iwm_to_ndev(iwm), + if (!test_bit(IWM_STATUS_RESETTING, &iwm->status)) + cfg80211_connect_result(iwm_to_ndev(iwm), + complete->bssid, + iwm->req_ie, iwm->req_ie_len, + iwm->resp_ie, iwm->resp_ie_len, + WLAN_STATUS_SUCCESS, + GFP_KERNEL); + else + cfg80211_roamed(iwm_to_ndev(iwm), complete->bssid, iwm->req_ie, iwm->req_ie_len, iwm->resp_ie, iwm->resp_ie_len, - WLAN_STATUS_SUCCESS, GFP_KERNEL); + GFP_KERNEL); break; case UMAC_ASSOC_COMPLETE_FAILURE: clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status); @@ -551,19 +561,26 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf, if (iwm->conf.mode == UMAC_MODE_IBSS) goto ibss; - cfg80211_connect_result(iwm_to_ndev(iwm), complete->bssid, - NULL, 0, NULL, 0, - WLAN_STATUS_UNSPECIFIED_FAILURE, - GFP_KERNEL); + if (!test_bit(IWM_STATUS_RESETTING, &iwm->status)) + cfg80211_connect_result(iwm_to_ndev(iwm), + complete->bssid, + NULL, 0, NULL, 0, + WLAN_STATUS_UNSPECIFIED_FAILURE, + GFP_KERNEL); + else + cfg80211_disconnected(iwm_to_ndev(iwm), 0, NULL, 0, + GFP_KERNEL); break; default: break; } + clear_bit(IWM_STATUS_RESETTING, &iwm->status); return 0; ibss: cfg80211_ibss_joined(iwm_to_ndev(iwm), iwm->bssid, GFP_KERNEL); + clear_bit(IWM_STATUS_RESETTING, &iwm->status); return 0; } -- cgit v1.2.3 From 04e715cd46ba523806070fbf9ded009f10e107cd Mon Sep 17 00:00:00 2001 From: Samuel Ortiz Date: Tue, 1 Sep 2009 15:14:06 +0200 Subject: iwmc3200wifi: Add a last_fw_err debugfs entry In order to check what was the last fw error we got accross resets, we add this debugfs entry. It displays the complete ASSERT information. Signed-off-by: Samuel Ortiz Signed-off-by: John W. Linville --- drivers/net/wireless/iwmc3200wifi/debug.h | 2 + drivers/net/wireless/iwmc3200wifi/debugfs.c | 105 ++++++++++++++++++++++++++-- drivers/net/wireless/iwmc3200wifi/iwm.h | 2 + drivers/net/wireless/iwmc3200wifi/main.c | 6 ++ drivers/net/wireless/iwmc3200wifi/rx.c | 2 + 5 files changed, 113 insertions(+), 4 deletions(-) (limited to 'drivers/net/wireless/iwmc3200wifi') diff --git a/drivers/net/wireless/iwmc3200wifi/debug.h b/drivers/net/wireless/iwmc3200wifi/debug.h index 8fbb42d9c21f..e35c9b693d1f 100644 --- a/drivers/net/wireless/iwmc3200wifi/debug.h +++ b/drivers/net/wireless/iwmc3200wifi/debug.h @@ -108,6 +108,8 @@ struct iwm_debugfs { struct dentry *txq_dentry; struct dentry *tx_credit_dentry; struct dentry *rx_ticket_dentry; + + struct dentry *fw_err_dentry; }; #ifdef CONFIG_IWM_DEBUG diff --git a/drivers/net/wireless/iwmc3200wifi/debugfs.c b/drivers/net/wireless/iwmc3200wifi/debugfs.c index 0fa7b9150d58..1465379f900a 100644 --- a/drivers/net/wireless/iwmc3200wifi/debugfs.c +++ b/drivers/net/wireless/iwmc3200wifi/debugfs.c @@ -98,7 +98,7 @@ DEFINE_SIMPLE_ATTRIBUTE(fops_iwm_dbg_modules, iwm_debugfs_u32_read, iwm_debugfs_dbg_modules_write, "%llu\n"); -static int iwm_txrx_open(struct inode *inode, struct file *filp) +static int iwm_generic_open(struct inode *inode, struct file *filp) { filp->private_data = inode->i_private; return 0; @@ -289,25 +289,111 @@ static ssize_t iwm_debugfs_rx_ticket_read(struct file *filp, return ret; } +static ssize_t iwm_debugfs_fw_err_read(struct file *filp, + char __user *buffer, + size_t count, loff_t *ppos) +{ + + struct iwm_priv *iwm = filp->private_data; + char buf[512]; + int buf_len = 512; + size_t len = 0; + + if (*ppos != 0) + return 0; + if (count < sizeof(buf)) + return -ENOSPC; + + if (!iwm->last_fw_err) + return -ENOMEM; + + if (iwm->last_fw_err->line_num == 0) + goto out; + + len += snprintf(buf + len, buf_len - len, "%cMAC FW ERROR:\n", + (le32_to_cpu(iwm->last_fw_err->category) == UMAC_SYS_ERR_CAT_LMAC) + ? 'L' : 'U'); + len += snprintf(buf + len, buf_len - len, + "\tCategory: %d\n", + le32_to_cpu(iwm->last_fw_err->category)); + + len += snprintf(buf + len, buf_len - len, + "\tStatus: 0x%x\n", + le32_to_cpu(iwm->last_fw_err->status)); + + len += snprintf(buf + len, buf_len - len, + "\tPC: 0x%x\n", + le32_to_cpu(iwm->last_fw_err->pc)); + + len += snprintf(buf + len, buf_len - len, + "\tblink1: %d\n", + le32_to_cpu(iwm->last_fw_err->blink1)); + + len += snprintf(buf + len, buf_len - len, + "\tblink2: %d\n", + le32_to_cpu(iwm->last_fw_err->blink2)); + + len += snprintf(buf + len, buf_len - len, + "\tilink1: %d\n", + le32_to_cpu(iwm->last_fw_err->ilink1)); + + len += snprintf(buf + len, buf_len - len, + "\tilink2: %d\n", + le32_to_cpu(iwm->last_fw_err->ilink2)); + + len += snprintf(buf + len, buf_len - len, + "\tData1: 0x%x\n", + le32_to_cpu(iwm->last_fw_err->data1)); + + len += snprintf(buf + len, buf_len - len, + "\tData2: 0x%x\n", + le32_to_cpu(iwm->last_fw_err->data2)); + + len += snprintf(buf + len, buf_len - len, + "\tLine number: %d\n", + le32_to_cpu(iwm->last_fw_err->line_num)); + + len += snprintf(buf + len, buf_len - len, + "\tUMAC status: 0x%x\n", + le32_to_cpu(iwm->last_fw_err->umac_status)); + + len += snprintf(buf + len, buf_len - len, + "\tLMAC status: 0x%x\n", + le32_to_cpu(iwm->last_fw_err->lmac_status)); + + len += snprintf(buf + len, buf_len - len, + "\tSDIO status: 0x%x\n", + le32_to_cpu(iwm->last_fw_err->sdio_status)); + +out: + + return simple_read_from_buffer(buffer, len, ppos, buf, buf_len); +} static const struct file_operations iwm_debugfs_txq_fops = { .owner = THIS_MODULE, - .open = iwm_txrx_open, + .open = iwm_generic_open, .read = iwm_debugfs_txq_read, }; static const struct file_operations iwm_debugfs_tx_credit_fops = { .owner = THIS_MODULE, - .open = iwm_txrx_open, + .open = iwm_generic_open, .read = iwm_debugfs_tx_credit_read, }; static const struct file_operations iwm_debugfs_rx_ticket_fops = { .owner = THIS_MODULE, - .open = iwm_txrx_open, + .open = iwm_generic_open, .read = iwm_debugfs_rx_ticket_read, }; +static const struct file_operations iwm_debugfs_fw_err_fops = { + .owner = THIS_MODULE, + .open = iwm_generic_open, + .read = iwm_debugfs_fw_err_read, +}; + int iwm_debugfs_init(struct iwm_priv *iwm) { int i, result; @@ -423,6 +509,16 @@ int iwm_debugfs_init(struct iwm_priv *iwm) goto error; } + iwm->dbg.fw_err_dentry = debugfs_create_file("last_fw_err", 0200, + iwm->dbg.dbgdir, iwm, + &iwm_debugfs_fw_err_fops); + result = PTR_ERR(iwm->dbg.fw_err_dentry); + if (IS_ERR(iwm->dbg.fw_err_dentry) && (result != -ENODEV)) { + IWM_ERR(iwm, "Couldn't create last FW err: %d\n", result); + goto error; + } + + return 0; error: @@ -441,6 +537,7 @@ void iwm_debugfs_exit(struct iwm_priv *iwm) debugfs_remove(iwm->dbg.txq_dentry); debugfs_remove(iwm->dbg.tx_credit_dentry); debugfs_remove(iwm->dbg.rx_ticket_dentry); + debugfs_remove(iwm->dbg.fw_err_dentry); if (iwm->bus_ops->debugfs_exit) iwm->bus_ops->debugfs_exit(iwm); diff --git a/drivers/net/wireless/iwmc3200wifi/iwm.h b/drivers/net/wireless/iwmc3200wifi/iwm.h index f5c2d6f3fd43..1b02a4e2a1ac 100644 --- a/drivers/net/wireless/iwmc3200wifi/iwm.h +++ b/drivers/net/wireless/iwmc3200wifi/iwm.h @@ -289,6 +289,8 @@ struct iwm_priv { u8 *resp_ie; int resp_ie_len; + struct iwm_fw_error_hdr *last_fw_err; + char private[0] __attribute__((__aligned__(NETDEV_ALIGN))); }; diff --git a/drivers/net/wireless/iwmc3200wifi/main.c b/drivers/net/wireless/iwmc3200wifi/main.c index 6a5b76acb645..d668e4756324 100644 --- a/drivers/net/wireless/iwmc3200wifi/main.c +++ b/drivers/net/wireless/iwmc3200wifi/main.c @@ -260,6 +260,11 @@ int iwm_priv_init(struct iwm_priv *iwm) iwm->watchdog.data = (unsigned long)iwm; mutex_init(&iwm->mutex); + iwm->last_fw_err = kzalloc(sizeof(struct iwm_fw_error_hdr), + GFP_KERNEL); + if (iwm->last_fw_err == NULL) + return -ENOMEM; + return 0; } @@ -271,6 +276,7 @@ void iwm_priv_deinit(struct iwm_priv *iwm) destroy_workqueue(iwm->txq[i].wq); destroy_workqueue(iwm->rx_wq); + kfree(iwm->last_fw_err); } /* diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index 14950b147f91..40dbcbc16593 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c @@ -102,6 +102,8 @@ static int iwm_ntf_error(struct iwm_priv *iwm, u8 *buf, error = (struct iwm_umac_notif_error *)buf; fw_err = &error->err; + memcpy(iwm->last_fw_err, fw_err, sizeof(struct iwm_fw_error_hdr)); + IWM_ERR(iwm, "%cMAC FW ERROR:\n", (le32_to_cpu(fw_err->category) == UMAC_SYS_ERR_CAT_LMAC) ? 'L' : 'U'); IWM_ERR(iwm, "\tCategory: %d\n", le32_to_cpu(fw_err->category)); -- cgit v1.2.3