From 8fa7425c6394117a541de82826d128d6c3d9161b Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Tue, 1 Jul 2008 10:44:48 +0300 Subject: iwlwifi: fix error path of iwl_rfkill_init This patch cleans rfkill error path. The problem was result of removing the input device Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.c b/drivers/net/wireless/iwlwifi/iwl-rfkill.c index aa9f31e..eebaf43 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rfkill.c +++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.c @@ -101,17 +101,13 @@ int iwl_rfkill_init(struct iwl_priv *priv) ret = rfkill_register(priv->rfkill_mngr.rfkill); if (ret) { IWL_ERROR("Unable to register rfkill: %d\n", ret); - goto unregister_rfkill; + goto free_rfkill; } IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n"); return ret; -unregister_rfkill: - rfkill_unregister(priv->rfkill_mngr.rfkill); - priv->rfkill_mngr.rfkill = NULL; - -freed_rfkill: +free_rfkill: if (priv->rfkill_mngr.rfkill != NULL) rfkill_free(priv->rfkill_mngr.rfkill); priv->rfkill_mngr.rfkill = NULL; -- cgit v0.10.2 From b2898a27809f54a33050a70d0eaa4a78194163a0 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Tue, 1 Jul 2008 10:45:13 +0200 Subject: mac80211: Don't request encryption for probe response Probe responses shouldn't be encrypted, and mac80211 doesn't set the crypto key accordingly. However it didn't set the IEEE80211_TX_CTL_DO_NOT_ENCRYPT flag which means drivers could make an attempt to encrypt it, and causing a NULL pointer dereference when accessing the provided hw_key field. Signed-off-by: Ivo van Doorn Acked-by: Johannes Berg Signed-off-by: John W. Linville diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 4a3bddd..86abdf9 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2481,6 +2481,7 @@ static int ieee80211_sta_join_ibss(struct net_device *dev, control->flags |= IEEE80211_TX_CTL_SHORT_PREAMBLE; control->antenna_sel_tx = local->hw.conf.antenna_sel_tx; control->flags |= IEEE80211_TX_CTL_NO_ACK; + control->flags |= IEEE80211_TX_CTL_DO_NOT_ENCRYPT; control->control.retry_limit = 1; ifsta->probe_resp = skb_copy(skb, GFP_ATOMIC); -- cgit v0.10.2 From 429a380571a6e6b8525b93161544eafc9b227e44 Mon Sep 17 00:00:00 2001 From: Ron Rindjunsky Date: Tue, 1 Jul 2008 14:16:03 +0300 Subject: mac80211: add block ack request capability This patch adds block ack request capability Signed-off-by: Ester Kummer Signed-off-by: Tomas Winkler Signed-off-by: Ron Rindjunsky Acked-by: Johannes Berg Signed-off-by: John W. Linville diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index cffd6d0..aa603c3 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -658,6 +658,10 @@ struct ieee80211_bar { __le16 start_seq_num; } __attribute__((packed)); +/* 802.11 BAR control masks */ +#define IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL 0x0000 +#define IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA 0x0004 + /** * struct ieee80211_ht_cap - HT capabilities * diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 3a204ac..0a5de3e 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -235,6 +235,8 @@ struct ieee80211_bss_conf { * @IEEE80211_TX_STAT_ACK: Frame was acknowledged * @IEEE80211_TX_STAT_AMPDU: The frame was aggregated, so status * is for the whole aggregation. + * @IEEE80211_TX_STAT_AMPDU_NO_BACK: no block ack was returned, + * so consider using block ack request (BAR). */ enum mac80211_tx_control_flags { IEEE80211_TX_CTL_REQ_TX_STATUS = BIT(0), @@ -260,6 +262,7 @@ enum mac80211_tx_control_flags { IEEE80211_TX_STAT_TX_FILTERED = BIT(20), IEEE80211_TX_STAT_ACK = BIT(21), IEEE80211_TX_STAT_AMPDU = BIT(22), + IEEE80211_TX_STAT_AMPDU_NO_BACK = BIT(23), }; diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index f90da1b..175cbdd 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -904,6 +904,7 @@ void ieee80211_send_addba_request(struct net_device *dev, const u8 *da, u16 agg_size, u16 timeout); void ieee80211_send_delba(struct net_device *dev, const u8 *da, u16 tid, u16 initiator, u16 reason_code); +void ieee80211_send_bar(struct net_device *dev, u8 *ra, u16 tid, u16 ssn); void ieee80211_sta_stop_rx_ba_session(struct net_device *dev, u8 *da, u16 tid, u16 initiator, u16 reason); diff --git a/net/mac80211/main.c b/net/mac80211/main.c index f18cfd7..074f71a 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -1404,14 +1404,15 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) struct ieee80211_local *local = hw_to_local(hw); struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); u16 frag, type; + __le16 fc; struct ieee80211_tx_status_rtap_hdr *rthdr; struct ieee80211_sub_if_data *sdata; struct net_device *prev_dev = NULL; + struct sta_info *sta; rcu_read_lock(); if (info->status.excessive_retries) { - struct sta_info *sta; sta = sta_info_get(local, hdr->addr1); if (sta) { if (test_sta_flags(sta, WLAN_STA_PS)) { @@ -1426,8 +1427,24 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) } } + fc = hdr->frame_control; + + if ((info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) && + (ieee80211_is_data_qos(fc))) { + u16 tid, ssn; + u8 *qc; + sta = sta_info_get(local, hdr->addr1); + if (sta) { + qc = ieee80211_get_qos_ctl(hdr); + tid = qc[0] & 0xf; + ssn = ((le16_to_cpu(hdr->seq_ctrl) + 0x10) + & IEEE80211_SCTL_SEQ); + ieee80211_send_bar(sta->sdata->dev, hdr->addr1, + tid, ssn); + } + } + if (info->flags & IEEE80211_TX_STAT_TX_FILTERED) { - struct sta_info *sta; sta = sta_info_get(local, hdr->addr1); if (sta) { ieee80211_handle_filtered_frame(local, sta, skb); diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 86abdf9..e080482 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1536,6 +1536,35 @@ void ieee80211_send_delba(struct net_device *dev, const u8 *da, u16 tid, ieee80211_sta_tx(dev, skb, 0); } +void ieee80211_send_bar(struct net_device *dev, u8 *ra, u16 tid, u16 ssn) +{ + struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct sk_buff *skb; + struct ieee80211_bar *bar; + u16 bar_control = 0; + + skb = dev_alloc_skb(sizeof(*bar) + local->hw.extra_tx_headroom); + if (!skb) { + printk(KERN_ERR "%s: failed to allocate buffer for " + "bar frame\n", dev->name); + return; + } + skb_reserve(skb, local->hw.extra_tx_headroom); + bar = (struct ieee80211_bar *)skb_put(skb, sizeof(*bar)); + memset(bar, 0, sizeof(*bar)); + bar->frame_control = IEEE80211_FC(IEEE80211_FTYPE_CTL, + IEEE80211_STYPE_BACK_REQ); + memcpy(bar->ra, ra, ETH_ALEN); + memcpy(bar->ta, dev->dev_addr, ETH_ALEN); + bar_control |= (u16)IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL; + bar_control |= (u16)IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA; + bar_control |= (u16)(tid << 12); + bar->control = cpu_to_le16(bar_control); + bar->start_seq_num = cpu_to_le16(ssn); + + ieee80211_sta_tx(dev, skb, 0); +} + void ieee80211_sta_stop_rx_ba_session(struct net_device *dev, u8 *ra, u16 tid, u16 initiator, u16 reason) { -- cgit v0.10.2 From d96a7bc0499d0332cecb0a1d7d7d0d44f9c8cc28 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Tue, 1 Jul 2008 14:29:20 +0300 Subject: mac80211: remove useless tid assignment for management and control frames This patch removes useless tid assignment for management and control frames Signed-off-by: Tomas Winkler Acked-by: Johannes Berg Signed-off-by: John W. Linville diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c index ffe1af8..a1a53a4 100644 --- a/net/mac80211/wme.c +++ b/net/mac80211/wme.c @@ -210,7 +210,6 @@ static int wme_qdiscop_enqueue(struct sk_buff *skb, struct Qdisc* qd) kfree_skb(skb); err = NET_XMIT_DROP; } else { - tid = skb->priority & QOS_CONTROL_TAG1D_MASK; skb_set_queue_mapping(skb, queue); qdisc = q->queues[queue]; err = qdisc->enqueue(skb, qdisc); -- cgit v0.10.2 From 3235427ecb092e4ff86528edd775e759dbeeecff Mon Sep 17 00:00:00 2001 From: Ron Rindjunsky Date: Tue, 1 Jul 2008 10:44:51 +0300 Subject: iwlwifi: request Tx of block ack request if necessary This patch sets the block ack request flag if needed Signed-off-by: Ron Rindjunsky Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 8c93f8d..04365b3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2285,9 +2285,9 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, iwl4965_tx_status_reply_tx(priv, agg, tx_resp, txq_id, index); - if ((tx_resp->frame_count == 1) && !iwl_is_tx_success(status)) { - /* TODO: send BAR */ - } + /* check if BAR is needed */ + if ((tx_resp->frame_count == 1) && !iwl_is_tx_success(status)) + info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; if (txq->q.read_ptr != (scd_ssn & 0xff)) { int freed, ampdu_q; diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 7cc73e9..717db0d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -1278,9 +1278,9 @@ static void iwl5000_rx_reply_tx(struct iwl_priv *priv, iwl5000_tx_status_reply_tx(priv, agg, tx_resp, txq_id, index); - if ((tx_resp->frame_count == 1) && !iwl_is_tx_success(status)) { - /* TODO: send BAR */ - } + /* check if BAR is needed */ + if ((tx_resp->frame_count == 1) && !iwl_is_tx_success(status)) + info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; if (txq->q.read_ptr != (scd_ssn & 0xff)) { int freed, ampdu_q; -- cgit v0.10.2 From ebd74487d4b7a48ab8513ecfe3d321346d7c602e Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Tue, 1 Jul 2008 10:44:50 +0300 Subject: mac80211: fix warning: unused variable ifsta This patch fixes warning unused variable ifsta when compiling without CONFIG_MAC80211_VERBOSE_DEBUG Signed-off-by: Tomas Winkler Acked-by: Johannes Berg Signed-off-by: John W. Linville diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index e080482..2a92708 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -366,8 +366,10 @@ static u32 ieee80211_handle_protect_preamb(struct ieee80211_sub_if_data *sdata, bool use_short_preamble) { struct ieee80211_bss_conf *bss_conf = &sdata->bss_conf; +#ifdef CONFIG_MAC80211_VERBOSE_DEBUG struct ieee80211_if_sta *ifsta = &sdata->u.sta; DECLARE_MAC_BUF(mac); +#endif u32 changed = 0; if (use_protection != bss_conf->use_cts_prot) { -- cgit v0.10.2 From 80fcc9e28cf3a209fbfb39a7bbddc313c59c7424 Mon Sep 17 00:00:00 2001 From: Adel Gadllah Date: Tue, 1 Jul 2008 17:49:50 +0200 Subject: iwlwifi: remove input device and fix rfkill state This patch fixes the iwlwifi rfkill. It removes the input device from iwl3945, adds support for RFKILL_STATE_HARD_BLOCKED and calls rfkill_force_state() to update the state rather than accessing it directly. The calls to iwl|iwl3945_rfkill_set_hw_state() had to be moved because rfkill_force_state() cannot be called from an atomic context. Tested on iwl3945 and seems to work fine. Cc: Randy Dunlap Cc: Ivo van Doorn Cc: Fabien Crespel Cc: Zhu Yi Cc: Henrique de Moraes Holschuh Signed-off-by: Adel Gadllah Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index b628a44..82b66a3 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig @@ -104,6 +104,7 @@ config IWL3945 select IWLWIFI select MAC80211_LEDS if IWL3945_LEDS select LEDS_CLASS if IWL3945_LEDS + select RFKILL if IWL3945_RFKILL ---help--- Select to build the driver supporting the: @@ -126,6 +127,10 @@ config IWL3945 say M here and read . The module will be called iwl3945.ko. +config IWL3945_RFKILL + bool "Enable RF kill support in iwl3945 drivers" + depends on IWL3945 + config IWL3945_SPECTRUM_MEASUREMENT bool "Enable Spectrum Measurement in iwl3945 drivers" depends on IWL3945 diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index a774978..9c0a09e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -690,14 +690,9 @@ enum { #endif -#ifdef CONFIG_IWLWIFI_RFKILL +#ifdef CONFIG_IWL3945_RFKILL struct iwl3945_priv; -struct iwl3945_rfkill_mngr { - struct rfkill *rfkill; - struct input_dev *input_dev; -}; - void iwl3945_rfkill_set_hw_state(struct iwl3945_priv *priv); void iwl3945_rfkill_unregister(struct iwl3945_priv *priv); int iwl3945_rfkill_init(struct iwl3945_priv *priv); @@ -800,8 +795,8 @@ struct iwl3945_priv { struct iwl3945_init_alive_resp card_alive_init; struct iwl3945_alive_resp card_alive; -#ifdef CONFIG_IWLWIFI_RFKILL - struct iwl3945_rfkill_mngr rfkill_mngr; +#ifdef CONFIG_IWL3945_RFKILL + struct rfkill *rfkill; #endif #ifdef CONFIG_IWL3945_LEDS diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index eb4abe1..dafd62c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -356,10 +356,19 @@ static inline int iwl_is_init(struct iwl_priv *priv) return test_bit(STATUS_INIT, &priv->status); } +static inline int iwl_is_rfkill_sw(struct iwl_priv *priv) +{ + return test_bit(STATUS_RF_KILL_SW, &priv->status); +} + +static inline int iwl_is_rfkill_hw(struct iwl_priv *priv) +{ + return test_bit(STATUS_RF_KILL_HW, &priv->status); +} + static inline int iwl_is_rfkill(struct iwl_priv *priv) { - return test_bit(STATUS_RF_KILL_HW, &priv->status) || - test_bit(STATUS_RF_KILL_SW, &priv->status); + return iwl_is_rfkill_hw(priv) || iwl_is_rfkill_sw(priv); } static inline int iwl_is_ready_rf(struct iwl_priv *priv) diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index d1289cf..70e10ea 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -929,7 +929,7 @@ struct iwl_priv { struct iwl_init_alive_resp card_alive_init; struct iwl_alive_resp card_alive; #ifdef CONFIG_IWLWIFI_RFKILL - struct iwl_rfkill_mngr rfkill_mngr; + struct rfkill *rfkill; #endif #ifdef CONFIG_IWLWIFI_LEDS diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.c b/drivers/net/wireless/iwlwifi/iwl-rfkill.c index eebaf43..e5e5846 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rfkill.c +++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.c @@ -44,7 +44,7 @@ static int iwl_rfkill_soft_rf_kill(void *data, enum rfkill_state state) struct iwl_priv *priv = data; int err = 0; - if (!priv->rfkill_mngr.rfkill) + if (!priv->rfkill) return 0; if (test_bit(STATUS_EXIT_PENDING, &priv->status)) @@ -55,20 +55,20 @@ static int iwl_rfkill_soft_rf_kill(void *data, enum rfkill_state state) switch (state) { case RFKILL_STATE_UNBLOCKED: - iwl_radio_kill_sw_enable_radio(priv); - /* if HW rf-kill is set dont allow ON state */ - if (iwl_is_rfkill(priv)) + if (iwl_is_rfkill_hw(priv)) { err = -EBUSY; + goto out_unlock; + } + iwl_radio_kill_sw_enable_radio(priv); break; case RFKILL_STATE_SOFT_BLOCKED: iwl_radio_kill_sw_disable_radio(priv); - if (!iwl_is_rfkill(priv)) - err = -EBUSY; break; default: IWL_WARNING("we recieved unexpected RFKILL state %d\n", state); break; } +out_unlock: mutex_unlock(&priv->mutex); return err; @@ -82,23 +82,23 @@ int iwl_rfkill_init(struct iwl_priv *priv) BUG_ON(device == NULL); IWL_DEBUG_RF_KILL("Initializing RFKILL.\n"); - priv->rfkill_mngr.rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN); - if (!priv->rfkill_mngr.rfkill) { + priv->rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN); + if (!priv->rfkill) { IWL_ERROR("Unable to allocate rfkill device.\n"); ret = -ENOMEM; goto error; } - priv->rfkill_mngr.rfkill->name = priv->cfg->name; - priv->rfkill_mngr.rfkill->data = priv; - priv->rfkill_mngr.rfkill->state = RFKILL_STATE_ON; - priv->rfkill_mngr.rfkill->toggle_radio = iwl_rfkill_soft_rf_kill; - priv->rfkill_mngr.rfkill->user_claim_unsupported = 1; + priv->rfkill->name = priv->cfg->name; + priv->rfkill->data = priv; + priv->rfkill->state = RFKILL_STATE_UNBLOCKED; + priv->rfkill->toggle_radio = iwl_rfkill_soft_rf_kill; + priv->rfkill->user_claim_unsupported = 1; - priv->rfkill_mngr.rfkill->dev.class->suspend = NULL; - priv->rfkill_mngr.rfkill->dev.class->resume = NULL; + priv->rfkill->dev.class->suspend = NULL; + priv->rfkill->dev.class->resume = NULL; - ret = rfkill_register(priv->rfkill_mngr.rfkill); + ret = rfkill_register(priv->rfkill); if (ret) { IWL_ERROR("Unable to register rfkill: %d\n", ret); goto free_rfkill; @@ -108,9 +108,9 @@ int iwl_rfkill_init(struct iwl_priv *priv) return ret; free_rfkill: - if (priv->rfkill_mngr.rfkill != NULL) - rfkill_free(priv->rfkill_mngr.rfkill); - priv->rfkill_mngr.rfkill = NULL; + if (priv->rfkill != NULL) + rfkill_free(priv->rfkill); + priv->rfkill = NULL; error: IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n"); @@ -121,22 +121,27 @@ EXPORT_SYMBOL(iwl_rfkill_init); void iwl_rfkill_unregister(struct iwl_priv *priv) { - if (priv->rfkill_mngr.rfkill) - rfkill_unregister(priv->rfkill_mngr.rfkill); + if (priv->rfkill) + rfkill_unregister(priv->rfkill); - priv->rfkill_mngr.rfkill = NULL; + priv->rfkill = NULL; } EXPORT_SYMBOL(iwl_rfkill_unregister); /* set rf-kill to the right state. */ void iwl_rfkill_set_hw_state(struct iwl_priv *priv) { - if (!priv->rfkill_mngr.rfkill) + if (!priv->rfkill) return; - if (!iwl_is_rfkill(priv)) - priv->rfkill_mngr.rfkill->state = RFKILL_STATE_ON; + if (iwl_is_rfkill_hw(priv)) { + rfkill_force_state(priv->rfkill, RFKILL_STATE_HARD_BLOCKED); + return; + } + + if (!iwl_is_rfkill_sw(priv)) + rfkill_force_state(priv->rfkill, RFKILL_STATE_UNBLOCKED); else - priv->rfkill_mngr.rfkill->state = RFKILL_STATE_OFF; + rfkill_force_state(priv->rfkill, RFKILL_STATE_SOFT_BLOCKED); } EXPORT_SYMBOL(iwl_rfkill_set_hw_state); diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.h b/drivers/net/wireless/iwlwifi/iwl-rfkill.h index 00692d2..402fd4c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rfkill.h +++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.h @@ -33,9 +33,6 @@ struct iwl_priv; #include #ifdef CONFIG_IWLWIFI_RFKILL -struct iwl_rfkill_mngr { - struct rfkill *rfkill; -}; void iwl_rfkill_set_hw_state(struct iwl_priv *priv); void iwl_rfkill_unregister(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index baa1abd..1a7d18f 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -537,10 +537,20 @@ static inline int iwl3945_is_init(struct iwl3945_priv *priv) return test_bit(STATUS_INIT, &priv->status); } +static inline int iwl3945_is_rfkill_sw(struct iwl3945_priv *priv) +{ + return test_bit(STATUS_RF_KILL_SW, &priv->status); +} + +static inline int iwl3945_is_rfkill_hw(struct iwl3945_priv *priv) +{ + return test_bit(STATUS_RF_KILL_HW, &priv->status); +} + static inline int iwl3945_is_rfkill(struct iwl3945_priv *priv) { - return test_bit(STATUS_RF_KILL_HW, &priv->status) || - test_bit(STATUS_RF_KILL_SW, &priv->status); + return iwl3945_is_rfkill_hw(priv) || + iwl3945_is_rfkill_sw(priv); } static inline int iwl3945_is_ready_rf(struct iwl3945_priv *priv) @@ -6013,12 +6023,11 @@ static int __iwl3945_up(struct iwl3945_priv *priv) else { set_bit(STATUS_RF_KILL_HW, &priv->status); if (!test_bit(STATUS_IN_SUSPEND, &priv->status)) { - iwl3945_rfkill_set_hw_state(priv); IWL_WARNING("Radio disabled by HW RF Kill switch\n"); return -ENODEV; } } - iwl3945_rfkill_set_hw_state(priv); + iwl3945_write32(priv, CSR_INT, 0xFFFFFFFF); rc = iwl3945_hw_nic_init(priv); @@ -6143,8 +6152,8 @@ static void iwl3945_bg_rf_kill(struct work_struct *work) "wireless networking to work.\n"); } - iwl3945_rfkill_set_hw_state(priv); mutex_unlock(&priv->mutex); + iwl3945_rfkill_set_hw_state(priv); } static void iwl3945_bg_set_monitor(struct work_struct *work) @@ -6398,6 +6407,7 @@ static void iwl3945_bg_up(struct work_struct *data) mutex_lock(&priv->mutex); __iwl3945_up(priv); mutex_unlock(&priv->mutex); + iwl3945_rfkill_set_hw_state(priv); } static void iwl3945_bg_restart(struct work_struct *data) @@ -6618,6 +6628,8 @@ static int iwl3945_mac_start(struct ieee80211_hw *hw) mutex_unlock(&priv->mutex); + iwl3945_rfkill_set_hw_state(priv); + if (ret) goto out_release_irq; @@ -8276,14 +8288,14 @@ static int iwl3945_pci_resume(struct pci_dev *pdev) #endif /* CONFIG_PM */ /*************** RFKILL FUNCTIONS **********/ -#ifdef CONFIG_IWLWIFI_RFKILL +#ifdef CONFIG_IWL3945_RFKILL /* software rf-kill from user */ static int iwl3945_rfkill_soft_rf_kill(void *data, enum rfkill_state state) { struct iwl3945_priv *priv = data; int err = 0; - if (!priv->rfkill_mngr.rfkill) + if (!priv->rfkill) return 0; if (test_bit(STATUS_EXIT_PENDING, &priv->status)) @@ -8294,20 +8306,20 @@ static int iwl3945_rfkill_soft_rf_kill(void *data, enum rfkill_state state) switch (state) { case RFKILL_STATE_UNBLOCKED: - iwl3945_radio_kill_sw(priv, 0); - /* if HW rf-kill is set dont allow ON state */ - if (iwl3945_is_rfkill(priv)) + if (iwl3945_is_rfkill_hw(priv)) { err = -EBUSY; + goto out_unlock; + } + iwl3945_radio_kill_sw(priv, 0); break; case RFKILL_STATE_SOFT_BLOCKED: iwl3945_radio_kill_sw(priv, 1); - if (!iwl3945_is_rfkill(priv)) - err = -EBUSY; break; default: IWL_WARNING("we recieved unexpected RFKILL state %d\n", state); break; } +out_unlock: mutex_unlock(&priv->mutex); return err; @@ -8321,64 +8333,35 @@ int iwl3945_rfkill_init(struct iwl3945_priv *priv) BUG_ON(device == NULL); IWL_DEBUG_RF_KILL("Initializing RFKILL.\n"); - priv->rfkill_mngr.rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN); - if (!priv->rfkill_mngr.rfkill) { + priv->rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN); + if (!priv->rfkill) { IWL_ERROR("Unable to allocate rfkill device.\n"); ret = -ENOMEM; goto error; } - priv->rfkill_mngr.rfkill->name = priv->cfg->name; - priv->rfkill_mngr.rfkill->data = priv; - priv->rfkill_mngr.rfkill->state = RFKILL_STATE_ON; - priv->rfkill_mngr.rfkill->toggle_radio = iwl3945_rfkill_soft_rf_kill; - priv->rfkill_mngr.rfkill->user_claim_unsupported = 1; - - priv->rfkill_mngr.rfkill->dev.class->suspend = NULL; - priv->rfkill_mngr.rfkill->dev.class->resume = NULL; + priv->rfkill->name = priv->cfg->name; + priv->rfkill->data = priv; + priv->rfkill->state = RFKILL_STATE_UNBLOCKED; + priv->rfkill->toggle_radio = iwl3945_rfkill_soft_rf_kill; + priv->rfkill->user_claim_unsupported = 1; - priv->rfkill_mngr.input_dev = input_allocate_device(); - if (!priv->rfkill_mngr.input_dev) { - IWL_ERROR("Unable to allocate rfkill input device.\n"); - ret = -ENOMEM; - goto freed_rfkill; - } + priv->rfkill->dev.class->suspend = NULL; + priv->rfkill->dev.class->resume = NULL; - priv->rfkill_mngr.input_dev->name = priv->cfg->name; - priv->rfkill_mngr.input_dev->phys = wiphy_name(priv->hw->wiphy); - priv->rfkill_mngr.input_dev->id.bustype = BUS_HOST; - priv->rfkill_mngr.input_dev->id.vendor = priv->pci_dev->vendor; - priv->rfkill_mngr.input_dev->dev.parent = device; - priv->rfkill_mngr.input_dev->evbit[0] = BIT(EV_KEY); - set_bit(KEY_WLAN, priv->rfkill_mngr.input_dev->keybit); - - ret = rfkill_register(priv->rfkill_mngr.rfkill); + ret = rfkill_register(priv->rfkill); if (ret) { IWL_ERROR("Unable to register rfkill: %d\n", ret); - goto free_input_dev; - } - - ret = input_register_device(priv->rfkill_mngr.input_dev); - if (ret) { - IWL_ERROR("Unable to register rfkill input device: %d\n", ret); - goto unregister_rfkill; + goto freed_rfkill; } IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n"); return ret; -unregister_rfkill: - rfkill_unregister(priv->rfkill_mngr.rfkill); - priv->rfkill_mngr.rfkill = NULL; - -free_input_dev: - input_free_device(priv->rfkill_mngr.input_dev); - priv->rfkill_mngr.input_dev = NULL; - freed_rfkill: - if (priv->rfkill_mngr.rfkill != NULL) - rfkill_free(priv->rfkill_mngr.rfkill); - priv->rfkill_mngr.rfkill = NULL; + if (priv->rfkill != NULL) + rfkill_free(priv->rfkill); + priv->rfkill = NULL; error: IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n"); @@ -8387,28 +8370,28 @@ error: void iwl3945_rfkill_unregister(struct iwl3945_priv *priv) { + if (priv->rfkill) + rfkill_unregister(priv->rfkill); - if (priv->rfkill_mngr.input_dev) - input_unregister_device(priv->rfkill_mngr.input_dev); - - if (priv->rfkill_mngr.rfkill) - rfkill_unregister(priv->rfkill_mngr.rfkill); - - priv->rfkill_mngr.input_dev = NULL; - priv->rfkill_mngr.rfkill = NULL; + priv->rfkill = NULL; } /* set rf-kill to the right state. */ void iwl3945_rfkill_set_hw_state(struct iwl3945_priv *priv) { - if (!priv->rfkill_mngr.rfkill) + if (!priv->rfkill) + return; + + if (iwl3945_is_rfkill_hw(priv)) { + rfkill_force_state(priv->rfkill, RFKILL_STATE_HARD_BLOCKED); return; + } - if (!iwl3945_is_rfkill(priv)) - priv->rfkill_mngr.rfkill->state = RFKILL_STATE_ON; + if (!iwl3945_is_rfkill_sw(priv)) + rfkill_force_state(priv->rfkill, RFKILL_STATE_UNBLOCKED); else - priv->rfkill_mngr.rfkill->state = RFKILL_STATE_OFF; + rfkill_force_state(priv->rfkill, RFKILL_STATE_SOFT_BLOCKED); } #endif diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 60b7a64..7f65d91 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -2187,13 +2187,11 @@ static int __iwl4965_up(struct iwl_priv *priv) if (!test_bit(STATUS_IN_SUSPEND, &priv->status) && iwl_is_rfkill(priv)) { - iwl_rfkill_set_hw_state(priv); IWL_WARNING("Radio disabled by %s RF Kill switch\n", test_bit(STATUS_RF_KILL_HW, &priv->status) ? "HW" : "SW"); return -ENODEV; } - iwl_rfkill_set_hw_state(priv); iwl_write32(priv, CSR_INT, 0xFFFFFFFF); ret = priv->cfg->ops->lib->alloc_shared_mem(priv); @@ -2330,9 +2328,8 @@ static void iwl4965_bg_rf_kill(struct work_struct *work) "Kill switch must be turned off for " "wireless networking to work.\n"); } - iwl_rfkill_set_hw_state(priv); - mutex_unlock(&priv->mutex); + iwl_rfkill_set_hw_state(priv); } static void iwl4965_bg_set_monitor(struct work_struct *work) @@ -2390,6 +2387,7 @@ static void iwl4965_bg_up(struct work_struct *data) mutex_lock(&priv->mutex); __iwl4965_up(priv); mutex_unlock(&priv->mutex); + iwl_rfkill_set_hw_state(priv); } static void iwl4965_bg_restart(struct work_struct *data) @@ -2604,6 +2602,8 @@ static int iwl4965_mac_start(struct ieee80211_hw *hw) mutex_unlock(&priv->mutex); + iwl_rfkill_set_hw_state(priv); + if (ret) goto out_release_irq; -- cgit v0.10.2 From 4e887d5b2fb909f18d153f47d2f3fdc2c76bb83a Mon Sep 17 00:00:00 2001 From: Rami Rosen Date: Wed, 2 Jul 2008 10:53:57 +0300 Subject: mac80211: remove MAC80211_DEBUG from net/mac80211/Kconfig. This patch removes MAC80211_DEBUG from /net/mac80211/Kconfig (in MAC80211_DEBUG_COUNTERS config entry), and replaces MAC80211_DEBUG_MENU instead of MAC80211_DEBUG (in MAC80211_VERBOSE_SPECT_MGMT_DEBUG config entry). Signed-off-by: Rami Rosen Signed-off-by: John W. Linville diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index 11a1e7f..40f1add 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig @@ -207,7 +207,6 @@ config MAC80211_LOWTX_FRAME_DUMP config MAC80211_DEBUG_COUNTERS bool "Extra statistics for TX/RX debugging" - depends on MAC80211_DEBUG depends on MAC80211_DEBUG_MENU depends on MAC80211_DEBUGFS ---help--- @@ -219,7 +218,7 @@ config MAC80211_DEBUG_COUNTERS config MAC80211_VERBOSE_SPECT_MGMT_DEBUG bool "Verbose Spectrum Management (IEEE 802.11h)debugging" - depends on MAC80211_DEBUG + depends on MAC80211_DEBUG_MENU ---help--- Say Y here to print out verbose Spectrum Management (IEEE 802.11h) debug messages. -- cgit v0.10.2 From 994d31f7430c3639b73c6ee038bd437c926b1227 Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Wed, 2 Jul 2008 12:17:06 +0200 Subject: iwlwifi: fix typo which caused iwl_get_tx_fail_reason to ever return an empty string Signed-off-by: Helmut Schaa Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 70e10ea..c8d3d97 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1103,7 +1103,7 @@ static inline void iwl_txq_ctx_deactivate(struct iwl_priv *priv, int txq_id) clear_bit(txq_id, &priv->txq_ctx_active_msk); } -#ifdef CONFIG_IWLWIF_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUG const char *iwl_get_tx_fail_reason(u32 status); #else static inline const char *iwl_get_tx_fail_reason(u32 status) { return ""; } diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 032641d..0be2a71 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -1493,7 +1493,7 @@ void iwl_rx_reply_compressed_ba(struct iwl_priv *priv, } EXPORT_SYMBOL(iwl_rx_reply_compressed_ba); -#ifdef CONFIG_IWLWIF_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUG #define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x const char *iwl_get_tx_fail_reason(u32 status) -- cgit v0.10.2 From 238f74a227fd7de8ea1bc66dcbbd36cf9920d1cb Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Wed, 2 Jul 2008 11:05:34 -0700 Subject: mac80211: move QOS control helpers into ieee80211.h Also remove the WLAN_IS_QOS_DATA inline after removing the last two users. This starts moving away from using rx->fc to using the header frame_control directly. Signed-off-by: Harvey Harrison Signed-off-by: John W. Linville diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index aa603c3..a1630ba 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -99,6 +99,8 @@ #define IEEE80211_MAX_SSID_LEN 32 #define IEEE80211_MAX_MESH_ID_LEN 32 #define IEEE80211_QOS_CTL_LEN 2 +#define IEEE80211_QOS_CTL_TID_MASK 0x000F +#define IEEE80211_QOS_CTL_TAG1D_MASK 0x0007 struct ieee80211_hdr { __le16 frame_control; diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 6a88e8f..a3a26e5 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -321,20 +321,20 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, static void ieee80211_parse_qos(struct ieee80211_rx_data *rx) { - u8 *data = rx->skb->data; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; int tid; /* does the frame have a qos control field? */ - if (WLAN_FC_IS_QOS_DATA(rx->fc)) { - u8 *qc = data + ieee80211_get_hdrlen(rx->fc) - QOS_CONTROL_LEN; + if (ieee80211_is_data_qos(hdr->frame_control)) { + u8 *qc = ieee80211_get_qos_ctl(hdr); /* frame has qos control */ - tid = qc[0] & QOS_CONTROL_TID_MASK; - if (qc[0] & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT) + tid = *qc & IEEE80211_QOS_CTL_TID_MASK; + if (*qc & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT) rx->flags |= IEEE80211_RX_AMSDU; else rx->flags &= ~IEEE80211_RX_AMSDU; } else { - if (unlikely((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT)) { + if (unlikely(ieee80211_is_mgmt(hdr->frame_control))) { /* Separate TID for management frames */ tid = NUM_RX_DATA_QUEUES - 1; } else { @@ -1037,19 +1037,19 @@ ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx) static ieee80211_rx_result debug_noinline ieee80211_rx_h_remove_qos_control(struct ieee80211_rx_data *rx) { - u16 fc = rx->fc; u8 *data = rx->skb->data; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) data; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)data; - if (!WLAN_FC_IS_QOS_DATA(fc)) + if (!ieee80211_is_data_qos(hdr->frame_control)) return RX_CONTINUE; /* remove the qos control field, update frame type and meta-data */ - memmove(data + 2, data, ieee80211_get_hdrlen(fc) - 2); - hdr = (struct ieee80211_hdr *) skb_pull(rx->skb, 2); + memmove(data + IEEE80211_QOS_CTL_LEN, data, + ieee80211_hdrlen(hdr->frame_control) - IEEE80211_QOS_CTL_LEN); + hdr = (struct ieee80211_hdr *)skb_pull(rx->skb, IEEE80211_QOS_CTL_LEN); /* change frame type to non QOS */ - rx->fc = fc &= ~IEEE80211_STYPE_QOS_DATA; - hdr->frame_control = cpu_to_le16(fc); + rx->fc &= ~IEEE80211_STYPE_QOS_DATA; + hdr->frame_control &= ~cpu_to_le16(IEEE80211_STYPE_QOS_DATA); return RX_CONTINUE; } @@ -2044,7 +2044,7 @@ static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local, if (!ieee80211_is_data_qos(hdr->frame_control)) goto end_reorder; - tid = *ieee80211_get_qos_ctl(hdr) & QOS_CONTROL_TID_MASK; + tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_OPERATIONAL) goto end_reorder; diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c index a1a53a4..5c666f7 100644 --- a/net/mac80211/wme.c +++ b/net/mac80211/wme.c @@ -154,7 +154,7 @@ static int wme_qdiscop_enqueue(struct sk_buff *skb, struct Qdisc* qd) queue = skb_get_queue_mapping(skb); rcu_read_lock(); sta = sta_info_get(local, hdr->addr1); - tid = skb->priority & QOS_CONTROL_TAG1D_MASK; + tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; if (sta) { int ampdu_queue = sta->tid_to_tx_q[tid]; if ((ampdu_queue < QD_NUM(hw)) && @@ -181,7 +181,7 @@ static int wme_qdiscop_enqueue(struct sk_buff *skb, struct Qdisc* qd) if (ieee80211_is_data_qos(hdr->frame_control)) { u8 *p = ieee80211_get_qos_ctl(hdr); u8 ack_policy = 0; - tid = skb->priority & QOS_CONTROL_TAG1D_MASK; + tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; if (local->wifi_wme_noack_test) ack_policy |= QOS_CONTROL_ACK_POLICY_NOACK << QOS_CONTROL_ACK_POLICY_SHIFT; diff --git a/net/mac80211/wme.h b/net/mac80211/wme.h index bbdb533..1aca609 100644 --- a/net/mac80211/wme.h +++ b/net/mac80211/wme.h @@ -19,18 +19,10 @@ #define QOS_CONTROL_ACK_POLICY_NORMAL 0 #define QOS_CONTROL_ACK_POLICY_NOACK 1 -#define QOS_CONTROL_TID_MASK 0x0f #define QOS_CONTROL_ACK_POLICY_SHIFT 5 -#define QOS_CONTROL_TAG1D_MASK 0x07 - extern const int ieee802_1d_to_ac[8]; -static inline int WLAN_FC_IS_QOS_DATA(u16 fc) -{ - return (fc & 0x8C) == 0x88; -} - #ifdef CONFIG_MAC80211_QOS void ieee80211_install_qdisc(struct net_device *dev); int ieee80211_qdisc_installed(struct net_device *dev); -- cgit v0.10.2 From 73e1f7c823252d671361cddde0b498bf2c0fe4e1 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Wed, 2 Jul 2008 11:05:34 -0700 Subject: mac80211: use symbolic defines in wpa.c ETH_ALEN and IEEE80211_QOS_CTL_LEN Signed-off-by: Harvey Harrison Signed-off-by: John W. Linville diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index b414d5d..222001c 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -38,7 +38,7 @@ static int ieee80211_get_hdr_info(const struct sk_buff *skb, u8 **sa, u8 **da, *data_len = skb->len - hdrlen; if (ieee80211_is_data_qos(fc)) - *qos_tid = (*ieee80211_get_qos_ctl(hdr) & 0x0f) | 0x80; + *qos_tid = (*ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK) | 0x80; else *qos_tid = 0; @@ -312,7 +312,7 @@ static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad, data_len -= CCMP_HDR_LEN + (encrypted ? CCMP_MIC_LEN : 0); if (qos_tid & 0x80) { qos_included = 1; - qos_tid &= 0x0f; + qos_tid &= IEEE80211_QOS_CTL_TID_MASK; } else qos_included = 0; /* First block, b_0 */ @@ -320,7 +320,7 @@ static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad, b_0[0] = 0x59; /* flags: Adata: 1, M: 011, L: 001 */ /* Nonce: QoS Priority | A2 | PN */ b_0[1] = qos_tid; - memcpy(&b_0[2], hdr->addr2, 6); + memcpy(&b_0[2], hdr->addr2, ETH_ALEN); memcpy(&b_0[8], pn, CCMP_PN_LEN); /* l(m) */ b_0[14] = (data_len >> 8) & 0xff; @@ -332,7 +332,7 @@ static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad, len_a = a4_included ? 28 : 22; if (qos_included) - len_a += 2; + len_a += IEEE80211_QOS_CTL_LEN; aad[0] = 0; /* (len_a >> 8) & 0xff; */ aad[1] = len_a & 0xff; @@ -340,17 +340,17 @@ static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad, aad[2] = fc_pos[0] & ~(BIT(4) | BIT(5) | BIT(6)); /* Retry, PwrMgt, MoreData; set Protected */ aad[3] = (fc_pos[1] & ~(BIT(3) | BIT(4) | BIT(5))) | BIT(6); - memcpy(&aad[4], &hdr->addr1, 18); + memcpy(&aad[4], &hdr->addr1, 3 * ETH_ALEN); /* Mask Seq#, leave Frag# */ aad[22] = *((u8 *) &hdr->seq_ctrl) & 0x0f; aad[23] = 0; if (a4_included) { - memcpy(&aad[24], hdr->addr4, 6); + memcpy(&aad[24], hdr->addr4, ETH_ALEN); aad[30] = 0; aad[31] = 0; } else - memset(&aad[24], 0, 8); + memset(&aad[24], 0, ETH_ALEN + IEEE80211_QOS_CTL_LEN); if (qos_included) { u8 *dpos = &aad[a4_included ? 30 : 24]; -- cgit v0.10.2 From f14df8049f9c9f34164dd598772fecea83a394a2 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Wed, 2 Jul 2008 11:05:35 -0700 Subject: mac80211: remove one user of ieee80211_get_hdr_info ccmp_special_blocks was only using it to calculate data_len, calculate that directly. Use unaligned helpers rather than masking/shifting. Use symbolic constants for the masked frame_control, and do it directly on a le16 value. Signed-off-by: Harvey Harrison Signed-off-by: John W. Linville diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 222001c..919e30c 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -11,6 +11,8 @@ #include #include #include +#include +#include #include #include "ieee80211_i.h" @@ -296,67 +298,61 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx) static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad, int encrypted) { - u16 fc; - int a4_included, qos_included; - u8 qos_tid, *fc_pos, *data, *sa, *da; - int len_a; - size_t data_len; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; + __le16 mask_fc; + int a4_included; + u8 qos_tid; + u16 data_len, len_a; + unsigned int hdrlen; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - fc_pos = (u8 *) &hdr->frame_control; - fc = fc_pos[0] ^ (fc_pos[1] << 8); - a4_included = (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) == - (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS); - - ieee80211_get_hdr_info(skb, &sa, &da, &qos_tid, &data, &data_len); - data_len -= CCMP_HDR_LEN + (encrypted ? CCMP_MIC_LEN : 0); - if (qos_tid & 0x80) { - qos_included = 1; - qos_tid &= IEEE80211_QOS_CTL_TID_MASK; - } else - qos_included = 0; - /* First block, b_0 */ + /* + * Mask FC: zero subtype b4 b5 b6 + * Retry, PwrMgt, MoreData; set Protected + */ + mask_fc = hdr->frame_control; + mask_fc &= ~cpu_to_le16(0x0070 | IEEE80211_FCTL_RETRY | + IEEE80211_FCTL_PM | IEEE80211_FCTL_MOREDATA); + mask_fc |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); + + hdrlen = ieee80211_hdrlen(hdr->frame_control); + len_a = hdrlen - 2; + a4_included = ieee80211_has_a4(hdr->frame_control); + if (ieee80211_is_data_qos(hdr->frame_control)) + qos_tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; + else + qos_tid = 0; + + data_len = skb->len - hdrlen - CCMP_HDR_LEN; + if (encrypted) + data_len -= CCMP_MIC_LEN; + + /* First block, b_0 */ b_0[0] = 0x59; /* flags: Adata: 1, M: 011, L: 001 */ /* Nonce: QoS Priority | A2 | PN */ b_0[1] = qos_tid; memcpy(&b_0[2], hdr->addr2, ETH_ALEN); memcpy(&b_0[8], pn, CCMP_PN_LEN); /* l(m) */ - b_0[14] = (data_len >> 8) & 0xff; - b_0[15] = data_len & 0xff; - + put_unaligned_be16(data_len, &b_0[14]); /* AAD (extra authenticate-only data) / masked 802.11 header * FC | A1 | A2 | A3 | SC | [A4] | [QC] */ - - len_a = a4_included ? 28 : 22; - if (qos_included) - len_a += IEEE80211_QOS_CTL_LEN; - - aad[0] = 0; /* (len_a >> 8) & 0xff; */ - aad[1] = len_a & 0xff; - /* Mask FC: zero subtype b4 b5 b6 */ - aad[2] = fc_pos[0] & ~(BIT(4) | BIT(5) | BIT(6)); - /* Retry, PwrMgt, MoreData; set Protected */ - aad[3] = (fc_pos[1] & ~(BIT(3) | BIT(4) | BIT(5))) | BIT(6); + put_unaligned_be16(len_a, &aad[0]); + put_unaligned(mask_fc, (__le16 *)&aad[2]); memcpy(&aad[4], &hdr->addr1, 3 * ETH_ALEN); /* Mask Seq#, leave Frag# */ aad[22] = *((u8 *) &hdr->seq_ctrl) & 0x0f; aad[23] = 0; + if (a4_included) { memcpy(&aad[24], hdr->addr4, ETH_ALEN); - aad[30] = 0; + aad[30] = qos_tid; aad[31] = 0; - } else + } else { memset(&aad[24], 0, ETH_ALEN + IEEE80211_QOS_CTL_LEN); - if (qos_included) { - u8 *dpos = &aad[a4_included ? 30 : 24]; - - /* Mask QoS Control field */ - dpos[0] = qos_tid; - dpos[1] = 0; + aad[24] = qos_tid; } } -- cgit v0.10.2 From 8e8862b79d2ce9177bfddd85b8328a86a25c69b2 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Wed, 2 Jul 2008 11:05:35 -0700 Subject: mac80211: remove ieee80211_get_hdr_info Do the check for sufficient skb->len explicitly and pass a pointer to the struct ieee80211_hdr directly to the michael_mic calculation. Signed-off-by: Harvey Harrison Signed-off-by: John W. Linville diff --git a/net/mac80211/michael.c b/net/mac80211/michael.c index 1fcdf38..408649bd 100644 --- a/net/mac80211/michael.c +++ b/net/mac80211/michael.c @@ -8,6 +8,7 @@ */ #include #include +#include #include #include "michael.h" @@ -26,9 +27,18 @@ static void michael_block(struct michael_mic_ctx *mctx, u32 val) mctx->l += mctx->r; } -static void michael_mic_hdr(struct michael_mic_ctx *mctx, - const u8 *key, const u8 *da, const u8 *sa, u8 priority) +static void michael_mic_hdr(struct michael_mic_ctx *mctx, const u8 *key, + struct ieee80211_hdr *hdr) { + u8 *da, *sa, tid; + + da = ieee80211_get_DA(hdr); + sa = ieee80211_get_SA(hdr); + if (ieee80211_is_data_qos(hdr->frame_control)) + tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; + else + tid = 0; + mctx->l = get_unaligned_le32(key); mctx->r = get_unaligned_le32(key + 4); @@ -40,17 +50,17 @@ static void michael_mic_hdr(struct michael_mic_ctx *mctx, michael_block(mctx, get_unaligned_le16(&da[4]) | (get_unaligned_le16(sa) << 16)); michael_block(mctx, get_unaligned_le32(&sa[2])); - michael_block(mctx, priority); + michael_block(mctx, tid); } -void michael_mic(const u8 *key, const u8 *da, const u8 *sa, u8 priority, +void michael_mic(const u8 *key, struct ieee80211_hdr *hdr, const u8 *data, size_t data_len, u8 *mic) { u32 val; size_t block, blocks, left; struct michael_mic_ctx mctx; - michael_mic_hdr(&mctx, key, da, sa, priority); + michael_mic_hdr(&mctx, key, hdr); /* Real data */ blocks = data_len / 4; diff --git a/net/mac80211/michael.h b/net/mac80211/michael.h index 69b4501..3b848da 100644 --- a/net/mac80211/michael.h +++ b/net/mac80211/michael.h @@ -18,7 +18,7 @@ struct michael_mic_ctx { u32 l, r; }; -void michael_mic(const u8 *key, const u8 *da, const u8 *sa, u8 priority, +void michael_mic(const u8 *key, struct ieee80211_hdr *hdr, const u8 *data, size_t data_len, u8 *mic); #endif /* MICHAEL_H */ diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 919e30c..241c932 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -21,38 +21,13 @@ #include "aes_ccm.h" #include "wpa.h" -static int ieee80211_get_hdr_info(const struct sk_buff *skb, u8 **sa, u8 **da, - u8 *qos_tid, u8 **data, size_t *data_len) -{ - struct ieee80211_hdr *hdr; - size_t hdrlen; - __le16 fc; - - hdr = (struct ieee80211_hdr *)skb->data; - fc = hdr->frame_control; - - hdrlen = ieee80211_hdrlen(fc); - - *sa = ieee80211_get_SA(hdr); - *da = ieee80211_get_DA(hdr); - - *data = skb->data + hdrlen; - *data_len = skb->len - hdrlen; - - if (ieee80211_is_data_qos(fc)) - *qos_tid = (*ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK) | 0x80; - else - *qos_tid = 0; - - return skb->len < hdrlen ? -1 : 0; -} - - ieee80211_tx_result ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) { - u8 *data, *sa, *da, *key, *mic, qos_tid, key_offset; + u8 *data, *key, *mic, key_offset; size_t data_len; + unsigned int hdrlen; + struct ieee80211_hdr *hdr; u16 fc; struct sk_buff *skb = tx->skb; int authenticator; @@ -65,9 +40,14 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) !WLAN_FC_DATA_PRESENT(fc)) return TX_CONTINUE; - if (ieee80211_get_hdr_info(skb, &sa, &da, &qos_tid, &data, &data_len)) + hdr = (struct ieee80211_hdr *)skb->data; + hdrlen = ieee80211_hdrlen(hdr->frame_control); + if (skb->len < hdrlen) return TX_DROP; + data = skb->data + hdrlen; + data_len = skb->len - hdrlen; + if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && !(tx->flags & IEEE80211_TX_FRAGMENTED) && !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) && @@ -97,7 +77,7 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY; key = &tx->key->conf.key[key_offset]; mic = skb_put(skb, MICHAEL_MIC_LEN); - michael_mic(key, da, sa, qos_tid & 0x0f, data, data_len, mic); + michael_mic(key, hdr, data, data_len, mic); return TX_CONTINUE; } @@ -106,8 +86,10 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) ieee80211_rx_result ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) { - u8 *data, *sa, *da, *key = NULL, qos_tid, key_offset; + u8 *data, *key = NULL, key_offset; size_t data_len; + unsigned int hdrlen; + struct ieee80211_hdr *hdr; u16 fc; u8 mic[MICHAEL_MIC_LEN]; struct sk_buff *skb = rx->skb; @@ -126,11 +108,13 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) !(rx->fc & IEEE80211_FCTL_PROTECTED) || !WLAN_FC_DATA_PRESENT(fc)) return RX_CONTINUE; - if (ieee80211_get_hdr_info(skb, &sa, &da, &qos_tid, &data, &data_len) - || data_len < MICHAEL_MIC_LEN) + hdr = (struct ieee80211_hdr *)skb->data; + hdrlen = ieee80211_hdrlen(hdr->frame_control); + if (skb->len < hdrlen + MICHAEL_MIC_LEN) return RX_DROP_UNUSABLE; - data_len -= MICHAEL_MIC_LEN; + data = skb->data + hdrlen; + data_len = skb->len - hdrlen - MICHAEL_MIC_LEN; #if 0 authenticator = fc & IEEE80211_FCTL_TODS; /* FIX */ @@ -143,7 +127,7 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY : NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY; key = &rx->key->conf.key[key_offset]; - michael_mic(key, da, sa, qos_tid & 0x0f, data, data_len, mic); + michael_mic(key, hdr, data, data_len, mic); if (memcmp(mic, data + data_len, MICHAEL_MIC_LEN) != 0 || wpa_test) { if (!(rx->flags & IEEE80211_RX_RA_MATCH)) return RX_DROP_UNUSABLE; -- cgit v0.10.2 From fc32f9243dc93e75f81457e95d9cb90ee6136d94 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Thu, 3 Jul 2008 01:27:13 +0300 Subject: mac80211: call bss_info_change only once upon disassociation This patch removes call of ieee80211_bss_info_change_notify from within ieee80211_reset_erp_info. This allows gathering all bss info changes into one call to the driver in the disassociation flow. Signed-off-by: Tomas Winkler Acked-by: Johannes Berg Signed-off-by: John W. Linville diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 175cbdd..02a8753 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -893,7 +893,7 @@ int ieee80211_sta_deauthenticate(struct net_device *dev, u16 reason); int ieee80211_sta_disassociate(struct net_device *dev, u16 reason); void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, u32 changed); -void ieee80211_reset_erp_info(struct net_device *dev); +u32 ieee80211_reset_erp_info(struct net_device *dev); int ieee80211_ht_cap_ie_to_ht_info(struct ieee80211_ht_cap *ht_cap_ie, struct ieee80211_ht_info *ht_info); int ieee80211_ht_addt_info_ie_to_ht_bss_info( diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 074f71a..cc756e9 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -182,10 +182,11 @@ static int ieee80211_open(struct net_device *dev) { struct ieee80211_sub_if_data *sdata, *nsdata; struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct sta_info *sta; struct ieee80211_if_init_conf conf; + u32 changed = 0; int res; bool need_hw_reconfig = 0; - struct sta_info *sta; sdata = IEEE80211_DEV_TO_SUB_IF(dev); @@ -329,7 +330,8 @@ static int ieee80211_open(struct net_device *dev) goto err_stop; ieee80211_if_config(dev); - ieee80211_reset_erp_info(dev); + changed |= ieee80211_reset_erp_info(dev); + ieee80211_bss_info_change_notify(sdata, changed); ieee80211_enable_keys(sdata); if (sdata->vif.type == IEEE80211_IF_TYPE_STA && @@ -1190,15 +1192,13 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, changed); } -void ieee80211_reset_erp_info(struct net_device *dev) +u32 ieee80211_reset_erp_info(struct net_device *dev) { struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); sdata->bss_conf.use_cts_prot = 0; sdata->bss_conf.use_short_preamble = 0; - ieee80211_bss_info_change_notify(sdata, - BSS_CHANGED_ERP_CTS_PROT | - BSS_CHANGED_ERP_PREAMBLE); + return BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_ERP_PREAMBLE; } void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw, diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 2a92708..37ea04f 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -573,7 +573,7 @@ static void ieee80211_set_associated(struct net_device *dev, ieee80211_sta_tear_down_BA_sessions(dev, ifsta->bssid); ifsta->flags &= ~IEEE80211_STA_ASSOCIATED; netif_carrier_off(dev); - ieee80211_reset_erp_info(dev); + changed |= ieee80211_reset_erp_info(dev); sdata->bss_conf.assoc_ht = 0; sdata->bss_conf.ht_conf = NULL; -- cgit v0.10.2 From a7767f958a3b09a1bcd0ddcb21ef6f9a8ebd782c Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Wed, 2 Jul 2008 16:30:51 -0700 Subject: mac80211: remove trivial rx_data->fc users Signed-off-by: Harvey Harrison Signed-off-by: John W. Linville diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index a3a26e5..fab443d 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -352,9 +352,10 @@ static void ieee80211_parse_qos(struct ieee80211_rx_data *rx) static void ieee80211_verify_ip_alignment(struct ieee80211_rx_data *rx) { #ifdef CONFIG_MAC80211_DEBUG_PACKET_ALIGNMENT + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; int hdrlen; - if (!WLAN_FC_DATA_PRESENT(rx->fc)) + if (!ieee80211_is_data_present(hdr->frame_control)) return; /* @@ -376,7 +377,7 @@ static void ieee80211_verify_ip_alignment(struct ieee80211_rx_data *rx) * header and the payload is not supported, the driver is required * to move the 802.11 header further back in that case. */ - hdrlen = ieee80211_get_hdrlen(rx->fc); + hdrlen = ieee80211_hdrlen(hdr->frame_control); if (rx->flags & IEEE80211_RX_AMSDU) hdrlen += ETH_HLEN; WARN_ON_ONCE(((unsigned long)(rx->skb->data + hdrlen)) & 3); @@ -415,14 +416,11 @@ ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx) static ieee80211_rx_result ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) { - int hdrlen = ieee80211_get_hdrlen(rx->fc); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data; - -#define msh_h_get(h, l) ((struct ieee80211s_hdr *) ((u8 *)h + l)) + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; + unsigned int hdrlen = ieee80211_hdrlen(hdr->frame_control); - if ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) { - if (!((rx->fc & IEEE80211_FCTL_FROMDS) && - (rx->fc & IEEE80211_FCTL_TODS))) + if (ieee80211_is_data(hdr->frame_control)) { + if (!ieee80211_has_a4(hdr->frame_control)) return RX_DROP_MONITOR; if (memcmp(hdr->addr4, rx->dev->dev_addr, ETH_ALEN) == 0) return RX_DROP_MONITOR; @@ -435,27 +433,30 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) if (!rx->sta || sta_plink_state(rx->sta) != PLINK_ESTAB) { struct ieee80211_mgmt *mgmt; - if ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT) + if (!ieee80211_is_mgmt(hdr->frame_control)) return RX_DROP_MONITOR; - switch (rx->fc & IEEE80211_FCTL_STYPE) { - case IEEE80211_STYPE_ACTION: + if (ieee80211_is_action(hdr->frame_control)) { mgmt = (struct ieee80211_mgmt *)hdr; if (mgmt->u.action.category != PLINK_CATEGORY) return RX_DROP_MONITOR; - /* fall through on else */ - case IEEE80211_STYPE_PROBE_REQ: - case IEEE80211_STYPE_PROBE_RESP: - case IEEE80211_STYPE_BEACON: return RX_CONTINUE; - break; - default: - return RX_DROP_MONITOR; } - } else if ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA && - is_multicast_ether_addr(hdr->addr1) && - mesh_rmc_check(hdr->addr4, msh_h_get(hdr, hdrlen), rx->dev)) + if (ieee80211_is_probe_req(hdr->frame_control) || + ieee80211_is_probe_resp(hdr->frame_control) || + ieee80211_is_beacon(hdr->frame_control)) + return RX_CONTINUE; + + return RX_DROP_MONITOR; + + } + +#define msh_h_get(h, l) ((struct ieee80211s_hdr *) ((u8 *)h + l)) + + if (ieee80211_is_data(hdr->frame_control) && + is_multicast_ether_addr(hdr->addr1) && + mesh_rmc_check(hdr->addr4, msh_h_get(hdr, hdrlen), rx->dev)) return RX_DROP_MONITOR; #undef msh_h_get @@ -466,13 +467,11 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) static ieee80211_rx_result debug_noinline ieee80211_rx_h_check(struct ieee80211_rx_data *rx) { - struct ieee80211_hdr *hdr; - - hdr = (struct ieee80211_hdr *) rx->skb->data; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; /* Drop duplicate 802.11 retransmissions (IEEE 802.11 Chap. 9.2.9) */ if (rx->sta && !is_multicast_ether_addr(hdr->addr1)) { - if (unlikely(rx->fc & IEEE80211_FCTL_RETRY && + if (unlikely(ieee80211_has_retry(hdr->frame_control) && rx->sta->last_seq_ctrl[rx->queue] == hdr->seq_ctrl)) { if (rx->flags & IEEE80211_RX_RA_MATCH) { @@ -501,15 +500,14 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx) if (ieee80211_vif_is_mesh(&rx->sdata->vif)) return ieee80211_rx_mesh_check(rx); - if (unlikely(((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA || - ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL && - (rx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PSPOLL)) && + if (unlikely((ieee80211_is_data(hdr->frame_control) || + ieee80211_is_pspoll(hdr->frame_control)) && rx->sdata->vif.type != IEEE80211_IF_TYPE_IBSS && (!rx->sta || !test_sta_flags(rx->sta, WLAN_STA_ASSOC)))) { - if ((!(rx->fc & IEEE80211_FCTL_FROMDS) && - !(rx->fc & IEEE80211_FCTL_TODS) && - (rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) - || !(rx->flags & IEEE80211_RX_RA_MATCH)) { + if ((!ieee80211_has_fromds(hdr->frame_control) && + !ieee80211_has_tods(hdr->frame_control) && + ieee80211_is_data(hdr->frame_control)) || + !(rx->flags & IEEE80211_RX_RA_MATCH)) { /* Drop IBSS frames and frames for other hosts * silently. */ return RX_DROP_MONITOR; @@ -525,7 +523,7 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx) static ieee80211_rx_result debug_noinline ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) { - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; int keyidx; int hdrlen; ieee80211_rx_result result = RX_DROP_UNUSABLE; @@ -557,7 +555,7 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) * possible. */ - if (!(rx->fc & IEEE80211_FCTL_PROTECTED)) + if (!ieee80211_has_protected(hdr->frame_control)) return RX_CONTINUE; /* @@ -586,7 +584,7 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) (rx->status->flag & RX_FLAG_IV_STRIPPED)) return RX_CONTINUE; - hdrlen = ieee80211_get_hdrlen(rx->fc); + hdrlen = ieee80211_hdrlen(hdr->frame_control); if (rx->skb->len < 8 + hdrlen) return RX_DROP_UNUSABLE; /* TODO: count this? */ @@ -618,7 +616,7 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) /* Check for weak IVs if possible */ if (rx->sta && rx->key->conf.alg == ALG_WEP && - ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) && + ieee80211_is_data(hdr->frame_control) && (!(rx->status->flag & RX_FLAG_IV_STRIPPED) || !(rx->status->flag & RX_FLAG_DECRYPTED)) && ieee80211_wep_is_weak_iv(rx->skb, rx->key)) @@ -710,7 +708,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) { struct sta_info *sta = rx->sta; struct net_device *dev = rx->dev; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; if (!sta) return RX_CONTINUE; @@ -744,21 +742,20 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) sta->last_qual = rx->status->qual; sta->last_noise = rx->status->noise; - if (!(rx->fc & IEEE80211_FCTL_MOREFRAGS)) { + if (!ieee80211_has_morefrags(hdr->frame_control)) { /* Change STA power saving mode only in the end of a frame * exchange sequence */ if (test_sta_flags(sta, WLAN_STA_PS) && - !(rx->fc & IEEE80211_FCTL_PM)) + !ieee80211_has_pm(hdr->frame_control)) rx->sent_ps_buffered += ap_sta_ps_end(dev, sta); else if (!test_sta_flags(sta, WLAN_STA_PS) && - (rx->fc & IEEE80211_FCTL_PM)) + ieee80211_has_pm(hdr->frame_control)) ap_sta_ps_start(dev, sta); } /* Drop data::nullfunc frames silently, since they are used only to * control station power saving mode. */ - if ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA && - (rx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_NULLFUNC) { + if (ieee80211_is_nullfunc(hdr->frame_control)) { I802_DEBUG_INC(rx->local->rx_handlers_drop_nullfunc); /* Update counter and free packet here to avoid counting this * as a dropped packed. */ @@ -1465,15 +1462,15 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx) struct ieee80211_local *local = rx->local; struct ieee80211_hw *hw = &local->hw; struct sk_buff *skb = rx->skb; - struct ieee80211_bar *bar = (struct ieee80211_bar *) skb->data; + struct ieee80211_bar *bar = (struct ieee80211_bar *)skb->data; struct tid_ampdu_rx *tid_agg_rx; u16 start_seq_num; u16 tid; - if (likely((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_CTL)) + if (likely(!ieee80211_is_ctl(bar->frame_control))) return RX_CONTINUE; - if ((rx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BACK_REQ) { + if (ieee80211_is_back_req(bar->frame_control)) { if (!rx->sta) return RX_CONTINUE; tid = le16_to_cpu(bar->control) >> 12; @@ -1527,11 +1524,12 @@ static void ieee80211_rx_michael_mic_report(struct net_device *dev, struct ieee80211_hdr *hdr, struct ieee80211_rx_data *rx) { - int keyidx, hdrlen; + int keyidx; + unsigned int hdrlen; DECLARE_MAC_BUF(mac); DECLARE_MAC_BUF(mac2); - hdrlen = ieee80211_get_hdrlen_from_skb(rx->skb); + hdrlen = ieee80211_hdrlen(hdr->frame_control); if (rx->skb->len >= hdrlen + 4) keyidx = rx->skb->data[hdrlen + 3] >> 6; else @@ -1545,7 +1543,7 @@ static void ieee80211_rx_michael_mic_report(struct net_device *dev, goto ignore; } - if (!(rx->fc & IEEE80211_FCTL_PROTECTED)) + if (!ieee80211_has_protected(hdr->frame_control)) goto ignore; if (rx->sdata->vif.type == IEEE80211_IF_TYPE_AP && keyidx) { @@ -1558,9 +1556,8 @@ static void ieee80211_rx_michael_mic_report(struct net_device *dev, goto ignore; } - if ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA && - ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT || - (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_AUTH)) + if (!ieee80211_is_data(hdr->frame_control) && + !ieee80211_is_auth(hdr->frame_control)) goto ignore; mac80211_ev_michael_mic_failure(rx->dev, keyidx, hdr); @@ -1731,8 +1728,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, case IEEE80211_IF_TYPE_IBSS: if (!bssid) return 0; - if ((rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT && - (rx->fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON) { + if (ieee80211_is_beacon(hdr->frame_control)) { if (!rx->sta) rx->sta = ieee80211_ibss_add_sta(sdata->dev, rx->skb, bssid, hdr->addr2, @@ -1783,8 +1779,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, return 0; break; case IEEE80211_IF_TYPE_WDS: - if (bssid || - (rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA) + if (bssid || !ieee80211_is_data(hdr->frame_control)) return 0; if (compare_ether_addr(sdata->u.wds.remote_addr, hdr->addr2)) return 0; -- cgit v0.10.2 From c34498b9e633baa3266af98106502633b6bc371b Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Wed, 2 Jul 2008 16:30:52 -0700 Subject: mac80211: wpa.c remove rx/tx_data ->fc users Signed-off-by: Harvey Harrison Signed-off-by: John W. Linville diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 241c932..ec2ae86 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -28,19 +28,16 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) size_t data_len; unsigned int hdrlen; struct ieee80211_hdr *hdr; - u16 fc; struct sk_buff *skb = tx->skb; int authenticator; int wpa_test = 0; int tail; - fc = tx->fc; - + hdr = (struct ieee80211_hdr *)skb->data; if (!tx->key || tx->key->conf.alg != ALG_TKIP || skb->len < 24 || - !WLAN_FC_DATA_PRESENT(fc)) + !ieee80211_is_data_present(hdr->frame_control)) return TX_CONTINUE; - hdr = (struct ieee80211_hdr *)skb->data; hdrlen = ieee80211_hdrlen(hdr->frame_control); if (skb->len < hdrlen) return TX_DROP; @@ -90,25 +87,23 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) size_t data_len; unsigned int hdrlen; struct ieee80211_hdr *hdr; - u16 fc; u8 mic[MICHAEL_MIC_LEN]; struct sk_buff *skb = rx->skb; int authenticator = 1, wpa_test = 0; DECLARE_MAC_BUF(mac); - fc = rx->fc; - /* * No way to verify the MIC if the hardware stripped it */ if (rx->status->flag & RX_FLAG_MMIC_STRIPPED) return RX_CONTINUE; + hdr = (struct ieee80211_hdr *)skb->data; if (!rx->key || rx->key->conf.alg != ALG_TKIP || - !(rx->fc & IEEE80211_FCTL_PROTECTED) || !WLAN_FC_DATA_PRESENT(fc)) + !ieee80211_has_protected(hdr->frame_control) || + !ieee80211_is_data_present(hdr->frame_control)) return RX_CONTINUE; - hdr = (struct ieee80211_hdr *)skb->data; hdrlen = ieee80211_hdrlen(hdr->frame_control); if (skb->len < hdrlen + MICHAEL_MIC_LEN) return RX_DROP_UNUSABLE; @@ -239,7 +234,7 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx) hdrlen = ieee80211_hdrlen(hdr->frame_control); - if ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA) + if (!ieee80211_is_data(hdr->frame_control)) return RX_CONTINUE; if (!rx->sta || skb->len - hdrlen < 12) @@ -458,7 +453,7 @@ ieee80211_crypto_ccmp_encrypt(struct ieee80211_tx_data *tx) ieee80211_rx_result ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) { - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; int hdrlen; struct ieee80211_key *key = rx->key; struct sk_buff *skb = rx->skb; @@ -468,7 +463,7 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) hdrlen = ieee80211_hdrlen(hdr->frame_control); - if ((rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA) + if (!ieee80211_is_data(hdr->frame_control)) return RX_CONTINUE; data_len = skb->len - hdrlen - CCMP_HDR_LEN - CCMP_MIC_LEN; -- cgit v0.10.2 From feccb466944cb1aeaabc701cfde6771f3be74919 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Wed, 2 Jul 2008 16:30:52 -0700 Subject: mac80211: pass scratch buffer directly, remove additional pointers Recalculate the offset pointers in the ccmp calculations rather than in the callers. Signed-off-by: Harvey Harrison Signed-off-by: John W. Linville diff --git a/net/mac80211/aes_ccm.c b/net/mac80211/aes_ccm.c index 4d4c2df..e756ed9 100644 --- a/net/mac80211/aes_ccm.c +++ b/net/mac80211/aes_ccm.c @@ -53,15 +53,17 @@ static inline void aes_ccm_prepare(struct crypto_cipher *tfm, u8 *b_0, u8 *aad, void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch, - u8 *b_0, u8 *aad, u8 *data, size_t data_len, + u8 *data, size_t data_len, u8 *cdata, u8 *mic) { int i, j, last_len, num_blocks; - u8 *pos, *cpos, *b, *s_0, *e; + u8 *pos, *cpos, *b, *s_0, *e, *b_0, *aad; b = scratch; s_0 = scratch + AES_BLOCK_LEN; e = scratch + 2 * AES_BLOCK_LEN; + b_0 = scratch + 3 * AES_BLOCK_LEN; + aad = scratch + 4 * AES_BLOCK_LEN; num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_LEN); last_len = data_len % AES_BLOCK_LEN; @@ -92,15 +94,16 @@ void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch, int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *scratch, - u8 *b_0, u8 *aad, u8 *cdata, size_t data_len, - u8 *mic, u8 *data) + u8 *cdata, size_t data_len, u8 *mic, u8 *data) { int i, j, last_len, num_blocks; - u8 *pos, *cpos, *b, *s_0, *a; + u8 *pos, *cpos, *b, *s_0, *a, *b_0, *aad; b = scratch; s_0 = scratch + AES_BLOCK_LEN; a = scratch + 2 * AES_BLOCK_LEN; + b_0 = scratch + 3 * AES_BLOCK_LEN; + aad = scratch + 4 * AES_BLOCK_LEN; num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_LEN); last_len = data_len % AES_BLOCK_LEN; diff --git a/net/mac80211/aes_ccm.h b/net/mac80211/aes_ccm.h index 8cd0f14..6e7820e 100644 --- a/net/mac80211/aes_ccm.h +++ b/net/mac80211/aes_ccm.h @@ -16,10 +16,10 @@ struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[]); void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch, - u8 *b_0, u8 *aad, u8 *data, size_t data_len, + u8 *data, size_t data_len, u8 *cdata, u8 *mic); int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *scratch, - u8 *b_0, u8 *aad, u8 *cdata, size_t data_len, + u8 *cdata, size_t data_len, u8 *mic, u8 *data); void ieee80211_aes_key_free(struct crypto_cipher *tfm); diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index ec2ae86..2f33df0 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -274,16 +274,20 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx) } -static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad, +static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch, int encrypted) { __le16 mask_fc; int a4_included; u8 qos_tid; + u8 *b_0, *aad; u16 data_len, len_a; unsigned int hdrlen; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + b_0 = scratch + 3 * AES_BLOCK_LEN; + aad = scratch + 4 * AES_BLOCK_LEN; + /* * Mask FC: zero subtype b4 b5 b6 * Retry, PwrMgt, MoreData; set Protected @@ -367,7 +371,7 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) struct ieee80211_key *key = tx->key; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); int hdrlen, len, tail; - u8 *pos, *pn, *b_0, *aad, *scratch; + u8 *pos, *pn; int i; info->control.icv_len = CCMP_MIC_LEN; @@ -381,10 +385,6 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) return 0; } - scratch = key->u.ccmp.tx_crypto_buf; - b_0 = scratch + 3 * AES_BLOCK_LEN; - aad = scratch + 4 * AES_BLOCK_LEN; - hdrlen = ieee80211_hdrlen(hdr->frame_control); len = skb->len - hdrlen; @@ -420,8 +420,8 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) } pos += CCMP_HDR_LEN; - ccmp_special_blocks(skb, pn, b_0, aad, 0); - ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, scratch, b_0, aad, pos, len, + ccmp_special_blocks(skb, pn, key->u.ccmp.tx_crypto_buf, 0); + ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, key->u.ccmp.tx_crypto_buf, pos, len, pos, skb_put(skb, CCMP_MIC_LEN)); return 0; @@ -483,16 +483,10 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) if (!(rx->status->flag & RX_FLAG_DECRYPTED)) { /* hardware didn't decrypt/verify MIC */ - u8 *scratch, *b_0, *aad; - - scratch = key->u.ccmp.rx_crypto_buf; - b_0 = scratch + 3 * AES_BLOCK_LEN; - aad = scratch + 4 * AES_BLOCK_LEN; - - ccmp_special_blocks(skb, pn, b_0, aad, 1); + ccmp_special_blocks(skb, pn, key->u.ccmp.rx_crypto_buf, 1); if (ieee80211_aes_ccm_decrypt( - key->u.ccmp.tfm, scratch, b_0, aad, + key->u.ccmp.tfm, key->u.ccmp.rx_crypto_buf, skb->data + hdrlen + CCMP_HDR_LEN, data_len, skb->data + skb->len - CCMP_MIC_LEN, skb->data + hdrlen + CCMP_HDR_LEN)) { -- cgit v0.10.2 From 5fdae6b37e9346dbaea1e51ed6235ed0269d445d Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Wed, 2 Jul 2008 16:30:53 -0700 Subject: mac80211: aes_ccm.c remove crypto wrapper and extra args Signed-off-by: Harvey Harrison Signed-off-by: John W. Linville diff --git a/net/mac80211/aes_ccm.c b/net/mac80211/aes_ccm.c index e756ed9..a87cb3b 100644 --- a/net/mac80211/aes_ccm.c +++ b/net/mac80211/aes_ccm.c @@ -16,31 +16,28 @@ #include "key.h" #include "aes_ccm.h" - -static void ieee80211_aes_encrypt(struct crypto_cipher *tfm, - const u8 pt[16], u8 ct[16]) -{ - crypto_cipher_encrypt_one(tfm, ct, pt); -} - - -static inline void aes_ccm_prepare(struct crypto_cipher *tfm, u8 *b_0, u8 *aad, - u8 *b, u8 *s_0, u8 *a) +static void aes_ccm_prepare(struct crypto_cipher *tfm, u8 *scratch, u8 *a) { int i; + u8 *b_0, *aad, *b, *s_0; - ieee80211_aes_encrypt(tfm, b_0, b); + b_0 = scratch + 3 * AES_BLOCK_LEN; + aad = scratch + 4 * AES_BLOCK_LEN; + b = scratch; + s_0 = scratch + AES_BLOCK_LEN; + + crypto_cipher_encrypt_one(tfm, b, b_0); /* Extra Authenticate-only data (always two AES blocks) */ for (i = 0; i < AES_BLOCK_LEN; i++) aad[i] ^= b[i]; - ieee80211_aes_encrypt(tfm, aad, b); + crypto_cipher_encrypt_one(tfm, b, aad); aad += AES_BLOCK_LEN; for (i = 0; i < AES_BLOCK_LEN; i++) aad[i] ^= b[i]; - ieee80211_aes_encrypt(tfm, aad, a); + crypto_cipher_encrypt_one(tfm, a, aad); /* Mask out bits from auth-only-b_0 */ b_0[0] &= 0x07; @@ -48,7 +45,7 @@ static inline void aes_ccm_prepare(struct crypto_cipher *tfm, u8 *b_0, u8 *aad, /* S_0 is used to encrypt T (= MIC) */ b_0[14] = 0; b_0[15] = 0; - ieee80211_aes_encrypt(tfm, b_0, s_0); + crypto_cipher_encrypt_one(tfm, s_0, b_0); } @@ -67,7 +64,7 @@ void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch, num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_LEN); last_len = data_len % AES_BLOCK_LEN; - aes_ccm_prepare(tfm, b_0, aad, b, s_0, b); + aes_ccm_prepare(tfm, scratch, b); /* Process payload blocks */ pos = data; @@ -79,11 +76,11 @@ void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch, /* Authentication followed by encryption */ for (i = 0; i < blen; i++) b[i] ^= pos[i]; - ieee80211_aes_encrypt(tfm, b, b); + crypto_cipher_encrypt_one(tfm, b, b); b_0[14] = (j >> 8) & 0xff; b_0[15] = j & 0xff; - ieee80211_aes_encrypt(tfm, b_0, e); + crypto_cipher_encrypt_one(tfm, e, b_0); for (i = 0; i < blen; i++) *cpos++ = *pos++ ^ e[i]; } @@ -107,7 +104,7 @@ int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *scratch, num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_LEN); last_len = data_len % AES_BLOCK_LEN; - aes_ccm_prepare(tfm, b_0, aad, b, s_0, a); + aes_ccm_prepare(tfm, scratch, a); /* Process payload blocks */ cpos = cdata; @@ -119,13 +116,12 @@ int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *scratch, /* Decryption followed by authentication */ b_0[14] = (j >> 8) & 0xff; b_0[15] = j & 0xff; - ieee80211_aes_encrypt(tfm, b_0, b); + crypto_cipher_encrypt_one(tfm, b, b_0); for (i = 0; i < blen; i++) { *pos = *cpos++ ^ b[i]; a[i] ^= *pos++; } - - ieee80211_aes_encrypt(tfm, a, a); + crypto_cipher_encrypt_one(tfm, a, a); } for (i = 0; i < CCMP_MIC_LEN; i++) { -- cgit v0.10.2 From e4abd4d49d6df6d5e94564c5e831c61ac722f6ec Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 3 Jul 2008 18:02:27 +0300 Subject: mac80211: add support for iwconfig wlanX frag auto Signed-off-by: Emmanuel Grumbach Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 1babb97..736c32e 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c @@ -800,6 +800,8 @@ static int ieee80211_ioctl_siwfrag(struct net_device *dev, if (frag->disabled) local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD; + else if (!frag->fixed) + local->fragmentation_threshold = IEEE80211_MAX_FRAG_THRESHOLD; else if (frag->value < 256 || frag->value > IEEE80211_MAX_FRAG_THRESHOLD) return -EINVAL; -- cgit v0.10.2 From 0f687e9aeb590e9581709379f47dd13ee9357258 Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Thu, 3 Jul 2008 13:14:56 -0300 Subject: rfkill: some minor kernel-doc changes for rfkill_toggle_radio Improve rfkill_toggle_radio's kernel-doc header a bit. Signed-off-by: Henrique de Moraes Holschuh Acked-by: Ivo van Doorn Signed-off-by: John W. Linville diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c index ce0e231..aa7039d 100644 --- a/net/rfkill/rfkill.c +++ b/net/rfkill/rfkill.c @@ -130,17 +130,19 @@ static void update_rfkill_state(struct rfkill *rfkill) /** * rfkill_toggle_radio - wrapper for toggle_radio hook - * calls toggle_radio taking into account a lot of "small" - * details. + * * @rfkill: the rfkill struct to use * @force: calls toggle_radio even if cache says it is not needed, * and also makes sure notifications of the state will be * sent even if it didn't change * @state: the new state to call toggle_radio() with * - * This wrappen protects and enforces the API for toggle_radio - * calls. Note that @force cannot override a (possibly cached) - * state of RFKILL_STATE_HARD_BLOCKED. Any device making use of + * Calls rfkill->toggle_radio, enforcing the API for toggle_radio + * calls and handling all the red tape such as issuing notifications + * if the call is successful. + * + * Note that @force cannot override a (possibly cached) state of + * RFKILL_STATE_HARD_BLOCKED. Any device making use of * RFKILL_STATE_HARD_BLOCKED implements either get_state() or * rfkill_force_state(), so the cache either is bypassed or valid. * -- cgit v0.10.2 From fd4484af7c02b31bcb6090eeb0d85cf947719f2d Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Thu, 3 Jul 2008 13:14:57 -0300 Subject: rfkill: ignore errors from rfkill_toggle_radio in rfkill_add_switch rfkill_add_switch() calls rfkill_toggle_radio() to set the state of a recently registered rfkill class to the current global state [for that rfkill->type]. The rfkill_toggle_radio() call is going to error out if the hardware is RFKILL_STATE_HARD_BLOCKED, and the global state is RFKILL_STATE_UNBLOCKED. That is a quite normal situation which I missed to account for. As things stand, the error return from rfkill_toggle_radio ends up causing rfkill_register to bail out with an error (de-registering the new switch in the process), which is Not Nice. Change rfkill_add_switch() to not return errors because of a failed call to rfkill_toggle_radio(). We can go back to returning errors again (if that's indeed the right thing to do) if we define the exact error codes the rfkill->toggle_radio callbacks are to return in each situation, so that we can ignore the right ones only. Bug reported by "kionez ". Signed-off-by: Henrique de Moraes Holschuh Cc: kionez Acked-by: Ivo van Doorn Signed-off-by: John W. Linville diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c index aa7039d..7a560b7 100644 --- a/net/rfkill/rfkill.c +++ b/net/rfkill/rfkill.c @@ -501,17 +501,15 @@ static struct class rfkill_class = { static int rfkill_add_switch(struct rfkill *rfkill) { - int error; - mutex_lock(&rfkill_mutex); - error = rfkill_toggle_radio(rfkill, rfkill_states[rfkill->type], 0); - if (!error) - list_add_tail(&rfkill->node, &rfkill_list); + rfkill_toggle_radio(rfkill, rfkill_states[rfkill->type], 0); + + list_add_tail(&rfkill->node, &rfkill_list); mutex_unlock(&rfkill_mutex); - return error; + return 0; } static void rfkill_remove_switch(struct rfkill *rfkill) -- cgit v0.10.2 From 6ef307bc561911c8cdda98ef3896b5982b602a43 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Thu, 3 Jul 2008 13:52:18 -0700 Subject: mac80211: fix lots of kernel-doc Fix more than 50 kernel-doc warnings in ieee80211/mac80211 kernel-doc notation. Fix a few typos also. Note: Some fields are marked as TBD and need to have their description corrected. Signed-off-by: Randy Dunlap Signed-off-by: John W. Linville diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 0a5de3e..656442c 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -42,7 +42,7 @@ * tasklet function. * * NOTE: If the driver opts to use the _irqsafe() functions, it may not also - * use the non-irqsafe functions! + * use the non-IRQ-safe functions! */ /** @@ -85,7 +85,7 @@ enum ieee80211_notification_types { * struct ieee80211_ht_bss_info - describing BSS's HT characteristics * * This structure describes most essential parameters needed - * to describe 802.11n HT characteristics in a BSS + * to describe 802.11n HT characteristics in a BSS. * * @primary_channel: channel number of primery channel * @bss_cap: 802.11n's general BSS capabilities (e.g. channel width) @@ -201,9 +201,9 @@ struct ieee80211_bss_conf { }; /** - * enum mac80211_tx_flags - flags to transmission information/status + * enum mac80211_tx_control_flags - flags to describe transmission information/status * - * These flags are used with the @flags member of &ieee80211_tx_info + * These flags are used with the @flags member of &ieee80211_tx_info. * * @IEEE80211_TX_CTL_REQ_TX_STATUS: request TX status callback for this frame. * @IEEE80211_TX_CTL_DO_NOT_ENCRYPT: send this frame without encryption; @@ -212,11 +212,12 @@ struct ieee80211_bss_conf { * @IEEE80211_TX_CTL_USE_CTS_PROTECT: use CTS protection for the frame (e.g., * for combined 802.11g / 802.11b networks) * @IEEE80211_TX_CTL_NO_ACK: tell the low level not to wait for an ack - * @IEEE80211_TX_CTL_RATE_CTRL_PROBE + * @IEEE80211_TX_CTL_RATE_CTRL_PROBE: TBD * @IEEE80211_TX_CTL_CLEAR_PS_FILT: clear powersave filter for destination * station - * @IEEE80211_TX_CTL_REQUEUE: + * @IEEE80211_TX_CTL_REQUEUE: TBD * @IEEE80211_TX_CTL_FIRST_FRAGMENT: this is a first fragment of the frame + * @IEEE80211_TX_CTL_SHORT_PREAMBLE: TBD * @IEEE80211_TX_CTL_LONG_RETRY_LIMIT: this frame should be send using the * through set_retry_limit configured long retry value * @IEEE80211_TX_CTL_EAPOL_FRAME: internal to mac80211 @@ -230,6 +231,7 @@ struct ieee80211_bss_conf { * @IEEE80211_TX_CTL_40_MHZ_WIDTH: send this frame using 40 Mhz channel width * @IEEE80211_TX_CTL_DUP_DATA: duplicate data frame on both 20 Mhz channels * @IEEE80211_TX_CTL_SHORT_GI: send this frame using short guard interval + * @IEEE80211_TX_CTL_INJECTED: TBD * @IEEE80211_TX_STAT_TX_FILTERED: The frame was not transmitted * because the destination STA was in powersave mode. * @IEEE80211_TX_STAT_ACK: Frame was acknowledged @@ -280,6 +282,12 @@ enum mac80211_tx_control_flags { * (3) TX status information - driver tells mac80211 what happened * * @flags: transmit info flags, defined above + * @band: TBD + * @tx_rate_idx: TBD + * @antenna_sel_tx: TBD + * @control: union for control data + * @status: union for status data + * @driver_data: array of driver_data pointers * @retry_count: number of retries * @excessive_retries: set to 1 if the frame was retried many times * but not acknowledged @@ -562,8 +570,8 @@ enum ieee80211_key_alg { /** * enum ieee80211_key_len - key length - * @WEP40: WEP 5 byte long key - * @WEP104: WEP 13 byte long key + * @LEN_WEP40: WEP 5-byte long key + * @LEN_WEP104: WEP 13-byte long key */ enum ieee80211_key_len { LEN_WEP40 = 5, @@ -640,7 +648,7 @@ enum set_key_cmd { * enum sta_notify_cmd - sta notify command * * Used with the sta_notify() callback in &struct ieee80211_ops, this - * indicates addition and removal of a station to station table + * indicates addition and removal of a station to station table. * * @STA_NOTIFY_ADD: a station was added to the station table * @STA_NOTIFY_REMOVE: a station being removed from the station table @@ -1340,7 +1348,7 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw); * * This function frees everything that was allocated, including the * private data for the driver. You must call ieee80211_unregister_hw() - * before calling this function + * before calling this function. * * @hw: the hardware to free */ @@ -1411,7 +1419,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb); /** - * ieee80211_tx_status_irqsafe - irq-safe transmit status callback + * ieee80211_tx_status_irqsafe - IRQ-safe transmit status callback * * Like ieee80211_tx_status() but can be called in IRQ context * (internally defers to a tasklet.) @@ -1589,6 +1597,8 @@ unsigned int ieee80211_hdrlen(__le16 fc); * @keyconf: the parameter passed with the set key * @skb: the skb for which the key is needed * @rc4key: a buffer to which the key will be written + * @type: TBD + * @key: TBD */ void ieee80211_get_tkip_key(struct ieee80211_key_conf *keyconf, struct sk_buff *skb, @@ -1639,7 +1649,7 @@ void ieee80211_wake_queues(struct ieee80211_hw *hw); void ieee80211_scan_completed(struct ieee80211_hw *hw); /** - * ieee80211_iterate_active_interfaces- iterate active interfaces + * ieee80211_iterate_active_interfaces - iterate active interfaces * * This function iterates over the interfaces associated with a given * hardware that are currently active and calls the callback for them. @@ -1706,7 +1716,7 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid); * * This function must be called by low level driver once it has * finished with preparations for the BA session. - * This version of the function is irq safe. + * This version of the function is IRQ-safe. */ void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, const u8 *ra, u16 tid); @@ -1746,7 +1756,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid); * * This function must be called by low level driver once it has * finished with preparations for the BA session tear down. - * This version of the function is irq safe. + * This version of the function is IRQ-safe. */ void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, const u8 *ra, u16 tid); @@ -1754,7 +1764,7 @@ void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, const u8 *ra, /** * ieee80211_notify_mac - low level driver notification * @hw: pointer as obtained from ieee80211_alloc_hw(). - * @notification_types: enum ieee80211_notification_types + * @notif_type: enum ieee80211_notification_types * * This function must be called by low level driver to inform mac80211 of * low level driver status change or force mac80211 to re-assoc for low diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index d8a16b7..47d2c1b 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -135,6 +135,7 @@ struct sta_info *sta_info_get_by_idx(struct ieee80211_local *local, int idx, /** * __sta_info_free - internal STA free helper * + * @local: pointer to the global information * @sta: STA info to free * * This function must undo everything done by sta_info_alloc() diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index fd228c1..94311dc 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -160,11 +160,21 @@ struct sta_ampdu_mlme { * @list: global linked list entry * @hnext: hash table linked list pointer * @local: pointer to the global information + * @sdata: TBD + * @key: TBD + * @rate_ctrl: TBD + * @rate_ctrl_priv: TBD + * @lock: used for locking all fields that require locking, see comments + * in the header file. + * @flaglock: spinlock for flags accesses + * @ht_info: HT capabilities of this STA + * @supp_rates: Bitmap of supported rates (per band) * @addr: MAC address of this STA * @aid: STA's unique AID (1..2007, 0 = not assigned yet), * only used in AP (and IBSS?) mode + * @listen_interval: TBD + * @pin_status: TBD * @flags: STA flags, see &enum ieee80211_sta_info_flags - * @flaglock: spinlock for flags accesses * @ps_tx_buf: buffer of frames to transmit to this station * when it leaves power saving state * @tx_filtered: buffer of frames we already tried to transmit @@ -172,10 +182,41 @@ struct sta_ampdu_mlme { * power saving state * @rx_packets: Number of MSDUs received from this STA * @rx_bytes: Number of bytes received from this STA - * @supp_rates: Bitmap of supported rates (per band) - * @ht_info: HT capabilities of this STA - * @lock: used for locking all fields that require locking, see comments - * in the header file. + * @wep_weak_iv_count: TBD + * @last_rx: TBD + * @num_duplicates: number of duplicate frames received from this STA + * @rx_fragments: number of received MPDUs + * @rx_dropped: number of dropped MPDUs from this STA + * @last_signal: signal of last received frame from this STA + * @last_qual: qual of last received frame from this STA + * @last_noise: noise of last received frame from this STA + * @last_seq_ctrl: last received seq/frag number from this STA (per RX queue) + * @wme_rx_queue: TBD + * @tx_filtered_count: TBD + * @tx_retry_failed: TBD + * @tx_retry_count: TBD + * @tx_num_consecutive_failures: TBD + * @tx_num_mpdu_ok: TBD + * @tx_num_mpdu_fail: TBD + * @fail_avg: moving percentage of failed MSDUs + * @tx_packets: number of RX/TX MSDUs + * @tx_bytes: TBD + * @tx_fragments: number of transmitted MPDUs + * @txrate_idx: TBD + * @last_txrate_idx: TBD + * @wme_tx_queue: TBD + * @ampdu_mlme: TBD + * @timer_to_tid: identity mapping to ID timers + * @tid_to_tx_q: map tid to tx queue + * @llid: Local link ID + * @plid: Peer link ID + * @reason: Cancel reason on PLINK_HOLDING state + * @plink_retries: Retries in establishment + * @ignore_plink_timer: TBD + * @plink_state plink_state: TBD + * @plink_timeout: TBD + * @plink_timer: TBD + * @debugfs: debug filesystem info */ struct sta_info { /* General information, mostly static */ @@ -217,14 +258,12 @@ struct sta_info { unsigned long rx_packets, rx_bytes; unsigned long wep_weak_iv_count; unsigned long last_rx; - unsigned long num_duplicates; /* number of duplicate frames received - * from this STA */ - unsigned long rx_fragments; /* number of received MPDUs */ - unsigned long rx_dropped; /* number of dropped MPDUs from this STA */ - int last_signal; /* signal of last received frame from this STA */ - int last_qual; /* qual of last received frame from this STA */ - int last_noise; /* noise of last received frame from this STA */ - /* last received seq/frag number from this STA (per RX queue) */ + unsigned long num_duplicates; + unsigned long rx_fragments; + unsigned long rx_dropped; + int last_signal; + int last_qual; + int last_noise; __le16 last_seq_ctrl[NUM_RX_DATA_QUEUES]; #ifdef CONFIG_MAC80211_DEBUG_COUNTERS unsigned int wme_rx_queue[NUM_RX_DATA_QUEUES]; @@ -241,9 +280,9 @@ struct sta_info { unsigned int fail_avg; /* Updated from TX path only, no locking requirements */ - unsigned long tx_packets; /* number of RX/TX MSDUs */ + unsigned long tx_packets; unsigned long tx_bytes; - unsigned long tx_fragments; /* number of transmitted MPDUs */ + unsigned long tx_fragments; int txrate_idx; int last_txrate_idx; #ifdef CONFIG_MAC80211_DEBUG_COUNTERS @@ -254,18 +293,18 @@ struct sta_info { * Aggregation information, locked with lock. */ struct sta_ampdu_mlme ampdu_mlme; - u8 timer_to_tid[STA_TID_NUM]; /* identity mapping to ID timers */ - u8 tid_to_tx_q[STA_TID_NUM]; /* map tid to tx queue */ + u8 timer_to_tid[STA_TID_NUM]; + u8 tid_to_tx_q[STA_TID_NUM]; #ifdef CONFIG_MAC80211_MESH /* * Mesh peer link attributes * TODO: move to a sub-structure that is referenced with pointer? */ - __le16 llid; /* Local link ID */ - __le16 plid; /* Peer link ID */ - __le16 reason; /* Cancel reason on PLINK_HOLDING state */ - u8 plink_retries; /* Retries in establishment */ + __le16 llid; + __le16 plid; + __le16 reason; + u8 plink_retries; bool ignore_plink_timer; enum plink_state plink_state; u32 plink_timeout; -- cgit v0.10.2 From f2cae6c5e41a979f85463aff60877b31fa3a383d Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Fri, 4 Jul 2008 04:30:49 +0100 Subject: zd1211rw: beacon config error checking Add some error checking to the new beacon configuration code. Signed-off-by: Daniel Drake Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index 317c5e2..665f76a 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -405,43 +405,66 @@ static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs, /* FIXME: Management frame? */ } -void zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon) +static int zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon) { struct zd_mac *mac = zd_hw_mac(hw); + int r; u32 tmp, j = 0; /* 4 more bytes for tail CRC */ u32 full_len = beacon->len + 4; - zd_iowrite32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, 0); - zd_ioread32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, &tmp); + + r = zd_iowrite32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, 0); + if (r < 0) + return r; + r = zd_ioread32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, &tmp); + if (r < 0) + return r; + while (tmp & 0x2) { - zd_ioread32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, &tmp); + r = zd_ioread32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, &tmp); + if (r < 0) + return r; if ((++j % 100) == 0) { printk(KERN_ERR "CR_BCN_FIFO_SEMAPHORE not ready\n"); if (j >= 500) { printk(KERN_ERR "Giving up beacon config.\n"); - return; + return -ETIMEDOUT; } } msleep(1); } - zd_iowrite32(&mac->chip, CR_BCN_FIFO, full_len - 1); - if (zd_chip_is_zd1211b(&mac->chip)) - zd_iowrite32(&mac->chip, CR_BCN_LENGTH, full_len - 1); + r = zd_iowrite32(&mac->chip, CR_BCN_FIFO, full_len - 1); + if (r < 0) + return r; + if (zd_chip_is_zd1211b(&mac->chip)) { + r = zd_iowrite32(&mac->chip, CR_BCN_LENGTH, full_len - 1); + if (r < 0) + return r; + } - for (j = 0 ; j < beacon->len; j++) - zd_iowrite32(&mac->chip, CR_BCN_FIFO, + for (j = 0 ; j < beacon->len; j++) { + r = zd_iowrite32(&mac->chip, CR_BCN_FIFO, *((u8 *)(beacon->data + j))); + if (r < 0) + return r; + } - for (j = 0; j < 4; j++) - zd_iowrite32(&mac->chip, CR_BCN_FIFO, 0x0); + for (j = 0; j < 4; j++) { + r = zd_iowrite32(&mac->chip, CR_BCN_FIFO, 0x0); + if (r < 0) + return r; + } + + r = zd_iowrite32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, 1); + if (r < 0) + return r; - zd_iowrite32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, 1); /* 802.11b/g 2.4G CCK 1Mb * 802.11a, not yet implemented, uses different values (see GPL vendor * driver) */ - zd_iowrite32(&mac->chip, CR_BCN_PLCP_CFG, 0x00000400 | + return zd_iowrite32(&mac->chip, CR_BCN_PLCP_CFG, 0x00000400 | (full_len << 19)); } @@ -699,15 +722,20 @@ static int zd_op_config_interface(struct ieee80211_hw *hw, { struct zd_mac *mac = zd_hw_mac(hw); int associated; + int r; if (mac->type == IEEE80211_IF_TYPE_MESH_POINT || mac->type == IEEE80211_IF_TYPE_IBSS) { associated = true; if (conf->beacon) { - zd_mac_config_beacon(hw, conf->beacon); - kfree_skb(conf->beacon); - zd_set_beacon_interval(&mac->chip, BCN_MODE_IBSS | + r = zd_mac_config_beacon(hw, conf->beacon); + if (r < 0) + return r; + r = zd_set_beacon_interval(&mac->chip, BCN_MODE_IBSS | hw->conf.beacon_int); + if (r < 0) + return r; + kfree_skb(conf->beacon); } } else associated = is_valid_ether_addr(conf->bssid); -- cgit v0.10.2 From 50db7875d9dcd89f7624b13535738612faf8db0c Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Fri, 4 Jul 2008 14:51:39 +0200 Subject: rt2x00: Remove input_polldev requirements for rfkill With the new rfkill interface there is no longer a need for the input_polldev. Create a delayed_work structure which we can put on the mac80211 workqueue and poll the hardware every 1000ms. v2: Decrease poll frequency from 100ms to 1000ms Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index 3a9b1d7..d485a86 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig @@ -36,9 +36,7 @@ config RT2X00_LIB_FIRMWARE config RT2X00_LIB_RFKILL boolean depends on RT2X00_LIB - depends on INPUT select RFKILL - select INPUT_POLLDEV config RT2X00_LIB_LEDS boolean @@ -57,7 +55,7 @@ config RT2400PCI config RT2400PCI_RFKILL bool "Ralink rt2400 rfkill support" - depends on RT2400PCI && INPUT + depends on RT2400PCI select RT2X00_LIB_RFKILL ---help--- This adds support for integrated rt2400 hardware that features a @@ -85,7 +83,7 @@ config RT2500PCI config RT2500PCI_RFKILL bool "Ralink rt2500 rfkill support" - depends on RT2500PCI && INPUT + depends on RT2500PCI select RT2X00_LIB_RFKILL ---help--- This adds support for integrated rt2500 hardware that features a @@ -115,7 +113,7 @@ config RT61PCI config RT61PCI_RFKILL bool "Ralink rt2501/rt61 rfkill support" - depends on RT61PCI && INPUT + depends on RT61PCI select RT2X00_LIB_RFKILL ---help--- This adds support for integrated rt61 hardware that features a diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 6842464..1b28dad 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -649,7 +649,7 @@ struct rt2x00_dev { #define RFKILL_STATE_ALLOCATED 1 #define RFKILL_STATE_REGISTERED 2 struct rfkill *rfkill; - struct input_polled_dev *poll_dev; + struct delayed_work rfkill_work; #endif /* CONFIG_RT2X00_LIB_RFKILL */ /* diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index ae8ab71..41b3289 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -1179,7 +1179,6 @@ int rt2x00lib_suspend(struct rt2x00_dev *rt2x00dev, pm_message_t state) * Suspend/disable extra components. */ rt2x00leds_suspend(rt2x00dev); - rt2x00rfkill_suspend(rt2x00dev); rt2x00debug_deregister(rt2x00dev); exit: @@ -1235,7 +1234,6 @@ int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev) * Restore/enable extra components. */ rt2x00debug_register(rt2x00dev); - rt2x00rfkill_resume(rt2x00dev); rt2x00leds_resume(rt2x00dev); /* diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index 1d1f074..eae5ce1 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -33,7 +33,7 @@ * Both the link tuner as the rfkill will be called once per second. */ #define LINK_TUNE_INTERVAL ( round_jiffies_relative(HZ) ) -#define RFKILL_POLL_INTERVAL ( 1000 ) +#define RFKILL_POLL_INTERVAL ( round_jiffies_relative(HZ) ) /* * rt2x00_rate: Per rate device information @@ -204,8 +204,6 @@ void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev); void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev); void rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev); void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev); -void rt2x00rfkill_suspend(struct rt2x00_dev *rt2x00dev); -void rt2x00rfkill_resume(struct rt2x00_dev *rt2x00dev); #else static inline void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev) { @@ -222,14 +220,6 @@ static inline void rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev) static inline void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev) { } - -static inline void rt2x00rfkill_suspend(struct rt2x00_dev *rt2x00dev) -{ -} - -static inline void rt2x00rfkill_resume(struct rt2x00_dev *rt2x00dev) -{ -} #endif /* CONFIG_RT2X00_LIB_RFKILL */ /* diff --git a/drivers/net/wireless/rt2x00/rt2x00rfkill.c b/drivers/net/wireless/rt2x00/rt2x00rfkill.c index 207281c..04b2971 100644 --- a/drivers/net/wireless/rt2x00/rt2x00rfkill.c +++ b/drivers/net/wireless/rt2x00/rt2x00rfkill.c @@ -23,7 +23,6 @@ Abstract: rt2x00 rfkill routines. */ -#include #include #include #include @@ -61,15 +60,35 @@ static int rt2x00rfkill_toggle_radio(void *data, enum rfkill_state state) return retval; } -static void rt2x00rfkill_poll(struct input_polled_dev *poll_dev) +static int rt2x00rfkill_get_state(void *data, enum rfkill_state *state) { - struct rt2x00_dev *rt2x00dev = poll_dev->private; - int state = rt2x00dev->ops->lib->rfkill_poll(rt2x00dev); + struct rt2x00_dev *rt2x00dev = data; - if (rt2x00dev->rfkill->state != state) { - input_report_key(poll_dev->input, KEY_WLAN, 1); - input_report_key(poll_dev->input, KEY_WLAN, 0); - } + *state = rt2x00dev->rfkill->state; + + return 0; +} + +static void rt2x00rfkill_poll(struct work_struct *work) +{ + struct rt2x00_dev *rt2x00dev = + container_of(work, struct rt2x00_dev, rfkill_work.work); + int state; + + if (!test_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state)) + return; + + /* + * rfkill_poll reports 1 when the key has been pressed and the + * radio should be blocked. + */ + state = !rt2x00dev->ops->lib->rfkill_poll(rt2x00dev) ? + RFKILL_STATE_UNBLOCKED : RFKILL_STATE_SOFT_BLOCKED; + + rfkill_force_state(rt2x00dev->rfkill, state); + + queue_delayed_work(rt2x00dev->hw->workqueue, + &rt2x00dev->rfkill_work, RFKILL_POLL_INTERVAL); } void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev) @@ -83,12 +102,6 @@ void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev) return; } - if (input_register_polled_device(rt2x00dev->poll_dev)) { - ERROR(rt2x00dev, "Failed to register polled device.\n"); - rfkill_unregister(rt2x00dev->rfkill); - return; - } - __set_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state); /* @@ -96,7 +109,7 @@ void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev) * and correctly sends the signal to the rfkill layer about this * state. */ - rt2x00rfkill_poll(rt2x00dev->poll_dev); + rt2x00rfkill_poll(&rt2x00dev->rfkill_work.work); } void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev) @@ -105,38 +118,13 @@ void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev) !test_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state)) return; - input_unregister_polled_device(rt2x00dev->poll_dev); + cancel_delayed_work_sync(&rt2x00dev->rfkill_work); + rfkill_unregister(rt2x00dev->rfkill); __clear_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state); } -static struct input_polled_dev * -rt2x00rfkill_allocate_polldev(struct rt2x00_dev *rt2x00dev) -{ - struct input_polled_dev *poll_dev; - - poll_dev = input_allocate_polled_device(); - if (!poll_dev) - return NULL; - - poll_dev->private = rt2x00dev; - poll_dev->poll = rt2x00rfkill_poll; - poll_dev->poll_interval = RFKILL_POLL_INTERVAL; - - poll_dev->input->name = rt2x00dev->ops->name; - poll_dev->input->phys = wiphy_name(rt2x00dev->hw->wiphy); - poll_dev->input->id.bustype = BUS_HOST; - poll_dev->input->id.vendor = 0x1814; - poll_dev->input->id.product = rt2x00dev->chip.rt; - poll_dev->input->id.version = rt2x00dev->chip.rev; - poll_dev->input->dev.parent = wiphy_dev(rt2x00dev->hw->wiphy); - poll_dev->input->evbit[0] = BIT(EV_KEY); - set_bit(KEY_WLAN, poll_dev->input->keybit); - - return poll_dev; -} - void rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev) { if (!test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags)) @@ -153,14 +141,9 @@ void rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev) rt2x00dev->rfkill->data = rt2x00dev; rt2x00dev->rfkill->state = -1; rt2x00dev->rfkill->toggle_radio = rt2x00rfkill_toggle_radio; + rt2x00dev->rfkill->get_state = rt2x00rfkill_get_state; - rt2x00dev->poll_dev = rt2x00rfkill_allocate_polldev(rt2x00dev); - if (!rt2x00dev->poll_dev) { - ERROR(rt2x00dev, "Failed to allocate polled device.\n"); - rfkill_free(rt2x00dev->rfkill); - rt2x00dev->rfkill = NULL; - return; - } + INIT_DELAYED_WORK(&rt2x00dev->rfkill_work, rt2x00rfkill_poll); return; } @@ -171,32 +154,8 @@ void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev) !test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state)) return; - input_free_polled_device(rt2x00dev->poll_dev); - rt2x00dev->poll_dev = NULL; + cancel_delayed_work_sync(&rt2x00dev->rfkill_work); rfkill_free(rt2x00dev->rfkill); rt2x00dev->rfkill = NULL; } - -void rt2x00rfkill_suspend(struct rt2x00_dev *rt2x00dev) -{ - if (!test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags) || - !test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state)) - return; - - input_free_polled_device(rt2x00dev->poll_dev); - rt2x00dev->poll_dev = NULL; -} - -void rt2x00rfkill_resume(struct rt2x00_dev *rt2x00dev) -{ - if (!test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags) || - !test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state)) - return; - - rt2x00dev->poll_dev = rt2x00rfkill_allocate_polldev(rt2x00dev); - if (!rt2x00dev->poll_dev) { - ERROR(rt2x00dev, "Failed to allocate polled device.\n"); - return; - } -} -- cgit v0.10.2 From ff352391acfac1e183c8c8b2858f9393bd064a65 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Fri, 4 Jul 2008 14:56:07 +0200 Subject: rt2x00: Decrease alignment headroom We only need 4 bytes of headroom for alignment purposes in the RX frame. It was previously higher for optimization purposes which are no longer possible due to DMA mappings. v2: Fix patch error Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 8e86611..3ddce53 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -45,10 +45,11 @@ struct sk_buff *rt2x00queue_alloc_rxskb(struct rt2x00_dev *rt2x00dev, frame_size = entry->queue->data_size + entry->queue->desc_size; /* - * Reserve a few bytes extra headroom to allow drivers some moving - * space (e.g. for alignment), while keeping the skb aligned. + * The payload should be aligned to a 4-byte boundary, + * this means we need at least 3 bytes for moving the frame + * into the correct offset. */ - reserved_size = 8; + reserved_size = 4; /* * Allocate skbuffer. -- cgit v0.10.2 From 8e260c22238dd8b57aefb1f5e4bd114486a9c17d Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Fri, 4 Jul 2008 13:41:31 +0200 Subject: rt2x00: Use ieee80211_hw->workqueue again Remove the rt2x00 singlethreaded workqueue and move the link tuner and packet filter scheduled work to the ieee80211_hw->workqueue again. The only exception is the interface scheduled work handler which uses the mac80211 interface iterator under the RTNL lock. This work needs to be handled on the kernel workqueue to prevent lockdep issues. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 1b28dad..c07d9ef 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -787,8 +787,10 @@ struct rt2x00_dev { /* * Scheduled work. + * NOTE: intf_work will use ieee80211_iterate_active_interfaces() + * which means it cannot be placed on the hw->workqueue + * due to RTNL locking requirements. */ - struct workqueue_struct *workqueue; struct work_struct intf_work; struct work_struct filter_work; diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 41b3289..8086263 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -74,7 +74,7 @@ static void rt2x00lib_start_link_tuner(struct rt2x00_dev *rt2x00dev) rt2x00lib_reset_link_tuner(rt2x00dev); - queue_delayed_work(rt2x00dev->workqueue, + queue_delayed_work(rt2x00dev->hw->workqueue, &rt2x00dev->link.work, LINK_TUNE_INTERVAL); } @@ -392,7 +392,7 @@ static void rt2x00lib_link_tuner(struct work_struct *work) * Increase tuner counter, and reschedule the next link tuner run. */ rt2x00dev->link.count++; - queue_delayed_work(rt2x00dev->workqueue, + queue_delayed_work(rt2x00dev->hw->workqueue, &rt2x00dev->link.work, LINK_TUNE_INTERVAL); } @@ -496,7 +496,7 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev) rt2x00lib_beacondone_iter, rt2x00dev); - queue_work(rt2x00dev->workqueue, &rt2x00dev->intf_work); + schedule_work(&rt2x00dev->intf_work); } EXPORT_SYMBOL_GPL(rt2x00lib_beacondone); @@ -1064,10 +1064,6 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) /* * Initialize configuration work. */ - rt2x00dev->workqueue = create_singlethread_workqueue("rt2x00lib"); - if (!rt2x00dev->workqueue) - goto exit; - INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled); INIT_WORK(&rt2x00dev->filter_work, rt2x00lib_packetfilter_scheduled); INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00lib_link_tuner); @@ -1128,13 +1124,6 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev) rt2x00leds_unregister(rt2x00dev); /* - * Stop all queued work. Note that most tasks will already be halted - * during rt2x00lib_disable_radio() and rt2x00lib_uninitialize(). - */ - flush_workqueue(rt2x00dev->workqueue); - destroy_workqueue(rt2x00dev->workqueue); - - /* * Free ieee80211_hw memory. */ rt2x00lib_remove_hw(rt2x00dev); diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 1253da8..3a1fb6d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -431,7 +431,7 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw, if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags)) rt2x00dev->ops->lib->config_filter(rt2x00dev, *total_flags); else - queue_work(rt2x00dev->workqueue, &rt2x00dev->filter_work); + queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->filter_work); } EXPORT_SYMBOL_GPL(rt2x00mac_configure_filter); @@ -512,7 +512,7 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, memcpy(&intf->conf, bss_conf, sizeof(*bss_conf)); if (delayed) { intf->delayed_flags |= delayed; - queue_work(rt2x00dev->workqueue, &rt2x00dev->intf_work); + schedule_work(&rt2x00dev->intf_work); } spin_unlock(&intf->lock); } -- cgit v0.10.2 From ae73e58ea64f121b26437a10937330e77ff48f33 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Fri, 4 Jul 2008 16:14:59 +0200 Subject: rt2x00: Report RX end time for rt2400pci rt2400 is the only currently available rt2x00 driver which supports reporting of the RX end time for frames. Since mac80211 uses this information for IBSS syncing, it is important that it is being reported. v2: Complement 32 bits of RX timestamp with upper 32bits from TSF Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index b3dffcf..ee953ca 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1087,14 +1087,20 @@ static void rt2400pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, static void rt2400pci_fill_rxdone(struct queue_entry *entry, struct rxdone_entry_desc *rxdesc) { + struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct queue_entry_priv_pci *entry_priv = entry->priv_data; u32 word0; u32 word2; u32 word3; + u32 word4; + u64 tsf; + u32 rx_low; + u32 rx_high; rt2x00_desc_read(entry_priv->desc, 0, &word0); rt2x00_desc_read(entry_priv->desc, 2, &word2); rt2x00_desc_read(entry_priv->desc, 3, &word3); + rt2x00_desc_read(entry_priv->desc, 4, &word4); if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR)) rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; @@ -1102,10 +1108,27 @@ static void rt2400pci_fill_rxdone(struct queue_entry *entry, rxdesc->flags |= RX_FLAG_FAILED_PLCP_CRC; /* + * We only get the lower 32bits from the timestamp, + * to get the full 64bits we must complement it with + * the timestamp from get_tsf(). + * Note that when a wraparound of the lower 32bits + * has occurred between the frame arrival and the get_tsf() + * call, we must decrease the higher 32bits with 1 to get + * to correct value. + */ + tsf = rt2x00dev->ops->hw->get_tsf(rt2x00dev->hw); + rx_low = rt2x00_get_field32(word4, RXD_W4_RX_END_TIME); + rx_high = upper_32_bits(tsf); + + if ((u32)tsf <= rx_low) + rx_high--; + + /* * Obtain the status about this packet. * The signal is the PLCP value, and needs to be stripped * of the preamble bit (0x08). */ + rxdesc->timestamp = ((u64)rx_high << 32) | rx_low; rxdesc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL) & ~0x08; rxdesc->rssi = rt2x00_get_field32(word2, RXD_W3_RSSI) - entry->queue->rt2x00dev->rssi_offset; diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 8086263..b48c04e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -664,6 +664,7 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, rt2x00dev->link.qual.rx_success++; + rx_status->mactime = rxdesc.timestamp; rx_status->rate_idx = idx; rx_status->qual = rt2x00lib_calculate_link_signal(rt2x00dev, rxdesc.rssi); diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 5dd9cca..8945945 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -146,6 +146,7 @@ enum rxdone_entry_desc_flags { * * Summary of information that has been read from the RX frame descriptor. * + * @timestamp: RX Timestamp * @signal: Signal of the received frame. * @rssi: RSSI of the received frame. * @size: Data size of the received frame. @@ -154,6 +155,7 @@ enum rxdone_entry_desc_flags { */ struct rxdone_entry_desc { + u64 timestamp; int signal; int rssi; int size; -- cgit v0.10.2 From 70197ede33134725f3e2e606fcabc28b0a4549a3 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Fri, 4 Jul 2008 08:39:01 -0500 Subject: b43legacy: Remove switch statement with 64-bit index The gcc 3.4 fork used to compile the MN10300 port emits unwanted __ucmpdi2() calls for switch statements that use a 64bit value. This patch removes such a switch from b43legacy, and makes the code more like that used in b43. Thanks to Adrian Bunk for reporting the problem. Signed-off-by: Larry Finger Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/b43legacy/dma.c b/drivers/net/wireless/b43legacy/dma.c index eb0243a..fb6819e 100644 --- a/drivers/net/wireless/b43legacy/dma.c +++ b/drivers/net/wireless/b43legacy/dma.c @@ -859,6 +859,18 @@ static u64 supported_dma_mask(struct b43legacy_wldev *dev) return DMA_30BIT_MASK; } +static enum b43legacy_dmatype dma_mask_to_engine_type(u64 dmamask) +{ + if (dmamask == DMA_30BIT_MASK) + return B43legacy_DMA_30BIT; + if (dmamask == DMA_32BIT_MASK) + return B43legacy_DMA_32BIT; + if (dmamask == DMA_64BIT_MASK) + return B43legacy_DMA_64BIT; + B43legacy_WARN_ON(1); + return B43legacy_DMA_30BIT; +} + /* Main initialization function. */ static struct b43legacy_dmaring *b43legacy_setup_dmaring(struct b43legacy_wldev *dev, @@ -1018,6 +1030,43 @@ void b43legacy_dma_free(struct b43legacy_wldev *dev) dma->tx_ring0 = NULL; } +static int b43legacy_dma_set_mask(struct b43legacy_wldev *dev, u64 mask) +{ + u64 orig_mask = mask; + bool fallback = 0; + int err; + + /* Try to set the DMA mask. If it fails, try falling back to a + * lower mask, as we can always also support a lower one. */ + while (1) { + err = ssb_dma_set_mask(dev->dev, mask); + if (!err) + break; + if (mask == DMA_64BIT_MASK) { + mask = DMA_32BIT_MASK; + fallback = 1; + continue; + } + if (mask == DMA_32BIT_MASK) { + mask = DMA_30BIT_MASK; + fallback = 1; + continue; + } + b43legacyerr(dev->wl, "The machine/kernel does not support " + "the required %u-bit DMA mask\n", + (unsigned int)dma_mask_to_engine_type(orig_mask)); + return -EOPNOTSUPP; + } + if (fallback) { + b43legacyinfo(dev->wl, "DMA mask fallback from %u-bit to %u-" + "bit\n", + (unsigned int)dma_mask_to_engine_type(orig_mask), + (unsigned int)dma_mask_to_engine_type(mask)); + } + + return 0; +} + int b43legacy_dma_init(struct b43legacy_wldev *dev) { struct b43legacy_dma *dma = &dev->dma; @@ -1027,21 +1076,8 @@ int b43legacy_dma_init(struct b43legacy_wldev *dev) enum b43legacy_dmatype type; dmamask = supported_dma_mask(dev); - switch (dmamask) { - default: - B43legacy_WARN_ON(1); - case DMA_30BIT_MASK: - type = B43legacy_DMA_30BIT; - break; - case DMA_32BIT_MASK: - type = B43legacy_DMA_32BIT; - break; - case DMA_64BIT_MASK: - type = B43legacy_DMA_64BIT; - break; - } - - err = ssb_dma_set_mask(dev->dev, dmamask); + type = dma_mask_to_engine_type(dmamask); + err = b43legacy_dma_set_mask(dev, dmamask); if (err) { #ifdef CONFIG_B43LEGACY_PIO b43legacywarn(dev->wl, "DMA for this device not supported. " -- cgit v0.10.2 From 0ac2a00c1035c749b720c4d817beea1795f02d47 Mon Sep 17 00:00:00 2001 From: Pavel Roskin Date: Sun, 6 Jul 2008 09:12:30 -0400 Subject: hostap: don't compile prism2_suspend() for hostap_pci without CONFIG_PM Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c index 6c158a5..09004a6 100644 --- a/drivers/net/wireless/hostap/hostap_hw.c +++ b/drivers/net/wireless/hostap/hostap_hw.c @@ -3417,7 +3417,7 @@ static void prism2_free_local_data(struct net_device *dev) } -#ifndef PRISM2_PLX +#if (defined(PRISM2_PCI) && defined(CONFIG_PM)) || defined(PRISM2_PCCARD) static void prism2_suspend(struct net_device *dev) { struct hostap_interface *iface; @@ -3436,7 +3436,7 @@ static void prism2_suspend(struct net_device *dev) /* Disable hardware and firmware */ prism2_hw_shutdown(dev, 0); } -#endif /* PRISM2_PLX */ +#endif /* (PRISM2_PCI && CONFIG_PM) || PRISM2_PCCARD */ /* These might at some point be compiled separately and used as separate -- cgit v0.10.2 From 84263b0c94431e686552a322ae84678fddd22ebd Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 6 Jul 2008 17:09:48 +0200 Subject: rt2x00: Fix register comments Fix some register documentation in the register header files. This allows better parsing by userspace scripts which in turn helps debugging. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/rt2x00/rt2500pci.h b/drivers/net/wireless/rt2x00/rt2500pci.h index cb648c3..42f3769 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.h +++ b/drivers/net/wireless/rt2x00/rt2500pci.h @@ -751,7 +751,7 @@ #define LEDCSR_LED_DEFAULT FIELD32(0x00100000) /* - * AES control register. + * SECCSR3: AES control register. */ #define SECCSR3 0x00fc @@ -895,7 +895,7 @@ #define ARTCSR2_ACK_CTS_54MBS FIELD32(0xff000000) /* - * SECCSR1_RT2509: WEP control register. + * SECCSR1: WEP control register. * KICK_ENCRYPT: Kick encryption engine, self-clear. * ONE_SHOT: 0: ring mode, 1: One shot only mode. * DESC_ADDRESS: Descriptor physical address of frame. diff --git a/drivers/net/wireless/rt2x00/rt2500usb.h b/drivers/net/wireless/rt2x00/rt2500usb.h index 3e21fdf..4769ffe 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.h +++ b/drivers/net/wireless/rt2x00/rt2500usb.h @@ -209,7 +209,7 @@ #define MAC_CSR21_OFF_PERIOD FIELD16(0xff00) /* - * Collision window control register. + * MAC_CSR22: Collision window control register. */ #define MAC_CSR22 0x042c @@ -296,7 +296,7 @@ #define TXRX_CSR7_BBP_ID1_VALID FIELD16(0x8000) /* - * TXRX_CSR5: OFDM TX BBP ID1. + * TXRX_CSR8: OFDM TX BBP ID1. */ #define TXRX_CSR8 0x0450 #define TXRX_CSR8_BBP_ID0 FIELD16(0x007f) @@ -370,7 +370,14 @@ */ /* - * SEC_CSR0-SEC_CSR7: Shared key 0, word 0-7 + * SEC_CSR0: Shared key 0, word 0 + * SEC_CSR1: Shared key 0, word 1 + * SEC_CSR2: Shared key 0, word 2 + * SEC_CSR3: Shared key 0, word 3 + * SEC_CSR4: Shared key 0, word 4 + * SEC_CSR5: Shared key 0, word 5 + * SEC_CSR6: Shared key 0, word 6 + * SEC_CSR7: Shared key 0, word 7 */ #define SEC_CSR0 0x0480 #define SEC_CSR1 0x0482 @@ -382,7 +389,14 @@ #define SEC_CSR7 0x048e /* - * SEC_CSR8-SEC_CSR15: Shared key 1, word 0-7 + * SEC_CSR8: Shared key 1, word 0 + * SEC_CSR9: Shared key 1, word 1 + * SEC_CSR10: Shared key 1, word 2 + * SEC_CSR11: Shared key 1, word 3 + * SEC_CSR12: Shared key 1, word 4 + * SEC_CSR13: Shared key 1, word 5 + * SEC_CSR14: Shared key 1, word 6 + * SEC_CSR15: Shared key 1, word 7 */ #define SEC_CSR8 0x0490 #define SEC_CSR9 0x0492 @@ -394,7 +408,14 @@ #define SEC_CSR15 0x049e /* - * SEC_CSR16-SEC_CSR23: Shared key 2, word 0-7 + * SEC_CSR16: Shared key 2, word 0 + * SEC_CSR17: Shared key 2, word 1 + * SEC_CSR18: Shared key 2, word 2 + * SEC_CSR19: Shared key 2, word 3 + * SEC_CSR20: Shared key 2, word 4 + * SEC_CSR21: Shared key 2, word 5 + * SEC_CSR22: Shared key 2, word 6 + * SEC_CSR23: Shared key 2, word 7 */ #define SEC_CSR16 0x04a0 #define SEC_CSR17 0x04a2 @@ -406,7 +427,14 @@ #define SEC_CSR23 0x04ae /* - * SEC_CSR24-SEC_CSR31: Shared key 3, word 0-7 + * SEC_CSR24: Shared key 3, word 0 + * SEC_CSR25: Shared key 3, word 1 + * SEC_CSR26: Shared key 3, word 2 + * SEC_CSR27: Shared key 3, word 3 + * SEC_CSR28: Shared key 3, word 4 + * SEC_CSR29: Shared key 3, word 5 + * SEC_CSR30: Shared key 3, word 6 + * SEC_CSR31: Shared key 3, word 7 */ #define SEC_CSR24 0x04b0 #define SEC_CSR25 0x04b2 -- cgit v0.10.2 From c44ac0b9855c62b5ec8af5935124cfbe6654a32d Mon Sep 17 00:00:00 2001 From: Hin-Tak Leung Date: Tue, 8 Jul 2008 12:27:54 +0100 Subject: rtl8187: updating rtl8187.h to support RTL8187B Signed-off-by: Larry Finger Signed-off-by: Herton Ronaldo Krzesinski Signed-off-by: Hin-Tak Leung Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/rtl8187.h b/drivers/net/wireless/rtl8187.h index a0cfb666..3afb49f 100644 --- a/drivers/net/wireless/rtl8187.h +++ b/drivers/net/wireless/rtl8187.h @@ -44,17 +44,48 @@ struct rtl8187_rx_hdr { __le64 mac_time; } __attribute__((packed)); -struct rtl8187_tx_hdr { +struct rtl8187b_rx_hdr { __le32 flags; + __le64 mac_time; + u8 noise; + u8 signal; + u8 agc; + u8 reserved; + __le32 unused; +} __attribute__((packed)); + +/* {rtl8187,rtl8187b}_tx_info is in skb */ + +/* Tx flags are common between rtl8187 and rtl8187b */ #define RTL8187_TX_FLAG_NO_ENCRYPT (1 << 15) #define RTL8187_TX_FLAG_MORE_FRAG (1 << 17) #define RTL8187_TX_FLAG_CTS (1 << 18) #define RTL8187_TX_FLAG_RTS (1 << 23) + +struct rtl8187_tx_hdr { + __le32 flags; __le16 rts_duration; __le16 len; __le32 retry; } __attribute__((packed)); +struct rtl8187b_tx_hdr { + __le32 flags; + __le16 rts_duration; + __le16 len; + __le32 unused_1; + __le16 unused_2; + __le16 tx_duration; + __le32 unused_3; + __le32 retry; + __le32 unused_4[2]; +} __attribute__((packed)); + +enum { + DEVICE_RTL8187, + DEVICE_RTL8187B +}; + struct rtl8187_priv { /* common between rtl818x drivers */ struct rtl818x_csr *map; @@ -70,70 +101,120 @@ struct rtl8187_priv { u32 rx_conf; u16 txpwr_base; u8 asic_rev; + u8 is_rtl8187b; + enum { + RTL8187BvB, + RTL8187BvD, + RTL8187BvE + } hw_rev; struct sk_buff_head rx_queue; + u8 signal; + u8 quality; + u8 noise; }; void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data); -static inline u8 rtl818x_ioread8(struct rtl8187_priv *priv, u8 *addr) +static inline u8 rtl818x_ioread8_idx(struct rtl8187_priv *priv, + u8 *addr, u8 idx) { u8 val; usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0), RTL8187_REQ_GET_REG, RTL8187_REQT_READ, - (unsigned long)addr, 0, &val, sizeof(val), HZ / 2); + (unsigned long)addr, idx & 0x03, &val, + sizeof(val), HZ / 2); return val; } -static inline u16 rtl818x_ioread16(struct rtl8187_priv *priv, __le16 *addr) +static inline u8 rtl818x_ioread8(struct rtl8187_priv *priv, u8 *addr) +{ + return rtl818x_ioread8_idx(priv, addr, 0); +} + +static inline u16 rtl818x_ioread16_idx(struct rtl8187_priv *priv, + __le16 *addr, u8 idx) { __le16 val; usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0), RTL8187_REQ_GET_REG, RTL8187_REQT_READ, - (unsigned long)addr, 0, &val, sizeof(val), HZ / 2); + (unsigned long)addr, idx & 0x03, &val, + sizeof(val), HZ / 2); return le16_to_cpu(val); } -static inline u32 rtl818x_ioread32(struct rtl8187_priv *priv, __le32 *addr) +static inline u16 rtl818x_ioread16(struct rtl8187_priv *priv, __le16 *addr) +{ + return rtl818x_ioread16_idx(priv, addr, 0); +} + +static inline u32 rtl818x_ioread32_idx(struct rtl8187_priv *priv, + __le32 *addr, u8 idx) { __le32 val; usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0), RTL8187_REQ_GET_REG, RTL8187_REQT_READ, - (unsigned long)addr, 0, &val, sizeof(val), HZ / 2); + (unsigned long)addr, idx & 0x03, &val, + sizeof(val), HZ / 2); return le32_to_cpu(val); } -static inline void rtl818x_iowrite8(struct rtl8187_priv *priv, - u8 *addr, u8 val) +static inline u32 rtl818x_ioread32(struct rtl8187_priv *priv, __le32 *addr) +{ + return rtl818x_ioread32_idx(priv, addr, 0); +} + +static inline void rtl818x_iowrite8_idx(struct rtl8187_priv *priv, + u8 *addr, u8 val, u8 idx) { usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0), RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE, - (unsigned long)addr, 0, &val, sizeof(val), HZ / 2); + (unsigned long)addr, idx & 0x03, &val, + sizeof(val), HZ / 2); +} + +static inline void rtl818x_iowrite8(struct rtl8187_priv *priv, u8 *addr, u8 val) +{ + rtl818x_iowrite8_idx(priv, addr, val, 0); } -static inline void rtl818x_iowrite16(struct rtl8187_priv *priv, - __le16 *addr, u16 val) +static inline void rtl818x_iowrite16_idx(struct rtl8187_priv *priv, + __le16 *addr, u16 val, u8 idx) { __le16 buf = cpu_to_le16(val); usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0), RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE, - (unsigned long)addr, 0, &buf, sizeof(buf), HZ / 2); + (unsigned long)addr, idx & 0x03, &buf, sizeof(buf), + HZ / 2); } -static inline void rtl818x_iowrite32(struct rtl8187_priv *priv, - __le32 *addr, u32 val) +static inline void rtl818x_iowrite16(struct rtl8187_priv *priv, __le16 *addr, + u16 val) +{ + rtl818x_iowrite16_idx(priv, addr, val, 0); +} + +static inline void rtl818x_iowrite32_idx(struct rtl8187_priv *priv, + __le32 *addr, u32 val, u8 idx) { __le32 buf = cpu_to_le32(val); usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0), RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE, - (unsigned long)addr, 0, &buf, sizeof(buf), HZ / 2); + (unsigned long)addr, idx & 0x03, &buf, sizeof(buf), + HZ / 2); +} + +static inline void rtl818x_iowrite32(struct rtl8187_priv *priv, __le32 *addr, + u32 val) +{ + rtl818x_iowrite32_idx(priv, addr, val, 0); } #endif /* RTL8187_H */ -- cgit v0.10.2 From d1e11af51657d18222bef9cc15591f8c0f289186 Mon Sep 17 00:00:00 2001 From: Hin-Tak Leung Date: Tue, 8 Jul 2008 12:30:02 +0100 Subject: rtl8187: updating rtl818x.h to support RTL8187B Signed-off-by: Larry Finger Signed-off-by: Herton Ronaldo Krzesinski Signed-off-by: Hin-Tak Leung Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/rtl818x.h b/drivers/net/wireless/rtl818x.h index 4f7d38f..85a6394 100644 --- a/drivers/net/wireless/rtl818x.h +++ b/drivers/net/wireless/rtl818x.h @@ -66,7 +66,10 @@ struct rtl818x_csr { #define RTL818X_TX_CONF_R8180_F (3 << 25) #define RTL818X_TX_CONF_R8185_ABC (4 << 25) #define RTL818X_TX_CONF_R8185_D (5 << 25) +#define RTL818X_TX_CONF_R8187vD_1 (5 << 25) +#define RTL818X_TX_CONF_R8187vD_2 (6 << 25) #define RTL818X_TX_CONF_HWVER_MASK (7 << 25) +#define RTL818X_TX_CONF_DISREQQSIZE (1 << 28) #define RTL818X_TX_CONF_PROBE_DTS (1 << 29) #define RTL818X_TX_CONF_HW_SEQNUM (1 << 30) #define RTL818X_TX_CONF_CW_MIN (1 << 31) @@ -106,8 +109,11 @@ struct rtl818x_csr { #define RTL818X_MSR_NO_LINK (0 << 2) #define RTL818X_MSR_ADHOC (1 << 2) #define RTL818X_MSR_INFRA (2 << 2) +#define RTL818X_MSR_MASTER (3 << 2) +#define RTL818X_MSR_ENEDCA (4 << 2) u8 CONFIG3; #define RTL818X_CONFIG3_ANAPARAM_WRITE (1 << 6) +#define RTL818X_CONFIG3_GNT_SELECT (1 << 7) u8 CONFIG4; #define RTL818X_CONFIG4_POWEROFF (1 << 6) #define RTL818X_CONFIG4_VCOOFF (1 << 7) @@ -133,7 +139,9 @@ struct rtl818x_csr { __le32 RF_TIMING; u8 GP_ENABLE; u8 GPIO; - u8 reserved_12[10]; + u8 reserved_12[2]; + __le32 HSSI_PARA; + u8 reserved_13[4]; u8 TX_AGC_CTL; #define RTL818X_TX_AGC_CTL_PERPACKET_GAIN_SHIFT (1 << 0) #define RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT (1 << 1) @@ -141,29 +149,39 @@ struct rtl818x_csr { u8 TX_GAIN_CCK; u8 TX_GAIN_OFDM; u8 TX_ANTENNA; - u8 reserved_13[16]; + u8 reserved_14[16]; u8 WPA_CONF; - u8 reserved_14[3]; + u8 reserved_15[3]; u8 SIFS; u8 DIFS; u8 SLOT; - u8 reserved_15[5]; + u8 reserved_16[5]; u8 CW_CONF; #define RTL818X_CW_CONF_PERPACKET_CW_SHIFT (1 << 0) #define RTL818X_CW_CONF_PERPACKET_RETRY_SHIFT (1 << 1) u8 CW_VAL; u8 RATE_FALLBACK; - u8 reserved_16[25]; +#define RTL818X_RATE_FALLBACK_ENABLE (1 << 7) + u8 ACM_CONTROL; + u8 reserved_17[24]; u8 CONFIG5; u8 TX_DMA_POLLING; - u8 reserved_17[2]; + u8 reserved_18[2]; __le16 CWR; u8 RETRY_CTR; - u8 reserved_18[5]; + u8 reserved_19[3]; + __le16 INT_MIG; +/* RTL818X_R8187B_*: magic numbers from ioregisters */ +#define RTL818X_R8187B_B 0 +#define RTL818X_R8187B_D 1 +#define RTL818X_R8187B_E 2 __le32 RDSAR; - u8 reserved_19[12]; - __le16 FEMR; + __le16 TID_AC_MAP; u8 reserved_20[4]; + u8 ANAPARAM3; + u8 reserved_21[5]; + __le16 FEMR; + u8 reserved_22[4]; __le16 TALLY_CNT; u8 TALLY_SEL; } __attribute__((packed)); -- cgit v0.10.2 From e7d414ff21a7e0b00295e838c004ff1de5fba6ce Mon Sep 17 00:00:00 2001 From: Hin-Tak Leung Date: Tue, 8 Jul 2008 12:31:57 +0100 Subject: rtl8187: updating rtl8187_rtl8225.c to support RTL8187B Signed-off-by: Larry Finger Signed-off-by: Herton Ronaldo Krzesinski Signed-off-by: Hin-Tak Leung Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/rtl8187_rtl8225.c b/drivers/net/wireless/rtl8187_rtl8225.c index 9146387..1e059de 100644 --- a/drivers/net/wireless/rtl8187_rtl8225.c +++ b/drivers/net/wireless/rtl8187_rtl8225.c @@ -305,9 +305,11 @@ static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel) /* anaparam2 on */ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE); + rtl818x_iowrite8(priv, &priv->map->CONFIG3, + reg | RTL818X_CONFIG3_ANAPARAM_WRITE); rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); + rtl818x_iowrite8(priv, &priv->map->CONFIG3, + reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); rtl8225_write_phy_ofdm(dev, 2, 0x42); @@ -471,12 +473,42 @@ static void rtl8225_rf_init(struct ieee80211_hw *dev) rtl8225_write_phy_cck(dev, 0x41, rtl8225_threshold[2]); } +static const u8 rtl8225z2_agc[] = { + 0x5e, 0x5e, 0x5e, 0x5e, 0x5d, 0x5b, 0x59, 0x57, 0x55, 0x53, 0x51, 0x4f, + 0x4d, 0x4b, 0x49, 0x47, 0x45, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x39, 0x37, + 0x35, 0x33, 0x31, 0x2f, 0x2d, 0x2b, 0x29, 0x27, 0x25, 0x23, 0x21, 0x1f, + 0x1d, 0x1b, 0x19, 0x17, 0x15, 0x13, 0x11, 0x0f, 0x0d, 0x0b, 0x09, 0x07, + 0x05, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, + 0x19, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x26, 0x27, 0x27, 0x28, + 0x28, 0x29, 0x2a, 0x2a, 0x2a, 0x2b, 0x2b, 0x2b, 0x2c, 0x2c, 0x2c, 0x2d, + 0x2d, 0x2d, 0x2d, 0x2e, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, 0x2f, 0x30, 0x30, + 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, + 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31 +}; +static const u8 rtl8225z2_ofdm[] = { + 0x10, 0x0d, 0x01, 0x00, 0x14, 0xfb, 0xfb, 0x60, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, + 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0xa8, 0x26, + 0x32, 0x33, 0x07, 0xa5, 0x6f, 0x55, 0xc8, 0xb3, + 0x0a, 0xe1, 0x2C, 0x8a, 0x86, 0x83, 0x34, 0x0f, + 0x4f, 0x24, 0x6f, 0xc2, 0x6b, 0x40, 0x80, 0x00, + 0xc0, 0xc1, 0x58, 0xf1, 0x00, 0xe4, 0x90, 0x3e, + 0x6d, 0x3c, 0xfb, 0x07 +}; + static const u8 rtl8225z2_tx_power_cck_ch14[] = { - 0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00 + 0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00, + 0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00 }; static const u8 rtl8225z2_tx_power_cck[] = { - 0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04 + 0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04, + 0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03, + 0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03, + 0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03 }; static const u8 rtl8225z2_tx_power_ofdm[] = { @@ -526,9 +558,11 @@ static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel) /* anaparam2 on */ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE); + rtl818x_iowrite8(priv, &priv->map->CONFIG3, + reg | RTL818X_CONFIG3_ANAPARAM_WRITE); rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); + rtl818x_iowrite8(priv, &priv->map->CONFIG3, + reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); rtl8225_write_phy_ofdm(dev, 2, 0x42); @@ -542,6 +576,85 @@ static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel) msleep(1); } +static void rtl8225z2_b_rf_set_tx_power(struct ieee80211_hw *dev, int channel) +{ + struct rtl8187_priv *priv = dev->priv; + u8 cck_power, ofdm_power; + const u8 *tmp; + int i; + + cck_power = priv->channels[channel - 1].hw_value & 0xF; + ofdm_power = priv->channels[channel - 1].hw_value >> 4; + + if (cck_power > 15) + cck_power = (priv->hw_rev == RTL8187BvB) ? 15 : 22; + else + cck_power += (priv->hw_rev == RTL8187BvB) ? 0 : 7; + cck_power += priv->txpwr_base & 0xF; + cck_power = min(cck_power, (u8)35); + + if (ofdm_power > 15) + ofdm_power = (priv->hw_rev == RTL8187BvB) ? 17 : 25; + else + ofdm_power += (priv->hw_rev == RTL8187BvB) ? 2 : 10; + ofdm_power += (priv->txpwr_base >> 4) & 0xF; + ofdm_power = min(ofdm_power, (u8)35); + + if (channel == 14) + tmp = rtl8225z2_tx_power_cck_ch14; + else + tmp = rtl8225z2_tx_power_cck; + + if (priv->hw_rev == RTL8187BvB) { + if (cck_power <= 6) + ; /* do nothing */ + else if (cck_power <= 11) + tmp += 8; + else + tmp += 16; + } else { + if (cck_power <= 5) + ; /* do nothing */ + else if (cck_power <= 11) + tmp += 8; + else if (cck_power <= 17) + tmp += 16; + else + tmp += 24; + } + + for (i = 0; i < 8; i++) + rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++); + + rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, + rtl8225z2_tx_gain_cck_ofdm[cck_power]); + msleep(1); + + rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, + rtl8225z2_tx_gain_cck_ofdm[ofdm_power] << 1); + if (priv->hw_rev == RTL8187BvB) { + if (ofdm_power <= 11) { + rtl8225_write_phy_ofdm(dev, 0x87, 0x60); + rtl8225_write_phy_ofdm(dev, 0x89, 0x60); + } else { + rtl8225_write_phy_ofdm(dev, 0x87, 0x5c); + rtl8225_write_phy_ofdm(dev, 0x89, 0x5c); + } + } else { + if (ofdm_power <= 11) { + rtl8225_write_phy_ofdm(dev, 0x87, 0x5c); + rtl8225_write_phy_ofdm(dev, 0x89, 0x5c); + } else if (ofdm_power <= 17) { + rtl8225_write_phy_ofdm(dev, 0x87, 0x54); + rtl8225_write_phy_ofdm(dev, 0x89, 0x54); + } else { + rtl8225_write_phy_ofdm(dev, 0x87, 0x50); + rtl8225_write_phy_ofdm(dev, 0x89, 0x50); + } + } + msleep(1); +} + static const u16 rtl8225z2_rxgain[] = { 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409, 0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541, @@ -715,6 +828,81 @@ static void rtl8225z2_rf_init(struct ieee80211_hw *dev) rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002); } +static void rtl8225z2_b_rf_init(struct ieee80211_hw *dev) +{ + struct rtl8187_priv *priv = dev->priv; + int i; + + rtl8225_write(dev, 0x0, 0x0B7); msleep(1); + rtl8225_write(dev, 0x1, 0xEE0); msleep(1); + rtl8225_write(dev, 0x2, 0x44D); msleep(1); + rtl8225_write(dev, 0x3, 0x441); msleep(1); + rtl8225_write(dev, 0x4, 0x8C3); msleep(1); + rtl8225_write(dev, 0x5, 0xC72); msleep(1); + rtl8225_write(dev, 0x6, 0x0E6); msleep(1); + rtl8225_write(dev, 0x7, 0x82A); msleep(1); + rtl8225_write(dev, 0x8, 0x03F); msleep(1); + rtl8225_write(dev, 0x9, 0x335); msleep(1); + rtl8225_write(dev, 0xa, 0x9D4); msleep(1); + rtl8225_write(dev, 0xb, 0x7BB); msleep(1); + rtl8225_write(dev, 0xc, 0x850); msleep(1); + rtl8225_write(dev, 0xd, 0xCDF); msleep(1); + rtl8225_write(dev, 0xe, 0x02B); msleep(1); + rtl8225_write(dev, 0xf, 0x114); msleep(1); + + rtl8225_write(dev, 0x0, 0x1B7); msleep(1); + + for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) { + rtl8225_write(dev, 0x1, i + 1); msleep(1); + rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]); msleep(1); + } + + rtl8225_write(dev, 0x3, 0x080); msleep(1); + rtl8225_write(dev, 0x5, 0x004); msleep(1); + rtl8225_write(dev, 0x0, 0x0B7); msleep(1); + msleep(3000); + + rtl8225_write(dev, 0x2, 0xC4D); msleep(1); + msleep(2000); + + rtl8225_write(dev, 0x2, 0x44D); msleep(1); + rtl8225_write(dev, 0x0, 0x2BF); msleep(1); + + rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, 0x03); + rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, 0x07); + rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); + + rtl8225_write_phy_ofdm(dev, 0x80, 0x12); + for (i = 0; i < ARRAY_SIZE(rtl8225z2_agc); i++) { + rtl8225_write_phy_ofdm(dev, 0xF, rtl8225z2_agc[i]); + rtl8225_write_phy_ofdm(dev, 0xE, 0x80 + i); + rtl8225_write_phy_ofdm(dev, 0xE, 0); + } + rtl8225_write_phy_ofdm(dev, 0x80, 0x10); + + for (i = 0; i < ARRAY_SIZE(rtl8225z2_ofdm); i++) + rtl8225_write_phy_ofdm(dev, i, rtl8225z2_ofdm[i]); + + rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22); + rtl818x_iowrite8(priv, &priv->map->SLOT, 9); + rtl818x_iowrite8(priv, (u8 *)0xFFF0, 28); + rtl818x_iowrite8(priv, (u8 *)0xFFF4, 28); + rtl818x_iowrite8(priv, (u8 *)0xFFF8, 28); + rtl818x_iowrite8(priv, (u8 *)0xFFFC, 28); + rtl818x_iowrite8(priv, (u8 *)0xFF2D, 0x5B); + rtl818x_iowrite8(priv, (u8 *)0xFF79, 0x5B); + rtl818x_iowrite32(priv, (__le32 *)0xFFF0, (7 << 12) | (3 << 8) | 28); + rtl818x_iowrite32(priv, (__le32 *)0xFFF4, (7 << 12) | (3 << 8) | 28); + rtl818x_iowrite32(priv, (__le32 *)0xFFF8, (7 << 12) | (3 << 8) | 28); + rtl818x_iowrite32(priv, (__le32 *)0xFFFC, (7 << 12) | (3 << 8) | 28); + rtl818x_iowrite8(priv, &priv->map->ACM_CONTROL, 0); + + rtl8225_write_phy_ofdm(dev, 0x97, 0x46); msleep(1); + rtl8225_write_phy_ofdm(dev, 0xa4, 0xb6); msleep(1); + rtl8225_write_phy_ofdm(dev, 0x85, 0xfc); msleep(1); + rtl8225_write_phy_cck(dev, 0xc1, 0x88); msleep(1); +} + static void rtl8225_rf_stop(struct ieee80211_hw *dev) { u8 reg; @@ -739,8 +927,10 @@ static void rtl8225_rf_set_channel(struct ieee80211_hw *dev, if (priv->rf->init == rtl8225_rf_init) rtl8225_rf_set_tx_power(dev, chan); - else + else if (priv->rf->init == rtl8225z2_rf_init) rtl8225z2_rf_set_tx_power(dev, chan); + else + rtl8225z2_b_rf_set_tx_power(dev, chan); rtl8225_write(dev, 0x7, rtl8225_chan[chan - 1]); msleep(10); @@ -760,19 +950,30 @@ static const struct rtl818x_rf_ops rtl8225z2_ops = { .set_chan = rtl8225_rf_set_channel }; +static const struct rtl818x_rf_ops rtl8225z2_b_ops = { + .name = "rtl8225z2", + .init = rtl8225z2_b_rf_init, + .stop = rtl8225_rf_stop, + .set_chan = rtl8225_rf_set_channel +}; + const struct rtl818x_rf_ops * rtl8187_detect_rf(struct ieee80211_hw *dev) { u16 reg8, reg9; + struct rtl8187_priv *priv = dev->priv; - rtl8225_write(dev, 0, 0x1B7); + if (!priv->is_rtl8187b) { + rtl8225_write(dev, 0, 0x1B7); - reg8 = rtl8225_read(dev, 8); - reg9 = rtl8225_read(dev, 9); + reg8 = rtl8225_read(dev, 8); + reg9 = rtl8225_read(dev, 9); - rtl8225_write(dev, 0, 0x0B7); + rtl8225_write(dev, 0, 0x0B7); - if (reg8 != 0x588 || reg9 != 0x700) - return &rtl8225_ops; + if (reg8 != 0x588 || reg9 != 0x700) + return &rtl8225_ops; - return &rtl8225z2_ops; + return &rtl8225z2_ops; + } else + return &rtl8225z2_b_ops; } -- cgit v0.10.2 From f8a08c34265b59710a8fc049911f487477c19fab Mon Sep 17 00:00:00 2001 From: Hin-Tak Leung Date: Tue, 8 Jul 2008 12:33:34 +0100 Subject: rtl8187: change rtl8187_dev.c to support RTL8187B (part 1) Signed-off-by: Larry Finger Signed-off-by: Herton Ronaldo Krzesinski Signed-off-by: Hin-Tak Leung Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c index bec96d7..b17f237 100644 --- a/drivers/net/wireless/rtl8187_dev.c +++ b/drivers/net/wireless/rtl8187_dev.c @@ -27,19 +27,21 @@ MODULE_AUTHOR("Michael Wu "); MODULE_AUTHOR("Andrea Merello "); -MODULE_DESCRIPTION("RTL8187 USB wireless driver"); +MODULE_DESCRIPTION("RTL8187/RTL8187B USB wireless driver"); MODULE_LICENSE("GPL"); static struct usb_device_id rtl8187_table[] __devinitdata = { /* Realtek */ - {USB_DEVICE(0x0bda, 0x8187)}, + {USB_DEVICE(0x0bda, 0x8187), .driver_info = DEVICE_RTL8187}, + {USB_DEVICE(0x0bda, 0x8189), .driver_info = DEVICE_RTL8187B}, + {USB_DEVICE(0x0bda, 0x8197), .driver_info = DEVICE_RTL8187B}, /* Netgear */ - {USB_DEVICE(0x0846, 0x6100)}, - {USB_DEVICE(0x0846, 0x6a00)}, + {USB_DEVICE(0x0846, 0x6100), .driver_info = DEVICE_RTL8187}, + {USB_DEVICE(0x0846, 0x6a00), .driver_info = DEVICE_RTL8187}, /* HP */ - {USB_DEVICE(0x03f0, 0xca02)}, + {USB_DEVICE(0x03f0, 0xca02), .driver_info = DEVICE_RTL8187}, /* Sitecom */ - {USB_DEVICE(0x0df6, 0x000d)}, + {USB_DEVICE(0x0df6, 0x000d), .driver_info = DEVICE_RTL8187}, {} }; @@ -318,29 +320,12 @@ static int rtl8187_init_urbs(struct ieee80211_hw *dev) return 0; } -static int rtl8187_init_hw(struct ieee80211_hw *dev) +static int rtl8187_cmd_reset(struct ieee80211_hw *dev) { struct rtl8187_priv *priv = dev->priv; u8 reg; int i; - /* reset */ - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); - reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE); - rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_ON); - rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); - - rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0); - - msleep(200); - rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x10); - rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x11); - rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x00); - msleep(200); - reg = rtl818x_ioread8(priv, &priv->map->CMD); reg &= (1 << 1); reg |= RTL818X_CMD_RESET; @@ -376,12 +361,48 @@ static int rtl8187_init_hw(struct ieee80211_hw *dev) return -ETIMEDOUT; } + return 0; +} + +static int rtl8187_init_hw(struct ieee80211_hw *dev) +{ + struct rtl8187_priv *priv = dev->priv; + u8 reg; + int res; + + /* reset */ + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, + RTL818X_EEPROM_CMD_CONFIG); + reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); + rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | + RTL818X_CONFIG3_ANAPARAM_WRITE); + rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_ON); + rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON); + rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & + ~RTL818X_CONFIG3_ANAPARAM_WRITE); + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, + RTL818X_EEPROM_CMD_NORMAL); + + rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0); + + msleep(200); + rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x10); + rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x11); + rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x00); + msleep(200); + + res = rtl8187_cmd_reset(dev); + if (res) + return res; + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE); + rtl818x_iowrite8(priv, &priv->map->CONFIG3, + reg | RTL818X_CONFIG3_ANAPARAM_WRITE); rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_ON); rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); + rtl818x_iowrite8(priv, &priv->map->CONFIG3, + reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); /* setup card */ @@ -426,9 +447,11 @@ static int rtl8187_init_hw(struct ieee80211_hw *dev) rtl818x_iowrite32(priv, &priv->map->RF_TIMING, 0x000a8008); rtl818x_iowrite16(priv, &priv->map->BRSR, 0xFFFF); rtl818x_iowrite32(priv, &priv->map->RF_PARA, 0x00100044); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, + RTL818X_EEPROM_CMD_CONFIG); rtl818x_iowrite8(priv, &priv->map->CONFIG3, 0x44); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, + RTL818X_EEPROM_CMD_NORMAL); rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FF7); msleep(100); @@ -445,16 +468,198 @@ static int rtl8187_init_hw(struct ieee80211_hw *dev) return 0; } +static const u8 rtl8187b_reg_table[][3] = { + {0xF0, 0x32, 0}, {0xF1, 0x32, 0}, {0xF2, 0x00, 0}, {0xF3, 0x00, 0}, + {0xF4, 0x32, 0}, {0xF5, 0x43, 0}, {0xF6, 0x00, 0}, {0xF7, 0x00, 0}, + {0xF8, 0x46, 0}, {0xF9, 0xA4, 0}, {0xFA, 0x00, 0}, {0xFB, 0x00, 0}, + {0xFC, 0x96, 0}, {0xFD, 0xA4, 0}, {0xFE, 0x00, 0}, {0xFF, 0x00, 0}, + + {0x58, 0x4B, 1}, {0x59, 0x00, 1}, {0x5A, 0x4B, 1}, {0x5B, 0x00, 1}, + {0x60, 0x4B, 1}, {0x61, 0x09, 1}, {0x62, 0x4B, 1}, {0x63, 0x09, 1}, + {0xCE, 0x0F, 1}, {0xCF, 0x00, 1}, {0xE0, 0xFF, 1}, {0xE1, 0x0F, 1}, + {0xE2, 0x00, 1}, {0xF0, 0x4E, 1}, {0xF1, 0x01, 1}, {0xF2, 0x02, 1}, + {0xF3, 0x03, 1}, {0xF4, 0x04, 1}, {0xF5, 0x05, 1}, {0xF6, 0x06, 1}, + {0xF7, 0x07, 1}, {0xF8, 0x08, 1}, + + {0x4E, 0x00, 2}, {0x0C, 0x04, 2}, {0x21, 0x61, 2}, {0x22, 0x68, 2}, + {0x23, 0x6F, 2}, {0x24, 0x76, 2}, {0x25, 0x7D, 2}, {0x26, 0x84, 2}, + {0x27, 0x8D, 2}, {0x4D, 0x08, 2}, {0x50, 0x05, 2}, {0x51, 0xF5, 2}, + {0x52, 0x04, 2}, {0x53, 0xA0, 2}, {0x54, 0x1F, 2}, {0x55, 0x23, 2}, + {0x56, 0x45, 2}, {0x57, 0x67, 2}, {0x58, 0x08, 2}, {0x59, 0x08, 2}, + {0x5A, 0x08, 2}, {0x5B, 0x08, 2}, {0x60, 0x08, 2}, {0x61, 0x08, 2}, + {0x62, 0x08, 2}, {0x63, 0x08, 2}, {0x64, 0xCF, 2}, {0x72, 0x56, 2}, + {0x73, 0x9A, 2}, + + {0x34, 0xF0, 0}, {0x35, 0x0F, 0}, {0x5B, 0x40, 0}, {0x84, 0x88, 0}, + {0x85, 0x24, 0}, {0x88, 0x54, 0}, {0x8B, 0xB8, 0}, {0x8C, 0x07, 0}, + {0x8D, 0x00, 0}, {0x94, 0x1B, 0}, {0x95, 0x12, 0}, {0x96, 0x00, 0}, + {0x97, 0x06, 0}, {0x9D, 0x1A, 0}, {0x9F, 0x10, 0}, {0xB4, 0x22, 0}, + {0xBE, 0x80, 0}, {0xDB, 0x00, 0}, {0xEE, 0x00, 0}, {0x91, 0x03, 0}, + + {0x4C, 0x00, 2}, {0x9F, 0x00, 3}, {0x8C, 0x01, 0}, {0x8D, 0x10, 0}, + {0x8E, 0x08, 0}, {0x8F, 0x00, 0} +}; + +static int rtl8187b_init_hw(struct ieee80211_hw *dev) +{ + struct rtl8187_priv *priv = dev->priv; + int res, i; + u8 reg; + + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, + RTL818X_EEPROM_CMD_CONFIG); + + reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); + reg |= RTL818X_CONFIG3_ANAPARAM_WRITE | RTL818X_CONFIG3_GNT_SELECT; + rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg); + rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, 0x727f3f52); + rtl818x_iowrite32(priv, &priv->map->ANAPARAM, 0x45090658); + rtl818x_iowrite8(priv, &priv->map->ANAPARAM3, 0); + + rtl818x_iowrite8(priv, (u8 *)0xFF61, 0x10); + reg = rtl818x_ioread8(priv, (u8 *)0xFF62); + rtl818x_iowrite8(priv, (u8 *)0xFF62, reg & ~(1 << 5)); + rtl818x_iowrite8(priv, (u8 *)0xFF62, reg | (1 << 5)); + + reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); + reg &= ~RTL818X_CONFIG3_ANAPARAM_WRITE; + rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg); + + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, + RTL818X_EEPROM_CMD_NORMAL); + + res = rtl8187_cmd_reset(dev); + if (res) + return res; + + rtl818x_iowrite16(priv, (__le16 *)0xFF2D, 0x0FFF); + reg = rtl818x_ioread8(priv, &priv->map->CW_CONF); + reg |= RTL818X_CW_CONF_PERPACKET_RETRY_SHIFT; + rtl818x_iowrite8(priv, &priv->map->CW_CONF, reg); + reg = rtl818x_ioread8(priv, &priv->map->TX_AGC_CTL); + reg |= RTL818X_TX_AGC_CTL_PERPACKET_GAIN_SHIFT | + RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT; + rtl818x_iowrite8(priv, &priv->map->TX_AGC_CTL, reg); + + rtl818x_iowrite16_idx(priv, (__le16 *)0xFFE0, 0x0FFF, 1); + reg = rtl818x_ioread8(priv, &priv->map->RATE_FALLBACK); + reg |= RTL818X_RATE_FALLBACK_ENABLE; + rtl818x_iowrite8(priv, &priv->map->RATE_FALLBACK, reg); + + rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL, 100); + rtl818x_iowrite16(priv, &priv->map->ATIM_WND, 2); + rtl818x_iowrite16_idx(priv, (__le16 *)0xFFD4, 0xFFFF, 1); + + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, + RTL818X_EEPROM_CMD_CONFIG); + reg = rtl818x_ioread8(priv, &priv->map->CONFIG1); + rtl818x_iowrite8(priv, &priv->map->CONFIG1, (reg & 0x3F) | 0x80); + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, + RTL818X_EEPROM_CMD_NORMAL); + + rtl818x_iowrite8(priv, &priv->map->WPA_CONF, 0); + for (i = 0; i < ARRAY_SIZE(rtl8187b_reg_table); i++) { + rtl818x_iowrite8_idx(priv, + (u8 *)(uintptr_t) + (rtl8187b_reg_table[i][0] | 0xFF00), + rtl8187b_reg_table[i][1], + rtl8187b_reg_table[i][2]); + } + + rtl818x_iowrite16(priv, &priv->map->TID_AC_MAP, 0xFA50); + rtl818x_iowrite16(priv, &priv->map->INT_MIG, 0); + + rtl818x_iowrite32_idx(priv, (__le32 *)0xFFF0, 0, 1); + rtl818x_iowrite32_idx(priv, (__le32 *)0xFFF4, 0, 1); + rtl818x_iowrite8_idx(priv, (u8 *)0xFFF8, 0, 1); + + rtl818x_iowrite32(priv, &priv->map->RF_TIMING, 0x00004001); + + rtl818x_iowrite16_idx(priv, (__le16 *)0xFF72, 0x569A, 2); + + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, + RTL818X_EEPROM_CMD_CONFIG); + reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); + reg |= RTL818X_CONFIG3_ANAPARAM_WRITE; + rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg); + rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, + RTL818X_EEPROM_CMD_NORMAL); + + rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x0480); + rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x2488); + rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF); + msleep(1100); + + priv->rf->init(dev); + + reg = RTL818X_CMD_TX_ENABLE | RTL818X_CMD_RX_ENABLE; + rtl818x_iowrite8(priv, &priv->map->CMD, reg); + rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0xFFFF); + + rtl818x_iowrite8(priv, (u8 *)0xFE41, 0xF4); + rtl818x_iowrite8(priv, (u8 *)0xFE40, 0x00); + rtl818x_iowrite8(priv, (u8 *)0xFE42, 0x00); + rtl818x_iowrite8(priv, (u8 *)0xFE42, 0x01); + rtl818x_iowrite8(priv, (u8 *)0xFE40, 0x0F); + rtl818x_iowrite8(priv, (u8 *)0xFE42, 0x00); + rtl818x_iowrite8(priv, (u8 *)0xFE42, 0x01); + + reg = rtl818x_ioread8(priv, (u8 *)0xFFDB); + rtl818x_iowrite8(priv, (u8 *)0xFFDB, reg | (1 << 2)); + rtl818x_iowrite16_idx(priv, (__le16 *)0xFF72, 0x59FA, 3); + rtl818x_iowrite16_idx(priv, (__le16 *)0xFF74, 0x59D2, 3); + rtl818x_iowrite16_idx(priv, (__le16 *)0xFF76, 0x59D2, 3); + rtl818x_iowrite16_idx(priv, (__le16 *)0xFF78, 0x19FA, 3); + rtl818x_iowrite16_idx(priv, (__le16 *)0xFF7A, 0x19FA, 3); + rtl818x_iowrite16_idx(priv, (__le16 *)0xFF7C, 0x00D0, 3); + rtl818x_iowrite8(priv, (u8 *)0xFF61, 0); + rtl818x_iowrite8_idx(priv, (u8 *)0xFF80, 0x0F, 1); + rtl818x_iowrite8_idx(priv, (u8 *)0xFF83, 0x03, 1); + rtl818x_iowrite8(priv, (u8 *)0xFFDA, 0x10); + rtl818x_iowrite8_idx(priv, (u8 *)0xFF4D, 0x08, 2); + + rtl818x_iowrite32(priv, &priv->map->HSSI_PARA, 0x0600321B); + + rtl818x_iowrite16_idx(priv, (__le16 *)0xFFEC, 0x0800, 1); + + return 0; +} + static int rtl8187_start(struct ieee80211_hw *dev) { struct rtl8187_priv *priv = dev->priv; u32 reg; int ret; - ret = rtl8187_init_hw(dev); + ret = (!priv->is_rtl8187b) ? rtl8187_init_hw(dev) : + rtl8187b_init_hw(dev); if (ret) return ret; + if (priv->is_rtl8187b) { + reg = RTL818X_RX_CONF_MGMT | + RTL818X_RX_CONF_DATA | + RTL818X_RX_CONF_BROADCAST | + RTL818X_RX_CONF_NICMAC | + RTL818X_RX_CONF_BSSID | + (7 << 13 /* RX FIFO threshold NONE */) | + (7 << 10 /* MAX RX DMA */) | + RTL818X_RX_CONF_RX_AUTORESETPHY | + RTL818X_RX_CONF_ONLYERLPKT | + RTL818X_RX_CONF_MULTICAST; + priv->rx_conf = reg; + rtl818x_iowrite32(priv, &priv->map->RX_CONF, reg); + + rtl818x_iowrite32(priv, &priv->map->TX_CONF, + RTL818X_TX_CONF_HW_SEQNUM | + RTL818X_TX_CONF_DISREQQSIZE | + (7 << 8 /* short retry limit */) | + (7 << 0 /* long retry limit */) | + (7 << 21 /* MAX TX DMA */)); + rtl8187_init_urbs(dev); + return 0; + } + rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0xFFFF); rtl818x_iowrite32(priv, &priv->map->MAR[0], ~0); -- cgit v0.10.2 From 6f7853f3cbe457067e9fe05461f56c7ea4ac488c Mon Sep 17 00:00:00 2001 From: Hin-Tak Leung Date: Tue, 8 Jul 2008 12:36:04 +0100 Subject: rtl8187: change rtl8187_dev.c to support RTL8187B (part 2) Signed-off-by: Larry Finger Signed-off-by: Herton Ronaldo Krzesinski Signed-off-by: Hin-Tak Leung Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c index b17f237..3bc4a1c 100644 --- a/drivers/net/wireless/rtl8187_dev.c +++ b/drivers/net/wireless/rtl8187_dev.c @@ -155,9 +155,11 @@ static void rtl8187_tx_cb(struct urb *urb) struct sk_buff *skb = (struct sk_buff *)urb->context; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_hw *hw = info->driver_data[0]; + struct rtl8187_priv *priv = hw->priv; usb_free_urb(info->driver_data[1]); - skb_pull(skb, sizeof(struct rtl8187_tx_hdr)); + skb_pull(skb, priv->is_rtl8187b ? sizeof(struct rtl8187b_tx_hdr) : + sizeof(struct rtl8187_tx_hdr)); memset(&info->status, 0, sizeof(info->status)); info->flags |= IEEE80211_TX_STAT_ACK; ieee80211_tx_status_irqsafe(hw, skb); @@ -167,7 +169,8 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb) { struct rtl8187_priv *priv = dev->priv; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct rtl8187_tx_hdr *hdr; + unsigned int ep; + void *buf; struct urb *urb; __le16 rts_dur = 0; u32 flags; @@ -195,16 +198,47 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb) flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19; } - hdr = (struct rtl8187_tx_hdr *)skb_push(skb, sizeof(*hdr)); - hdr->flags = cpu_to_le32(flags); - hdr->len = 0; - hdr->rts_duration = rts_dur; - hdr->retry = cpu_to_le32(info->control.retry_limit << 8); + if (!priv->is_rtl8187b) { + struct rtl8187_tx_hdr *hdr = + (struct rtl8187_tx_hdr *)skb_push(skb, sizeof(*hdr)); + hdr->flags = cpu_to_le32(flags); + hdr->len = 0; + hdr->rts_duration = rts_dur; + hdr->retry = cpu_to_le32(info->control.retry_limit << 8); + buf = hdr; + + ep = 2; + } else { + /* fc needs to be calculated before skb_push() */ + unsigned int epmap[4] = { 6, 7, 5, 4 }; + struct ieee80211_hdr *tx_hdr = + (struct ieee80211_hdr *)(skb->data); + u16 fc = le16_to_cpu(tx_hdr->frame_control); + + struct rtl8187b_tx_hdr *hdr = + (struct rtl8187b_tx_hdr *)skb_push(skb, sizeof(*hdr)); + struct ieee80211_rate *txrate = + ieee80211_get_tx_rate(dev, info); + memset(hdr, 0, sizeof(*hdr)); + hdr->flags = cpu_to_le32(flags); + hdr->rts_duration = rts_dur; + hdr->retry = cpu_to_le32(info->control.retry_limit << 8); + hdr->tx_duration = + ieee80211_generic_frame_duration(dev, priv->vif, + skb->len, txrate); + buf = hdr; + + if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) + ep = 12; + else + ep = epmap[skb_get_queue_mapping(skb)]; + } info->driver_data[0] = dev; info->driver_data[1] = urb; - usb_fill_bulk_urb(urb, priv->udev, usb_sndbulkpipe(priv->udev, 2), - hdr, skb->len, rtl8187_tx_cb, skb); + + usb_fill_bulk_urb(urb, priv->udev, usb_sndbulkpipe(priv->udev, ep), + buf, skb->len, rtl8187_tx_cb, skb); rc = usb_submit_urb(urb, GFP_ATOMIC); if (rc < 0) { usb_free_urb(urb); @@ -220,7 +254,6 @@ static void rtl8187_rx_cb(struct urb *urb) struct rtl8187_rx_info *info = (struct rtl8187_rx_info *)skb->cb; struct ieee80211_hw *dev = info->dev; struct rtl8187_priv *priv = dev->priv; - struct rtl8187_rx_hdr *hdr; struct ieee80211_rx_status rx_status = { 0 }; int rate, signal; u32 flags; @@ -241,11 +274,33 @@ static void rtl8187_rx_cb(struct urb *urb) } skb_put(skb, urb->actual_length); - hdr = (struct rtl8187_rx_hdr *)(skb_tail_pointer(skb) - sizeof(*hdr)); - flags = le32_to_cpu(hdr->flags); - skb_trim(skb, flags & 0x0FFF); + if (!priv->is_rtl8187b) { + struct rtl8187_rx_hdr *hdr = + (typeof(hdr))(skb_tail_pointer(skb) - sizeof(*hdr)); + flags = le32_to_cpu(hdr->flags); + signal = hdr->signal & 0x7f; + rx_status.antenna = (hdr->signal >> 7) & 1; + rx_status.signal = signal; + rx_status.noise = hdr->noise; + rx_status.mactime = le64_to_cpu(hdr->mac_time); + priv->signal = signal; + priv->quality = signal; + priv->noise = hdr->noise; + } else { + struct rtl8187b_rx_hdr *hdr = + (typeof(hdr))(skb_tail_pointer(skb) - sizeof(*hdr)); + flags = le32_to_cpu(hdr->flags); + signal = hdr->agc >> 1; + rx_status.antenna = (hdr->signal >> 7) & 1; + rx_status.signal = 64 - min(hdr->noise, (u8)64); + rx_status.noise = hdr->noise; + rx_status.mactime = le64_to_cpu(hdr->mac_time); + priv->signal = hdr->signal; + priv->quality = hdr->agc >> 1; + priv->noise = hdr->noise; + } - signal = hdr->agc >> 1; + skb_trim(skb, flags & 0x0FFF); rate = (flags >> 20) & 0xF; if (rate > 3) { /* OFDM rate */ if (signal > 90) @@ -261,13 +316,11 @@ static void rtl8187_rx_cb(struct urb *urb) signal = 95 - signal; } - rx_status.antenna = (hdr->signal >> 7) & 1; - rx_status.qual = 64 - min(hdr->noise, (u8)64); + rx_status.qual = priv->quality; rx_status.signal = signal; rx_status.rate_idx = rate; rx_status.freq = dev->conf.channel->center_freq; rx_status.band = dev->conf.channel->band; - rx_status.mactime = le64_to_cpu(hdr->mac_time); rx_status.flag |= RX_FLAG_TSFT; if (flags & (1 << 13)) rx_status.flag |= RX_FLAG_FAILED_FCS_CRC; @@ -307,7 +360,8 @@ static int rtl8187_init_urbs(struct ieee80211_hw *dev) break; } usb_fill_bulk_urb(entry, priv->udev, - usb_rcvbulkpipe(priv->udev, 1), + usb_rcvbulkpipe(priv->udev, + priv->is_rtl8187b ? 3 : 1), skb_tail_pointer(skb), RTL8187_MAX_RX, rtl8187_rx_cb, skb); info = (struct rtl8187_rx_info *)skb->cb; @@ -786,18 +840,20 @@ static int rtl8187_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf) msleep(10); rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg); - rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22); - - if (conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME) { - rtl818x_iowrite8(priv, &priv->map->SLOT, 0x9); - rtl818x_iowrite8(priv, &priv->map->DIFS, 0x14); - rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x14); - rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0x73); - } else { - rtl818x_iowrite8(priv, &priv->map->SLOT, 0x14); - rtl818x_iowrite8(priv, &priv->map->DIFS, 0x24); - rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x24); - rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0xa5); + if (!priv->is_rtl8187b) { + rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22); + + if (conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME) { + rtl818x_iowrite8(priv, &priv->map->SLOT, 0x9); + rtl818x_iowrite8(priv, &priv->map->DIFS, 0x14); + rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x14); + rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0x73); + } else { + rtl818x_iowrite8(priv, &priv->map->SLOT, 0x14); + rtl818x_iowrite8(priv, &priv->map->DIFS, 0x24); + rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x24); + rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0xa5); + } } rtl818x_iowrite16(priv, &priv->map->ATIM_WND, 2); @@ -813,14 +869,20 @@ static int rtl8187_config_interface(struct ieee80211_hw *dev, { struct rtl8187_priv *priv = dev->priv; int i; + u8 reg; for (i = 0; i < ETH_ALEN; i++) rtl818x_iowrite8(priv, &priv->map->BSSID[i], conf->bssid[i]); - if (is_valid_ether_addr(conf->bssid)) - rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_INFRA); - else - rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_NO_LINK); + if (is_valid_ether_addr(conf->bssid)) { + reg = RTL818X_MSR_INFRA; + if (priv->is_rtl8187b) + reg |= RTL818X_MSR_ENEDCA; + rtl818x_iowrite8(priv, &priv->map->MSR, reg); + } else { + reg = RTL818X_MSR_NO_LINK; + rtl818x_iowrite8(priv, &priv->map->MSR, reg); + } return 0; } @@ -907,6 +969,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, struct rtl8187_priv *priv; struct eeprom_93cx6 eeprom; struct ieee80211_channel *channel; + const char *chip_name; u16 txpwr, reg; int err, i; DECLARE_MAC_BUF(mac); @@ -918,6 +981,8 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, } priv = dev->priv; + priv->is_rtl8187b = (id->driver_info == DEVICE_RTL8187B) || + !memcmp(udev->product, "RTL8187B", 8); SET_IEEE80211_DEV(dev, &intf->dev); usb_set_intfdata(intf, dev); @@ -946,8 +1011,13 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_SIGNAL_UNSPEC; - dev->extra_tx_headroom = sizeof(struct rtl8187_tx_hdr); - dev->queues = 1; + dev->extra_tx_headroom = (!priv->is_rtl8187b) ? + sizeof(struct rtl8187_tx_hdr) : + sizeof(struct rtl8187b_tx_hdr); + if (!priv->is_rtl8187b) + dev->queues = 1; + else + dev->queues = 4; dev->max_signal = 65; eeprom.data = dev; @@ -982,10 +1052,24 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, (*channel++).hw_value = txpwr & 0xFF; (*channel++).hw_value = txpwr >> 8; } - for (i = 0; i < 2; i++) { - eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_6 + i, + if (!priv->is_rtl8187b) { + for (i = 0; i < 2; i++) { + eeprom_93cx6_read(&eeprom, + RTL8187_EEPROM_TXPWR_CHAN_6 + i, + &txpwr); + (*channel++).hw_value = txpwr & 0xFF; + (*channel++).hw_value = txpwr >> 8; + } + } else { + eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_6, &txpwr); (*channel++).hw_value = txpwr & 0xFF; + + eeprom_93cx6_read(&eeprom, 0x0A, &txpwr); + (*channel++).hw_value = txpwr & 0xFF; + + eeprom_93cx6_read(&eeprom, 0x1C, &txpwr); + (*channel++).hw_value = txpwr & 0xFF; (*channel++).hw_value = txpwr >> 8; } @@ -1001,6 +1085,50 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg); rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); + if (!priv->is_rtl8187b) { + u32 reg32; + reg32 = rtl818x_ioread32(priv, &priv->map->TX_CONF); + reg32 &= RTL818X_TX_CONF_HWVER_MASK; + switch (reg32) { + case RTL818X_TX_CONF_R8187vD_1: + case RTL818X_TX_CONF_R8187vD_2: + chip_name = "RTL8187vD"; + break; + default: + chip_name = "RTL8187vB (default)"; + } + } else { + printk(KERN_WARNING "rtl8187: 8187B chip detected. Support " + "is EXPERIMENTAL, and could damage your\n" + " hardware, use at your own risk\n"); + /* + * Force USB request to write radio registers for 8187B, Realtek + * only uses it in their sources + */ + /*if (priv->asic_rev == 0) { + printk(KERN_WARNING "rtl8187: Forcing use of USB " + "requests to write to radio registers\n"); + priv->asic_rev = 1; + }*/ + switch (rtl818x_ioread8(priv, (u8 *)0xFFE1)) { + case RTL818X_R8187B_B: + chip_name = "RTL8187BvB"; + priv->hw_rev = RTL8187BvB; + break; + case RTL818X_R8187B_D: + chip_name = "RTL8187BvD"; + priv->hw_rev = RTL8187BvD; + break; + case RTL818X_R8187B_E: + chip_name = "RTL8187BvE"; + priv->hw_rev = RTL8187BvE; + break; + default: + chip_name = "RTL8187BvB (default)"; + priv->hw_rev = RTL8187BvB; + } + } + priv->rf = rtl8187_detect_rf(dev); err = ieee80211_register_hw(dev); @@ -1009,9 +1137,9 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, goto err_free_dev; } - printk(KERN_INFO "%s: hwaddr %s, rtl8187 V%d + %s\n", + printk(KERN_INFO "%s: hwaddr %s, %s V%d + %s\n", wiphy_name(dev->wiphy), print_mac(mac, dev->wiphy->perm_addr), - priv->asic_rev, priv->rf->name); + chip_name, priv->asic_rev, priv->rf->name); return 0; -- cgit v0.10.2 From 5c036b217a1fe3ae0616e9c43c6bcd13b3c134b6 Mon Sep 17 00:00:00 2001 From: Hin-Tak Leung Date: Tue, 8 Jul 2008 12:38:02 +0100 Subject: rtl8187: updating Kconfig to support RTL8187B Signed-off-by: Larry Finger Signed-off-by: Herton Ronaldo Krzesinski Signed-off-by: Hin-Tak Leung Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 865f298..d5b006f 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -611,14 +611,20 @@ config RTL8180 Thanks to Realtek for their support! config RTL8187 - tristate "Realtek 8187 USB support" + tristate "Realtek 8187 and 8187B USB support" depends on MAC80211 && USB && WLAN_80211 && EXPERIMENTAL select EEPROM_93CX6 ---help--- - This is a driver for RTL8187 based cards. - These are USB based chips found in cards such as: + This is a driver for RTL8187 and RTL8187B based cards. + These are USB based chips found in devices such as: Netgear WG111v2 + Level 1 WNC-0301USB + Micronet SP907GK V5 + Encore ENUWI-G2 + Trendnet TEW-424UB + ASUS P5B Deluxe + Toshiba Satellite Pro series of laptops Thanks to Realtek for their support! -- cgit v0.10.2 From 0e25b4ef220f6ef4eed120543182385b13005db9 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Tue, 8 Jul 2008 09:43:43 -0500 Subject: rtl8187: Change detection of RTL8187B with USB ID of 8187 Some early versions of RTL8187B devices have a USB ID of 0x8187 rather than the 0x8189 of later models. In addition, it appears that these early units also must be programmed with lower power. Previous patches used the Product ID string to detect this situation, but did not address the low power question. This patch uses the hardware version and sets the power accordingly. Signed-off-by: Hin-Tak Leung Signed-off-by: Larry Finger Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c index 3bc4a1c..33527e5 100644 --- a/drivers/net/wireless/rtl8187_dev.c +++ b/drivers/net/wireless/rtl8187_dev.c @@ -981,8 +981,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, } priv = dev->priv; - priv->is_rtl8187b = (id->driver_info == DEVICE_RTL8187B) || - !memcmp(udev->product, "RTL8187B", 8); + priv->is_rtl8187b = (id->driver_info == DEVICE_RTL8187B); SET_IEEE80211_DEV(dev, &intf->dev); usb_set_intfdata(intf, dev); @@ -1011,13 +1010,6 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | IEEE80211_HW_RX_INCLUDES_FCS | IEEE80211_HW_SIGNAL_UNSPEC; - dev->extra_tx_headroom = (!priv->is_rtl8187b) ? - sizeof(struct rtl8187_tx_hdr) : - sizeof(struct rtl8187b_tx_hdr); - if (!priv->is_rtl8187b) - dev->queues = 1; - else - dev->queues = 4; dev->max_signal = 65; eeprom.data = dev; @@ -1052,26 +1044,6 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, (*channel++).hw_value = txpwr & 0xFF; (*channel++).hw_value = txpwr >> 8; } - if (!priv->is_rtl8187b) { - for (i = 0; i < 2; i++) { - eeprom_93cx6_read(&eeprom, - RTL8187_EEPROM_TXPWR_CHAN_6 + i, - &txpwr); - (*channel++).hw_value = txpwr & 0xFF; - (*channel++).hw_value = txpwr >> 8; - } - } else { - eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_6, - &txpwr); - (*channel++).hw_value = txpwr & 0xFF; - - eeprom_93cx6_read(&eeprom, 0x0A, &txpwr); - (*channel++).hw_value = txpwr & 0xFF; - - eeprom_93cx6_read(&eeprom, 0x1C, &txpwr); - (*channel++).hw_value = txpwr & 0xFF; - (*channel++).hw_value = txpwr >> 8; - } eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_BASE, &priv->txpwr_base); @@ -1090,17 +1062,20 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, reg32 = rtl818x_ioread32(priv, &priv->map->TX_CONF); reg32 &= RTL818X_TX_CONF_HWVER_MASK; switch (reg32) { - case RTL818X_TX_CONF_R8187vD_1: - case RTL818X_TX_CONF_R8187vD_2: + case RTL818X_TX_CONF_R8187vD_B: + /* Some RTL8187B devices have a USB ID of 0x8187 + * detect them here */ + chip_name = "RTL8187BvB(early)"; + priv->is_rtl8187b = 1; + priv->hw_rev = RTL8187BvB; + break; + case RTL818X_TX_CONF_R8187vD: chip_name = "RTL8187vD"; break; default: chip_name = "RTL8187vB (default)"; } } else { - printk(KERN_WARNING "rtl8187: 8187B chip detected. Support " - "is EXPERIMENTAL, and could damage your\n" - " hardware, use at your own risk\n"); /* * Force USB request to write radio registers for 8187B, Realtek * only uses it in their sources @@ -1129,7 +1104,43 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, } } + if (!priv->is_rtl8187b) { + for (i = 0; i < 2; i++) { + eeprom_93cx6_read(&eeprom, + RTL8187_EEPROM_TXPWR_CHAN_6 + i, + &txpwr); + (*channel++).hw_value = txpwr & 0xFF; + (*channel++).hw_value = txpwr >> 8; + } + } else { + eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_6, + &txpwr); + (*channel++).hw_value = txpwr & 0xFF; + + eeprom_93cx6_read(&eeprom, 0x0A, &txpwr); + (*channel++).hw_value = txpwr & 0xFF; + + eeprom_93cx6_read(&eeprom, 0x1C, &txpwr); + (*channel++).hw_value = txpwr & 0xFF; + (*channel++).hw_value = txpwr >> 8; + } + + if (priv->is_rtl8187b) + printk(KERN_WARNING "rtl8187: 8187B chip detected. Support " + "is EXPERIMENTAL, and could damage your\n" + " hardware, use at your own risk\n"); + if ((id->driver_info == DEVICE_RTL8187) && priv->is_rtl8187b) + printk(KERN_INFO "rtl8187: inconsistency between id with OEM" + " info!\n"); + priv->rf = rtl8187_detect_rf(dev); + dev->extra_tx_headroom = (!priv->is_rtl8187b) ? + sizeof(struct rtl8187_tx_hdr) : + sizeof(struct rtl8187b_tx_hdr); + if (!priv->is_rtl8187b) + dev->queues = 1; + else + dev->queues = 4; err = ieee80211_register_hw(dev); if (err) { diff --git a/drivers/net/wireless/rtl818x.h b/drivers/net/wireless/rtl818x.h index 85a6394..00900fe 100644 --- a/drivers/net/wireless/rtl818x.h +++ b/drivers/net/wireless/rtl818x.h @@ -66,8 +66,8 @@ struct rtl818x_csr { #define RTL818X_TX_CONF_R8180_F (3 << 25) #define RTL818X_TX_CONF_R8185_ABC (4 << 25) #define RTL818X_TX_CONF_R8185_D (5 << 25) -#define RTL818X_TX_CONF_R8187vD_1 (5 << 25) -#define RTL818X_TX_CONF_R8187vD_2 (6 << 25) +#define RTL818X_TX_CONF_R8187vD (5 << 25) +#define RTL818X_TX_CONF_R8187vD_B (6 << 25) #define RTL818X_TX_CONF_HWVER_MASK (7 << 25) #define RTL818X_TX_CONF_DISREQQSIZE (1 << 28) #define RTL818X_TX_CONF_PROBE_DTS (1 << 29) -- cgit v0.10.2 From b46372710ab536c0967f76be5dc41341583d4a54 Mon Sep 17 00:00:00 2001 From: Julius Volz Date: Tue, 8 Jul 2008 14:02:19 +0200 Subject: net/wireless/nl80211.c: fix endless Netlink callback loop. Although I only tested similar code (I don't use any of this wireless code), the state maintainance between Netlink dump callback invocations seems wrong here and should lead to an endless loop. There are also other examples in the same file which might have the same problem. Perhaps someone can actually test this (or refute my logic). Take the simple example with only one element in the list (which should fit into the message): 1. invocation: Start: idx = 0, start = 0 Loop: condition (++idx < start) => (1 < 0) => false => no continue, fill one entry, exit loop, return skb->len > 0 2. invocation: Start: idx = 0, start = 1 Loop: condition (++idx < start) => (1 < 1) => false => no continue, fill the same entry again, exit loop, return skb->len > 0 3. invocation: Same as 2. invocation, endless invocation of callback. Also, iterations where the filling of an element fails should not be counted as completed, so idx should not be incremented in this case. Signed-off-by: Julius Volz Signed-off-by: John W. Linville diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index fb75f26..b7fefff 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -199,12 +199,14 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb) mutex_lock(&cfg80211_drv_mutex); list_for_each_entry(dev, &cfg80211_drv_list, list) { - if (++idx < start) + if (++idx <= start) continue; if (nl80211_send_wiphy(skb, NETLINK_CB(cb->skb).pid, cb->nlh->nlmsg_seq, NLM_F_MULTI, - dev) < 0) + dev) < 0) { + idx--; break; + } } mutex_unlock(&cfg80211_drv_mutex); -- cgit v0.10.2