From 1afc09ab7c62d0e59596ce76e8e256b0cf695654 Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Tue, 29 Jan 2008 09:14:40 +0100 Subject: libertas: trim overly long debug statement Signed-off-by: Holger Schurig Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/cmd.c | 23 +++++++---------------- drivers/net/wireless/libertas/cmdresp.c | 4 ++-- 2 files changed, 9 insertions(+), 18 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index b3c1acbcc655..3f9074df91e4 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -1153,9 +1153,9 @@ static void lbs_submit_command(struct lbs_private *priv, command == CMD_802_11_AUTHENTICATE) timeo = 10 * HZ; - lbs_deb_host("DNLD_CMD: command 0x%04x, seq %d, size %d, jiffies %lu\n", + lbs_deb_cmd("DNLD_CMD: command 0x%04x, seq %d, size %d, jiffies %lu\n", command, le16_to_cpu(cmd->seqnum), cmdsize, jiffies); - lbs_deb_hex(LBS_DEB_HOST, "DNLD_CMD", (void *) cmdnode->cmdbuf, cmdsize); + lbs_deb_hex(LBS_DEB_CMD, "DNLD_CMD", (void *) cmdnode->cmdbuf, cmdsize); ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) cmd, cmdsize); @@ -1164,9 +1164,7 @@ static void lbs_submit_command(struct lbs_private *priv, /* Let the timer kick in and retry, and potentially reset the whole thing if the condition persists */ timeo = HZ; - } else - lbs_deb_cmd("DNLD_CMD: sent command 0x%04x, jiffies %lu\n", - command, jiffies); + } /* Setup the timer after transmit command */ mod_timer(&priv->command_timer, jiffies + timeo); @@ -1185,7 +1183,7 @@ static int lbs_cmd_mac_control(struct lbs_private *priv, cmd->size = cpu_to_le16(sizeof(struct cmd_ds_mac_control) + S_DS_GEN); mac->action = cpu_to_le16(priv->currentpacketfilter); - lbs_deb_cmd("MAC_CONTROL: action 0x%x, size %d\n", + lbs_deb_cmd("MAC_CONTROL: action 0x%04x, size %d\n", le16_to_cpu(mac->action), le16_to_cpu(cmd->size)); lbs_deb_leave(LBS_DEB_CMD); @@ -1741,9 +1739,9 @@ int lbs_execute_next_command(struct lbs_private *priv) unsigned long flags; int ret = 0; - // Debug group is LBS_DEB_THREAD and not LBS_DEB_HOST, because the - // only caller to us is lbs_thread() and we get even when a - // data packet is received + /* Debug group is LBS_DEB_THREAD and not LBS_DEB_HOST, because the + * only caller to us is lbs_thread() and we get even when a + * data packet is received */ lbs_deb_enter(LBS_DEB_THREAD); spin_lock_irqsave(&priv->driver_lock, flags); @@ -2043,15 +2041,8 @@ int lbs_cmd_copyback(struct lbs_private *priv, unsigned long extra, struct cmd_header *buf = (void *)extra; uint16_t copy_len; - lbs_deb_enter(LBS_DEB_CMD); - copy_len = min(le16_to_cpu(buf->size), le16_to_cpu(resp->size)); - lbs_deb_cmd("Copying back %u bytes; command response was %u bytes, " - "copy back buffer was %u bytes\n", copy_len, - le16_to_cpu(resp->size), le16_to_cpu(buf->size)); memcpy(buf, resp, copy_len); - - lbs_deb_leave(LBS_DEB_CMD); return 0; } EXPORT_SYMBOL_GPL(lbs_cmd_copyback); diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c index 159216a91903..bd2e6668d85f 100644 --- a/drivers/net/wireless/libertas/cmdresp.c +++ b/drivers/net/wireless/libertas/cmdresp.c @@ -568,9 +568,9 @@ int lbs_process_rx_command(struct lbs_private *priv) respcmd = le16_to_cpu(resp->command); result = le16_to_cpu(resp->result); - lbs_deb_host("CMD_RESP: response 0x%04x, seq %d, size %d, jiffies %lu\n", + lbs_deb_cmd("CMD_RESP: response 0x%04x, seq %d, size %d, jiffies %lu\n", respcmd, le16_to_cpu(resp->seqnum), priv->upld_len, jiffies); - lbs_deb_hex(LBS_DEB_HOST, "CMD_RESP", (void *) resp, priv->upld_len); + lbs_deb_hex(LBS_DEB_CMD, "CMD_RESP", (void *) resp, priv->upld_len); if (resp->seqnum != resp->seqnum) { lbs_pr_info("Received CMD_RESP with invalid sequence %d (expected %d)\n", -- cgit v1.2.1 From 52507c20870dbd58921b42b801f0a92fc057221b Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Mon, 28 Jan 2008 17:25:53 +0100 Subject: libertas: make association debug output nicer This also fixes a bug where should_deauth_infrastructure() always returned 0. Signed-off-by: Holger Schurig Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/assoc.c | 9 +++------ drivers/net/wireless/libertas/cmdresp.c | 2 +- drivers/net/wireless/libertas/join.c | 3 --- 3 files changed, 4 insertions(+), 10 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c index 87e145ffe8f1..4360deac943b 100644 --- a/drivers/net/wireless/libertas/assoc.c +++ b/drivers/net/wireless/libertas/assoc.c @@ -413,11 +413,10 @@ static int should_deauth_infrastructure(struct lbs_private *priv, { int ret = 0; - lbs_deb_enter(LBS_DEB_ASSOC); - if (priv->connect_status != LBS_CONNECTED) return 0; + lbs_deb_enter(LBS_DEB_ASSOC); if (test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) { lbs_deb_assoc("Deauthenticating due to new SSID\n"); ret = 1; @@ -456,7 +455,7 @@ static int should_deauth_infrastructure(struct lbs_private *priv, out: lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); - return 0; + return ret; } @@ -643,9 +642,7 @@ void lbs_association_worker(struct work_struct *work) } if (success) { - lbs_deb_assoc("ASSOC: associated to '%s', %s\n", - escape_essid(priv->curbssparams.ssid, - priv->curbssparams.ssid_len), + lbs_deb_assoc("associated to %s\n", print_mac(mac, priv->curbssparams.bssid)); lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c index bd2e6668d85f..a0a5dbe81b3b 100644 --- a/drivers/net/wireless/libertas/cmdresp.c +++ b/drivers/net/wireless/libertas/cmdresp.c @@ -74,7 +74,7 @@ void lbs_mac_event_disconnected(struct lbs_private *priv) lbs_deb_cmd("disconnected, so exit PS mode\n"); lbs_ps_wakeup(priv, 0); } - lbs_deb_leave(LBS_DEB_CMD); + lbs_deb_leave(LBS_DEB_ASSOC); } /** diff --git a/drivers/net/wireless/libertas/join.c b/drivers/net/wireless/libertas/join.c index 2d4508048b68..a0a060939322 100644 --- a/drivers/net/wireless/libertas/join.c +++ b/drivers/net/wireless/libertas/join.c @@ -769,9 +769,6 @@ int lbs_ret_80211_associate(struct lbs_private *priv, priv->curbssparams.ssid_len = bss->ssid_len; memcpy(priv->curbssparams.bssid, bss->bssid, ETH_ALEN); - lbs_deb_assoc("ASSOC_RESP: currentpacketfilter is 0x%x\n", - priv->currentpacketfilter); - priv->SNR[TYPE_RXPD][TYPE_AVG] = 0; priv->NF[TYPE_RXPD][TYPE_AVG] = 0; -- cgit v1.2.1 From e226868ec3f3f98544ed2e6e7af7b6b8a629f492 Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Mon, 28 Jan 2008 17:26:28 +0100 Subject: libertas: make lbs_sync_channel() static ... by moving it into the file where it's sole user resides Signed-off-by: Holger Schurig Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/assoc.c | 11 ----------- drivers/net/wireless/libertas/assoc.h | 1 - drivers/net/wireless/libertas/main.c | 14 +++++++++++++- 3 files changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c index 4360deac943b..75f6191e718d 100644 --- a/drivers/net/wireless/libertas/assoc.c +++ b/drivers/net/wireless/libertas/assoc.c @@ -181,17 +181,6 @@ int lbs_update_channel(struct lbs_private *priv) return ret; } -void lbs_sync_channel(struct work_struct *work) -{ - struct lbs_private *priv = container_of(work, struct lbs_private, - sync_channel); - - lbs_deb_enter(LBS_DEB_ASSOC); - if (lbs_update_channel(priv)) - lbs_pr_info("Channel synchronization failed."); - lbs_deb_leave(LBS_DEB_ASSOC); -} - static int assoc_helper_channel(struct lbs_private *priv, struct assoc_request * assoc_req) { diff --git a/drivers/net/wireless/libertas/assoc.h b/drivers/net/wireless/libertas/assoc.h index 08372bbf3761..d489cf4cc1e2 100644 --- a/drivers/net/wireless/libertas/assoc.h +++ b/drivers/net/wireless/libertas/assoc.h @@ -7,6 +7,5 @@ void lbs_association_worker(struct work_struct *work); struct assoc_request *lbs_get_association_request(struct lbs_private *priv); -void lbs_sync_channel(struct work_struct *work); #endif /* _LBS_ASSOC_H */ diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 4d4e2f3b66ac..2e5bac826c48 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -985,6 +985,18 @@ out: lbs_deb_leave(LBS_DEB_CMD); } +static void lbs_sync_channel_worker(struct work_struct *work) +{ + struct lbs_private *priv = container_of(work, struct lbs_private, + sync_channel); + + lbs_deb_enter(LBS_DEB_MAIN); + if (lbs_update_channel(priv)) + lbs_pr_info("Channel synchronization failed."); + lbs_deb_leave(LBS_DEB_MAIN); +} + + static int lbs_init_adapter(struct lbs_private *priv) { size_t bufsize; @@ -1128,7 +1140,7 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev) priv->work_thread = create_singlethread_workqueue("lbs_worker"); INIT_DELAYED_WORK(&priv->assoc_work, lbs_association_worker); INIT_DELAYED_WORK(&priv->scan_work, lbs_scan_worker); - INIT_WORK(&priv->sync_channel, lbs_sync_channel); + INIT_WORK(&priv->sync_channel, lbs_sync_channel_worker); sprintf(priv->mesh_ssid, "mesh"); priv->mesh_ssid_len = 4; -- cgit v1.2.1 From 23ff50361f23355334bffe33de84f0b52aa34b9d Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Mon, 28 Jan 2008 17:27:03 +0100 Subject: libertas: make lbs_unset_basic_rate_flags() static ... by moving it into the file where it's sole user resides Signed-off-by: Holger Schurig Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/join.c | 17 ----------------- drivers/net/wireless/libertas/join.h | 2 -- drivers/net/wireless/libertas/scan.c | 17 +++++++++++++++++ 3 files changed, 17 insertions(+), 19 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/libertas/join.c b/drivers/net/wireless/libertas/join.c index a0a060939322..56e64a697c37 100644 --- a/drivers/net/wireless/libertas/join.c +++ b/drivers/net/wireless/libertas/join.c @@ -98,23 +98,6 @@ static void lbs_set_basic_rate_flags(u8 *rates, size_t len) } } -/** - * @brief Unsets the MSB on basic rates - * - * Scan through an array and unset the MSB for basic data rates. - * - * @param rates buffer of data rates - * @param len size of buffer - */ -void lbs_unset_basic_rate_flags(u8 *rates, size_t len) -{ - int i; - - for (i = 0; i < len; i++) - rates[i] &= 0x7f; -} - - /** * @brief Associate to a specific BSS discovered in a scan * diff --git a/drivers/net/wireless/libertas/join.h b/drivers/net/wireless/libertas/join.h index c617d071f781..792c64fe3514 100644 --- a/drivers/net/wireless/libertas/join.h +++ b/drivers/net/wireless/libertas/join.h @@ -48,6 +48,4 @@ int lbs_send_deauthentication(struct lbs_private *priv); int lbs_associate(struct lbs_private *priv, struct assoc_request *assoc_req); -void lbs_unset_basic_rate_flags(u8 *rates, size_t len); - #endif diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c index 69f94c92b32d..37b9684bf29c 100644 --- a/drivers/net/wireless/libertas/scan.c +++ b/drivers/net/wireless/libertas/scan.c @@ -73,6 +73,23 @@ static const u8 bcastmac[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; /* */ /*********************************************************************/ +/** + * @brief Unsets the MSB on basic rates + * + * Scan through an array and unset the MSB for basic data rates. + * + * @param rates buffer of data rates + * @param len size of buffer + */ +static void lbs_unset_basic_rate_flags(u8 *rates, size_t len) +{ + int i; + + for (i = 0; i < len; i++) + rates[i] &= 0x7f; +} + + static inline void clear_bss_descriptor (struct bss_descriptor * bss) { /* Don't blow away ->list, just BSS data */ -- cgit v1.2.1 From 8816edcea9009b66570bef10acde5a552a9b3b3c Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Mon, 28 Jan 2008 17:28:05 +0100 Subject: libertas: rename/document scan_channel Rename last_scanned_channel to scan_channel, just so that a grep for struct bss_descriptor's last_scanned element doesn't show up so many positives. Also documented the variable and moved it to other scan related entries in lbs_private. Signed-off-by: Holger Schurig Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/debugfs.c | 2 +- drivers/net/wireless/libertas/dev.h | 4 +++- drivers/net/wireless/libertas/scan.c | 22 +++++++++++----------- 3 files changed, 15 insertions(+), 13 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c index fd67b770dd78..b600f2439b57 100644 --- a/drivers/net/wireless/libertas/debugfs.c +++ b/drivers/net/wireless/libertas/debugfs.c @@ -315,7 +315,7 @@ static ssize_t lbs_setuserscan(struct file *file, lbs_scan_networks(priv, scan_cfg, 1); wait_event_interruptible(priv->cmd_pending, - priv->surpriseremoved || !priv->last_scanned_channel); + priv->surpriseremoved || !priv->scan_channel); if (priv->surpriseremoved) goto out_scan_cfg; diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index 5a69f2b60865..fd1fcc748010 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h @@ -143,9 +143,12 @@ struct lbs_private { wait_queue_head_t waitq; struct workqueue_struct *work_thread; + /** Scanning */ struct delayed_work scan_work; struct delayed_work assoc_work; struct work_struct sync_channel; + /* remember which channel was scanned last, != 0 if currently scanning */ + int scan_channel; /** Hardware access */ int (*hw_host_to_card) (struct lbs_private *priv, u8 type, u8 *payload, u16 nb); @@ -321,7 +324,6 @@ struct lbs_private { struct cmd_ds_802_11_get_log logmsg; u32 monitormode; - int last_scanned_channel; u8 fw_ready; }; diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c index 37b9684bf29c..7d4f3afa8cc5 100644 --- a/drivers/net/wireless/libertas/scan.c +++ b/drivers/net/wireless/libertas/scan.c @@ -612,13 +612,13 @@ int lbs_scan_networks(struct lbs_private *priv, } /* Prepare to continue an interrupted scan */ - lbs_deb_scan("chan_count %d, last_scanned_channel %d\n", - chan_count, priv->last_scanned_channel); + lbs_deb_scan("chan_count %d, scan_channel %d\n", + chan_count, priv->scan_channel); curr_chans = chan_list; /* advance channel list by already-scanned-channels */ - if (priv->last_scanned_channel > 0) { - curr_chans += priv->last_scanned_channel; - chan_count -= priv->last_scanned_channel; + if (priv->scan_channel > 0) { + curr_chans += priv->scan_channel; + chan_count -= priv->scan_channel; } /* Send scan command(s) @@ -644,10 +644,10 @@ int lbs_scan_networks(struct lbs_private *priv, !full_scan && !priv->surpriseremoved) { /* -1 marks just that we're currently scanning */ - if (priv->last_scanned_channel < 0) - priv->last_scanned_channel = to_scan; + if (priv->scan_channel < 0) + priv->scan_channel = to_scan; else - priv->last_scanned_channel += to_scan; + priv->scan_channel += to_scan; cancel_delayed_work(&priv->scan_work); queue_delayed_work(priv->work_thread, &priv->scan_work, msecs_to_jiffies(300)); @@ -671,7 +671,7 @@ int lbs_scan_networks(struct lbs_private *priv, #endif out2: - priv->last_scanned_channel = 0; + priv->scan_channel = 0; out: if (priv->connect_status == LBS_CONNECTED) { @@ -1393,7 +1393,7 @@ int lbs_set_scan(struct net_device *dev, struct iw_request_info *info, queue_delayed_work(priv->work_thread, &priv->scan_work, msecs_to_jiffies(50)); /* set marker that currently a scan is taking place */ - priv->last_scanned_channel = -1; + priv->scan_channel = -1; if (priv->surpriseremoved) return -EIO; @@ -1427,7 +1427,7 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info, lbs_deb_enter(LBS_DEB_SCAN); /* iwlist should wait until the current scan is finished */ - if (priv->last_scanned_channel) + if (priv->scan_channel) return -EAGAIN; /* Update RSSI if current BSS is a locally created ad-hoc BSS */ -- cgit v1.2.1 From 0df3ef45a3d7b59cc53ce4e3611033c6e3b51a1b Mon Sep 17 00:00:00 2001 From: Ron Rindjunsky Date: Mon, 28 Jan 2008 14:07:15 +0200 Subject: mac80211: A-MPDU Tx add session's and low level driver's API This patch adds the API for 3 stages in A-MPDU Tx session flow: - request mac80211 to start/stop A-MPDU Tx session for specific TID. such a request should be issued by a load aware element, either mac80211 itself or external element. - requests by mac80211 to low-level driver to start/stop Tx aggregation. notice that low level driver responds now with Starting Sequence Number. - async feedback by low-level to mac80211 to inform that HW is ready for next A-MPDU Tx state. Changes in API to Rx A-MPDU were also made, reflected in iwlwifi changes as well. Signed-off-by: Ron Rindjunsky Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-4965.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index d727de8b96fe..cd4f5e383e60 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -4732,7 +4732,7 @@ static void iwl4965_sta_modify_del_ba_tid(struct iwl4965_priv *priv, int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw, enum ieee80211_ampdu_mlme_action action, - const u8 *addr, u16 tid, u16 ssn) + const u8 *addr, u16 tid, u16 *ssn) { struct iwl4965_priv *priv = hw->priv; int sta_id; @@ -4744,7 +4744,7 @@ int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw, switch (action) { case IEEE80211_AMPDU_RX_START: IWL_DEBUG_HT("start Rx\n"); - iwl4965_sta_modify_add_ba_tid(priv, sta_id, tid, ssn); + iwl4965_sta_modify_add_ba_tid(priv, sta_id, tid, *ssn); break; case IEEE80211_AMPDU_RX_STOP: IWL_DEBUG_HT("stop Rx\n"); diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index 9cb82be0ff80..6edf869d4d54 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -777,7 +777,7 @@ extern void iwl4965_set_ht_add_station(struct iwl4965_priv *priv, u8 index, struct ieee80211_ht_info *sta_ht_inf); extern int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw, enum ieee80211_ampdu_mlme_action action, - const u8 *addr, u16 tid, u16 ssn); + const u8 *addr, u16 tid, u16 *ssn); #ifdef CONFIG_IWL4965_HT_AGG extern int iwl4965_mac_ht_tx_agg_start(struct ieee80211_hw *hw, u8 *da, u16 tid, u16 *start_seq_num); -- cgit v1.2.1 From 8114fcf185c58b23dc9fcaf4944b59b4c1407b39 Mon Sep 17 00:00:00 2001 From: Ron Rindjunsky Date: Mon, 28 Jan 2008 14:07:23 +0200 Subject: iwlwifi: A-MPDU Tx conform API to mac80211 This patch alters the current API in order to fit the new API mac80211 gives for A-MPDU Tx Signed-off-by: Ron Rindjunsky Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965.c | 77 ++++++++++++++++++----------- drivers/net/wireless/iwlwifi/iwl-4965.h | 4 -- drivers/net/wireless/iwlwifi/iwl4965-base.c | 4 -- 3 files changed, 47 insertions(+), 38 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index cd4f5e383e60..3fc18dc311e9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -4730,34 +4730,6 @@ static void iwl4965_sta_modify_del_ba_tid(struct iwl4965_priv *priv, iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, CMD_ASYNC); } -int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw, - enum ieee80211_ampdu_mlme_action action, - const u8 *addr, u16 tid, u16 *ssn) -{ - struct iwl4965_priv *priv = hw->priv; - int sta_id; - DECLARE_MAC_BUF(mac); - - IWL_DEBUG_HT("A-MPDU action on da=%s tid=%d ", - print_mac(mac, addr), tid); - sta_id = iwl4965_hw_find_station(priv, addr); - switch (action) { - case IEEE80211_AMPDU_RX_START: - IWL_DEBUG_HT("start Rx\n"); - iwl4965_sta_modify_add_ba_tid(priv, sta_id, tid, *ssn); - break; - case IEEE80211_AMPDU_RX_STOP: - IWL_DEBUG_HT("stop Rx\n"); - iwl4965_sta_modify_del_ba_tid(priv, sta_id, tid); - break; - default: - IWL_DEBUG_HT("unknown\n"); - return -EINVAL; - break; - } - return 0; -} - #ifdef CONFIG_IWL4965_HT_AGG static const u16 default_tid_to_tx_fifo[] = { @@ -4848,8 +4820,7 @@ int iwl4965_mac_ht_tx_agg_start(struct ieee80211_hw *hw, u8 *da, u16 tid, } -int iwl4965_mac_ht_tx_agg_stop(struct ieee80211_hw *hw, u8 *da, u16 tid, - int generator) +int iwl4965_mac_ht_tx_agg_stop(struct ieee80211_hw *hw, u8 *da, u16 tid) { struct iwl4965_priv *priv = hw->priv; @@ -4891,6 +4862,52 @@ int iwl4965_mac_ht_tx_agg_stop(struct ieee80211_hw *hw, u8 *da, u16 tid, #endif /* CONFIG_IWL4965_HT_AGG */ + +int iwl4965_mac_ht_tx_agg_start(struct ieee80211_hw *hw, const u8 *da, u16 tid, + u16 *start_seq_num) +{ + return 0; +} + +int iwl4965_mac_ht_tx_agg_stop(struct ieee80211_hw *hw, const u8 *da, u16 tid) +{ + return 0; +} + +int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw, + enum ieee80211_ampdu_mlme_action action, + const u8 *addr, u16 tid, u16 *ssn) +{ + struct iwl4965_priv *priv = hw->priv; + int sta_id; + DECLARE_MAC_BUF(mac); + + IWL_DEBUG_HT("A-MPDU action on da=%s tid=%d ", + print_mac(mac, addr), tid); + sta_id = iwl4965_hw_find_station(priv, addr); + switch (action) { + case IEEE80211_AMPDU_RX_START: + IWL_DEBUG_HT("start Rx\n"); + iwl4965_sta_modify_add_ba_tid(priv, sta_id, tid, *ssn); + break; + case IEEE80211_AMPDU_RX_STOP: + IWL_DEBUG_HT("stop Rx\n"); + iwl4965_sta_modify_del_ba_tid(priv, sta_id, tid); + break; + case IEEE80211_AMPDU_TX_START: + IWL_DEBUG_HT("start Tx\n"); + return iwl4965_mac_ht_tx_agg_start(hw, addr, tid, ssn); + case IEEE80211_AMPDU_TX_STOP: + IWL_DEBUG_HT("stop Tx\n"); + return iwl4965_mac_ht_tx_agg_stop(hw, addr, tid); + default: + IWL_DEBUG_HT("unknown\n"); + return -EINVAL; + break; + } + return 0; +} + #endif /* CONFIG_IWL4965_HT */ /* Set up 4965-specific Rx frame reply handlers */ diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index 6edf869d4d54..4992b8a06367 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -779,10 +779,6 @@ extern int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw, enum ieee80211_ampdu_mlme_action action, const u8 *addr, u16 tid, u16 *ssn); #ifdef CONFIG_IWL4965_HT_AGG -extern int iwl4965_mac_ht_tx_agg_start(struct ieee80211_hw *hw, u8 *da, - u16 tid, u16 *start_seq_num); -extern int iwl4965_mac_ht_tx_agg_stop(struct ieee80211_hw *hw, u8 *da, - u16 tid, int generator); extern void iwl4965_turn_off_agg(struct iwl4965_priv *priv, u8 tid); extern void iwl4965_tl_get_stats(struct iwl4965_priv *priv, struct ieee80211_hdr *hdr); diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index a23d4798653b..3f5114f5fe16 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -9021,10 +9021,6 @@ static struct ieee80211_ops iwl4965_hw_ops = { #ifdef CONFIG_IWL4965_HT .conf_ht = iwl4965_mac_conf_ht, .ampdu_action = iwl4965_mac_ampdu_action, -#ifdef CONFIG_IWL4965_HT_AGG - .ht_tx_agg_start = iwl4965_mac_ht_tx_agg_start, - .ht_tx_agg_stop = iwl4965_mac_ht_tx_agg_stop, -#endif /* CONFIG_IWL4965_HT_AGG */ #endif /* CONFIG_IWL4965_HT */ .hw_scan = iwl4965_mac_hw_scan }; -- cgit v1.2.1 From fe01b477bbd23e69c3bdc6bce5be510ddad8297d Mon Sep 17 00:00:00 2001 From: Ron Rindjunsky Date: Mon, 28 Jan 2008 14:07:24 +0200 Subject: iwlwifi: A-MPDU Tx conform flows to mac80211 This patch alters the current iwlwifi behavior to fit the flows introduced by the mac80211, mainly queues handling and start/stop call backs flows Signed-off-by: Ron Rindjunsky Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965-commands.h | 24 +- drivers/net/wireless/iwlwifi/iwl-4965.c | 358 +++++++++++++---------- drivers/net/wireless/iwlwifi/iwl-4965.h | 20 +- drivers/net/wireless/iwlwifi/iwl4965-base.c | 121 ++++---- 4 files changed, 302 insertions(+), 221 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h index f3470c896d9a..9edd8abcf570 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h @@ -1300,6 +1300,25 @@ struct iwl4965_tx_resp { __le32 status; /* TX status (for aggregation status of 1st frame) */ } __attribute__ ((packed)); +struct agg_tx_status { + __le16 status; + __le16 sequence; +} __attribute__ ((packed)); + +struct iwl4965_tx_resp_agg { + u8 frame_count; /* 1 no aggregation, >1 aggregation */ + u8 reserved1; + u8 failure_rts; + u8 failure_frame; + __le32 rate_n_flags; + __le16 wireless_media_time; + __le16 reserved3; + __le32 pa_power1; + __le32 pa_power2; + struct agg_tx_status status; /* TX status (for aggregation status */ + /* of 1st frame) */ +} __attribute__ ((packed)); + /* * REPLY_COMPRESSED_BA = 0xc5 (response only, not a command) * @@ -1313,9 +1332,8 @@ struct iwl4965_compressed_ba_resp { /* Index of recipient (BA-sending) station in uCode's station table */ u8 sta_id; u8 tid; - __le16 ba_seq_ctl; - __le32 ba_bitmap0; - __le32 ba_bitmap1; + __le16 seq_ctl; + __le64 bitmap; __le16 scd_flow; __le16 scd_ssn; } __attribute__ ((packed)); diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 3fc18dc311e9..b315a099d1a0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -79,6 +79,30 @@ const struct iwl4965_rate_info iwl4965_rates[IWL_RATE_COUNT] = { IWL_DECLARE_RATE_INFO(60, 60, 48, INV, 48, INV, 48, INV),/* 60mbps */ }; +#ifdef CONFIG_IWL4965_HT + +static const u16 default_tid_to_tx_fifo[] = { + IWL_TX_FIFO_AC1, + IWL_TX_FIFO_AC0, + IWL_TX_FIFO_AC0, + IWL_TX_FIFO_AC1, + IWL_TX_FIFO_AC2, + IWL_TX_FIFO_AC2, + IWL_TX_FIFO_AC3, + IWL_TX_FIFO_AC3, + IWL_TX_FIFO_NONE, + IWL_TX_FIFO_NONE, + IWL_TX_FIFO_NONE, + IWL_TX_FIFO_NONE, + IWL_TX_FIFO_NONE, + IWL_TX_FIFO_NONE, + IWL_TX_FIFO_NONE, + IWL_TX_FIFO_NONE, + IWL_TX_FIFO_AC3 +}; + +#endif /*CONFIG_IWL4965_HT */ + static int is_fat_channel(__le32 rxon_flags) { return (rxon_flags & RXON_FLG_CHANNEL_MODE_PURE_40_MSK) || @@ -4185,6 +4209,7 @@ static void iwl4965_set_tx_status(struct iwl4965_priv *priv, int txq_id, int idx tx_status->control.tx_rate = rate; } +#endif/* CONFIG_IWL4965_HT_AGG */ /** * iwl4965_sta_modify_enable_tid_tx - Enable Tx for this TID in station table @@ -4204,7 +4229,6 @@ static void iwl4965_sta_modify_enable_tid_tx(struct iwl4965_priv *priv, iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, CMD_ASYNC); } - /** * iwl4965_tx_status_reply_compressed_ba - Update tx status from block-ack * @@ -4218,10 +4242,11 @@ static int iwl4965_tx_status_reply_compressed_ba(struct iwl4965_priv *priv, { int i, sh, ack; - u16 ba_seq_ctl = le16_to_cpu(ba_resp->ba_seq_ctl); - u32 bitmap0, bitmap1; - u32 resp_bitmap0 = le32_to_cpu(ba_resp->ba_bitmap0); - u32 resp_bitmap1 = le32_to_cpu(ba_resp->ba_bitmap1); + u16 seq_ctl = le16_to_cpu(ba_resp->seq_ctl); + u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); + u64 bitmap; + int successes = 0; + struct ieee80211_tx_status *tx_status; if (unlikely(!agg->wait_for_ba)) { IWL_ERROR("Received BA when not expected\n"); @@ -4230,17 +4255,15 @@ static int iwl4965_tx_status_reply_compressed_ba(struct iwl4965_priv *priv, /* Mark that the expected block-ack response arrived */ agg->wait_for_ba = 0; - IWL_DEBUG_TX_REPLY("BA %d %d\n", agg->start_idx, ba_resp->ba_seq_ctl); + IWL_DEBUG_TX_REPLY("BA %d %d\n", agg->start_idx, ba_resp->seq_ctl); /* Calculate shift to align block-ack bits with our Tx window bits */ - sh = agg->start_idx - SEQ_TO_INDEX(ba_seq_ctl >> 4); + sh = agg->start_idx - SEQ_TO_INDEX(seq_ctl>>4); if (sh < 0) /* tbw something is wrong with indices */ sh += 0x100; /* don't use 64-bit values for now */ - bitmap0 = resp_bitmap0 >> sh; - bitmap1 = resp_bitmap1 >> sh; - bitmap0 |= (resp_bitmap1 & ((1 << sh) | ((1 << sh) - 1))) << (32 - sh); + bitmap = le64_to_cpu(ba_resp->bitmap) >> sh; if (agg->frame_count > (64 - sh)) { IWL_DEBUG_TX_REPLY("more frames than bitmap size"); @@ -4249,23 +4272,106 @@ static int iwl4965_tx_status_reply_compressed_ba(struct iwl4965_priv *priv, /* check for success or failure according to the * transmitted bitmap and block-ack bitmap */ - bitmap0 &= agg->bitmap0; - bitmap1 &= agg->bitmap1; + bitmap &= agg->bitmap; /* For each frame attempted in aggregation, * update driver's record of tx frame's status. */ for (i = 0; i < agg->frame_count ; i++) { - int idx = (agg->start_idx + i) & 0xff; - ack = bitmap0 & (1 << i); + ack = bitmap & (1 << i); + successes += !!ack; IWL_DEBUG_TX_REPLY("%s ON i=%d idx=%d raw=%d\n", - ack? "ACK":"NACK", i, idx, agg->start_idx + i); - iwl4965_set_tx_status(priv, agg->txq_id, idx, ack, 0, - agg->rate_n_flags); + ack? "ACK":"NACK", i, (agg->start_idx + i) & 0xff, + agg->start_idx + i); + } + + tx_status = &priv->txq[scd_flow].txb[agg->start_idx].status; + tx_status->flags = IEEE80211_TX_STATUS_ACK; + tx_status->retry_count++; +#ifdef CONFIG_IWL4965_HT_AGG + tx_status->flags |= IEEE80211_TX_STATUS_AGG_STATS; + tx_status->successes = successes; + tx_status->frame_count = agg->frame_count; +#endif /* CONFIG_IWL4965_HT_AGG */ + tx_status->control.tx_rate = agg->rate_n_flags; + + IWL_DEBUG_TX_REPLY("Bitmap %llx\n", bitmap); + + return 0; +} + +/** + * iwl4965_tx_queue_stop_scheduler - Stop queue, but keep configuration + */ +static void iwl4965_tx_queue_stop_scheduler(struct iwl4965_priv *priv, + u16 txq_id) +{ + /* Simply stop the queue, but don't change any configuration; + * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */ + iwl4965_write_prph(priv, + KDR_SCD_QUEUE_STATUS_BITS(txq_id), + (0 << SCD_QUEUE_STTS_REG_POS_ACTIVE)| + (1 << SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN)); +} +/** + * txq_id must be greater than IWL_BACK_QUEUE_FIRST_ID + */ +static int iwl4965_tx_queue_agg_disable(struct iwl4965_priv *priv, u16 txq_id, + u16 ssn_idx, u8 tx_fifo) +{ + if (IWL_BACK_QUEUE_FIRST_ID > txq_id) { + IWL_WARNING("queue number too small: %d, must be > %d\n", + txq_id, IWL_BACK_QUEUE_FIRST_ID); + return -EINVAL; } - IWL_DEBUG_TX_REPLY("Bitmap %x%x\n", bitmap0, bitmap1); + iwl4965_tx_queue_stop_scheduler(priv, txq_id); + + iwl4965_clear_bits_prph(priv, KDR_SCD_QUEUECHAIN_SEL, (1 << txq_id)); + + priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff); + priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); + /* supposes that ssn_idx is valid (!= 0xFFF) */ + iwl4965_set_wr_ptrs(priv, txq_id, ssn_idx); + + iwl4965_clear_bits_prph(priv, KDR_SCD_INTERRUPT_MASK, (1 << txq_id)); + iwl4965_txq_ctx_deactivate(priv, txq_id); + iwl4965_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0); + + return 0; +} +int iwl4965_check_empty_hw_queue(struct iwl4965_priv *priv, int sta_id, + u8 tid, int txq_id) +{ + struct iwl4965_queue *q = &priv->txq[txq_id].q; + u8 *addr = priv->stations[sta_id].sta.sta.addr; + struct iwl4965_tid_data *tid_data = &priv->stations[sta_id].tid[tid]; + + switch (priv->stations[sta_id].tid[tid].agg.state) { + case IWL_EMPTYING_HW_QUEUE_DELBA: + /* We are reclaiming the last packet of the */ + /* aggregated HW queue */ + if (txq_id == tid_data->agg.txq_id && + q->read_ptr == q->write_ptr) { + u16 ssn = SEQ_TO_SN(tid_data->seq_number); + int tx_fifo = default_tid_to_tx_fifo[tid]; + IWL_DEBUG_HT("HW queue empty: continue DELBA flow\n"); + iwl4965_tx_queue_agg_disable(priv, txq_id, + ssn, tx_fifo); + tid_data->agg.state = IWL_AGG_OFF; + ieee80211_stop_tx_ba_cb_irqsafe(priv->hw, addr, tid); + } + break; + case IWL_EMPTYING_HW_QUEUE_ADDBA: + /* We are reclaiming the last packet of the queue */ + if (tid_data->tfds_in_queue == 0) { + IWL_DEBUG_HT("HW queue empty: continue ADDBA flow\n"); + tid_data->agg.state = IWL_AGG_ON; + ieee80211_start_tx_ba_cb_irqsafe(priv->hw, addr, tid); + } + break; + } return 0; } @@ -4293,48 +4399,43 @@ static void iwl4965_rx_reply_compressed_ba(struct iwl4965_priv *priv, int index; struct iwl4965_tx_queue *txq = NULL; struct iwl4965_ht_agg *agg; + DECLARE_MAC_BUF(mac); /* "flow" corresponds to Tx queue */ - u16 ba_resp_scd_flow = le16_to_cpu(ba_resp->scd_flow); + u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); /* "ssn" is start of block-ack Tx window, corresponds to index * (in Tx queue's circular buffer) of first TFD/frame in window */ u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn); - if (ba_resp_scd_flow >= ARRAY_SIZE(priv->txq)) { + if (scd_flow >= ARRAY_SIZE(priv->txq)) { IWL_ERROR("BUG_ON scd_flow is bigger than number of queues"); return; } - txq = &priv->txq[ba_resp_scd_flow]; + txq = &priv->txq[scd_flow]; agg = &priv->stations[ba_resp->sta_id].tid[ba_resp->tid].agg; /* Find index just before block-ack window */ index = iwl4965_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd); /* TODO: Need to get this copy more safely - now good for debug */ -/* - { - DECLARE_MAC_BUF(mac); + IWL_DEBUG_TX_REPLY("REPLY_COMPRESSED_BA [%d]Received from %s, " "sta_id = %d\n", agg->wait_for_ba, print_mac(mac, (u8*) &ba_resp->sta_addr_lo32), ba_resp->sta_id); - IWL_DEBUG_TX_REPLY("TID = %d, SeqCtl = %d, bitmap = 0x%X%X, scd_flow = " + IWL_DEBUG_TX_REPLY("TID = %d, SeqCtl = %d, bitmap = 0x%llx, scd_flow = " "%d, scd_ssn = %d\n", ba_resp->tid, - ba_resp->ba_seq_ctl, - ba_resp->ba_bitmap1, - ba_resp->ba_bitmap0, + ba_resp->seq_ctl, + ba_resp->bitmap, ba_resp->scd_flow, ba_resp->scd_ssn); - IWL_DEBUG_TX_REPLY("DAT start_idx = %d, bitmap = 0x%X%X \n", + IWL_DEBUG_TX_REPLY("DAT start_idx = %d, bitmap = 0x%llx \n", agg->start_idx, - agg->bitmap1, - agg->bitmap0); - } -*/ + agg->bitmap); /* Update driver's record of ACK vs. not for each frame in window */ iwl4965_tx_status_reply_compressed_ba(priv, agg, ba_resp); @@ -4342,23 +4443,17 @@ static void iwl4965_rx_reply_compressed_ba(struct iwl4965_priv *priv, /* Release all TFDs before the SSN, i.e. all TFDs in front of * block-ack window (we assume that they've been successfully * transmitted ... if not, it's too late anyway). */ - if (txq->q.read_ptr != (ba_resp_scd_ssn & 0xff)) - iwl4965_tx_queue_reclaim(priv, ba_resp_scd_flow, index); - -} - - -/** - * iwl4965_tx_queue_stop_scheduler - Stop queue, but keep configuration - */ -static void iwl4965_tx_queue_stop_scheduler(struct iwl4965_priv *priv, u16 txq_id) -{ - /* Simply stop the queue, but don't change any configuration; - * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */ - iwl4965_write_prph(priv, - KDR_SCD_QUEUE_STATUS_BITS(txq_id), - (0 << SCD_QUEUE_STTS_REG_POS_ACTIVE)| - (1 << SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN)); + if (txq->q.read_ptr != (ba_resp_scd_ssn & 0xff)) { + int freed = iwl4965_tx_queue_reclaim(priv, scd_flow, index); + priv->stations[ba_resp->sta_id]. + tid[ba_resp->tid].tfds_in_queue -= freed; + if (iwl4965_queue_space(&txq->q) > txq->q.low_mark && + priv->mac80211_registered && + agg->state != IWL_EMPTYING_HW_QUEUE_DELBA) + ieee80211_wake_queue(priv->hw, scd_flow); + iwl4965_check_empty_hw_queue(priv, ba_resp->sta_id, + ba_resp->tid, scd_flow); + } } /** @@ -4388,6 +4483,7 @@ static int iwl4965_tx_queue_set_q2ratid(struct iwl4965_priv *priv, u16 ra_tid, return 0; } + /** * iwl4965_tx_queue_agg_enable - Set up & enable aggregation for selected queue * @@ -4455,48 +4551,6 @@ static int iwl4965_tx_queue_agg_enable(struct iwl4965_priv *priv, int txq_id, return 0; } -/** - * txq_id must be greater than IWL_BACK_QUEUE_FIRST_ID - */ -static int iwl4965_tx_queue_agg_disable(struct iwl4965_priv *priv, u16 txq_id, - u16 ssn_idx, u8 tx_fifo) -{ - unsigned long flags; - int rc; - - if (IWL_BACK_QUEUE_FIRST_ID > txq_id) { - IWL_WARNING("queue number too small: %d, must be > %d\n", - txq_id, IWL_BACK_QUEUE_FIRST_ID); - return -EINVAL; - } - - spin_lock_irqsave(&priv->lock, flags); - rc = iwl4965_grab_nic_access(priv); - if (rc) { - spin_unlock_irqrestore(&priv->lock, flags); - return rc; - } - - iwl4965_tx_queue_stop_scheduler(priv, txq_id); - - iwl4965_clear_bits_prph(priv, KDR_SCD_QUEUECHAIN_SEL, (1 << txq_id)); - - priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff); - priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); - /* supposes that ssn_idx is valid (!= 0xFFF) */ - iwl4965_set_wr_ptrs(priv, txq_id, ssn_idx); - - iwl4965_clear_bits_prph(priv, KDR_SCD_INTERRUPT_MASK, (1 << txq_id)); - iwl4965_txq_ctx_deactivate(priv, txq_id); - iwl4965_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0); - - iwl4965_release_nic_access(priv); - spin_unlock_irqrestore(&priv->lock, flags); - - return 0; -} - -#endif/* CONFIG_IWL4965_HT_AGG */ #endif /* CONFIG_IWL4965_HT */ /** @@ -4730,28 +4784,6 @@ static void iwl4965_sta_modify_del_ba_tid(struct iwl4965_priv *priv, iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, CMD_ASYNC); } -#ifdef CONFIG_IWL4965_HT_AGG - -static const u16 default_tid_to_tx_fifo[] = { - IWL_TX_FIFO_AC1, - IWL_TX_FIFO_AC0, - IWL_TX_FIFO_AC0, - IWL_TX_FIFO_AC1, - IWL_TX_FIFO_AC2, - IWL_TX_FIFO_AC2, - IWL_TX_FIFO_AC3, - IWL_TX_FIFO_AC3, - IWL_TX_FIFO_NONE, - IWL_TX_FIFO_NONE, - IWL_TX_FIFO_NONE, - IWL_TX_FIFO_NONE, - IWL_TX_FIFO_NONE, - IWL_TX_FIFO_NONE, - IWL_TX_FIFO_NONE, - IWL_TX_FIFO_NONE, - IWL_TX_FIFO_AC3 -}; - /* * Find first available (lowest unused) Tx Queue, mark it "active". * Called only when finding queue for aggregation. @@ -4768,69 +4800,78 @@ static int iwl4965_txq_ctx_activate_free(struct iwl4965_priv *priv) return -1; } -int iwl4965_mac_ht_tx_agg_start(struct ieee80211_hw *hw, u8 *da, u16 tid, - u16 *start_seq_num) +static int iwl4965_mac_ht_tx_agg_start(struct ieee80211_hw *hw, const u8 *da, + u16 tid, u16 *start_seq_num) { - struct iwl4965_priv *priv = hw->priv; int sta_id; int tx_fifo; int txq_id; int ssn = -1; + int rc = 0; unsigned long flags; struct iwl4965_tid_data *tid_data; DECLARE_MAC_BUF(mac); - /* Determine Tx DMA/FIFO channel for this Traffic ID */ if (likely(tid < ARRAY_SIZE(default_tid_to_tx_fifo))) tx_fifo = default_tid_to_tx_fifo[tid]; else return -EINVAL; - IWL_WARNING("iwl-AGG iwl4965_mac_ht_tx_agg_start on da=%s" - " tid=%d\n", print_mac(mac, da), tid); + IWL_WARNING("%s on da = %s tid = %d\n", + __func__, print_mac(mac, da), tid); - /* Get index into station table */ sta_id = iwl4965_hw_find_station(priv, da); if (sta_id == IWL_INVALID_STATION) return -ENXIO; - /* Find available Tx queue for aggregation */ + if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_OFF) { + IWL_ERROR("Start AGG when state is not IWL_AGG_OFF !\n"); + return -ENXIO; + } + txq_id = iwl4965_txq_ctx_activate_free(priv); if (txq_id == -1) return -ENXIO; spin_lock_irqsave(&priv->sta_lock, flags); tid_data = &priv->stations[sta_id].tid[tid]; - - /* Get starting sequence number for 1st frame in block ack window. - * We'll use least signif byte as 1st frame's index into Tx queue. */ ssn = SEQ_TO_SN(tid_data->seq_number); tid_data->agg.txq_id = txq_id; spin_unlock_irqrestore(&priv->sta_lock, flags); *start_seq_num = ssn; - - /* Update driver's link quality manager */ - iwl4965_ba_status(priv, tid, BA_STATUS_ACTIVE); - - /* Set up and enable aggregation for selected Tx queue and FIFO */ - return iwl4965_tx_queue_agg_enable(priv, txq_id, tx_fifo, + rc = iwl4965_tx_queue_agg_enable(priv, txq_id, tx_fifo, sta_id, tid, ssn); -} + if (rc) + return rc; + rc = 0; + if (tid_data->tfds_in_queue == 0) { + printk(KERN_ERR "HW queue is empty\n"); + tid_data->agg.state = IWL_AGG_ON; + ieee80211_start_tx_ba_cb_irqsafe(hw, da, tid); + } else { + IWL_DEBUG_HT("HW queue is NOT empty: %d packets in HW queue\n", + tid_data->tfds_in_queue); + tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA; + } + return rc; +} -int iwl4965_mac_ht_tx_agg_stop(struct ieee80211_hw *hw, u8 *da, u16 tid) +static int iwl4965_mac_ht_tx_agg_stop(struct ieee80211_hw *hw, const u8 *da, + u16 tid) { struct iwl4965_priv *priv = hw->priv; int tx_fifo_id, txq_id, sta_id, ssn = -1; struct iwl4965_tid_data *tid_data; - int rc; + int rc, write_ptr, read_ptr; + unsigned long flags; DECLARE_MAC_BUF(mac); if (!da) { - IWL_ERROR("%s: da = NULL\n", __func__); + IWL_ERROR("da = NULL\n"); return -EINVAL; } @@ -4844,33 +4885,44 @@ int iwl4965_mac_ht_tx_agg_stop(struct ieee80211_hw *hw, u8 *da, u16 tid) if (sta_id == IWL_INVALID_STATION) return -ENXIO; + if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_ON) + IWL_WARNING("Stopping AGG while state not IWL_AGG_ON\n"); + tid_data = &priv->stations[sta_id].tid[tid]; ssn = (tid_data->seq_number & IEEE80211_SCTL_SEQ) >> 4; txq_id = tid_data->agg.txq_id; + write_ptr = priv->txq[txq_id].q.write_ptr; + read_ptr = priv->txq[txq_id].q.read_ptr; + + /* The queue is not empty */ + if (write_ptr != read_ptr) { + IWL_DEBUG_HT("Stopping a non empty AGG HW QUEUE\n"); + priv->stations[sta_id].tid[tid].agg.state = + IWL_EMPTYING_HW_QUEUE_DELBA; + return 0; + } + + IWL_DEBUG_HT("HW queue empty\n");; + priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; + spin_lock_irqsave(&priv->lock, flags); + rc = iwl4965_grab_nic_access(priv); + if (rc) { + spin_unlock_irqrestore(&priv->lock, flags); + return rc; + } rc = iwl4965_tx_queue_agg_disable(priv, txq_id, ssn, tx_fifo_id); - /* FIXME: need more safe way to handle error condition */ + iwl4965_release_nic_access(priv); + spin_unlock_irqrestore(&priv->lock, flags); + if (rc) return rc; - iwl4965_ba_status(priv, tid, BA_STATUS_INITIATOR_DELBA); - IWL_DEBUG_INFO("iwl4965_mac_ht_tx_agg_stop on da=%s tid=%d\n", - print_mac(mac, da), tid); + ieee80211_stop_tx_ba_cb_irqsafe(priv->hw, da, tid); - return 0; -} - - -#endif /* CONFIG_IWL4965_HT_AGG */ - -int iwl4965_mac_ht_tx_agg_start(struct ieee80211_hw *hw, const u8 *da, u16 tid, - u16 *start_seq_num) -{ - return 0; -} + IWL_DEBUG_INFO("iwl4965_mac_ht_tx_agg_stop on da=%s tid=%d\n", + print_mac(mac, da), tid); -int iwl4965_mac_ht_tx_agg_stop(struct ieee80211_hw *hw, const u8 *da, u16 tid) -{ return 0; } @@ -4924,9 +4976,7 @@ void iwl4965_hw_rx_handler_setup(struct iwl4965_priv *priv) iwl4965_rx_missed_beacon_notif; #ifdef CONFIG_IWL4965_HT -#ifdef CONFIG_IWL4965_HT_AGG priv->rx_handlers[REPLY_COMPRESSED_BA] = iwl4965_rx_reply_compressed_ba; -#endif /* CONFIG_IWL4965_HT_AGG */ #endif /* CONFIG_IWL4965_HT */ } diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index 4992b8a06367..47c7f3ffe369 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -433,7 +433,6 @@ struct iwl4965_rx_queue { #define IWL_INVALID_VALUE -1 #ifdef CONFIG_IWL4965_HT -#ifdef CONFIG_IWL4965_HT_AGG /** * struct iwl4965_ht_agg -- aggregation status while waiting for block-ack * @txq_id: Tx queue used for Tx attempt @@ -453,19 +452,22 @@ struct iwl4965_ht_agg { u16 frame_count; u16 wait_for_ba; u16 start_idx; - u32 bitmap0; - u32 bitmap1; + u64 bitmap; u32 rate_n_flags; +#define IWL_AGG_OFF 0 +#define IWL_AGG_ON 1 +#define IWL_EMPTYING_HW_QUEUE_ADDBA 2 +#define IWL_EMPTYING_HW_QUEUE_DELBA 3 + u8 state; }; -#endif /* CONFIG_IWL4965_HT_AGG */ + #endif /* CONFIG_IWL4965_HT */ struct iwl4965_tid_data { u16 seq_number; + u16 tfds_in_queue; #ifdef CONFIG_IWL4965_HT -#ifdef CONFIG_IWL4965_HT_AGG struct iwl4965_ht_agg agg; -#endif /* CONFIG_IWL4965_HT_AGG */ #endif /* CONFIG_IWL4965_HT */ }; @@ -743,7 +745,7 @@ extern u8 iwl4965_hw_find_station(struct iwl4965_priv *priv, const u8 *bssid); extern int iwl4965_hw_channel_switch(struct iwl4965_priv *priv, u16 channel); extern int iwl4965_tx_queue_reclaim(struct iwl4965_priv *priv, int txq_id, int index); - +extern int iwl4965_queue_space(const struct iwl4965_queue *q); struct iwl4965_priv; /* @@ -778,6 +780,8 @@ extern void iwl4965_set_ht_add_station(struct iwl4965_priv *priv, u8 index, extern int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw, enum ieee80211_ampdu_mlme_action action, const u8 *addr, u16 tid, u16 *ssn); +extern int iwl4965_check_empty_hw_queue(struct iwl4965_priv *priv, int sta_id, + u8 tid, int txq_id); #ifdef CONFIG_IWL4965_HT_AGG extern void iwl4965_turn_off_agg(struct iwl4965_priv *priv, u8 tid); extern void iwl4965_tl_get_stats(struct iwl4965_priv *priv, @@ -855,7 +859,7 @@ struct iwl4965_agg_control { u32 ba_timeout; struct iwl4965_traffic_load traffic_load[TID_MAX_LOAD_COUNT]; }; -#endif /*CONFIG_IWL4965_HT_AGG */ +#endif /*CONFIG_IWL4965_HT_AGG */ struct iwl4965_lq_mngr { #ifdef CONFIG_IWL4965_HT_AGG diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 3f5114f5fe16..16cb990e06fa 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -205,7 +205,7 @@ static void iwl4965_print_hex_dump(int level, void *p, u32 len) * See more detailed info in iwl-4965-hw.h. ***************************************************/ -static int iwl4965_queue_space(const struct iwl4965_queue *q) +int iwl4965_queue_space(const struct iwl4965_queue *q) { int s = q->read_ptr - q->write_ptr; @@ -2972,11 +2972,10 @@ static int iwl4965_tx_skb(struct iwl4965_priv *priv, __constant_cpu_to_le16(IEEE80211_SCTL_FRAG)); seq_number += 0x10; #ifdef CONFIG_IWL4965_HT -#ifdef CONFIG_IWL4965_HT_AGG /* aggregation is on for this */ - if (ctl->flags & IEEE80211_TXCTL_HT_MPDU_AGG) + if (ctl->flags & IEEE80211_TXCTL_AMPDU) txq_id = priv->stations[sta_id].tid[tid].agg.txq_id; -#endif /* CONFIG_IWL4965_HT_AGG */ + priv->stations[sta_id].tid[tid].tfds_in_queue++; #endif /* CONFIG_IWL4965_HT */ } @@ -3528,10 +3527,10 @@ int iwl4965_tx_queue_reclaim(struct iwl4965_priv *priv, int txq_id, int index) nfreed++; } - if (iwl4965_queue_space(q) > q->low_mark && (txq_id >= 0) && +/* if (iwl4965_queue_space(q) > q->low_mark && (txq_id >= 0) && (txq_id != IWL_CMD_QUEUE_NUM) && priv->mac80211_registered) - ieee80211_wake_queue(priv->hw, txq_id); + ieee80211_wake_queue(priv->hw, txq_id); */ return nfreed; @@ -3550,7 +3549,6 @@ static int iwl4965_is_tx_success(u32 status) * ******************************************************************************/ #ifdef CONFIG_IWL4965_HT -#ifdef CONFIG_IWL4965_HT_AGG static inline int iwl4965_get_ra_sta_id(struct iwl4965_priv *priv, struct ieee80211_hdr *hdr) @@ -3585,11 +3583,11 @@ static inline u32 iwl4965_get_scd_ssn(struct iwl4965_tx_resp *tx_resp) */ static int iwl4965_tx_status_reply_tx(struct iwl4965_priv *priv, struct iwl4965_ht_agg *agg, - struct iwl4965_tx_resp *tx_resp, + struct iwl4965_tx_resp_agg *tx_resp, u16 start_idx) { - u32 status; - __le32 *frame_status = &tx_resp->status; + u16 status; + struct agg_tx_status *frame_status = &tx_resp->status; struct ieee80211_tx_status *tx_status = NULL; struct ieee80211_hdr *hdr = NULL; int i, sh; @@ -3602,26 +3600,25 @@ static int iwl4965_tx_status_reply_tx(struct iwl4965_priv *priv, agg->frame_count = tx_resp->frame_count; agg->start_idx = start_idx; agg->rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags); - agg->bitmap0 = agg->bitmap1 = 0; + agg->bitmap = 0; /* # frames attempted by Tx command */ if (agg->frame_count == 1) { /* Only one frame was attempted; no block-ack will arrive */ - struct iwl4965_tx_queue *txq ; - status = le32_to_cpu(frame_status[0]); + status = le16_to_cpu(frame_status[0].status); + seq = le16_to_cpu(frame_status[0].sequence); + idx = SEQ_TO_INDEX(seq); + txq_id = SEQ_TO_QUEUE(seq); - txq_id = agg->txq_id; - txq = &priv->txq[txq_id]; /* FIXME: code repetition */ - IWL_DEBUG_TX_REPLY("FrameCnt = %d, StartIdx=%d \n", - agg->frame_count, agg->start_idx); + IWL_DEBUG_TX_REPLY("FrameCnt = %d, StartIdx=%d idx=%d\n", + agg->frame_count, agg->start_idx, idx); - tx_status = &(priv->txq[txq_id].txb[txq->q.read_ptr].status); + tx_status = &(priv->txq[txq_id].txb[idx].status); tx_status->retry_count = tx_resp->failure_frame; tx_status->queue_number = status & 0xff; - tx_status->queue_length = tx_resp->bt_kill_count; - tx_status->queue_length |= tx_resp->failure_rts; - + tx_status->queue_length = tx_resp->failure_rts; + tx_status->control.flags &= ~IEEE80211_TXCTL_AMPDU; tx_status->flags = iwl4965_is_tx_success(status)? IEEE80211_TX_STATUS_ACK : 0; tx_status->control.tx_rate = @@ -3642,8 +3639,8 @@ static int iwl4965_tx_status_reply_tx(struct iwl4965_priv *priv, /* Construct bit-map of pending frames within Tx window */ for (i = 0; i < agg->frame_count; i++) { u16 sc; - status = le32_to_cpu(frame_status[i]); - seq = status >> 16; + status = le16_to_cpu(frame_status[i].status); + seq = le16_to_cpu(frame_status[i].sequence); idx = SEQ_TO_INDEX(seq); txq_id = SEQ_TO_QUEUE(seq); @@ -3687,13 +3684,12 @@ static int iwl4965_tx_status_reply_tx(struct iwl4965_priv *priv, start, (u32)(bitmap & 0xFFFFFFFF)); } - agg->bitmap0 = bitmap & 0xFFFFFFFF; - agg->bitmap1 = bitmap >> 32; + agg->bitmap = bitmap; agg->start_idx = start; agg->rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags); - IWL_DEBUG_TX_REPLY("Frames %d start_idx=%d bitmap=0x%x\n", + IWL_DEBUG_TX_REPLY("Frames %d start_idx=%d bitmap=0x%llx\n", agg->frame_count, agg->start_idx, - agg->bitmap0); + agg->bitmap); if (bitmap) agg->wait_for_ba = 1; @@ -3701,7 +3697,6 @@ static int iwl4965_tx_status_reply_tx(struct iwl4965_priv *priv, return 0; } #endif -#endif /** * iwl4965_rx_reply_tx - Handle standard (non-aggregation) Tx response @@ -3718,9 +3713,9 @@ static void iwl4965_rx_reply_tx(struct iwl4965_priv *priv, struct iwl4965_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; u32 status = le32_to_cpu(tx_resp->status); #ifdef CONFIG_IWL4965_HT -#ifdef CONFIG_IWL4965_HT_AGG - int tid, sta_id; -#endif + int tid = MAX_TID_COUNT, sta_id = IWL_INVALID_STATION; + struct ieee80211_hdr *hdr; + __le16 *qc; #endif if ((index >= txq->q.n_bd) || (x2_queue_used(&txq->q, index) == 0)) { @@ -3732,44 +3727,51 @@ static void iwl4965_rx_reply_tx(struct iwl4965_priv *priv, } #ifdef CONFIG_IWL4965_HT -#ifdef CONFIG_IWL4965_HT_AGG + hdr = iwl4965_tx_queue_get_hdr(priv, txq_id, index); + qc = ieee80211_get_qos_ctrl(hdr); + + if (qc) + tid = le16_to_cpu(*qc) & 0xf; + + sta_id = iwl4965_get_ra_sta_id(priv, hdr); + if (txq->sched_retry && unlikely(sta_id == IWL_INVALID_STATION)) { + IWL_ERROR("Station not known\n"); + return; + } + if (txq->sched_retry) { const u32 scd_ssn = iwl4965_get_scd_ssn(tx_resp); - struct ieee80211_hdr *hdr = - iwl4965_tx_queue_get_hdr(priv, txq_id, index); struct iwl4965_ht_agg *agg = NULL; - __le16 *qc = ieee80211_get_qos_ctrl(hdr); - if (qc == NULL) { - IWL_ERROR("BUG_ON qc is null!!!!\n"); + if (!qc) return; - } - - tid = le16_to_cpu(*qc) & 0xf; - - sta_id = iwl4965_get_ra_sta_id(priv, hdr); - if (unlikely(sta_id == IWL_INVALID_STATION)) { - IWL_ERROR("Station not known for\n"); - return; - } agg = &priv->stations[sta_id].tid[tid].agg; - iwl4965_tx_status_reply_tx(priv, agg, tx_resp, index); + iwl4965_tx_status_reply_tx(priv, agg, + (struct iwl4965_tx_resp_agg *)tx_resp, index); if ((tx_resp->frame_count == 1) && !iwl4965_is_tx_success(status)) { /* TODO: send BAR */ } - if ((txq->q.read_ptr != (scd_ssn & 0xff))) { + if (txq->q.read_ptr != (scd_ssn & 0xff)) { + int freed; index = iwl4965_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd); IWL_DEBUG_TX_REPLY("Retry scheduler reclaim scd_ssn " "%d index %d\n", scd_ssn , index); - iwl4965_tx_queue_reclaim(priv, txq_id, index); + freed = iwl4965_tx_queue_reclaim(priv, txq_id, index); + priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; + + if (iwl4965_queue_space(&txq->q) > txq->q.low_mark && + txq_id >= 0 && priv->mac80211_registered && + agg->state != IWL_EMPTYING_HW_QUEUE_DELBA) + ieee80211_wake_queue(priv->hw, txq_id); + + iwl4965_check_empty_hw_queue(priv, sta_id, tid, txq_id); } } else { -#endif /* CONFIG_IWL4965_HT_AGG */ #endif /* CONFIG_IWL4965_HT */ tx_status = &(txq->txb[txq->q.read_ptr].status); @@ -3790,12 +3792,21 @@ static void iwl4965_rx_reply_tx(struct iwl4965_priv *priv, tx_resp->failure_frame); IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index); - if (index != -1) - iwl4965_tx_queue_reclaim(priv, txq_id, index); + if (index != -1) { + int freed = iwl4965_tx_queue_reclaim(priv, txq_id, index); +#ifdef CONFIG_IWL4965_HT + if (tid != MAX_TID_COUNT) + priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; + if (iwl4965_queue_space(&txq->q) > txq->q.low_mark && + (txq_id >= 0) && + priv->mac80211_registered) + ieee80211_wake_queue(priv->hw, txq_id); + if (tid != MAX_TID_COUNT) + iwl4965_check_empty_hw_queue(priv, sta_id, tid, txq_id); +#endif + } #ifdef CONFIG_IWL4965_HT -#ifdef CONFIG_IWL4965_HT_AGG } -#endif /* CONFIG_IWL4965_HT_AGG */ #endif /* CONFIG_IWL4965_HT */ if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK)) @@ -9089,10 +9100,8 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e /* Default value; 4 EDCA QOS priorities */ hw->queues = 4; #ifdef CONFIG_IWL4965_HT -#ifdef CONFIG_IWL4965_HT_AGG /* Enhanced value; more queues, to support 11n aggregation */ hw->queues = 16; -#endif /* CONFIG_IWL4965_HT_AGG */ #endif /* CONFIG_IWL4965_HT */ spin_lock_init(&priv->lock); -- cgit v1.2.1 From 995564382f9d177214b6ec64db6b9109d4cd41dd Mon Sep 17 00:00:00 2001 From: Ron Rindjunsky Date: Mon, 28 Jan 2008 14:07:25 +0200 Subject: iwlwifi: A-MPDU Tx conform block Ack rate scaling to mac80211 This patch uses the changes in ieee80211_tx_status to pass Block Ack data to rate scaling module, and uses this data in rate scaling calculations Signed-off-by: Ron Rindjunsky Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965-rs.c | 85 ++++++++++++++++++++---------- drivers/net/wireless/iwlwifi/iwl-4965.c | 9 ++-- 2 files changed, 60 insertions(+), 34 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c index d06462264147..f4f2497646bd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c @@ -277,7 +277,8 @@ static void rs_rate_scale_clear_window(struct iwl4965_rate_scale_data *window) * packets. */ static int rs_collect_tx_data(struct iwl4965_rate_scale_data *windows, - int scale_index, s32 tpt, u32 status) + int scale_index, s32 tpt, int retries, + int successes) { struct iwl4965_rate_scale_data *window = NULL; u64 mask; @@ -298,26 +299,33 @@ static int rs_collect_tx_data(struct iwl4965_rate_scale_data *windows, * subtract "1" from the success counter (this is the main reason * we keep these bitmaps!). */ - if (window->counter >= win_size) { - window->counter = win_size - 1; - mask = 1; - mask = (mask << (win_size - 1)); - if ((window->data & mask)) { - window->data &= ~mask; - window->success_counter = window->success_counter - 1; + while (retries > 0) { + if (window->counter >= win_size) { + window->counter = win_size - 1; + mask = 1; + mask = (mask << (win_size - 1)); + if (window->data & mask) { + window->data &= ~mask; + window->success_counter = + window->success_counter - 1; + } } - } - /* Increment frames-attempted counter */ - window->counter = window->counter + 1; + /* Increment frames-attempted counter */ + window->counter++; + + /* Shift bitmap by one frame (throw away oldest history), + * OR in "1", and increment "success" if this + * frame was successful. */ + mask = window->data; + window->data = (mask << 1); + if (successes > 0) { + window->success_counter = window->success_counter + 1; + window->data |= 0x1; + successes--; + } - /* Shift bitmap by one frame (throw away oldest history), - * OR in "1", and increment "success" if this frame was successful. */ - mask = window->data; - window->data = (mask << 1); - if (status != 0) { - window->success_counter = window->success_counter + 1; - window->data |= 0x1; + retries--; } /* Calculate current success ratio, avoid divide-by-0! */ @@ -677,6 +685,11 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1)) return; + /* This packet was aggregated but doesn't carry rate scale info */ + if ((tx_resp->control.flags & IEEE80211_TXCTL_AMPDU) && + !(tx_resp->flags & IEEE80211_TX_STATUS_AMPDU)) + return; + retries = tx_resp->retry_count; if (retries > 15) @@ -766,7 +779,7 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, tpt = search_tbl->expected_tpt[rs_index]; else tpt = 0; - rs_collect_tx_data(search_win, rs_index, tpt, 0); + rs_collect_tx_data(search_win, rs_index, tpt, 1, 0); /* Else if type matches "current/active" table, * add failure to "current/active" history */ @@ -777,7 +790,7 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, tpt = curr_tbl->expected_tpt[rs_index]; else tpt = 0; - rs_collect_tx_data(window, rs_index, tpt, 0); + rs_collect_tx_data(window, rs_index, tpt, 1, 0); } /* If not searching for a new mode, increment failed counter @@ -818,9 +831,13 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, tpt = search_tbl->expected_tpt[rs_index]; else tpt = 0; - rs_collect_tx_data(search_win, - rs_index, tpt, status); - + if (tx_resp->control.flags & IEEE80211_TXCTL_AMPDU) + rs_collect_tx_data(search_win, rs_index, tpt, + tx_resp->ampdu_ack_len, + tx_resp->ampdu_ack_map); + else + rs_collect_tx_data(search_win, rs_index, tpt, + 1, status); /* Else if type matches "current/active" table, * add final tx status to "current/active" history */ } else if ((tbl_type.lq_type == curr_tbl->lq_type) && @@ -830,16 +847,28 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, tpt = curr_tbl->expected_tpt[rs_index]; else tpt = 0; - rs_collect_tx_data(window, rs_index, tpt, status); + if (tx_resp->control.flags & IEEE80211_TXCTL_AMPDU) + rs_collect_tx_data(window, rs_index, tpt, + tx_resp->ampdu_ack_len, + tx_resp->ampdu_ack_map); + else + rs_collect_tx_data(window, rs_index, tpt, + 1, status); } /* If not searching for new mode, increment success/failed counter * ... these help determine when to start searching again */ if (lq_sta->stay_in_tbl) { - if (status) - lq_sta->total_success++; - else - lq_sta->total_failed++; + if (tx_resp->control.flags & IEEE80211_TXCTL_AMPDU) { + lq_sta->total_success += tx_resp->ampdu_ack_map; + lq_sta->total_failed += + (tx_resp->ampdu_ack_len - tx_resp->ampdu_ack_map); + } else { + if (status) + lq_sta->total_success++; + else + lq_sta->total_failed++; + } } /* See if there's a better rate or modulation mode to try. */ diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index b315a099d1a0..89aff4aae45f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -4286,12 +4286,9 @@ static int iwl4965_tx_status_reply_compressed_ba(struct iwl4965_priv *priv, tx_status = &priv->txq[scd_flow].txb[agg->start_idx].status; tx_status->flags = IEEE80211_TX_STATUS_ACK; - tx_status->retry_count++; -#ifdef CONFIG_IWL4965_HT_AGG - tx_status->flags |= IEEE80211_TX_STATUS_AGG_STATS; - tx_status->successes = successes; - tx_status->frame_count = agg->frame_count; -#endif /* CONFIG_IWL4965_HT_AGG */ + tx_status->flags |= IEEE80211_TX_STATUS_AMPDU; + tx_status->ampdu_ack_map = successes; + tx_status->ampdu_ack_len = agg->frame_count; tx_status->control.tx_rate = agg->rate_n_flags; IWL_DEBUG_TX_REPLY("Bitmap %llx\n", bitmap); -- cgit v1.2.1 From 0c11b4de5d81771ba0fdc8a5d13d59ed01d41252 Mon Sep 17 00:00:00 2001 From: Ron Rindjunsky Date: Mon, 28 Jan 2008 14:07:26 +0200 Subject: iwlwifi: A-MPDU Tx activation by load measures This patch gives a heuristic for activation of the A-MPDU Tx. As the rate scaling is rate aware, it now also measures estimated load, and sends A-MPDU activation after a threshold has been met. Signed-off-by: Ron Rindjunsky Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965-rs.c | 204 ++++++++++++-- drivers/net/wireless/iwlwifi/iwl-4965-rs.h | 12 + drivers/net/wireless/iwlwifi/iwl-4965.c | 396 ---------------------------- drivers/net/wireless/iwlwifi/iwl-4965.h | 54 +--- drivers/net/wireless/iwlwifi/iwl4965-base.c | 20 -- 5 files changed, 199 insertions(+), 487 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c index f4f2497646bd..660671f17a3b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c @@ -83,7 +83,7 @@ struct iwl4965_rate_scale_data { /** * struct iwl4965_scale_tbl_info -- tx params and success history for all rates * - * There are two of these in struct iwl_rate_scale_priv, + * There are two of these in struct iwl4965_lq_sta, * one for "active", and one for "search". */ struct iwl4965_scale_tbl_info { @@ -98,8 +98,23 @@ struct iwl4965_scale_tbl_info { struct iwl4965_rate_scale_data win[IWL_RATE_COUNT]; /* rate histories */ }; +#ifdef CONFIG_IWL4965_HT + +struct iwl4965_traffic_load { + unsigned long time_stamp; /* age of the oldest statistics */ + u32 packet_count[TID_QUEUE_MAX_SIZE]; /* packet count in this time + * slice */ + u32 total; /* total num of packets during the + * last TID_MAX_TIME_DIFF */ + u8 queue_count; /* number of queues that has + * been used since the last cleanup */ + u8 head; /* start of the circular buffer */ +}; + +#endif /* CONFIG_IWL4965_HT */ + /** - * struct iwl_rate_scale_priv -- driver's rate scaling private structure + * struct iwl4965_lq_sta -- driver's rate scaling private structure * * Pointer to this gets passed back and forth between driver and mac80211. */ @@ -136,9 +151,16 @@ struct iwl4965_lq_sta { struct iwl4965_link_quality_cmd lq; struct iwl4965_scale_tbl_info lq_info[LQ_SIZE]; /* "active", "search" */ +#ifdef CONFIG_IWL4965_HT + struct iwl4965_traffic_load load[TID_MAX_LOAD_COUNT]; + u8 tx_agg_tid_en; +#endif #ifdef CONFIG_MAC80211_DEBUGFS struct dentry *rs_sta_dbgfs_scale_table_file; struct dentry *rs_sta_dbgfs_stats_table_file; +#ifdef CONFIG_IWL4965_HT + struct dentry *rs_sta_dbgfs_tx_agg_tid_en_file; +#endif struct iwl4965_rate dbg_fixed; struct iwl4965_priv *drv; #endif @@ -269,6 +291,135 @@ static void rs_rate_scale_clear_window(struct iwl4965_rate_scale_data *window) window->stamp = 0; } +#ifdef CONFIG_IWL4965_HT +/* + * removes the old data from the statistics. All data that is older than + * TID_MAX_TIME_DIFF, will be deleted. + */ +static void rs_tl_rm_old_stats(struct iwl4965_traffic_load *tl, u32 curr_time) +{ + /* The oldest age we want to keep */ + u32 oldest_time = curr_time - TID_MAX_TIME_DIFF; + + while (tl->queue_count && + (tl->time_stamp < oldest_time)) { + tl->total -= tl->packet_count[tl->head]; + tl->packet_count[tl->head] = 0; + tl->time_stamp += TID_QUEUE_CELL_SPACING; + tl->queue_count--; + tl->head++; + if (tl->head >= TID_QUEUE_MAX_SIZE) + tl->head = 0; + } +} + +/* + * increment traffic load value for tid and also remove + * any old values if passed the certain time period + */ +static void rs_tl_add_packet(struct iwl4965_lq_sta *lq_data, u8 tid) +{ + u32 curr_time = jiffies_to_msecs(jiffies); + u32 time_diff; + s32 index; + struct iwl4965_traffic_load *tl = NULL; + + if (tid >= TID_MAX_LOAD_COUNT) + return; + + tl = &lq_data->load[tid]; + + curr_time -= curr_time % TID_ROUND_VALUE; + + /* Happens only for the first packet. Initialize the data */ + if (!(tl->queue_count)) { + tl->total = 1; + tl->time_stamp = curr_time; + tl->queue_count = 1; + tl->head = 0; + tl->packet_count[0] = 1; + return; + } + + time_diff = TIME_WRAP_AROUND(tl->time_stamp, curr_time); + index = time_diff / TID_QUEUE_CELL_SPACING; + + /* The history is too long: remove data that is older than */ + /* TID_MAX_TIME_DIFF */ + if (index >= TID_QUEUE_MAX_SIZE) + rs_tl_rm_old_stats(tl, curr_time); + + index = (tl->head + index) % TID_QUEUE_MAX_SIZE; + tl->packet_count[index] = tl->packet_count[index] + 1; + tl->total = tl->total + 1; + + if ((index + 1) > tl->queue_count) + tl->queue_count = index + 1; +} + +/* + get the traffic load value for tid +*/ +static u32 rs_tl_get_load(struct iwl4965_lq_sta *lq_data, u8 tid) +{ + u32 curr_time = jiffies_to_msecs(jiffies); + u32 time_diff; + s32 index; + struct iwl4965_traffic_load *tl = NULL; + + if (tid >= TID_MAX_LOAD_COUNT) + return 0; + + tl = &(lq_data->load[tid]); + + curr_time -= curr_time % TID_ROUND_VALUE; + + if (!(tl->queue_count)) + return 0; + + time_diff = TIME_WRAP_AROUND(tl->time_stamp, curr_time); + index = time_diff / TID_QUEUE_CELL_SPACING; + + /* The history is too long: remove data that is older than */ + /* TID_MAX_TIME_DIFF */ + if (index >= TID_QUEUE_MAX_SIZE) + rs_tl_rm_old_stats(tl, curr_time); + + return tl->total; +} + +static void rs_tl_turn_on_agg_for_tid(struct iwl4965_priv *priv, + struct iwl4965_lq_sta *lq_data, u8 tid, + struct sta_info *sta) +{ + unsigned long state; + DECLARE_MAC_BUF(mac); + + spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); + state = sta->ampdu_mlme.tid_tx[tid].state; + spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); + + if (state == HT_AGG_STATE_IDLE && + rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) { + IWL_DEBUG_HT("Starting Tx agg: STA: %s tid: %d\n", + print_mac(mac, sta->addr), tid); + ieee80211_start_tx_ba_session(priv->hw, sta->addr, tid); + } +} + +static void rs_tl_turn_on_agg(struct iwl4965_priv *priv, u8 tid, + struct iwl4965_lq_sta *lq_data, + struct sta_info *sta) +{ + if ((tid < TID_MAX_LOAD_COUNT)) + rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta); + else if (tid == IWL_AGG_ALL_TID) + for (tid = 0; tid < TID_MAX_LOAD_COUNT; tid++) + rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta); +} + +#endif /* CONFIG_IWLWIFI_HT */ + /** * rs_collect_tx_data - Update the success/failure sliding window * @@ -1134,7 +1285,7 @@ static int rs_switch_to_mimo(struct iwl4965_priv *priv, return 0; #else return -1; -#endif /*CONFIG_IWL4965_HT */ +#endif /*CONFIG_IWL4965_HT */ } /* @@ -1197,7 +1348,7 @@ static int rs_switch_to_siso(struct iwl4965_priv *priv, #else return -1; -#endif /*CONFIG_IWL4965_HT */ +#endif /*CONFIG_IWL4965_HT */ } /* @@ -1354,6 +1505,7 @@ static int rs_move_siso_to_other(struct iwl4965_priv *priv, break; case IWL_SISO_SWITCH_GI: IWL_DEBUG_HT("LQ: SISO SWITCH TO GI\n"); + memcpy(search_tbl, tbl, sz); search_tbl->action = 0; if (search_tbl->is_SGI) @@ -1419,6 +1571,7 @@ static int rs_move_mimo_to_other(struct iwl4965_priv *priv, case IWL_MIMO_SWITCH_ANTENNA_B: IWL_DEBUG_HT("LQ: MIMO SWITCH TO SISO\n"); + /* Set up new search table for SISO */ memcpy(search_tbl, tbl, sz); search_tbl->lq_type = LQ_SISO; @@ -1603,6 +1756,10 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv, u8 active_tbl = 0; u8 done_search = 0; u16 high_low; +#ifdef CONFIG_IWL4965_HT + u8 tid = MAX_TID_COUNT; + __le16 *qc; +#endif IWL_DEBUG_RATE("rate scale calculate new rate for skb\n"); @@ -1623,6 +1780,13 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv, } lq_sta = (struct iwl4965_lq_sta *)sta->rate_ctrl_priv; +#ifdef CONFIG_IWL4965_HT + qc = ieee80211_get_qos_ctrl(hdr); + if (qc) { + tid = (u8)(le16_to_cpu(*qc) & 0xf); + rs_tl_add_packet(lq_sta, tid); + } +#endif /* * Select rate-scale / modulation-mode table to work with in * the rest of this function: "search" if searching for better @@ -1943,15 +2107,14 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv, * mode for a while before next round of mode comparisons. */ if (lq_sta->enable_counter && (lq_sta->action_counter >= IWL_ACTION_LIMIT)) { -#ifdef CONFIG_IWL4965_HT_AGG - /* If appropriate, set up aggregation! */ - if ((lq_sta->last_tpt > TID_AGG_TPT_THREHOLD) && - (priv->lq_mngr.agg_ctrl.auto_agg)) { - priv->lq_mngr.agg_ctrl.tid_retry = - TID_ALL_SPECIFIED; - schedule_work(&priv->agg_work); +#ifdef CONFIG_IWL4965_HT + if ((lq_sta->last_tpt > IWL_AGG_TPT_THREHOLD) && + (lq_sta->tx_agg_tid_en & (1 << tid)) && + (tid != MAX_TID_COUNT)) { + IWL_DEBUG_HT("try to aggregate tid %d\n", tid); + rs_tl_turn_on_agg(priv, tid, lq_sta, sta); } -#endif /*CONFIG_IWL4965_HT_AGG */ +#endif /*CONFIG_IWL4965_HT */ lq_sta->action_counter = 0; rs_set_stay_in_table(0, lq_sta); } @@ -2209,6 +2372,8 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, IWL_DEBUG_HT("SISO RATE 0x%X MIMO RATE 0x%X\n", lq_sta->active_siso_rate, lq_sta->active_mimo_rate); + /* as default allow aggregation for all tids */ + lq_sta->tx_agg_tid_en = IWL_AGG_ALL_TID; #endif /*CONFIG_IWL4965_HT*/ #ifdef CONFIG_MAC80211_DEBUGFS lq_sta->drv = priv; @@ -2352,12 +2517,6 @@ static void rs_clear(void *priv_rate) IWL_DEBUG_RATE("enter\n"); priv->lq_mngr.lq_ready = 0; -#ifdef CONFIG_IWL4965_HT -#ifdef CONFIG_IWL4965_HT_AGG - if (priv->lq_mngr.agg_ctrl.granted_ba) - iwl4965_turn_off_agg(priv, TID_ALL_SPECIFIED); -#endif /*CONFIG_IWL4965_HT_AGG */ -#endif /* CONFIG_IWL4965_HT */ IWL_DEBUG_RATE("leave\n"); } @@ -2524,6 +2683,12 @@ static void rs_add_debugfs(void *priv, void *priv_sta, lq_sta->rs_sta_dbgfs_stats_table_file = debugfs_create_file("rate_stats_table", 0600, dir, lq_sta, &rs_sta_dbgfs_stats_table_ops); +#ifdef CONFIG_IWL4965_HT + lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file = + debugfs_create_u8("tx_agg_tid_enable", 0600, dir, + &lq_sta->tx_agg_tid_en); +#endif + } static void rs_remove_debugfs(void *priv, void *priv_sta) @@ -2531,6 +2696,9 @@ static void rs_remove_debugfs(void *priv, void *priv_sta) struct iwl4965_lq_sta *lq_sta = priv_sta; debugfs_remove(lq_sta->rs_sta_dbgfs_scale_table_file); debugfs_remove(lq_sta->rs_sta_dbgfs_stats_table_file); +#ifdef CONFIG_IWL4965_HT + debugfs_remove(lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file); +#endif } #endif diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.h b/drivers/net/wireless/iwlwifi/iwl-4965-rs.h index 55f707382787..13b6c72eeb73 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.h @@ -212,6 +212,18 @@ enum { #define LQ_SIZE 2 /* 2 mode tables: "Active" and "Search" */ +/* load per tid defines for A-MPDU activation */ +#define IWL_AGG_TPT_THREHOLD 0 +#define IWL_AGG_LOAD_THRESHOLD 10 +#define IWL_AGG_ALL_TID 0xff +#define TID_QUEUE_CELL_SPACING 50 /*mS */ +#define TID_QUEUE_MAX_SIZE 20 +#define TID_ROUND_VALUE 5 /* mS */ +#define TID_MAX_LOAD_COUNT 8 + +#define TID_MAX_TIME_DIFF ((TID_QUEUE_MAX_SIZE - 1) * TID_QUEUE_CELL_SPACING) +#define TIME_WRAP_AROUND(x, y) (((y) > (x)) ? (y) - (x) : (0-(x)) + (y)) + extern const struct iwl4965_rate_info iwl4965_rates[IWL_RATE_COUNT]; enum iwl4965_table_type { diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 89aff4aae45f..e81120cc45f3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2946,378 +2946,6 @@ void iwl4965_set_rxon_chain(struct iwl4965_priv *priv) IWL_DEBUG_ASSOC("rx chain %X\n", priv->staging_rxon.rx_chain); } -#ifdef CONFIG_IWL4965_HT -#ifdef CONFIG_IWL4965_HT_AGG -/* - get the traffic load value for tid -*/ -static u32 iwl4965_tl_get_load(struct iwl4965_priv *priv, u8 tid) -{ - u32 load = 0; - u32 current_time = jiffies_to_msecs(jiffies); - u32 time_diff; - s32 index; - unsigned long flags; - struct iwl4965_traffic_load *tid_ptr = NULL; - - if (tid >= TID_MAX_LOAD_COUNT) - return 0; - - tid_ptr = &(priv->lq_mngr.agg_ctrl.traffic_load[tid]); - - current_time -= current_time % TID_ROUND_VALUE; - - spin_lock_irqsave(&priv->lq_mngr.lock, flags); - if (!(tid_ptr->queue_count)) - goto out; - - time_diff = TIME_WRAP_AROUND(tid_ptr->time_stamp, current_time); - index = time_diff / TID_QUEUE_CELL_SPACING; - - if (index >= TID_QUEUE_MAX_SIZE) { - u32 oldest_time = current_time - TID_MAX_TIME_DIFF; - - while (tid_ptr->queue_count && - (tid_ptr->time_stamp < oldest_time)) { - tid_ptr->total -= tid_ptr->packet_count[tid_ptr->head]; - tid_ptr->packet_count[tid_ptr->head] = 0; - tid_ptr->time_stamp += TID_QUEUE_CELL_SPACING; - tid_ptr->queue_count--; - tid_ptr->head++; - if (tid_ptr->head >= TID_QUEUE_MAX_SIZE) - tid_ptr->head = 0; - } - } - load = tid_ptr->total; - - out: - spin_unlock_irqrestore(&priv->lq_mngr.lock, flags); - return load; -} - -/* - increment traffic load value for tid and also remove - any old values if passed the certian time period -*/ -static void iwl4965_tl_add_packet(struct iwl4965_priv *priv, u8 tid) -{ - u32 current_time = jiffies_to_msecs(jiffies); - u32 time_diff; - s32 index; - unsigned long flags; - struct iwl4965_traffic_load *tid_ptr = NULL; - - if (tid >= TID_MAX_LOAD_COUNT) - return; - - tid_ptr = &(priv->lq_mngr.agg_ctrl.traffic_load[tid]); - - current_time -= current_time % TID_ROUND_VALUE; - - spin_lock_irqsave(&priv->lq_mngr.lock, flags); - if (!(tid_ptr->queue_count)) { - tid_ptr->total = 1; - tid_ptr->time_stamp = current_time; - tid_ptr->queue_count = 1; - tid_ptr->head = 0; - tid_ptr->packet_count[0] = 1; - goto out; - } - - time_diff = TIME_WRAP_AROUND(tid_ptr->time_stamp, current_time); - index = time_diff / TID_QUEUE_CELL_SPACING; - - if (index >= TID_QUEUE_MAX_SIZE) { - u32 oldest_time = current_time - TID_MAX_TIME_DIFF; - - while (tid_ptr->queue_count && - (tid_ptr->time_stamp < oldest_time)) { - tid_ptr->total -= tid_ptr->packet_count[tid_ptr->head]; - tid_ptr->packet_count[tid_ptr->head] = 0; - tid_ptr->time_stamp += TID_QUEUE_CELL_SPACING; - tid_ptr->queue_count--; - tid_ptr->head++; - if (tid_ptr->head >= TID_QUEUE_MAX_SIZE) - tid_ptr->head = 0; - } - } - - index = (tid_ptr->head + index) % TID_QUEUE_MAX_SIZE; - tid_ptr->packet_count[index] = tid_ptr->packet_count[index] + 1; - tid_ptr->total = tid_ptr->total + 1; - - if ((index + 1) > tid_ptr->queue_count) - tid_ptr->queue_count = index + 1; - out: - spin_unlock_irqrestore(&priv->lq_mngr.lock, flags); - -} - -#define MMAC_SCHED_MAX_NUMBER_OF_HT_BACK_FLOWS 7 -enum HT_STATUS { - BA_STATUS_FAILURE = 0, - BA_STATUS_INITIATOR_DELBA, - BA_STATUS_RECIPIENT_DELBA, - BA_STATUS_RENEW_ADDBA_REQUEST, - BA_STATUS_ACTIVE, -}; - -/** - * iwl4964_tl_ba_avail - Find out if an unused aggregation queue is available - */ -static u8 iwl4964_tl_ba_avail(struct iwl4965_priv *priv) -{ - int i; - struct iwl4965_lq_mngr *lq; - u8 count = 0; - u16 msk; - - lq = (struct iwl4965_lq_mngr *)&(priv->lq_mngr); - - /* Find out how many agg queues are in use */ - for (i = 0; i < TID_MAX_LOAD_COUNT ; i++) { - msk = 1 << i; - if ((lq->agg_ctrl.granted_ba & msk) || - (lq->agg_ctrl.wait_for_agg_status & msk)) - count++; - } - - if (count < MMAC_SCHED_MAX_NUMBER_OF_HT_BACK_FLOWS) - return 1; - - return 0; -} - -static void iwl4965_ba_status(struct iwl4965_priv *priv, - u8 tid, enum HT_STATUS status); - -static int iwl4965_perform_addba(struct iwl4965_priv *priv, u8 tid, u32 length, - u32 ba_timeout) -{ - int rc; - - rc = ieee80211_start_BA_session(priv->hw, priv->bssid, tid); - if (rc) - iwl4965_ba_status(priv, tid, BA_STATUS_FAILURE); - - return rc; -} - -static int iwl4965_perform_delba(struct iwl4965_priv *priv, u8 tid) -{ - int rc; - - rc = ieee80211_stop_BA_session(priv->hw, priv->bssid, tid); - if (rc) - iwl4965_ba_status(priv, tid, BA_STATUS_FAILURE); - - return rc; -} - -static void iwl4965_turn_on_agg_for_tid(struct iwl4965_priv *priv, - struct iwl4965_lq_mngr *lq, - u8 auto_agg, u8 tid) -{ - u32 tid_msk = (1 << tid); - unsigned long flags; - - spin_lock_irqsave(&priv->lq_mngr.lock, flags); -/* - if ((auto_agg) && (!lq->enable_counter)){ - lq->agg_ctrl.next_retry = 0; - lq->agg_ctrl.tid_retry = 0; - spin_unlock_irqrestore(&priv->lq_mngr.lock, flags); - return; - } -*/ - if (!(lq->agg_ctrl.granted_ba & tid_msk) && - (lq->agg_ctrl.requested_ba & tid_msk)) { - u8 available_queues; - u32 load; - - spin_unlock_irqrestore(&priv->lq_mngr.lock, flags); - available_queues = iwl4964_tl_ba_avail(priv); - load = iwl4965_tl_get_load(priv, tid); - - spin_lock_irqsave(&priv->lq_mngr.lock, flags); - if (!available_queues) { - if (auto_agg) - lq->agg_ctrl.tid_retry |= tid_msk; - else { - lq->agg_ctrl.requested_ba &= ~tid_msk; - lq->agg_ctrl.wait_for_agg_status &= ~tid_msk; - } - } else if ((auto_agg) && - ((load <= lq->agg_ctrl.tid_traffic_load_threshold) || - ((lq->agg_ctrl.wait_for_agg_status & tid_msk)))) - lq->agg_ctrl.tid_retry |= tid_msk; - else { - lq->agg_ctrl.wait_for_agg_status |= tid_msk; - spin_unlock_irqrestore(&priv->lq_mngr.lock, flags); - iwl4965_perform_addba(priv, tid, 0x40, - lq->agg_ctrl.ba_timeout); - spin_lock_irqsave(&priv->lq_mngr.lock, flags); - } - } - spin_unlock_irqrestore(&priv->lq_mngr.lock, flags); -} - -static void iwl4965_turn_on_agg(struct iwl4965_priv *priv, u8 tid) -{ - struct iwl4965_lq_mngr *lq; - unsigned long flags; - - lq = (struct iwl4965_lq_mngr *)&(priv->lq_mngr); - - if ((tid < TID_MAX_LOAD_COUNT)) - iwl4965_turn_on_agg_for_tid(priv, lq, lq->agg_ctrl.auto_agg, - tid); - else if (tid == TID_ALL_SPECIFIED) { - if (lq->agg_ctrl.requested_ba) { - for (tid = 0; tid < TID_MAX_LOAD_COUNT; tid++) - iwl4965_turn_on_agg_for_tid(priv, lq, - lq->agg_ctrl.auto_agg, tid); - } else { - spin_lock_irqsave(&priv->lq_mngr.lock, flags); - lq->agg_ctrl.tid_retry = 0; - lq->agg_ctrl.next_retry = 0; - spin_unlock_irqrestore(&priv->lq_mngr.lock, flags); - } - } - -} - -void iwl4965_turn_off_agg(struct iwl4965_priv *priv, u8 tid) -{ - u32 tid_msk; - struct iwl4965_lq_mngr *lq; - unsigned long flags; - - lq = (struct iwl4965_lq_mngr *)&(priv->lq_mngr); - - if ((tid < TID_MAX_LOAD_COUNT)) { - tid_msk = 1 << tid; - spin_lock_irqsave(&priv->lq_mngr.lock, flags); - lq->agg_ctrl.wait_for_agg_status |= tid_msk; - lq->agg_ctrl.requested_ba &= ~tid_msk; - spin_unlock_irqrestore(&priv->lq_mngr.lock, flags); - iwl4965_perform_delba(priv, tid); - } else if (tid == TID_ALL_SPECIFIED) { - spin_lock_irqsave(&priv->lq_mngr.lock, flags); - for (tid = 0; tid < TID_MAX_LOAD_COUNT; tid++) { - tid_msk = 1 << tid; - lq->agg_ctrl.wait_for_agg_status |= tid_msk; - spin_unlock_irqrestore(&priv->lq_mngr.lock, flags); - iwl4965_perform_delba(priv, tid); - spin_lock_irqsave(&priv->lq_mngr.lock, flags); - } - lq->agg_ctrl.requested_ba = 0; - spin_unlock_irqrestore(&priv->lq_mngr.lock, flags); - } -} - -/** - * iwl4965_ba_status - Update driver's link quality mgr with tid's HT status - */ -static void iwl4965_ba_status(struct iwl4965_priv *priv, - u8 tid, enum HT_STATUS status) -{ - struct iwl4965_lq_mngr *lq; - u32 tid_msk = (1 << tid); - unsigned long flags; - - lq = (struct iwl4965_lq_mngr *)&(priv->lq_mngr); - - if ((tid >= TID_MAX_LOAD_COUNT)) - goto out; - - spin_lock_irqsave(&priv->lq_mngr.lock, flags); - switch (status) { - case BA_STATUS_ACTIVE: - if (!(lq->agg_ctrl.granted_ba & tid_msk)) - lq->agg_ctrl.granted_ba |= tid_msk; - break; - default: - if ((lq->agg_ctrl.granted_ba & tid_msk)) - lq->agg_ctrl.granted_ba &= ~tid_msk; - break; - } - - lq->agg_ctrl.wait_for_agg_status &= ~tid_msk; - if (status != BA_STATUS_ACTIVE) { - if (lq->agg_ctrl.auto_agg) { - lq->agg_ctrl.tid_retry |= tid_msk; - lq->agg_ctrl.next_retry = - jiffies + msecs_to_jiffies(500); - } else - lq->agg_ctrl.requested_ba &= ~tid_msk; - } - spin_unlock_irqrestore(&priv->lq_mngr.lock, flags); - out: - return; -} - -static void iwl4965_bg_agg_work(struct work_struct *work) -{ - struct iwl4965_priv *priv = container_of(work, struct iwl4965_priv, - agg_work); - - u32 tid; - u32 retry_tid; - u32 tid_msk; - unsigned long flags; - struct iwl4965_lq_mngr *lq = (struct iwl4965_lq_mngr *)&(priv->lq_mngr); - - spin_lock_irqsave(&priv->lq_mngr.lock, flags); - retry_tid = lq->agg_ctrl.tid_retry; - lq->agg_ctrl.tid_retry = 0; - spin_unlock_irqrestore(&priv->lq_mngr.lock, flags); - - if (retry_tid == TID_ALL_SPECIFIED) - iwl4965_turn_on_agg(priv, TID_ALL_SPECIFIED); - else { - for (tid = 0; tid < TID_MAX_LOAD_COUNT; tid++) { - tid_msk = (1 << tid); - if (retry_tid & tid_msk) - iwl4965_turn_on_agg(priv, tid); - } - } - - spin_lock_irqsave(&priv->lq_mngr.lock, flags); - if (lq->agg_ctrl.tid_retry) - lq->agg_ctrl.next_retry = jiffies + msecs_to_jiffies(500); - spin_unlock_irqrestore(&priv->lq_mngr.lock, flags); - return; -} - -/* TODO: move this functionality to rate scaling */ -void iwl4965_tl_get_stats(struct iwl4965_priv *priv, - struct ieee80211_hdr *hdr) -{ - __le16 *qc = ieee80211_get_qos_ctrl(hdr); - - if (qc && - (priv->iw_mode != IEEE80211_IF_TYPE_IBSS)) { - u8 tid = 0; - tid = (u8) (le16_to_cpu(*qc) & 0xF); - if (tid < TID_MAX_LOAD_COUNT) - iwl4965_tl_add_packet(priv, tid); - } - - if (priv->lq_mngr.agg_ctrl.next_retry && - (time_after(priv->lq_mngr.agg_ctrl.next_retry, jiffies))) { - unsigned long flags; - - spin_lock_irqsave(&priv->lq_mngr.lock, flags); - priv->lq_mngr.agg_ctrl.next_retry = 0; - spin_unlock_irqrestore(&priv->lq_mngr.lock, flags); - schedule_work(&priv->agg_work); - } -} - -#endif /*CONFIG_IWL4965_HT_AGG */ -#endif /* CONFIG_IWL4965_HT */ - /** * sign_extend - Sign extend a value using specified bit as sign-bit * @@ -4191,25 +3819,6 @@ static void iwl4965_rx_missed_beacon_notif(struct iwl4965_priv *priv, } #ifdef CONFIG_IWL4965_HT -#ifdef CONFIG_IWL4965_HT_AGG - -/** - * iwl4965_set_tx_status - Update driver's record of one Tx frame's status - * - * This will get sent to mac80211. - */ -static void iwl4965_set_tx_status(struct iwl4965_priv *priv, int txq_id, int idx, - u32 status, u32 retry_count, u32 rate) -{ - struct ieee80211_tx_status *tx_status = - &(priv->txq[txq_id].txb[idx].status); - - tx_status->flags = status ? IEEE80211_TX_STATUS_ACK : 0; - tx_status->retry_count += retry_count; - tx_status->control.tx_rate = rate; -} - -#endif/* CONFIG_IWL4965_HT_AGG */ /** * iwl4965_sta_modify_enable_tid_tx - Enable Tx for this TID in station table @@ -4984,11 +4593,6 @@ void iwl4965_hw_setup_deferred_work(struct iwl4965_priv *priv) #ifdef CONFIG_IWL4965_SENSITIVITY INIT_WORK(&priv->sensitivity_work, iwl4965_bg_sensitivity_work); #endif -#ifdef CONFIG_IWL4965_HT -#ifdef CONFIG_IWL4965_HT_AGG - INIT_WORK(&priv->agg_work, iwl4965_bg_agg_work); -#endif /* CONFIG_IWL4965_HT_AGG */ -#endif /* CONFIG_IWL4965_HT */ init_timer(&priv->statistics_periodic); priv->statistics_periodic.data = (unsigned long)priv; priv->statistics_periodic.function = iwl4965_bg_statistics_periodic; diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index 47c7f3ffe369..de5c1bf8fc42 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -782,11 +782,6 @@ extern int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw, const u8 *addr, u16 tid, u16 *ssn); extern int iwl4965_check_empty_hw_queue(struct iwl4965_priv *priv, int sta_id, u8 tid, int txq_id); -#ifdef CONFIG_IWL4965_HT_AGG -extern void iwl4965_turn_off_agg(struct iwl4965_priv *priv, u8 tid); -extern void iwl4965_tl_get_stats(struct iwl4965_priv *priv, - struct ieee80211_hdr *hdr); -#endif /* CONFIG_IWL4965_HT_AGG */ #endif /*CONFIG_IWL4965_HT */ /* Structures, enum, and defines specific to the 4965 */ @@ -798,18 +793,6 @@ struct iwl4965_kw { size_t size; }; -#define TID_QUEUE_CELL_SPACING 50 /*mS */ -#define TID_QUEUE_MAX_SIZE 20 -#define TID_ROUND_VALUE 5 /* mS */ -#define TID_MAX_LOAD_COUNT 8 - -#define TID_MAX_TIME_DIFF ((TID_QUEUE_MAX_SIZE - 1) * TID_QUEUE_CELL_SPACING) -#define TIME_WRAP_AROUND(x, y) (((y) > (x)) ? (y) - (x) : (0-(x)) + (y)) - -#define TID_ALL_ENABLED 0x7f -#define TID_ALL_SPECIFIED 0xff -#define TID_AGG_TPT_THREHOLD 0x0 - #define IWL_CHANNEL_WIDTH_20MHZ 0 #define IWL_CHANNEL_WIDTH_40MHZ 1 @@ -834,37 +817,7 @@ struct iwl4965_kw { #define TX_POWER_IWL_ILLEGAL_VOLTAGE -10000 -struct iwl4965_traffic_load { - unsigned long time_stamp; - u32 packet_count[TID_QUEUE_MAX_SIZE]; - u8 queue_count; - u8 head; - u32 total; -}; - -#ifdef CONFIG_IWL4965_HT_AGG -/** - * struct iwl4965_agg_control - * @requested_ba: bit map of tids requesting aggregation/block-ack - * @granted_ba: bit map of tids granted aggregation/block-ack - */ -struct iwl4965_agg_control { - unsigned long next_retry; - u32 wait_for_agg_status; - u32 tid_retry; - u32 requested_ba; - u32 granted_ba; - u8 auto_agg; - u32 tid_traffic_load_threshold; - u32 ba_timeout; - struct iwl4965_traffic_load traffic_load[TID_MAX_LOAD_COUNT]; -}; -#endif /*CONFIG_IWL4965_HT_AGG */ - struct iwl4965_lq_mngr { -#ifdef CONFIG_IWL4965_HT_AGG - struct iwl4965_agg_control agg_ctrl; -#endif spinlock_t lock; s32 max_window_size; s32 *expected_tpt; @@ -877,7 +830,6 @@ struct iwl4965_lq_mngr { u8 lq_ready; }; - /* Sensitivity and chain noise calibration */ #define INTERFERENCE_DATA_AVAILABLE __constant_cpu_to_le32(1) #define INITIALIZATION_VALUE 0xFFFF @@ -1265,11 +1217,7 @@ struct iwl4965_priv { #endif struct work_struct statistics_work; struct timer_list statistics_periodic; - -#ifdef CONFIG_IWL4965_HT_AGG - struct work_struct agg_work; -#endif -}; /*iwl4965_priv */ +}; /*iwl4965_priv */ static inline int iwl4965_is_associated(struct iwl4965_priv *priv) { diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 16cb990e06fa..5f38fc585eda 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -3075,14 +3075,6 @@ static int iwl4965_tx_skb(struct iwl4965_priv *priv, out_cmd->cmd.tx.dram_lsb_ptr = cpu_to_le32(scratch_phys); out_cmd->cmd.tx.dram_msb_ptr = iwl_get_dma_hi_address(scratch_phys); -#ifdef CONFIG_IWL4965_HT_AGG -#ifdef CONFIG_IWL4965_HT - /* TODO: move this functionality to rate scaling */ - iwl4965_tl_get_stats(priv, hdr); -#endif /* CONFIG_IWL4965_HT_AGG */ -#endif /*CONFIG_IWL4965_HT */ - - if (!ieee80211_get_morefrag(hdr)) { txq->need_update = 1; if (qc) { @@ -8102,18 +8094,6 @@ static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw) spin_lock_irqsave(&priv->lock, flags); memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_info)); spin_unlock_irqrestore(&priv->lock, flags); -#ifdef CONFIG_IWL4965_HT_AGG -/* if (priv->lq_mngr.agg_ctrl.granted_ba) - iwl4965_turn_off_agg(priv, TID_ALL_SPECIFIED);*/ - - memset(&(priv->lq_mngr.agg_ctrl), 0, sizeof(struct iwl4965_agg_control)); - priv->lq_mngr.agg_ctrl.tid_traffic_load_threshold = 10; - priv->lq_mngr.agg_ctrl.ba_timeout = 5000; - priv->lq_mngr.agg_ctrl.auto_agg = 1; - - if (priv->lq_mngr.agg_ctrl.auto_agg) - priv->lq_mngr.agg_ctrl.requested_ba = TID_ALL_ENABLED; -#endif /*CONFIG_IWL4965_HT_AGG */ #endif /* CONFIG_IWL4965_HT */ #ifdef CONFIG_IWL4965_QOS -- cgit v1.2.1 From 145de9b693943f052c2c15efbc31b2851fedb6e0 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Sun, 27 Jan 2008 15:06:23 +0200 Subject: iwlwifi: enable 802.11n in Kconfig This patch removes 'IWL4965_HT: depends on n' from iwlwifi's Kconfig 1. 11n is functional so no need to make it invisible in the configuration 2. Latest Johannes patch 'cfg80211 API for channels/bitrates, mac80211 and driver conversion' broke compilation because this config option was invisible - patch fixing it will be provided later Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/Kconfig | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index d1af938b9aa6..9c3fe1835a12 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig @@ -35,7 +35,6 @@ config IWL4965_HT bool "Enable 802.11n HT features in iwl4965 driver" depends on EXPERIMENTAL depends on IWL4965 && IWL4965_QOS - depends on n ---help--- This option enables IEEE 802.11n High Throughput features for the iwl4965 driver. -- cgit v1.2.1 From 194c7ca664065e7671c094c4a7cf32c171426ff4 Mon Sep 17 00:00:00 2001 From: Roel Kluin <12o3l@tiscali.nl> Date: Sat, 2 Feb 2008 20:48:48 +0100 Subject: wireless/iwlwifi/iwl-4965.c: add parentheses '!' has a higher priority than '&': bitanding has no effect. Signed-off-by: Roel Kluin <12o3l@tiscali.nl> Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index e81120cc45f3..0bded8570275 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -4249,7 +4249,7 @@ static u8 iwl4965_is_fat_tx_allowed(struct iwl4965_priv *priv, if (sta_ht_inf) { if ((!sta_ht_inf->ht_supported) || - (!sta_ht_inf->cap & IEEE80211_HT_CAP_SUP_WIDTH)) + (!(sta_ht_inf->cap & IEEE80211_HT_CAP_SUP_WIDTH))) return 0; } -- cgit v1.2.1 From 811aa9cad1bd927999888ab56ed9592519d2fef6 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 3 Feb 2008 15:42:53 +0100 Subject: rt2x00: Update copyright notice Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 2 +- drivers/net/wireless/rt2x00/rt2400pci.h | 2 +- drivers/net/wireless/rt2x00/rt2500pci.c | 2 +- drivers/net/wireless/rt2x00/rt2500pci.h | 2 +- drivers/net/wireless/rt2x00/rt2500usb.c | 2 +- drivers/net/wireless/rt2x00/rt2500usb.h | 2 +- drivers/net/wireless/rt2x00/rt2x00.h | 2 +- drivers/net/wireless/rt2x00/rt2x00config.c | 2 +- drivers/net/wireless/rt2x00/rt2x00debug.c | 2 +- drivers/net/wireless/rt2x00/rt2x00debug.h | 2 +- drivers/net/wireless/rt2x00/rt2x00dev.c | 2 +- drivers/net/wireless/rt2x00/rt2x00dump.h | 2 +- drivers/net/wireless/rt2x00/rt2x00firmware.c | 2 +- drivers/net/wireless/rt2x00/rt2x00lib.h | 2 +- drivers/net/wireless/rt2x00/rt2x00mac.c | 2 +- drivers/net/wireless/rt2x00/rt2x00pci.c | 2 +- drivers/net/wireless/rt2x00/rt2x00pci.h | 2 +- drivers/net/wireless/rt2x00/rt2x00reg.h | 2 +- drivers/net/wireless/rt2x00/rt2x00rfkill.c | 2 +- drivers/net/wireless/rt2x00/rt2x00ring.h | 2 +- drivers/net/wireless/rt2x00/rt2x00usb.c | 2 +- drivers/net/wireless/rt2x00/rt2x00usb.h | 2 +- drivers/net/wireless/rt2x00/rt61pci.c | 2 +- drivers/net/wireless/rt2x00/rt61pci.h | 2 +- drivers/net/wireless/rt2x00/rt73usb.c | 2 +- drivers/net/wireless/rt2x00/rt73usb.h | 2 +- 26 files changed, 26 insertions(+), 26 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index c69f85ed7669..763af7f19b8e 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2007 rt2x00 SourceForge Project + Copyright (C) 2004 - 2008 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2400pci.h b/drivers/net/wireless/rt2x00/rt2400pci.h index 369aac6d0336..3d59d6621145 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.h +++ b/drivers/net/wireless/rt2x00/rt2400pci.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2007 rt2x00 SourceForge Project + Copyright (C) 2004 - 2008 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 91e87b53374f..884e225f7b9f 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2007 rt2x00 SourceForge Project + Copyright (C) 2004 - 2008 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2500pci.h b/drivers/net/wireless/rt2x00/rt2500pci.h index 92ba0902d107..0af130ca23c5 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.h +++ b/drivers/net/wireless/rt2x00/rt2500pci.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2007 rt2x00 SourceForge Project + Copyright (C) 2004 - 2008 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 638c3d243108..bd4bbcc639c3 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2007 rt2x00 SourceForge Project + Copyright (C) 2004 - 2008 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2500usb.h b/drivers/net/wireless/rt2x00/rt2500usb.h index 9e0433722e3d..e9f2cd90da58 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.h +++ b/drivers/net/wireless/rt2x00/rt2500usb.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2007 rt2x00 SourceForge Project + Copyright (C) 2004 - 2008 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 05927b908f80..86e4624a63ea 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2007 rt2x00 SourceForge Project + Copyright (C) 2004 - 2008 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index 07adc576db49..c247ee77b3a3 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2007 rt2x00 SourceForge Project + Copyright (C) 2004 - 2008 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c index b44a9f4b9b7f..d70ce6ec8de8 100644 --- a/drivers/net/wireless/rt2x00/rt2x00debug.c +++ b/drivers/net/wireless/rt2x00/rt2x00debug.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2007 rt2x00 SourceForge Project + Copyright (C) 2004 - 2008 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.h b/drivers/net/wireless/rt2x00/rt2x00debug.h index d37efbd09c41..c4ce895aa1c7 100644 --- a/drivers/net/wireless/rt2x00/rt2x00debug.h +++ b/drivers/net/wireless/rt2x00/rt2x00debug.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2007 rt2x00 SourceForge Project + Copyright (C) 2004 - 2008 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 0d51f478bcdf..57355077fb7c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2007 rt2x00 SourceForge Project + Copyright (C) 2004 - 2008 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00dump.h b/drivers/net/wireless/rt2x00/rt2x00dump.h index 99f3f367adce..93f8967e5dc4 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dump.h +++ b/drivers/net/wireless/rt2x00/rt2x00dump.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2007 rt2x00 SourceForge Project + Copyright (C) 2004 - 2008 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00firmware.c b/drivers/net/wireless/rt2x00/rt2x00firmware.c index 0a475e4e2442..442ff8047dce 100644 --- a/drivers/net/wireless/rt2x00/rt2x00firmware.c +++ b/drivers/net/wireless/rt2x00/rt2x00firmware.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2007 rt2x00 SourceForge Project + Copyright (C) 2004 - 2008 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index 1adbd28e0973..7540d29c47a0 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2007 rt2x00 SourceForge Project + Copyright (C) 2004 - 2008 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index e3f15e518c76..e638c653e094 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2007 rt2x00 SourceForge Project + Copyright (C) 2004 - 2008 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index 804a9980055d..0f2590bc31ec 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2007 rt2x00 SourceForge Project + Copyright (C) 2004 - 2008 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.h b/drivers/net/wireless/rt2x00/rt2x00pci.h index 2d1eb8144da4..9ac560b87b2b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.h +++ b/drivers/net/wireless/rt2x00/rt2x00pci.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2007 rt2x00 SourceForge Project + Copyright (C) 2004 - 2008 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00reg.h b/drivers/net/wireless/rt2x00/rt2x00reg.h index b1915dc7dda1..e99eab19e9d7 100644 --- a/drivers/net/wireless/rt2x00/rt2x00reg.h +++ b/drivers/net/wireless/rt2x00/rt2x00reg.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2007 rt2x00 SourceForge Project + Copyright (C) 2004 - 2008 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00rfkill.c b/drivers/net/wireless/rt2x00/rt2x00rfkill.c index 34a96d44e306..67121427a5bd 100644 --- a/drivers/net/wireless/rt2x00/rt2x00rfkill.c +++ b/drivers/net/wireless/rt2x00/rt2x00rfkill.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2007 rt2x00 SourceForge Project + Copyright (C) 2004 - 2008 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00ring.h b/drivers/net/wireless/rt2x00/rt2x00ring.h index 1caa6d688c40..764c2553d06c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00ring.h +++ b/drivers/net/wireless/rt2x00/rt2x00ring.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2007 rt2x00 SourceForge Project + Copyright (C) 2004 - 2008 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 84e9bdb73910..47cd0a5bf17c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2007 rt2x00 SourceForge Project + Copyright (C) 2004 - 2008 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h index e40df4050cd0..b5c1d176c481 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.h +++ b/drivers/net/wireless/rt2x00/rt2x00usb.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2007 rt2x00 SourceForge Project + Copyright (C) 2004 - 2008 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index e808db98f2f5..42cd1dc09164 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2007 rt2x00 SourceForge Project + Copyright (C) 2004 - 2008 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h index 4c6524eedad0..e4578fbdb361 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.h +++ b/drivers/net/wireless/rt2x00/rt61pci.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2007 rt2x00 SourceForge Project + Copyright (C) 2004 - 2008 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 4fac2d414d84..416e44943e71 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2007 rt2x00 SourceForge Project + Copyright (C) 2004 - 2008 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify diff --git a/drivers/net/wireless/rt2x00/rt73usb.h b/drivers/net/wireless/rt2x00/rt73usb.h index d49dcaacecee..bc635908c470 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.h +++ b/drivers/net/wireless/rt2x00/rt73usb.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2004 - 2007 rt2x00 SourceForge Project + Copyright (C) 2004 - 2008 rt2x00 SourceForge Project This program is free software; you can redistribute it and/or modify -- cgit v1.2.1 From 181d6902b6bad978d157e69479c95cc0ff213a76 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Tue, 5 Feb 2008 16:42:23 -0500 Subject: rt2x00: Queue handling overhaul This introduces a big queue handling overhaul, this also renames "ring" to "queues". Move queue handling into rt2x00queue.c and the matching header, use Kerneldoc to improve rt2x00 library documentation. Access to the queues is now protected under a spinlock, this to prevent race conditions which could corrupt the indexing system of the queue. Each queue entry allocates x bytes for driver/device specific data, this cleans up the queue structure significantly and improves code readability. rt2500usb no longer needs 2 entries in the beacon queue to correctly send out the guardian byte. This is now handled in the entry specific structure. rt61 and rt73 now use the correct descriptor size for beacon frames, since this data is written into the registers not the entire TXD descriptor was used but instead of a subset of it named TXINFO. Finally this also fixes numerous other bugs related to incorrect beacon handling or beacon related code. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/Makefile | 2 +- drivers/net/wireless/rt2x00/rt2400pci.c | 204 ++++++++------ drivers/net/wireless/rt2x00/rt2500pci.c | 199 ++++++++------ drivers/net/wireless/rt2x00/rt2500usb.c | 201 ++++++++------ drivers/net/wireless/rt2x00/rt2x00.h | 133 ++++----- drivers/net/wireless/rt2x00/rt2x00debug.c | 32 +-- drivers/net/wireless/rt2x00/rt2x00dev.c | 403 +++++++-------------------- drivers/net/wireless/rt2x00/rt2x00dump.h | 6 +- drivers/net/wireless/rt2x00/rt2x00lib.h | 10 + drivers/net/wireless/rt2x00/rt2x00mac.c | 55 ++-- drivers/net/wireless/rt2x00/rt2x00pci.c | 223 +++++++-------- drivers/net/wireless/rt2x00/rt2x00pci.h | 49 +++- drivers/net/wireless/rt2x00/rt2x00queue.c | 291 ++++++++++++++++++++ drivers/net/wireless/rt2x00/rt2x00queue.h | 435 ++++++++++++++++++++++++++++++ drivers/net/wireless/rt2x00/rt2x00reg.h | 2 +- drivers/net/wireless/rt2x00/rt2x00ring.h | 290 -------------------- drivers/net/wireless/rt2x00/rt2x00usb.c | 290 +++++++++++--------- drivers/net/wireless/rt2x00/rt2x00usb.h | 48 +++- drivers/net/wireless/rt2x00/rt61pci.c | 256 +++++++++--------- drivers/net/wireless/rt2x00/rt61pci.h | 1 + drivers/net/wireless/rt2x00/rt73usb.c | 134 +++++---- drivers/net/wireless/rt2x00/rt73usb.h | 1 + 22 files changed, 1881 insertions(+), 1384 deletions(-) create mode 100644 drivers/net/wireless/rt2x00/rt2x00queue.c create mode 100644 drivers/net/wireless/rt2x00/rt2x00queue.h delete mode 100644 drivers/net/wireless/rt2x00/rt2x00ring.h (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/Makefile b/drivers/net/wireless/rt2x00/Makefile index 30d654a42eea..ab40e1f6b303 100644 --- a/drivers/net/wireless/rt2x00/Makefile +++ b/drivers/net/wireless/rt2x00/Makefile @@ -1,4 +1,4 @@ -rt2x00lib-objs := rt2x00dev.o rt2x00mac.o rt2x00config.o +rt2x00lib-objs := rt2x00dev.o rt2x00mac.o rt2x00config.o rt2x00queue.o ifeq ($(CONFIG_RT2X00_LIB_DEBUGFS),y) rt2x00lib-objs += rt2x00debug.o diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 763af7f19b8e..fc161084a8d3 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -498,13 +498,13 @@ static void rt2400pci_config(struct rt2x00_dev *rt2x00dev, } static void rt2400pci_config_cw(struct rt2x00_dev *rt2x00dev, - struct ieee80211_tx_queue_params *params) + const int cw_min, const int cw_max) { u32 reg; rt2x00pci_register_read(rt2x00dev, CSR11, ®); - rt2x00_set_field32(®, CSR11_CWMIN, params->cw_min); - rt2x00_set_field32(®, CSR11_CWMAX, params->cw_max); + rt2x00_set_field32(®, CSR11_CWMIN, cw_min); + rt2x00_set_field32(®, CSR11_CWMAX, cw_max); rt2x00pci_register_write(rt2x00dev, CSR11, reg); } @@ -593,90 +593,89 @@ static void rt2400pci_link_tuner(struct rt2x00_dev *rt2x00dev) * Initialization functions. */ static void rt2400pci_init_rxentry(struct rt2x00_dev *rt2x00dev, - struct data_entry *entry) + struct queue_entry *entry) { - __le32 *rxd = entry->priv; + struct queue_entry_priv_pci_rx *priv_rx = entry->priv_data; u32 word; - rt2x00_desc_read(rxd, 2, &word); - rt2x00_set_field32(&word, RXD_W2_BUFFER_LENGTH, entry->ring->data_size); - rt2x00_desc_write(rxd, 2, word); + rt2x00_desc_read(priv_rx->desc, 2, &word); + rt2x00_set_field32(&word, RXD_W2_BUFFER_LENGTH, entry->queue->data_size); + rt2x00_desc_write(priv_rx->desc, 2, word); - rt2x00_desc_read(rxd, 1, &word); - rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, entry->data_dma); - rt2x00_desc_write(rxd, 1, word); + rt2x00_desc_read(priv_rx->desc, 1, &word); + rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, priv_rx->dma); + rt2x00_desc_write(priv_rx->desc, 1, word); - rt2x00_desc_read(rxd, 0, &word); + rt2x00_desc_read(priv_rx->desc, 0, &word); rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1); - rt2x00_desc_write(rxd, 0, word); + rt2x00_desc_write(priv_rx->desc, 0, word); } static void rt2400pci_init_txentry(struct rt2x00_dev *rt2x00dev, - struct data_entry *entry) + struct queue_entry *entry) { - __le32 *txd = entry->priv; + struct queue_entry_priv_pci_tx *priv_tx = entry->priv_data; u32 word; - rt2x00_desc_read(txd, 1, &word); - rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, entry->data_dma); - rt2x00_desc_write(txd, 1, word); + rt2x00_desc_read(priv_tx->desc, 1, &word); + rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, priv_tx->dma); + rt2x00_desc_write(priv_tx->desc, 1, word); - rt2x00_desc_read(txd, 2, &word); - rt2x00_set_field32(&word, TXD_W2_BUFFER_LENGTH, entry->ring->data_size); - rt2x00_desc_write(txd, 2, word); + rt2x00_desc_read(priv_tx->desc, 2, &word); + rt2x00_set_field32(&word, TXD_W2_BUFFER_LENGTH, + entry->queue->data_size); + rt2x00_desc_write(priv_tx->desc, 2, word); - rt2x00_desc_read(txd, 0, &word); + rt2x00_desc_read(priv_tx->desc, 0, &word); rt2x00_set_field32(&word, TXD_W0_VALID, 0); rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0); - rt2x00_desc_write(txd, 0, word); + rt2x00_desc_write(priv_tx->desc, 0, word); } -static int rt2400pci_init_rings(struct rt2x00_dev *rt2x00dev) +static int rt2400pci_init_queues(struct rt2x00_dev *rt2x00dev) { + struct queue_entry_priv_pci_rx *priv_rx; + struct queue_entry_priv_pci_tx *priv_tx; u32 reg; /* * Initialize registers. */ rt2x00pci_register_read(rt2x00dev, TXCSR2, ®); - rt2x00_set_field32(®, TXCSR2_TXD_SIZE, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].desc_size); - rt2x00_set_field32(®, TXCSR2_NUM_TXD, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].stats.limit); - rt2x00_set_field32(®, TXCSR2_NUM_ATIM, - rt2x00dev->bcn[1].stats.limit); - rt2x00_set_field32(®, TXCSR2_NUM_PRIO, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].stats.limit); + rt2x00_set_field32(®, TXCSR2_TXD_SIZE, rt2x00dev->tx[0].desc_size); + rt2x00_set_field32(®, TXCSR2_NUM_TXD, rt2x00dev->tx[1].limit); + rt2x00_set_field32(®, TXCSR2_NUM_ATIM, rt2x00dev->bcn[1].limit); + rt2x00_set_field32(®, TXCSR2_NUM_PRIO, rt2x00dev->tx[0].limit); rt2x00pci_register_write(rt2x00dev, TXCSR2, reg); + priv_tx = rt2x00dev->tx[1].entries[0].priv_data; rt2x00pci_register_read(rt2x00dev, TXCSR3, ®); - rt2x00_set_field32(®, TXCSR3_TX_RING_REGISTER, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].data_dma); + rt2x00_set_field32(®, TXCSR3_TX_RING_REGISTER, priv_tx->dma); rt2x00pci_register_write(rt2x00dev, TXCSR3, reg); + priv_tx = rt2x00dev->tx[0].entries[0].priv_data; rt2x00pci_register_read(rt2x00dev, TXCSR5, ®); - rt2x00_set_field32(®, TXCSR5_PRIO_RING_REGISTER, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].data_dma); + rt2x00_set_field32(®, TXCSR5_PRIO_RING_REGISTER, priv_tx->dma); rt2x00pci_register_write(rt2x00dev, TXCSR5, reg); + priv_tx = rt2x00dev->bcn[1].entries[0].priv_data; rt2x00pci_register_read(rt2x00dev, TXCSR4, ®); - rt2x00_set_field32(®, TXCSR4_ATIM_RING_REGISTER, - rt2x00dev->bcn[1].data_dma); + rt2x00_set_field32(®, TXCSR4_ATIM_RING_REGISTER, priv_tx->dma); rt2x00pci_register_write(rt2x00dev, TXCSR4, reg); + priv_tx = rt2x00dev->bcn[0].entries[0].priv_data; rt2x00pci_register_read(rt2x00dev, TXCSR6, ®); - rt2x00_set_field32(®, TXCSR6_BEACON_RING_REGISTER, - rt2x00dev->bcn[0].data_dma); + rt2x00_set_field32(®, TXCSR6_BEACON_RING_REGISTER, priv_tx->dma); rt2x00pci_register_write(rt2x00dev, TXCSR6, reg); rt2x00pci_register_read(rt2x00dev, RXCSR1, ®); rt2x00_set_field32(®, RXCSR1_RXD_SIZE, rt2x00dev->rx->desc_size); - rt2x00_set_field32(®, RXCSR1_NUM_RXD, rt2x00dev->rx->stats.limit); + rt2x00_set_field32(®, RXCSR1_NUM_RXD, rt2x00dev->rx->limit); rt2x00pci_register_write(rt2x00dev, RXCSR1, reg); + priv_rx = rt2x00dev->rx->entries[0].priv_data; rt2x00pci_register_read(rt2x00dev, RXCSR2, ®); - rt2x00_set_field32(®, RXCSR2_RX_RING_REGISTER, - rt2x00dev->rx->data_dma); + rt2x00_set_field32(®, RXCSR2_RX_RING_REGISTER, priv_tx->dma); rt2x00pci_register_write(rt2x00dev, RXCSR2, reg); return 0; @@ -859,7 +858,7 @@ static int rt2400pci_enable_radio(struct rt2x00_dev *rt2x00dev) /* * Initialize all registers. */ - if (rt2400pci_init_rings(rt2x00dev) || + if (rt2400pci_init_queues(rt2x00dev) || rt2400pci_init_registers(rt2x00dev) || rt2400pci_init_bbp(rt2x00dev)) { ERROR(rt2x00dev, "Register initialization failed.\n"); @@ -986,10 +985,10 @@ static int rt2400pci_set_device_state(struct rt2x00_dev *rt2x00dev, */ static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb, - struct txdata_entry_desc *desc, + struct txentry_desc *txdesc, struct ieee80211_tx_control *control) { - struct skb_desc *skbdesc = get_skb_desc(skb); + struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); __le32 *txd = skbdesc->desc; u32 word; @@ -1001,19 +1000,19 @@ static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_desc_write(txd, 2, word); rt2x00_desc_read(txd, 3, &word); - rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, desc->signal); + rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, txdesc->signal); rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL_REGNUM, 5); rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL_BUSY, 1); - rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, desc->service); + rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, txdesc->service); rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE_REGNUM, 6); rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE_BUSY, 1); rt2x00_desc_write(txd, 3, word); rt2x00_desc_read(txd, 4, &word); - rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_LOW, desc->length_low); + rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_LOW, txdesc->length_low); rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW_REGNUM, 8); rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW_BUSY, 1); - rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_HIGH, desc->length_high); + rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_HIGH, txdesc->length_high); rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH_REGNUM, 7); rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH_BUSY, 1); rt2x00_desc_write(txd, 4, word); @@ -1022,14 +1021,14 @@ static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 1); rt2x00_set_field32(&word, TXD_W0_VALID, 1); rt2x00_set_field32(&word, TXD_W0_MORE_FRAG, - test_bit(ENTRY_TXD_MORE_FRAG, &desc->flags)); + test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_ACK, - test_bit(ENTRY_TXD_ACK, &desc->flags)); + test_bit(ENTRY_TXD_ACK, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_TIMESTAMP, - test_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc->flags)); + test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_RTS, - test_bit(ENTRY_TXD_RTS_FRAME, &desc->flags)); - rt2x00_set_field32(&word, TXD_W0_IFS, desc->ifs); + test_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags)); + rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs); rt2x00_set_field32(&word, TXD_W0_RETRY_MODE, !!(control->flags & IEEE80211_TXCTL_LONG_RETRY_LIMIT)); @@ -1066,49 +1065,49 @@ static void rt2400pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, /* * RX control handlers */ -static void rt2400pci_fill_rxdone(struct data_entry *entry, - struct rxdata_entry_desc *desc) +static void rt2400pci_fill_rxdone(struct queue_entry *entry, + struct rxdone_entry_desc *rxdesc) { - __le32 *rxd = entry->priv; + struct queue_entry_priv_pci_rx *priv_rx = entry->priv_data; u32 word0; u32 word2; - rt2x00_desc_read(rxd, 0, &word0); - rt2x00_desc_read(rxd, 2, &word2); + rt2x00_desc_read(priv_rx->desc, 0, &word0); + rt2x00_desc_read(priv_rx->desc, 2, &word2); - desc->flags = 0; + rxdesc->flags = 0; if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR)) - desc->flags |= RX_FLAG_FAILED_FCS_CRC; + rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; if (rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR)) - desc->flags |= RX_FLAG_FAILED_PLCP_CRC; + rxdesc->flags |= RX_FLAG_FAILED_PLCP_CRC; /* * Obtain the status about this packet. */ - desc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL); - desc->rssi = rt2x00_get_field32(word2, RXD_W2_RSSI) - - entry->ring->rt2x00dev->rssi_offset; - desc->ofdm = 0; - desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); - desc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS); + rxdesc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL); + rxdesc->rssi = rt2x00_get_field32(word2, RXD_W2_RSSI) - + entry->queue->rt2x00dev->rssi_offset; + rxdesc->ofdm = 0; + rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); + rxdesc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS); } /* * Interrupt functions. */ -static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev, const int queue) +static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev, + const enum ieee80211_tx_queue queue_idx) { - struct data_ring *ring = rt2x00lib_get_ring(rt2x00dev, queue); - struct data_entry *entry; - __le32 *txd; + struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, queue_idx); + struct queue_entry_priv_pci_tx *priv_tx; + struct queue_entry *entry; + struct txdone_entry_desc txdesc; u32 word; - int tx_status; - int retry; - while (!rt2x00_ring_empty(ring)) { - entry = rt2x00_get_data_entry_done(ring); - txd = entry->priv; - rt2x00_desc_read(txd, 0, &word); + while (!rt2x00queue_empty(queue)) { + entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); + priv_tx = entry->priv_data; + rt2x00_desc_read(priv_tx->desc, 0, &word); if (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) || !rt2x00_get_field32(word, TXD_W0_VALID)) @@ -1117,10 +1116,10 @@ static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev, const int queue) /* * Obtain the status about this packet. */ - tx_status = rt2x00_get_field32(word, TXD_W0_RESULT); - retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT); + txdesc.status = rt2x00_get_field32(word, TXD_W0_RESULT); + txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT); - rt2x00pci_txdone(rt2x00dev, entry, tx_status, retry); + rt2x00pci_txdone(rt2x00dev, entry, &txdesc); } } @@ -1374,9 +1373,9 @@ static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev) rt2400pci_probe_hw_mode(rt2x00dev); /* - * This device requires the beacon ring + * This device requires the atim queue */ - __set_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags); + __set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags); /* * Set the rssi offset. @@ -1481,7 +1480,8 @@ static int rt2400pci_conf_tx(struct ieee80211_hw *hw, /* * Write configuration to register. */ - rt2400pci_config_cw(rt2x00dev, &rt2x00dev->tx->tx_params); + rt2400pci_config_cw(rt2x00dev, + rt2x00dev->tx->cw_min, rt2x00dev->tx->cw_max); return 0; } @@ -1560,12 +1560,42 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { .config = rt2400pci_config, }; +static const struct data_queue_desc rt2400pci_queue_rx = { + .entry_num = RX_ENTRIES, + .data_size = DATA_FRAME_SIZE, + .desc_size = RXD_DESC_SIZE, + .priv_size = sizeof(struct queue_entry_priv_pci_rx), +}; + +static const struct data_queue_desc rt2400pci_queue_tx = { + .entry_num = TX_ENTRIES, + .data_size = DATA_FRAME_SIZE, + .desc_size = TXD_DESC_SIZE, + .priv_size = sizeof(struct queue_entry_priv_pci_tx), +}; + +static const struct data_queue_desc rt2400pci_queue_bcn = { + .entry_num = BEACON_ENTRIES, + .data_size = MGMT_FRAME_SIZE, + .desc_size = TXD_DESC_SIZE, + .priv_size = sizeof(struct queue_entry_priv_pci_tx), +}; + +static const struct data_queue_desc rt2400pci_queue_atim = { + .entry_num = ATIM_ENTRIES, + .data_size = DATA_FRAME_SIZE, + .desc_size = TXD_DESC_SIZE, + .priv_size = sizeof(struct queue_entry_priv_pci_tx), +}; + static const struct rt2x00_ops rt2400pci_ops = { .name = KBUILD_MODNAME, - .rxd_size = RXD_DESC_SIZE, - .txd_size = TXD_DESC_SIZE, .eeprom_size = EEPROM_SIZE, .rf_size = RF_SIZE, + .rx = &rt2400pci_queue_rx, + .tx = &rt2400pci_queue_tx, + .bcn = &rt2400pci_queue_bcn, + .atim = &rt2400pci_queue_atim, .lib = &rt2400pci_rt2x00_ops, .hw = &rt2400pci_mac80211_ops, #ifdef CONFIG_RT2X00_LIB_DEBUGFS diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 884e225f7b9f..0a54b6512207 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -263,6 +263,8 @@ static void rt2500pci_config_bssid(struct rt2x00_dev *rt2x00dev, static void rt2500pci_config_type(struct rt2x00_dev *rt2x00dev, const int type, const int tsf_sync) { + struct data_queue *queue = + rt2x00queue_get_queue(rt2x00dev, IEEE80211_TX_QUEUE_BEACON); u32 reg; rt2x00pci_register_write(rt2x00dev, CSR14, 0); @@ -273,10 +275,7 @@ static void rt2500pci_config_type(struct rt2x00_dev *rt2x00dev, const int type, rt2x00pci_register_read(rt2x00dev, BCNCSR1, ®); rt2x00_set_field32(®, BCNCSR1_PRELOAD, PREAMBLE + get_duration(IEEE80211_HEADER, 20)); - rt2x00_set_field32(®, BCNCSR1_BEACON_CWMIN, - rt2x00lib_get_ring(rt2x00dev, - IEEE80211_TX_QUEUE_BEACON) - ->tx_params.cw_min); + rt2x00_set_field32(®, BCNCSR1_BEACON_CWMIN, queue->cw_min); rt2x00pci_register_write(rt2x00dev, BCNCSR1, reg); /* @@ -684,82 +683,80 @@ dynamic_cca_tune: * Initialization functions. */ static void rt2500pci_init_rxentry(struct rt2x00_dev *rt2x00dev, - struct data_entry *entry) + struct queue_entry *entry) { - __le32 *rxd = entry->priv; + struct queue_entry_priv_pci_rx *priv_rx = entry->priv_data; u32 word; - rt2x00_desc_read(rxd, 1, &word); - rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, entry->data_dma); - rt2x00_desc_write(rxd, 1, word); + rt2x00_desc_read(priv_rx->desc, 1, &word); + rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, priv_rx->dma); + rt2x00_desc_write(priv_rx->desc, 1, word); - rt2x00_desc_read(rxd, 0, &word); + rt2x00_desc_read(priv_rx->desc, 0, &word); rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1); - rt2x00_desc_write(rxd, 0, word); + rt2x00_desc_write(priv_rx->desc, 0, word); } static void rt2500pci_init_txentry(struct rt2x00_dev *rt2x00dev, - struct data_entry *entry) + struct queue_entry *entry) { - __le32 *txd = entry->priv; + struct queue_entry_priv_pci_tx *priv_tx = entry->priv_data; u32 word; - rt2x00_desc_read(txd, 1, &word); - rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, entry->data_dma); - rt2x00_desc_write(txd, 1, word); + rt2x00_desc_read(priv_tx->desc, 1, &word); + rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, priv_tx->dma); + rt2x00_desc_write(priv_tx->desc, 1, word); - rt2x00_desc_read(txd, 0, &word); + rt2x00_desc_read(priv_tx->desc, 0, &word); rt2x00_set_field32(&word, TXD_W0_VALID, 0); rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0); - rt2x00_desc_write(txd, 0, word); + rt2x00_desc_write(priv_tx->desc, 0, word); } -static int rt2500pci_init_rings(struct rt2x00_dev *rt2x00dev) +static int rt2500pci_init_queues(struct rt2x00_dev *rt2x00dev) { + struct queue_entry_priv_pci_rx *priv_rx; + struct queue_entry_priv_pci_tx *priv_tx; u32 reg; /* * Initialize registers. */ rt2x00pci_register_read(rt2x00dev, TXCSR2, ®); - rt2x00_set_field32(®, TXCSR2_TXD_SIZE, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].desc_size); - rt2x00_set_field32(®, TXCSR2_NUM_TXD, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].stats.limit); - rt2x00_set_field32(®, TXCSR2_NUM_ATIM, - rt2x00dev->bcn[1].stats.limit); - rt2x00_set_field32(®, TXCSR2_NUM_PRIO, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].stats.limit); + rt2x00_set_field32(®, TXCSR2_TXD_SIZE, rt2x00dev->tx[0].desc_size); + rt2x00_set_field32(®, TXCSR2_NUM_TXD, rt2x00dev->tx[1].limit); + rt2x00_set_field32(®, TXCSR2_NUM_ATIM, rt2x00dev->bcn[1].limit); + rt2x00_set_field32(®, TXCSR2_NUM_PRIO, rt2x00dev->tx[0].limit); rt2x00pci_register_write(rt2x00dev, TXCSR2, reg); + priv_tx = rt2x00dev->tx[1].entries[0].priv_data; rt2x00pci_register_read(rt2x00dev, TXCSR3, ®); - rt2x00_set_field32(®, TXCSR3_TX_RING_REGISTER, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].data_dma); + rt2x00_set_field32(®, TXCSR3_TX_RING_REGISTER, priv_tx->dma); rt2x00pci_register_write(rt2x00dev, TXCSR3, reg); + priv_tx = rt2x00dev->tx[0].entries[0].priv_data; rt2x00pci_register_read(rt2x00dev, TXCSR5, ®); - rt2x00_set_field32(®, TXCSR5_PRIO_RING_REGISTER, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].data_dma); + rt2x00_set_field32(®, TXCSR5_PRIO_RING_REGISTER, priv_tx->dma); rt2x00pci_register_write(rt2x00dev, TXCSR5, reg); + priv_tx = rt2x00dev->bcn[1].entries[0].priv_data; rt2x00pci_register_read(rt2x00dev, TXCSR4, ®); - rt2x00_set_field32(®, TXCSR4_ATIM_RING_REGISTER, - rt2x00dev->bcn[1].data_dma); + rt2x00_set_field32(®, TXCSR4_ATIM_RING_REGISTER, priv_tx->dma); rt2x00pci_register_write(rt2x00dev, TXCSR4, reg); + priv_tx = rt2x00dev->bcn[0].entries[0].priv_data; rt2x00pci_register_read(rt2x00dev, TXCSR6, ®); - rt2x00_set_field32(®, TXCSR6_BEACON_RING_REGISTER, - rt2x00dev->bcn[0].data_dma); + rt2x00_set_field32(®, TXCSR6_BEACON_RING_REGISTER, priv_tx->dma); rt2x00pci_register_write(rt2x00dev, TXCSR6, reg); rt2x00pci_register_read(rt2x00dev, RXCSR1, ®); rt2x00_set_field32(®, RXCSR1_RXD_SIZE, rt2x00dev->rx->desc_size); - rt2x00_set_field32(®, RXCSR1_NUM_RXD, rt2x00dev->rx->stats.limit); + rt2x00_set_field32(®, RXCSR1_NUM_RXD, rt2x00dev->rx->limit); rt2x00pci_register_write(rt2x00dev, RXCSR1, reg); + priv_rx = rt2x00dev->rx->entries[0].priv_data; rt2x00pci_register_read(rt2x00dev, RXCSR2, ®); - rt2x00_set_field32(®, RXCSR2_RX_RING_REGISTER, - rt2x00dev->rx->data_dma); + rt2x00_set_field32(®, RXCSR2_RX_RING_REGISTER, priv_tx->dma); rt2x00pci_register_write(rt2x00dev, RXCSR2, reg); return 0; @@ -1011,7 +1008,7 @@ static int rt2500pci_enable_radio(struct rt2x00_dev *rt2x00dev) /* * Initialize all registers. */ - if (rt2500pci_init_rings(rt2x00dev) || + if (rt2500pci_init_queues(rt2x00dev) || rt2500pci_init_registers(rt2x00dev) || rt2500pci_init_bbp(rt2x00dev)) { ERROR(rt2x00dev, "Register initialization failed.\n"); @@ -1138,10 +1135,10 @@ static int rt2500pci_set_device_state(struct rt2x00_dev *rt2x00dev, */ static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb, - struct txdata_entry_desc *desc, + struct txentry_desc *txdesc, struct ieee80211_tx_control *control) { - struct skb_desc *skbdesc = get_skb_desc(skb); + struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); __le32 *txd = skbdesc->desc; u32 word; @@ -1150,36 +1147,36 @@ static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, */ rt2x00_desc_read(txd, 2, &word); rt2x00_set_field32(&word, TXD_W2_IV_OFFSET, IEEE80211_HEADER); - rt2x00_set_field32(&word, TXD_W2_AIFS, desc->aifs); - rt2x00_set_field32(&word, TXD_W2_CWMIN, desc->cw_min); - rt2x00_set_field32(&word, TXD_W2_CWMAX, desc->cw_max); + rt2x00_set_field32(&word, TXD_W2_AIFS, txdesc->aifs); + rt2x00_set_field32(&word, TXD_W2_CWMIN, txdesc->cw_min); + rt2x00_set_field32(&word, TXD_W2_CWMAX, txdesc->cw_max); rt2x00_desc_write(txd, 2, word); rt2x00_desc_read(txd, 3, &word); - rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, desc->signal); - rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, desc->service); - rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW, desc->length_low); - rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH, desc->length_high); + rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, txdesc->signal); + rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, txdesc->service); + rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW, txdesc->length_low); + rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH, txdesc->length_high); rt2x00_desc_write(txd, 3, word); rt2x00_desc_read(txd, 10, &word); rt2x00_set_field32(&word, TXD_W10_RTS, - test_bit(ENTRY_TXD_RTS_FRAME, &desc->flags)); + test_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags)); rt2x00_desc_write(txd, 10, word); rt2x00_desc_read(txd, 0, &word); rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 1); rt2x00_set_field32(&word, TXD_W0_VALID, 1); rt2x00_set_field32(&word, TXD_W0_MORE_FRAG, - test_bit(ENTRY_TXD_MORE_FRAG, &desc->flags)); + test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_ACK, - test_bit(ENTRY_TXD_ACK, &desc->flags)); + test_bit(ENTRY_TXD_ACK, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_TIMESTAMP, - test_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc->flags)); + test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_OFDM, - test_bit(ENTRY_TXD_OFDM_RATE, &desc->flags)); + test_bit(ENTRY_TXD_OFDM_RATE, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_CIPHER_OWNER, 1); - rt2x00_set_field32(&word, TXD_W0_IFS, desc->ifs); + rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs); rt2x00_set_field32(&word, TXD_W0_RETRY_MODE, !!(control->flags & IEEE80211_TXCTL_LONG_RETRY_LIMIT)); @@ -1218,46 +1215,46 @@ static void rt2500pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, /* * RX control handlers */ -static void rt2500pci_fill_rxdone(struct data_entry *entry, - struct rxdata_entry_desc *desc) +static void rt2500pci_fill_rxdone(struct queue_entry *entry, + struct rxdone_entry_desc *rxdesc) { - __le32 *rxd = entry->priv; + struct queue_entry_priv_pci_rx *priv_rx = entry->priv_data; u32 word0; u32 word2; - rt2x00_desc_read(rxd, 0, &word0); - rt2x00_desc_read(rxd, 2, &word2); + rt2x00_desc_read(priv_rx->desc, 0, &word0); + rt2x00_desc_read(priv_rx->desc, 2, &word2); - desc->flags = 0; + rxdesc->flags = 0; if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR)) - desc->flags |= RX_FLAG_FAILED_FCS_CRC; + rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; if (rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR)) - desc->flags |= RX_FLAG_FAILED_PLCP_CRC; - - desc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL); - desc->rssi = rt2x00_get_field32(word2, RXD_W2_RSSI) - - entry->ring->rt2x00dev->rssi_offset; - desc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM); - desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); - desc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS); + rxdesc->flags |= RX_FLAG_FAILED_PLCP_CRC; + + rxdesc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL); + rxdesc->rssi = rt2x00_get_field32(word2, RXD_W2_RSSI) - + entry->queue->rt2x00dev->rssi_offset; + rxdesc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM); + rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); + rxdesc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS); } /* * Interrupt functions. */ -static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev, const int queue) +static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev, + const enum ieee80211_tx_queue queue_idx) { - struct data_ring *ring = rt2x00lib_get_ring(rt2x00dev, queue); - struct data_entry *entry; - __le32 *txd; + struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, queue_idx); + struct queue_entry_priv_pci_tx *priv_tx; + struct queue_entry *entry; + struct txdone_entry_desc txdesc; u32 word; - int tx_status; - int retry; - while (!rt2x00_ring_empty(ring)) { - entry = rt2x00_get_data_entry_done(ring); - txd = entry->priv; - rt2x00_desc_read(txd, 0, &word); + while (!rt2x00queue_empty(queue)) { + entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); + priv_tx = entry->priv_data; + rt2x00_desc_read(priv_tx->desc, 0, &word); if (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) || !rt2x00_get_field32(word, TXD_W0_VALID)) @@ -1266,10 +1263,10 @@ static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev, const int queue) /* * Obtain the status about this packet. */ - tx_status = rt2x00_get_field32(word, TXD_W0_RESULT); - retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT); + txdesc.status = rt2x00_get_field32(word, TXD_W0_RESULT); + txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT); - rt2x00pci_txdone(rt2x00dev, entry, tx_status, retry); + rt2x00pci_txdone(rt2x00dev, entry, &txdesc); } } @@ -1705,9 +1702,9 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev) rt2500pci_probe_hw_mode(rt2x00dev); /* - * This device requires the beacon ring + * This device requires the atim queue */ - __set_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags); + __set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags); /* * Set the rssi offset. @@ -1871,12 +1868,42 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = { .config = rt2500pci_config, }; +static const struct data_queue_desc rt2500pci_queue_rx = { + .entry_num = RX_ENTRIES, + .data_size = DATA_FRAME_SIZE, + .desc_size = RXD_DESC_SIZE, + .priv_size = sizeof(struct queue_entry_priv_pci_rx), +}; + +static const struct data_queue_desc rt2500pci_queue_tx = { + .entry_num = TX_ENTRIES, + .data_size = DATA_FRAME_SIZE, + .desc_size = TXD_DESC_SIZE, + .priv_size = sizeof(struct queue_entry_priv_pci_tx), +}; + +static const struct data_queue_desc rt2500pci_queue_bcn = { + .entry_num = BEACON_ENTRIES, + .data_size = MGMT_FRAME_SIZE, + .desc_size = TXD_DESC_SIZE, + .priv_size = sizeof(struct queue_entry_priv_pci_tx), +}; + +static const struct data_queue_desc rt2500pci_queue_atim = { + .entry_num = ATIM_ENTRIES, + .data_size = DATA_FRAME_SIZE, + .desc_size = TXD_DESC_SIZE, + .priv_size = sizeof(struct queue_entry_priv_pci_tx), +}; + static const struct rt2x00_ops rt2500pci_ops = { .name = KBUILD_MODNAME, - .rxd_size = RXD_DESC_SIZE, - .txd_size = TXD_DESC_SIZE, .eeprom_size = EEPROM_SIZE, .rf_size = RF_SIZE, + .rx = &rt2500pci_queue_rx, + .tx = &rt2500pci_queue_tx, + .bcn = &rt2500pci_queue_bcn, + .atim = &rt2500pci_queue_atim, .lib = &rt2500pci_rt2x00_ops, .hw = &rt2500pci_mac80211_ops, #ifdef CONFIG_RT2X00_LIB_DEBUGFS diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index bd4bbcc639c3..edc16a5fc754 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1027,10 +1027,10 @@ static int rt2500usb_set_device_state(struct rt2x00_dev *rt2x00dev, */ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb, - struct txdata_entry_desc *desc, + struct txentry_desc *txdesc, struct ieee80211_tx_control *control) { - struct skb_desc *skbdesc = get_skb_desc(skb); + struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); __le32 *txd = skbdesc->desc; u32 word; @@ -1039,31 +1039,31 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, */ rt2x00_desc_read(txd, 1, &word); rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, IEEE80211_HEADER); - rt2x00_set_field32(&word, TXD_W1_AIFS, desc->aifs); - rt2x00_set_field32(&word, TXD_W1_CWMIN, desc->cw_min); - rt2x00_set_field32(&word, TXD_W1_CWMAX, desc->cw_max); + rt2x00_set_field32(&word, TXD_W1_AIFS, txdesc->aifs); + rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min); + rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max); rt2x00_desc_write(txd, 1, word); rt2x00_desc_read(txd, 2, &word); - rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, desc->signal); - rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, desc->service); - rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, desc->length_low); - rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, desc->length_high); + rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->signal); + rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->service); + rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, txdesc->length_low); + rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, txdesc->length_high); rt2x00_desc_write(txd, 2, word); rt2x00_desc_read(txd, 0, &word); rt2x00_set_field32(&word, TXD_W0_RETRY_LIMIT, control->retry_limit); rt2x00_set_field32(&word, TXD_W0_MORE_FRAG, - test_bit(ENTRY_TXD_MORE_FRAG, &desc->flags)); + test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_ACK, - test_bit(ENTRY_TXD_ACK, &desc->flags)); + test_bit(ENTRY_TXD_ACK, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_TIMESTAMP, - test_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc->flags)); + test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_OFDM, - test_bit(ENTRY_TXD_OFDM_RATE, &desc->flags)); + test_bit(ENTRY_TXD_OFDM_RATE, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_NEW_SEQ, !!(control->flags & IEEE80211_TXCTL_FIRST_FRAGMENT)); - rt2x00_set_field32(&word, TXD_W0_IFS, desc->ifs); + rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs); rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skbdesc->data_len); rt2x00_set_field32(&word, TXD_W0_CIPHER, CIPHER_NONE); rt2x00_desc_write(txd, 0, word); @@ -1114,42 +1114,61 @@ static void rt2500usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, /* * RX control handlers */ -static void rt2500usb_fill_rxdone(struct data_entry *entry, - struct rxdata_entry_desc *desc) +static void rt2500usb_fill_rxdone(struct queue_entry *entry, + struct rxdone_entry_desc *rxdesc) { - struct skb_desc *skbdesc = get_skb_desc(entry->skb); - struct urb *urb = entry->priv; - __le32 *rxd = (__le32 *)(entry->skb->data + - (urb->actual_length - entry->ring->desc_size)); + struct queue_entry_priv_usb_rx *priv_rx = entry->priv_data; + struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); + __le32 *rxd = + (__le32 *)(entry->skb->data + + (priv_rx->urb->actual_length - entry->queue->desc_size)); + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data; + int header_size = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control)); u32 word0; u32 word1; rt2x00_desc_read(rxd, 0, &word0); rt2x00_desc_read(rxd, 1, &word1); - desc->flags = 0; + rxdesc->flags = 0; if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR)) - desc->flags |= RX_FLAG_FAILED_FCS_CRC; + rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; if (rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR)) - desc->flags |= RX_FLAG_FAILED_PLCP_CRC; + rxdesc->flags |= RX_FLAG_FAILED_PLCP_CRC; /* * Obtain the status about this packet. */ - desc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL); - desc->rssi = rt2x00_get_field32(word1, RXD_W1_RSSI) - - entry->ring->rt2x00dev->rssi_offset; - desc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM); - desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); - desc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS); + rxdesc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL); + rxdesc->rssi = rt2x00_get_field32(word1, RXD_W1_RSSI) - + entry->queue->rt2x00dev->rssi_offset; + rxdesc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM); + rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); + rxdesc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS); /* - * Set descriptor and data pointer. + * The data behind the ieee80211 header must be + * aligned on a 4 byte boundary. + */ + if (header_size % 4 == 0) { + skb_push(entry->skb, 2); + memmove(entry->skb->data, entry->skb->data + 2, + entry->skb->len - 2); + } + + /* + * Set descriptor pointer. */ - skbdesc->desc = entry->skb->data + desc->size; - skbdesc->desc_len = entry->ring->desc_size; skbdesc->data = entry->skb->data; - skbdesc->data_len = desc->size; + skbdesc->data_len = entry->queue->data_size; + skbdesc->desc = entry->skb->data + rxdesc->size; + skbdesc->desc_len = entry->queue->desc_size; + + /* + * Remove descriptor from skb buffer and trim the whole thing + * down to only contain data. + */ + skb_trim(entry->skb, rxdesc->size); } /* @@ -1157,10 +1176,10 @@ static void rt2500usb_fill_rxdone(struct data_entry *entry, */ static void rt2500usb_beacondone(struct urb *urb) { - struct data_entry *entry = (struct data_entry *)urb->context; - struct data_ring *ring = entry->ring; + struct queue_entry *entry = (struct queue_entry *)urb->context; + struct queue_entry_priv_usb_bcn *priv_bcn = entry->priv_data; - if (!test_bit(DEVICE_ENABLED_RADIO, &ring->rt2x00dev->flags)) + if (!test_bit(DEVICE_ENABLED_RADIO, &entry->queue->rt2x00dev->flags)) return; /* @@ -1169,18 +1188,11 @@ static void rt2500usb_beacondone(struct urb *urb) * Otherwise we should free the sk_buffer, the device * should be doing the rest of the work now. */ - if (ring->index == 1) { - rt2x00_ring_index_done_inc(ring); - entry = rt2x00_get_data_entry(ring); - usb_submit_urb(entry->priv, GFP_ATOMIC); - rt2x00_ring_index_inc(ring); - } else if (ring->index_done == 1) { - entry = rt2x00_get_data_entry_done(ring); - if (entry->skb) { - dev_kfree_skb(entry->skb); - entry->skb = NULL; - } - rt2x00_ring_index_done_inc(ring); + if (priv_bcn->guardian_urb == urb) { + usb_submit_urb(priv_bcn->urb, GFP_ATOMIC); + } else if (priv_bcn->urb == urb) { + dev_kfree_skb(entry->skb); + entry->skb = NULL; } } @@ -1599,9 +1611,10 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev) rt2500usb_probe_hw_mode(rt2x00dev); /* - * This device requires the beacon ring + * This device requires the atim queue */ - __set_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags); + __set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags); + __set_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags); /* * Set the rssi offset. @@ -1691,12 +1704,11 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw, struct ieee80211_tx_control *control) { struct rt2x00_dev *rt2x00dev = hw->priv; - struct usb_device *usb_dev = - interface_to_usbdev(rt2x00dev_usb(rt2x00dev)); - struct skb_desc *desc; - struct data_ring *ring; - struct data_entry *beacon; - struct data_entry *guardian; + struct usb_device *usb_dev = rt2x00dev_usb_dev(rt2x00dev); + struct queue_entry_priv_usb_bcn *priv_bcn; + struct skb_frame_desc *skbdesc; + struct data_queue *queue; + struct queue_entry *entry; int pipe = usb_sndbulkpipe(usb_dev, 1); int length; @@ -1706,32 +1718,26 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw, * initialization. */ control->queue = IEEE80211_TX_QUEUE_BEACON; - ring = rt2x00lib_get_ring(rt2x00dev, control->queue); - - /* - * Obtain 2 entries, one for the guardian byte, - * the second for the actual beacon. - */ - guardian = rt2x00_get_data_entry(ring); - rt2x00_ring_index_inc(ring); - beacon = rt2x00_get_data_entry(ring); + queue = rt2x00queue_get_queue(rt2x00dev, control->queue); + entry = rt2x00queue_get_entry(queue, Q_INDEX); + priv_bcn = entry->priv_data; /* * Add the descriptor in front of the skb. */ - skb_push(skb, ring->desc_size); - memset(skb->data, 0, ring->desc_size); + skb_push(skb, queue->desc_size); + memset(skb->data, 0, queue->desc_size); /* * Fill in skb descriptor */ - desc = get_skb_desc(skb); - desc->desc_len = ring->desc_size; - desc->data_len = skb->len - ring->desc_size; - desc->desc = skb->data; - desc->data = skb->data + ring->desc_size; - desc->ring = ring; - desc->entry = beacon; + skbdesc = get_skb_frame_desc(skb); + memset(skbdesc, 0, sizeof(*skbdesc)); + skbdesc->data = skb->data + queue->desc_size; + skbdesc->data_len = queue->data_size; + skbdesc->desc = skb->data; + skbdesc->desc_len = queue->desc_size; + skbdesc->entry = entry; rt2x00lib_write_tx_desc(rt2x00dev, skb, control); @@ -1742,22 +1748,23 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw, */ length = rt2500usb_get_tx_data_len(rt2x00dev, skb); - usb_fill_bulk_urb(beacon->priv, usb_dev, pipe, - skb->data, length, rt2500usb_beacondone, beacon); + usb_fill_bulk_urb(priv_bcn->urb, usb_dev, pipe, + skb->data, length, rt2500usb_beacondone, entry); /* * Second we need to create the guardian byte. * We only need a single byte, so lets recycle * the 'flags' field we are not using for beacons. */ - guardian->flags = 0; - usb_fill_bulk_urb(guardian->priv, usb_dev, pipe, - &guardian->flags, 1, rt2500usb_beacondone, guardian); + priv_bcn->guardian_data = 0; + usb_fill_bulk_urb(priv_bcn->guardian_urb, usb_dev, pipe, + &priv_bcn->guardian_data, 1, rt2500usb_beacondone, + entry); /* * Send out the guardian byte. */ - usb_submit_urb(guardian->priv, GFP_ATOMIC); + usb_submit_urb(priv_bcn->guardian_urb, GFP_ATOMIC); /* * Enable beacon generation. @@ -1805,12 +1812,42 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { .config = rt2500usb_config, }; +static const struct data_queue_desc rt2500usb_queue_rx = { + .entry_num = RX_ENTRIES, + .data_size = DATA_FRAME_SIZE, + .desc_size = RXD_DESC_SIZE, + .priv_size = sizeof(struct queue_entry_priv_usb_rx), +}; + +static const struct data_queue_desc rt2500usb_queue_tx = { + .entry_num = TX_ENTRIES, + .data_size = DATA_FRAME_SIZE, + .desc_size = TXD_DESC_SIZE, + .priv_size = sizeof(struct queue_entry_priv_usb_tx), +}; + +static const struct data_queue_desc rt2500usb_queue_bcn = { + .entry_num = BEACON_ENTRIES, + .data_size = MGMT_FRAME_SIZE, + .desc_size = TXD_DESC_SIZE, + .priv_size = sizeof(struct queue_entry_priv_usb_bcn), +}; + +static const struct data_queue_desc rt2500usb_queue_atim = { + .entry_num = ATIM_ENTRIES, + .data_size = DATA_FRAME_SIZE, + .desc_size = TXD_DESC_SIZE, + .priv_size = sizeof(struct queue_entry_priv_usb_tx), +}; + static const struct rt2x00_ops rt2500usb_ops = { .name = KBUILD_MODNAME, - .rxd_size = RXD_DESC_SIZE, - .txd_size = TXD_DESC_SIZE, .eeprom_size = EEPROM_SIZE, .rf_size = RF_SIZE, + .rx = &rt2500usb_queue_rx, + .tx = &rt2500usb_queue_tx, + .bcn = &rt2500usb_queue_bcn, + .atim = &rt2500usb_queue_atim, .lib = &rt2500usb_rt2x00_ops, .hw = &rt2500usb_mac80211_ops, #ifdef CONFIG_RT2X00_LIB_DEBUGFS diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 86e4624a63ea..7b67f9666c3b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -27,7 +27,6 @@ #define RT2X00_H #include -#include #include #include #include @@ -38,7 +37,7 @@ #include "rt2x00debug.h" #include "rt2x00reg.h" -#include "rt2x00ring.h" +#include "rt2x00queue.h" /* * Module information. @@ -90,26 +89,6 @@ #define EEPROM(__dev, __msg, __args...) \ DEBUG_PRINTK(__dev, KERN_DEBUG, "EEPROM recovery", __msg, ##__args) -/* - * Ring sizes. - * Ralink PCI devices demand the Frame size to be a multiple of 128 bytes. - * DATA_FRAME_SIZE is used for TX, RX, ATIM and PRIO rings. - * MGMT_FRAME_SIZE is used for the BEACON ring. - */ -#define DATA_FRAME_SIZE 2432 -#define MGMT_FRAME_SIZE 256 - -/* - * Number of entries in a packet ring. - * PCI devices only need 1 Beacon entry, - * but USB devices require a second because they - * have to send a Guardian byte first. - */ -#define RX_ENTRIES 12 -#define TX_ENTRIES 12 -#define ATIM_ENTRIES 1 -#define BEACON_ENTRIES 2 - /* * Standard timing and size defines. * These values should follow the ieee80211 specifications. @@ -474,12 +453,12 @@ struct rt2x00lib_ops { void (*uninitialize) (struct rt2x00_dev *rt2x00dev); /* - * Ring initialization handlers + * queue initialization handlers */ void (*init_rxentry) (struct rt2x00_dev *rt2x00dev, - struct data_entry *entry); + struct queue_entry *entry); void (*init_txentry) (struct rt2x00_dev *rt2x00dev, - struct data_entry *entry); + struct queue_entry *entry); /* * Radio control handlers. @@ -497,10 +476,10 @@ struct rt2x00lib_ops { */ void (*write_tx_desc) (struct rt2x00_dev *rt2x00dev, struct sk_buff *skb, - struct txdata_entry_desc *desc, + struct txentry_desc *txdesc, struct ieee80211_tx_control *control); int (*write_tx_data) (struct rt2x00_dev *rt2x00dev, - struct data_ring *ring, struct sk_buff *skb, + struct data_queue *queue, struct sk_buff *skb, struct ieee80211_tx_control *control); int (*get_tx_data_len) (struct rt2x00_dev *rt2x00dev, struct sk_buff *skb); @@ -510,8 +489,8 @@ struct rt2x00lib_ops { /* * RX control handlers */ - void (*fill_rxdone) (struct data_entry *entry, - struct rxdata_entry_desc *desc); + void (*fill_rxdone) (struct queue_entry *entry, + struct rxdone_entry_desc *rxdesc); /* * Configuration handlers. @@ -540,10 +519,12 @@ struct rt2x00lib_ops { */ struct rt2x00_ops { const char *name; - const unsigned int rxd_size; - const unsigned int txd_size; const unsigned int eeprom_size; const unsigned int rf_size; + const struct data_queue_desc *rx; + const struct data_queue_desc *tx; + const struct data_queue_desc *bcn; + const struct data_queue_desc *atim; const struct rt2x00lib_ops *lib; const struct ieee80211_ops *hw; #ifdef CONFIG_RT2X00_LIB_DEBUGFS @@ -570,7 +551,8 @@ enum rt2x00_flags { * Driver features */ DRIVER_REQUIRE_FIRMWARE, - DRIVER_REQUIRE_BEACON_RING, + DRIVER_REQUIRE_BEACON_GUARD, + DRIVER_REQUIRE_ATIM_QUEUE, /* * Driver configuration @@ -597,8 +579,10 @@ struct rt2x00_dev { * macro's should be used for correct typecasting. */ void *dev; -#define rt2x00dev_pci(__dev) ( (struct pci_dev*)(__dev)->dev ) -#define rt2x00dev_usb(__dev) ( (struct usb_interface*)(__dev)->dev ) +#define rt2x00dev_pci(__dev) ( (struct pci_dev *)(__dev)->dev ) +#define rt2x00dev_usb(__dev) ( (struct usb_interface *)(__dev)->dev ) +#define rt2x00dev_usb_dev(__dev)\ + ( (struct usb_device *)interface_to_usbdev(rt2x00dev_usb(__dev)) ) /* * Callback functions. @@ -757,14 +741,14 @@ struct rt2x00_dev { struct work_struct config_work; /* - * Data ring arrays for RX, TX and Beacon. - * The Beacon array also contains the Atim ring + * Data queue arrays for RX, TX and Beacon. + * The Beacon array also contains the Atim queue * if that is supported by the device. */ - int data_rings; - struct data_ring *rx; - struct data_ring *tx; - struct data_ring *bcn; + int data_queues; + struct data_queue *rx; + struct data_queue *tx; + struct data_queue *bcn; /* * Firmware image. @@ -772,37 +756,6 @@ struct rt2x00_dev { const struct firmware *fw; }; -/* - * For-each loop for the ring array. - * All rings have been allocated as a single array, - * this means we can create a very simply loop macro - * that is capable of looping through all rings. - * ring_end(), txring_end() and ring_loop() are helper macro's which - * should not be used directly. Instead the following should be used: - * ring_for_each() - Loops through all rings (RX, TX, Beacon & Atim) - * txring_for_each() - Loops through TX data rings (TX only) - * txringall_for_each() - Loops through all TX rings (TX, Beacon & Atim) - */ -#define ring_end(__dev) \ - &(__dev)->rx[(__dev)->data_rings] - -#define txring_end(__dev) \ - &(__dev)->tx[(__dev)->hw->queues] - -#define ring_loop(__entry, __start, __end) \ - for ((__entry) = (__start); \ - prefetch(&(__entry)[1]), (__entry) != (__end); \ - (__entry) = &(__entry)[1]) - -#define ring_for_each(__dev, __entry) \ - ring_loop(__entry, (__dev)->rx, ring_end(__dev)) - -#define txring_for_each(__dev, __entry) \ - ring_loop(__entry, (__dev)->tx, txring_end(__dev)) - -#define txringall_for_each(__dev, __entry) \ - ring_loop(__entry, (__dev)->tx, ring_end(__dev)) - /* * Generic RF access. * The RF is being accessed by word index. @@ -895,20 +848,42 @@ static inline u16 get_duration_res(const unsigned int size, const u8 rate) return ((size * 8 * 10) % rate); } -/* - * Library functions. +/** + * rt2x00queue_get_queue - Convert mac80211 queue index to rt2x00 queue + * @rt2x00dev: Pointer to &struct rt2x00_dev. + * @queue: mac80211 queue index (see &enum ieee80211_tx_queue). */ -struct data_ring *rt2x00lib_get_ring(struct rt2x00_dev *rt2x00dev, - const unsigned int queue); +struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev, + const enum ieee80211_tx_queue queue); + +/** + * rt2x00queue_get_entry - Get queue entry where the given index points to. + * @rt2x00dev: Pointer to &struct rt2x00_dev. + * @index: Index identifier for obtaining the correct index. + */ +struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue, + enum queue_index index); + +/** + * rt2x00queue_index_inc - Index incrementation function + * @queue: Queue (&struct data_queue) to perform the action on. + * @action: Index type (&enum queue_index) to perform the action on. + * + * This function will increase the requested index on the queue, + * it will grab the appropriate locks and handle queue overflow events by + * resetting the index to the start of the queue. + */ +void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index); + /* * Interrupt context handlers. */ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev); -void rt2x00lib_txdone(struct data_entry *entry, - const int status, const int retry); -void rt2x00lib_rxdone(struct data_entry *entry, struct sk_buff *skb, - struct rxdata_entry_desc *desc); +void rt2x00lib_txdone(struct queue_entry *entry, + struct txdone_entry_desc *txdesc); +void rt2x00lib_rxdone(struct queue_entry *entry, + struct rxdone_entry_desc *rxdesc); /* * TX descriptor initializer diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c index d70ce6ec8de8..4e048ac0a684 100644 --- a/drivers/net/wireless/rt2x00/rt2x00debug.c +++ b/drivers/net/wireless/rt2x00/rt2x00debug.c @@ -116,7 +116,7 @@ void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb) { struct rt2x00debug_intf *intf = rt2x00dev->debugfs_intf; - struct skb_desc *desc = get_skb_desc(skb); + struct skb_frame_desc *desc = get_skb_frame_desc(skb); struct sk_buff *skbcopy; struct rt2x00dump_hdr *dump_hdr; struct timeval timestamp; @@ -147,7 +147,7 @@ void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, dump_hdr->chip_rf = cpu_to_le16(rt2x00dev->chip.rf); dump_hdr->chip_rev = cpu_to_le32(rt2x00dev->chip.rev); dump_hdr->type = cpu_to_le16(desc->frame_type); - dump_hdr->ring_index = desc->ring->queue_idx; + dump_hdr->queue_index = desc->entry->queue->qid; dump_hdr->entry_index = desc->entry->entry_idx; dump_hdr->timestamp_sec = cpu_to_le32(timestamp.tv_sec); dump_hdr->timestamp_usec = cpu_to_le32(timestamp.tv_usec); @@ -186,7 +186,7 @@ static int rt2x00debug_file_release(struct inode *inode, struct file *file) return 0; } -static int rt2x00debug_open_ring_dump(struct inode *inode, struct file *file) +static int rt2x00debug_open_queue_dump(struct inode *inode, struct file *file) { struct rt2x00debug_intf *intf = inode->i_private; int retval; @@ -203,7 +203,7 @@ static int rt2x00debug_open_ring_dump(struct inode *inode, struct file *file) return 0; } -static int rt2x00debug_release_ring_dump(struct inode *inode, struct file *file) +static int rt2x00debug_release_queue_dump(struct inode *inode, struct file *file) { struct rt2x00debug_intf *intf = inode->i_private; @@ -214,10 +214,10 @@ static int rt2x00debug_release_ring_dump(struct inode *inode, struct file *file) return rt2x00debug_file_release(inode, file); } -static ssize_t rt2x00debug_read_ring_dump(struct file *file, - char __user *buf, - size_t length, - loff_t *offset) +static ssize_t rt2x00debug_read_queue_dump(struct file *file, + char __user *buf, + size_t length, + loff_t *offset) { struct rt2x00debug_intf *intf = file->private_data; struct sk_buff *skb; @@ -248,8 +248,8 @@ exit: return status; } -static unsigned int rt2x00debug_poll_ring_dump(struct file *file, - poll_table *wait) +static unsigned int rt2x00debug_poll_queue_dump(struct file *file, + poll_table *wait) { struct rt2x00debug_intf *intf = file->private_data; @@ -261,12 +261,12 @@ static unsigned int rt2x00debug_poll_ring_dump(struct file *file, return 0; } -static const struct file_operations rt2x00debug_fop_ring_dump = { +static const struct file_operations rt2x00debug_fop_queue_dump = { .owner = THIS_MODULE, - .read = rt2x00debug_read_ring_dump, - .poll = rt2x00debug_poll_ring_dump, - .open = rt2x00debug_open_ring_dump, - .release = rt2x00debug_release_ring_dump, + .read = rt2x00debug_read_queue_dump, + .poll = rt2x00debug_poll_queue_dump, + .open = rt2x00debug_open_queue_dump, + .release = rt2x00debug_release_queue_dump, }; #define RT2X00DEBUGFS_OPS_READ(__name, __format, __type) \ @@ -503,7 +503,7 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev) intf->frame_dump_entry = debugfs_create_file("dump", S_IRUGO, intf->frame_folder, - intf, &rt2x00debug_fop_ring_dump); + intf, &rt2x00debug_fop_queue_dump); if (IS_ERR(intf->frame_dump_entry)) goto exit; diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 57355077fb7c..7620427887b6 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -30,34 +30,6 @@ #include "rt2x00lib.h" #include "rt2x00dump.h" -/* - * Ring handler. - */ -struct data_ring *rt2x00lib_get_ring(struct rt2x00_dev *rt2x00dev, - const unsigned int queue) -{ - int beacon = test_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags); - - /* - * Check if we are requesting a reqular TX ring, - * or if we are requesting a Beacon or Atim ring. - * For Atim rings, we should check if it is supported. - */ - if (queue < rt2x00dev->hw->queues && rt2x00dev->tx) - return &rt2x00dev->tx[queue]; - - if (!rt2x00dev->bcn || !beacon) - return NULL; - - if (queue == IEEE80211_TX_QUEUE_BEACON) - return &rt2x00dev->bcn[0]; - else if (queue == IEEE80211_TX_QUEUE_AFTER_BEACON) - return &rt2x00dev->bcn[1]; - - return NULL; -} -EXPORT_SYMBOL_GPL(rt2x00lib_get_ring); - /* * Link tuning handlers */ @@ -112,46 +84,6 @@ static void rt2x00lib_stop_link_tuner(struct rt2x00_dev *rt2x00dev) cancel_delayed_work_sync(&rt2x00dev->link.work); } -/* - * Ring initialization - */ -static void rt2x00lib_init_rxrings(struct rt2x00_dev *rt2x00dev) -{ - struct data_ring *ring = rt2x00dev->rx; - unsigned int i; - - if (!rt2x00dev->ops->lib->init_rxentry) - return; - - if (ring->data_addr) - memset(ring->data_addr, 0, rt2x00_get_ring_size(ring)); - - for (i = 0; i < ring->stats.limit; i++) - rt2x00dev->ops->lib->init_rxentry(rt2x00dev, &ring->entry[i]); - - rt2x00_ring_index_clear(ring); -} - -static void rt2x00lib_init_txrings(struct rt2x00_dev *rt2x00dev) -{ - struct data_ring *ring; - unsigned int i; - - if (!rt2x00dev->ops->lib->init_txentry) - return; - - txringall_for_each(rt2x00dev, ring) { - if (ring->data_addr) - memset(ring->data_addr, 0, rt2x00_get_ring_size(ring)); - - for (i = 0; i < ring->stats.limit; i++) - rt2x00dev->ops->lib->init_txentry(rt2x00dev, - &ring->entry[i]); - - rt2x00_ring_index_clear(ring); - } -} - /* * Radio control handlers. */ @@ -168,10 +100,10 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev) return 0; /* - * Initialize all data rings. + * Initialize all data queues. */ - rt2x00lib_init_rxrings(rt2x00dev); - rt2x00lib_init_txrings(rt2x00dev); + rt2x00queue_init_rx(rt2x00dev); + rt2x00queue_init_tx(rt2x00dev); /* * Enable radio. @@ -504,19 +436,15 @@ static void rt2x00lib_beacondone_scheduled(struct work_struct *work) { struct rt2x00_dev *rt2x00dev = container_of(work, struct rt2x00_dev, beacon_work); - struct data_ring *ring = - rt2x00lib_get_ring(rt2x00dev, IEEE80211_TX_QUEUE_BEACON); - struct data_entry *entry = rt2x00_get_data_entry(ring); + struct ieee80211_tx_control control; struct sk_buff *skb; skb = ieee80211_beacon_get(rt2x00dev->hw, - rt2x00dev->interface.id, - &entry->tx_status.control); + rt2x00dev->interface.id, &control); if (!skb) return; - rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw, skb, - &entry->tx_status.control); + rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw, skb, &control); dev_kfree_skb(skb); } @@ -530,58 +458,64 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev) } EXPORT_SYMBOL_GPL(rt2x00lib_beacondone); -void rt2x00lib_txdone(struct data_entry *entry, - const int status, const int retry) +void rt2x00lib_txdone(struct queue_entry *entry, + struct txdone_entry_desc *txdesc) { - struct rt2x00_dev *rt2x00dev = entry->ring->rt2x00dev; - struct ieee80211_tx_status *tx_status = &entry->tx_status; - struct ieee80211_low_level_stats *stats = &rt2x00dev->low_level_stats; - int success = !!(status == TX_SUCCESS || status == TX_SUCCESS_RETRY); - int fail = !!(status == TX_FAIL_RETRY || status == TX_FAIL_INVALID || - status == TX_FAIL_OTHER); + struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; + struct ieee80211_tx_status tx_status; + int success = !!(txdesc->status == TX_SUCCESS || + txdesc->status == TX_SUCCESS_RETRY); + int fail = !!(txdesc->status == TX_FAIL_RETRY || + txdesc->status == TX_FAIL_INVALID || + txdesc->status == TX_FAIL_OTHER); /* * Update TX statistics. */ - tx_status->flags = 0; - tx_status->ack_signal = 0; - tx_status->excessive_retries = (status == TX_FAIL_RETRY); - tx_status->retry_count = retry; rt2x00dev->link.qual.tx_success += success; - rt2x00dev->link.qual.tx_failed += retry + fail; + rt2x00dev->link.qual.tx_failed += txdesc->retry + fail; - if (!(tx_status->control.flags & IEEE80211_TXCTL_NO_ACK)) { + /* + * Initialize TX status + */ + tx_status.flags = 0; + tx_status.ack_signal = 0; + tx_status.excessive_retries = (txdesc->status == TX_FAIL_RETRY); + tx_status.retry_count = txdesc->retry; + memcpy(&tx_status.control, txdesc->control, sizeof(txdesc->control)); + + if (!(tx_status.control.flags & IEEE80211_TXCTL_NO_ACK)) { if (success) - tx_status->flags |= IEEE80211_TX_STATUS_ACK; + tx_status.flags |= IEEE80211_TX_STATUS_ACK; else - stats->dot11ACKFailureCount++; + rt2x00dev->low_level_stats.dot11ACKFailureCount++; } - tx_status->queue_length = entry->ring->stats.limit; - tx_status->queue_number = tx_status->control.queue; + tx_status.queue_length = entry->queue->limit; + tx_status.queue_number = tx_status.control.queue; - if (tx_status->control.flags & IEEE80211_TXCTL_USE_RTS_CTS) { + if (tx_status.control.flags & IEEE80211_TXCTL_USE_RTS_CTS) { if (success) - stats->dot11RTSSuccessCount++; + rt2x00dev->low_level_stats.dot11RTSSuccessCount++; else - stats->dot11RTSFailureCount++; + rt2x00dev->low_level_stats.dot11RTSFailureCount++; } /* * Send the tx_status to mac80211 & debugfs. * mac80211 will clean up the skb structure. */ - get_skb_desc(entry->skb)->frame_type = DUMP_FRAME_TXDONE; + get_skb_frame_desc(entry->skb)->frame_type = DUMP_FRAME_TXDONE; rt2x00debug_dump_frame(rt2x00dev, entry->skb); - ieee80211_tx_status_irqsafe(rt2x00dev->hw, entry->skb, tx_status); + ieee80211_tx_status_irqsafe(rt2x00dev->hw, entry->skb, &tx_status); entry->skb = NULL; } EXPORT_SYMBOL_GPL(rt2x00lib_txdone); -void rt2x00lib_rxdone(struct data_entry *entry, struct sk_buff *skb, - struct rxdata_entry_desc *desc) +void rt2x00lib_rxdone(struct queue_entry *entry, + struct rxdone_entry_desc *rxdesc) { - struct rt2x00_dev *rt2x00dev = entry->ring->rt2x00dev; + struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status; struct ieee80211_hw_mode *mode; struct ieee80211_rate *rate; @@ -602,12 +536,12 @@ void rt2x00lib_rxdone(struct data_entry *entry, struct sk_buff *skb, * the signal is the PLCP value. If it was received with * a CCK bitrate the signal is the rate in 0.5kbit/s. */ - if (!desc->ofdm) + if (!rxdesc->ofdm) val = DEVICE_GET_RATE_FIELD(rate->val, RATE); else val = DEVICE_GET_RATE_FIELD(rate->val, PLCP); - if (val == desc->signal) { + if (val == rxdesc->signal) { val = rate->val; break; } @@ -616,26 +550,28 @@ void rt2x00lib_rxdone(struct data_entry *entry, struct sk_buff *skb, /* * Only update link status if this is a beacon frame carrying our bssid. */ - hdr = (struct ieee80211_hdr*)skb->data; + hdr = (struct ieee80211_hdr*)entry->skb->data; fc = le16_to_cpu(hdr->frame_control); - if (is_beacon(fc) && desc->my_bss) - rt2x00lib_update_link_stats(&rt2x00dev->link, desc->rssi); + if (is_beacon(fc) && rxdesc->my_bss) + rt2x00lib_update_link_stats(&rt2x00dev->link, rxdesc->rssi); rt2x00dev->link.qual.rx_success++; rx_status->rate = val; rx_status->signal = - rt2x00lib_calculate_link_signal(rt2x00dev, desc->rssi); - rx_status->ssi = desc->rssi; - rx_status->flag = desc->flags; + rt2x00lib_calculate_link_signal(rt2x00dev, rxdesc->rssi); + rx_status->ssi = rxdesc->rssi; + rx_status->flag = rxdesc->flags; rx_status->antenna = rt2x00dev->link.ant.active.rx; /* - * Send frame to mac80211 & debugfs + * Send frame to mac80211 & debugfs. + * mac80211 will clean up the skb structure. */ - get_skb_desc(skb)->frame_type = DUMP_FRAME_RXDONE; - rt2x00debug_dump_frame(rt2x00dev, skb); - ieee80211_rx_irqsafe(rt2x00dev->hw, skb, rx_status); + get_skb_frame_desc(entry->skb)->frame_type = DUMP_FRAME_RXDONE; + rt2x00debug_dump_frame(rt2x00dev, entry->skb); + ieee80211_rx_irqsafe(rt2x00dev->hw, entry->skb, rx_status); + entry->skb = NULL; } EXPORT_SYMBOL_GPL(rt2x00lib_rxdone); @@ -646,9 +582,9 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb, struct ieee80211_tx_control *control) { - struct txdata_entry_desc desc; - struct skb_desc *skbdesc = get_skb_desc(skb); - struct ieee80211_hdr *ieee80211hdr = skbdesc->data; + struct txentry_desc txdesc; + struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); + struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data; int tx_rate; int bitrate; int length; @@ -657,22 +593,22 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev, u16 frame_control; u16 seq_ctrl; - memset(&desc, 0, sizeof(desc)); + memset(&txdesc, 0, sizeof(txdesc)); - desc.cw_min = skbdesc->ring->tx_params.cw_min; - desc.cw_max = skbdesc->ring->tx_params.cw_max; - desc.aifs = skbdesc->ring->tx_params.aifs; + txdesc.cw_min = skbdesc->entry->queue->cw_min; + txdesc.cw_max = skbdesc->entry->queue->cw_max; + txdesc.aifs = skbdesc->entry->queue->aifs; /* * Identify queue */ if (control->queue < rt2x00dev->hw->queues) - desc.queue = control->queue; + txdesc.queue = control->queue; else if (control->queue == IEEE80211_TX_QUEUE_BEACON || control->queue == IEEE80211_TX_QUEUE_AFTER_BEACON) - desc.queue = QUEUE_MGMT; + txdesc.queue = QID_MGMT; else - desc.queue = QUEUE_OTHER; + txdesc.queue = QID_OTHER; /* * Read required fields from ieee80211 header. @@ -686,18 +622,18 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev, * Check whether this frame is to be acked */ if (!(control->flags & IEEE80211_TXCTL_NO_ACK)) - __set_bit(ENTRY_TXD_ACK, &desc.flags); + __set_bit(ENTRY_TXD_ACK, &txdesc.flags); /* * Check if this is a RTS/CTS frame */ if (is_rts_frame(frame_control) || is_cts_frame(frame_control)) { - __set_bit(ENTRY_TXD_BURST, &desc.flags); + __set_bit(ENTRY_TXD_BURST, &txdesc.flags); if (is_rts_frame(frame_control)) { - __set_bit(ENTRY_TXD_RTS_FRAME, &desc.flags); - __set_bit(ENTRY_TXD_ACK, &desc.flags); + __set_bit(ENTRY_TXD_RTS_FRAME, &txdesc.flags); + __set_bit(ENTRY_TXD_ACK, &txdesc.flags); } else - __clear_bit(ENTRY_TXD_ACK, &desc.flags); + __clear_bit(ENTRY_TXD_ACK, &txdesc.flags); if (control->rts_cts_rate) tx_rate = control->rts_cts_rate; } @@ -706,14 +642,14 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev, * Check for OFDM */ if (DEVICE_GET_RATE_FIELD(tx_rate, RATEMASK) & DEV_OFDM_RATEMASK) - __set_bit(ENTRY_TXD_OFDM_RATE, &desc.flags); + __set_bit(ENTRY_TXD_OFDM_RATE, &txdesc.flags); /* * Check if more fragments are pending */ if (ieee80211_get_morefrag(ieee80211hdr)) { - __set_bit(ENTRY_TXD_BURST, &desc.flags); - __set_bit(ENTRY_TXD_MORE_FRAG, &desc.flags); + __set_bit(ENTRY_TXD_BURST, &txdesc.flags); + __set_bit(ENTRY_TXD_MORE_FRAG, &txdesc.flags); } /* @@ -722,7 +658,7 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev, */ if (control->queue == IEEE80211_TX_QUEUE_BEACON || is_probe_resp(frame_control)) - __set_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc.flags); + __set_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc.flags); /* * Determine with what IFS priority this frame should be send. @@ -730,22 +666,22 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev, * or this fragment came after RTS/CTS. */ if ((seq_ctrl & IEEE80211_SCTL_FRAG) > 0 || - test_bit(ENTRY_TXD_RTS_FRAME, &desc.flags)) - desc.ifs = IFS_SIFS; + test_bit(ENTRY_TXD_RTS_FRAME, &txdesc.flags)) + txdesc.ifs = IFS_SIFS; else - desc.ifs = IFS_BACKOFF; + txdesc.ifs = IFS_BACKOFF; /* * PLCP setup * Length calculation depends on OFDM/CCK rate. */ - desc.signal = DEVICE_GET_RATE_FIELD(tx_rate, PLCP); - desc.service = 0x04; + txdesc.signal = DEVICE_GET_RATE_FIELD(tx_rate, PLCP); + txdesc.service = 0x04; - length = skbdesc->data_len + FCS_LEN; - if (test_bit(ENTRY_TXD_OFDM_RATE, &desc.flags)) { - desc.length_high = (length >> 6) & 0x3f; - desc.length_low = length & 0x3f; + length = skb->len + FCS_LEN; + if (test_bit(ENTRY_TXD_OFDM_RATE, &txdesc.flags)) { + txdesc.length_high = (length >> 6) & 0x3f; + txdesc.length_low = length & 0x3f; } else { bitrate = DEVICE_GET_RATE_FIELD(tx_rate, RATE); @@ -762,27 +698,26 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev, * Check if we need to set the Length Extension */ if (bitrate == 110 && residual <= 30) - desc.service |= 0x80; + txdesc.service |= 0x80; } - desc.length_high = (duration >> 8) & 0xff; - desc.length_low = duration & 0xff; + txdesc.length_high = (duration >> 8) & 0xff; + txdesc.length_low = duration & 0xff; /* * When preamble is enabled we should set the * preamble bit for the signal. */ if (DEVICE_GET_RATE_FIELD(tx_rate, PREAMBLE)) - desc.signal |= 0x08; + txdesc.signal |= 0x08; } - rt2x00dev->ops->lib->write_tx_desc(rt2x00dev, skb, &desc, control); + rt2x00dev->ops->lib->write_tx_desc(rt2x00dev, skb, &txdesc, control); /* - * Update ring entry. + * Update queue entry. */ skbdesc->entry->skb = skb; - memcpy(&skbdesc->entry->tx_status.control, control, sizeof(*control)); /* * The frame has been completely initialized and ready @@ -1012,86 +947,6 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev) /* * Initialization/uninitialization handlers. */ -static int rt2x00lib_alloc_entries(struct data_ring *ring, - const u16 max_entries, const u16 data_size, - const u16 desc_size) -{ - struct data_entry *entry; - unsigned int i; - - ring->stats.limit = max_entries; - ring->data_size = data_size; - ring->desc_size = desc_size; - - /* - * Allocate all ring entries. - */ - entry = kzalloc(ring->stats.limit * sizeof(*entry), GFP_KERNEL); - if (!entry) - return -ENOMEM; - - for (i = 0; i < ring->stats.limit; i++) { - entry[i].flags = 0; - entry[i].ring = ring; - entry[i].skb = NULL; - entry[i].entry_idx = i; - } - - ring->entry = entry; - - return 0; -} - -static int rt2x00lib_alloc_ring_entries(struct rt2x00_dev *rt2x00dev) -{ - struct data_ring *ring; - - /* - * Allocate the RX ring. - */ - if (rt2x00lib_alloc_entries(rt2x00dev->rx, RX_ENTRIES, DATA_FRAME_SIZE, - rt2x00dev->ops->rxd_size)) - return -ENOMEM; - - /* - * First allocate the TX rings. - */ - txring_for_each(rt2x00dev, ring) { - if (rt2x00lib_alloc_entries(ring, TX_ENTRIES, DATA_FRAME_SIZE, - rt2x00dev->ops->txd_size)) - return -ENOMEM; - } - - if (!test_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags)) - return 0; - - /* - * Allocate the BEACON ring. - */ - if (rt2x00lib_alloc_entries(&rt2x00dev->bcn[0], BEACON_ENTRIES, - MGMT_FRAME_SIZE, rt2x00dev->ops->txd_size)) - return -ENOMEM; - - /* - * Allocate the Atim ring. - */ - if (rt2x00lib_alloc_entries(&rt2x00dev->bcn[1], ATIM_ENTRIES, - DATA_FRAME_SIZE, rt2x00dev->ops->txd_size)) - return -ENOMEM; - - return 0; -} - -static void rt2x00lib_free_ring_entries(struct rt2x00_dev *rt2x00dev) -{ - struct data_ring *ring; - - ring_for_each(rt2x00dev, ring) { - kfree(ring->entry); - ring->entry = NULL; - } -} - static void rt2x00lib_uninitialize(struct rt2x00_dev *rt2x00dev) { if (!__test_and_clear_bit(DEVICE_INITIALIZED, &rt2x00dev->flags)) @@ -1108,9 +963,9 @@ static void rt2x00lib_uninitialize(struct rt2x00_dev *rt2x00dev) rt2x00dev->ops->lib->uninitialize(rt2x00dev); /* - * Free allocated ring entries. + * Free allocated queue entries. */ - rt2x00lib_free_ring_entries(rt2x00dev); + rt2x00queue_uninitialize(rt2x00dev); } static int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev) @@ -1121,13 +976,11 @@ static int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev) return 0; /* - * Allocate all ring entries. + * Allocate all queue entries. */ - status = rt2x00lib_alloc_ring_entries(rt2x00dev); - if (status) { - ERROR(rt2x00dev, "Ring entries allocation failed.\n"); + status = rt2x00queue_initialize(rt2x00dev); + if (status) return status; - } /* * Initialize the device. @@ -1143,15 +996,12 @@ static int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev) */ status = rt2x00rfkill_register(rt2x00dev); if (status) - goto exit_unitialize; + goto exit; return 0; -exit_unitialize: - rt2x00lib_uninitialize(rt2x00dev); - exit: - rt2x00lib_free_ring_entries(rt2x00dev); + rt2x00lib_uninitialize(rt2x00dev); return status; } @@ -1211,65 +1061,6 @@ void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev) /* * driver allocation handlers. */ -static int rt2x00lib_alloc_rings(struct rt2x00_dev *rt2x00dev) -{ - struct data_ring *ring; - unsigned int index; - - /* - * We need the following rings: - * RX: 1 - * TX: hw->queues - * Beacon: 1 (if required) - * Atim: 1 (if required) - */ - rt2x00dev->data_rings = 1 + rt2x00dev->hw->queues + - (2 * test_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags)); - - ring = kzalloc(rt2x00dev->data_rings * sizeof(*ring), GFP_KERNEL); - if (!ring) { - ERROR(rt2x00dev, "Ring allocation failed.\n"); - return -ENOMEM; - } - - /* - * Initialize pointers - */ - rt2x00dev->rx = ring; - rt2x00dev->tx = &rt2x00dev->rx[1]; - if (test_bit(DRIVER_REQUIRE_BEACON_RING, &rt2x00dev->flags)) - rt2x00dev->bcn = &rt2x00dev->tx[rt2x00dev->hw->queues]; - - /* - * Initialize ring parameters. - * RX: queue_idx = 0 - * TX: queue_idx = IEEE80211_TX_QUEUE_DATA0 + index - * TX: cw_min: 2^5 = 32. - * TX: cw_max: 2^10 = 1024. - */ - rt2x00dev->rx->rt2x00dev = rt2x00dev; - rt2x00dev->rx->queue_idx = 0; - - index = IEEE80211_TX_QUEUE_DATA0; - txring_for_each(rt2x00dev, ring) { - ring->rt2x00dev = rt2x00dev; - ring->queue_idx = index++; - ring->tx_params.aifs = 2; - ring->tx_params.cw_min = 5; - ring->tx_params.cw_max = 10; - } - - return 0; -} - -static void rt2x00lib_free_rings(struct rt2x00_dev *rt2x00dev) -{ - kfree(rt2x00dev->rx); - rt2x00dev->rx = NULL; - rt2x00dev->tx = NULL; - rt2x00dev->bcn = NULL; -} - int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) { int retval = -ENOMEM; @@ -1297,9 +1088,9 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) rt2x00dev->interface.type = IEEE80211_IF_TYPE_INVALID; /* - * Allocate ring array. + * Allocate queue array. */ - retval = rt2x00lib_alloc_rings(rt2x00dev); + retval = rt2x00queue_allocate(rt2x00dev); if (retval) goto exit; @@ -1370,9 +1161,9 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev) rt2x00lib_free_firmware(rt2x00dev); /* - * Free ring structures. + * Free queue structures. */ - rt2x00lib_free_rings(rt2x00dev); + rt2x00queue_free(rt2x00dev); } EXPORT_SYMBOL_GPL(rt2x00lib_remove_dev); diff --git a/drivers/net/wireless/rt2x00/rt2x00dump.h b/drivers/net/wireless/rt2x00/rt2x00dump.h index 93f8967e5dc4..7169c222a486 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dump.h +++ b/drivers/net/wireless/rt2x00/rt2x00dump.h @@ -93,8 +93,8 @@ enum rt2x00_dump_type { * @chip_rf: RF chipset * @chip_rev: Chipset revision * @type: The frame type (&rt2x00_dump_type) - * @ring_index: The index number of the data ring. - * @entry_index: The index number of the entry inside the data ring. + * @queue_index: The index number of the data queue. + * @entry_index: The index number of the entry inside the data queue. * @timestamp_sec: Timestamp - seconds * @timestamp_usec: Timestamp - microseconds */ @@ -111,7 +111,7 @@ struct rt2x00dump_hdr { __le32 chip_rev; __le16 type; - __u8 ring_index; + __u8 queue_index; __u8 entry_index; __le32 timestamp_sec; diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index 7540d29c47a0..5c835f42a455 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -58,6 +58,16 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, struct ieee80211_conf *conf, const int force_config); +/* + * Queue handlers. + */ +void rt2x00queue_init_rx(struct rt2x00_dev *rt2x00dev); +void rt2x00queue_init_tx(struct rt2x00_dev *rt2x00dev); +int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev); +void rt2x00queue_uninitialize(struct rt2x00_dev *rt2x00dev); +int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev); +void rt2x00queue_free(struct rt2x00_dev *rt2x00dev); + /* * Firmware handlers. */ diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index e638c653e094..411ed5d08598 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -30,7 +30,7 @@ #include "rt2x00lib.h" static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev, - struct data_ring *ring, + struct data_queue *queue, struct sk_buff *frag_skb, struct ieee80211_tx_control *control) { @@ -60,7 +60,7 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev, frag_skb->data, frag_skb->len, control, (struct ieee80211_rts *)(skb->data)); - if (rt2x00dev->ops->lib->write_tx_data(rt2x00dev, ring, skb, control)) { + if (rt2x00dev->ops->lib->write_tx_data(rt2x00dev, queue, skb, control)) { WARNING(rt2x00dev, "Failed to send RTS/CTS frame.\n"); return NETDEV_TX_BUSY; } @@ -73,7 +73,7 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb, { struct rt2x00_dev *rt2x00dev = hw->priv; struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data; - struct data_ring *ring; + struct data_queue *queue; u16 frame_control; /* @@ -88,10 +88,10 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb, } /* - * Determine which ring to put packet on. + * Determine which queue to put packet on. */ - ring = rt2x00lib_get_ring(rt2x00dev, control->queue); - if (unlikely(!ring)) { + queue = rt2x00queue_get_queue(rt2x00dev, control->queue); + if (unlikely(!queue)) { ERROR(rt2x00dev, "Attempt to send packet over invalid queue %d.\n" "Please file bug report to %s.\n", @@ -110,23 +110,23 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb, if (!is_rts_frame(frame_control) && !is_cts_frame(frame_control) && (control->flags & (IEEE80211_TXCTL_USE_RTS_CTS | IEEE80211_TXCTL_USE_CTS_PROTECT))) { - if (rt2x00_ring_free(ring) <= 1) { + if (rt2x00queue_available(queue) <= 1) { ieee80211_stop_queue(rt2x00dev->hw, control->queue); return NETDEV_TX_BUSY; } - if (rt2x00mac_tx_rts_cts(rt2x00dev, ring, skb, control)) { + if (rt2x00mac_tx_rts_cts(rt2x00dev, queue, skb, control)) { ieee80211_stop_queue(rt2x00dev->hw, control->queue); return NETDEV_TX_BUSY; } } - if (rt2x00dev->ops->lib->write_tx_data(rt2x00dev, ring, skb, control)) { + if (rt2x00dev->ops->lib->write_tx_data(rt2x00dev, queue, skb, control)) { ieee80211_stop_queue(rt2x00dev->hw, control->queue); return NETDEV_TX_BUSY; } - if (rt2x00_ring_full(ring)) + if (rt2x00queue_full(queue)) ieee80211_stop_queue(rt2x00dev->hw, control->queue); if (rt2x00dev->ops->lib->kick_tx_queue) @@ -214,7 +214,7 @@ void rt2x00mac_remove_interface(struct ieee80211_hw *hw, !is_interface_present(intf)) return; - intf->id = 0; + intf->id = NULL; intf->type = IEEE80211_IF_TYPE_INVALID; memset(&intf->bssid, 0x00, ETH_ALEN); memset(&intf->mac, 0x00, ETH_ALEN); @@ -334,9 +334,11 @@ int rt2x00mac_get_tx_stats(struct ieee80211_hw *hw, struct rt2x00_dev *rt2x00dev = hw->priv; unsigned int i; - for (i = 0; i < hw->queues; i++) - memcpy(&stats->data[i], &rt2x00dev->tx[i].stats, - sizeof(rt2x00dev->tx[i].stats)); + for (i = 0; i < hw->queues; i++) { + stats->data[i].len = rt2x00dev->tx[i].length; + stats->data[i].limit = rt2x00dev->tx[i].limit; + stats->data[i].count = rt2x00dev->tx[i].count; + } return 0; } @@ -380,14 +382,14 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, } EXPORT_SYMBOL_GPL(rt2x00mac_bss_info_changed); -int rt2x00mac_conf_tx(struct ieee80211_hw *hw, int queue, +int rt2x00mac_conf_tx(struct ieee80211_hw *hw, int queue_idx, const struct ieee80211_tx_queue_params *params) { struct rt2x00_dev *rt2x00dev = hw->priv; - struct data_ring *ring; + struct data_queue *queue; - ring = rt2x00lib_get_ring(rt2x00dev, queue); - if (unlikely(!ring)) + queue = rt2x00queue_get_queue(rt2x00dev, queue_idx); + if (unlikely(!queue)) return -EINVAL; /* @@ -395,24 +397,23 @@ int rt2x00mac_conf_tx(struct ieee80211_hw *hw, int queue, * Ralink registers require to know the bit number 'n'. */ if (params->cw_min) - ring->tx_params.cw_min = fls(params->cw_min); + queue->cw_min = fls(params->cw_min); else - ring->tx_params.cw_min = 5; /* cw_min: 2^5 = 32. */ + queue->cw_min = 5; /* cw_min: 2^5 = 32. */ if (params->cw_max) - ring->tx_params.cw_max = fls(params->cw_max); + queue->cw_max = fls(params->cw_max); else - ring->tx_params.cw_max = 10; /* cw_min: 2^10 = 1024. */ + queue->cw_max = 10; /* cw_min: 2^10 = 1024. */ if (params->aifs) - ring->tx_params.aifs = params->aifs; + queue->aifs = params->aifs; else - ring->tx_params.aifs = 2; + queue->aifs = 2; INFO(rt2x00dev, - "Configured TX ring %d - CWmin: %d, CWmax: %d, Aifs: %d.\n", - queue, ring->tx_params.cw_min, ring->tx_params.cw_max, - ring->tx_params.aifs); + "Configured TX queue %d - CWmin: %d, CWmax: %d, Aifs: %d.\n", + queue_idx, queue->cw_min, queue->cw_max, queue->aifs); return 0; } diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index 0f2590bc31ec..63cfe33e95da 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c @@ -38,9 +38,10 @@ int rt2x00pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, struct ieee80211_tx_control *control) { struct rt2x00_dev *rt2x00dev = hw->priv; - struct skb_desc *desc; - struct data_ring *ring; - struct data_entry *entry; + struct queue_entry_priv_pci_tx *priv_tx; + struct skb_frame_desc *skbdesc; + struct data_queue *queue; + struct queue_entry *entry; /* * Just in case mac80211 doesn't set this correctly, @@ -48,21 +49,22 @@ int rt2x00pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, * initialization. */ control->queue = IEEE80211_TX_QUEUE_BEACON; - ring = rt2x00lib_get_ring(rt2x00dev, control->queue); - entry = rt2x00_get_data_entry(ring); + queue = rt2x00queue_get_queue(rt2x00dev, control->queue); + entry = rt2x00queue_get_entry(queue, Q_INDEX); + priv_tx = entry->priv_data; /* * Fill in skb descriptor */ - desc = get_skb_desc(skb); - desc->desc_len = ring->desc_size; - desc->data_len = skb->len; - desc->desc = entry->priv; - desc->data = skb->data; - desc->ring = ring; - desc->entry = entry; - - memcpy(entry->data_addr, skb->data, skb->len); + skbdesc = get_skb_frame_desc(skb); + memset(skbdesc, 0, sizeof(*skbdesc)); + skbdesc->data = skb->data; + skbdesc->data_len = queue->data_size; + skbdesc->desc = priv_tx->desc; + skbdesc->desc_len = queue->desc_size; + skbdesc->entry = entry; + + memcpy(priv_tx->data, skb->data, skb->len); rt2x00lib_write_tx_desc(rt2x00dev, skb, control); /* @@ -78,18 +80,18 @@ EXPORT_SYMBOL_GPL(rt2x00pci_beacon_update); * TX data handlers. */ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev, - struct data_ring *ring, struct sk_buff *skb, + struct data_queue *queue, struct sk_buff *skb, struct ieee80211_tx_control *control) { - struct data_entry *entry = rt2x00_get_data_entry(ring); - __le32 *txd = entry->priv; - struct skb_desc *desc; + struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX); + struct queue_entry_priv_pci_tx *priv_tx = entry->priv_data; + struct skb_frame_desc *skbdesc; u32 word; - if (rt2x00_ring_full(ring)) + if (rt2x00queue_full(queue)) return -EINVAL; - rt2x00_desc_read(txd, 0, &word); + rt2x00_desc_read(priv_tx->desc, 0, &word); if (rt2x00_get_field32(word, TXD_ENTRY_OWNER_NIC) || rt2x00_get_field32(word, TXD_ENTRY_VALID)) { @@ -103,18 +105,18 @@ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev, /* * Fill in skb descriptor */ - desc = get_skb_desc(skb); - desc->desc_len = ring->desc_size; - desc->data_len = skb->len; - desc->desc = entry->priv; - desc->data = skb->data; - desc->ring = ring; - desc->entry = entry; - - memcpy(entry->data_addr, skb->data, skb->len); + skbdesc = get_skb_frame_desc(skb); + memset(skbdesc, 0, sizeof(*skbdesc)); + skbdesc->data = skb->data; + skbdesc->data_len = queue->data_size; + skbdesc->desc = priv_tx->desc; + skbdesc->desc_len = queue->desc_size; + skbdesc->entry = entry; + + memcpy(priv_tx->data, skb->data, skb->len); rt2x00lib_write_tx_desc(rt2x00dev, skb, control); - rt2x00_ring_index_inc(ring); + rt2x00queue_index_inc(queue, Q_INDEX); return 0; } @@ -125,29 +127,28 @@ EXPORT_SYMBOL_GPL(rt2x00pci_write_tx_data); */ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) { - struct data_ring *ring = rt2x00dev->rx; - struct data_entry *entry; - struct sk_buff *skb; + struct data_queue *queue = rt2x00dev->rx; + struct queue_entry *entry; + struct queue_entry_priv_pci_rx *priv_rx; struct ieee80211_hdr *hdr; - struct skb_desc *skbdesc; - struct rxdata_entry_desc desc; + struct skb_frame_desc *skbdesc; + struct rxdone_entry_desc rxdesc; int header_size; - __le32 *rxd; int align; u32 word; while (1) { - entry = rt2x00_get_data_entry(ring); - rxd = entry->priv; - rt2x00_desc_read(rxd, 0, &word); + entry = rt2x00queue_get_entry(queue, Q_INDEX); + priv_rx = entry->priv_data; + rt2x00_desc_read(priv_rx->desc, 0, &word); if (rt2x00_get_field32(word, RXD_ENTRY_OWNER_NIC)) break; - memset(&desc, 0, sizeof(desc)); - rt2x00dev->ops->lib->fill_rxdone(entry, &desc); + memset(&rxdesc, 0, sizeof(rxdesc)); + rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc); - hdr = (struct ieee80211_hdr *)entry->data_addr; + hdr = (struct ieee80211_hdr *)priv_rx->data; header_size = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control)); @@ -161,66 +162,68 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) * Allocate the sk_buffer, initialize it and copy * all data into it. */ - skb = dev_alloc_skb(desc.size + align); - if (!skb) + entry->skb = dev_alloc_skb(rxdesc.size + align); + if (!entry->skb) return; - skb_reserve(skb, align); - memcpy(skb_put(skb, desc.size), entry->data_addr, desc.size); + skb_reserve(entry->skb, align); + memcpy(skb_put(entry->skb, rxdesc.size), + priv_rx->data, rxdesc.size); /* * Fill in skb descriptor */ - skbdesc = get_skb_desc(skb); - skbdesc->desc_len = entry->ring->desc_size; - skbdesc->data_len = skb->len; - skbdesc->desc = entry->priv; - skbdesc->data = skb->data; - skbdesc->ring = ring; + skbdesc = get_skb_frame_desc(entry->skb); + memset(skbdesc, 0, sizeof(*skbdesc)); + skbdesc->data = entry->skb->data; + skbdesc->data_len = queue->data_size; + skbdesc->desc = priv_rx->desc; + skbdesc->desc_len = queue->desc_size; skbdesc->entry = entry; /* * Send the frame to rt2x00lib for further processing. */ - rt2x00lib_rxdone(entry, skb, &desc); + rt2x00lib_rxdone(entry, &rxdesc); - if (test_bit(DEVICE_ENABLED_RADIO, &ring->rt2x00dev->flags)) { + if (test_bit(DEVICE_ENABLED_RADIO, &queue->rt2x00dev->flags)) { rt2x00_set_field32(&word, RXD_ENTRY_OWNER_NIC, 1); - rt2x00_desc_write(rxd, 0, word); + rt2x00_desc_write(priv_rx->desc, 0, word); } - rt2x00_ring_index_inc(ring); + rt2x00queue_index_inc(queue, Q_INDEX); } } EXPORT_SYMBOL_GPL(rt2x00pci_rxdone); -void rt2x00pci_txdone(struct rt2x00_dev *rt2x00dev, struct data_entry *entry, - const int tx_status, const int retry) +void rt2x00pci_txdone(struct rt2x00_dev *rt2x00dev, struct queue_entry *entry, + struct txdone_entry_desc *txdesc) { + struct queue_entry_priv_pci_tx *priv_tx = entry->priv_data; u32 word; - rt2x00lib_txdone(entry, tx_status, retry); + txdesc->control = &priv_tx->control; + rt2x00lib_txdone(entry, txdesc); /* * Make this entry available for reuse. */ entry->flags = 0; - rt2x00_desc_read(entry->priv, 0, &word); + rt2x00_desc_read(priv_tx->desc, 0, &word); rt2x00_set_field32(&word, TXD_ENTRY_OWNER_NIC, 0); rt2x00_set_field32(&word, TXD_ENTRY_VALID, 0); - rt2x00_desc_write(entry->priv, 0, word); + rt2x00_desc_write(priv_tx->desc, 0, word); - rt2x00_ring_index_done_inc(entry->ring); + rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE); /* - * If the data ring was full before the txdone handler + * If the data queue was full before the txdone handler * we must make sure the packet queue in the mac80211 stack * is reenabled when the txdone handler has finished. */ - if (!rt2x00_ring_full(entry->ring)) - ieee80211_wake_queue(rt2x00dev->hw, - entry->tx_status.control.queue); + if (!rt2x00queue_full(entry->queue)) + ieee80211_wake_queue(rt2x00dev->hw, priv_tx->control.queue); } EXPORT_SYMBOL_GPL(rt2x00pci_txdone); @@ -228,73 +231,83 @@ EXPORT_SYMBOL_GPL(rt2x00pci_txdone); /* * Device initialization handlers. */ -#define priv_offset(__ring, __i) \ -({ \ - ring->data_addr + (i * ring->desc_size); \ +#define dma_size(__queue) \ +({ \ + (__queue)->limit * \ + ((__queue)->desc_size + (__queue)->data_size);\ }) -#define data_addr_offset(__ring, __i) \ -({ \ - (__ring)->data_addr + \ - ((__ring)->stats.limit * (__ring)->desc_size) + \ - ((__i) * (__ring)->data_size); \ +#define priv_offset(__queue, __base, __i) \ +({ \ + (__base) + ((__i) * (__queue)->desc_size); \ }) -#define data_dma_offset(__ring, __i) \ -({ \ - (__ring)->data_dma + \ - ((__ring)->stats.limit * (__ring)->desc_size) + \ - ((__i) * (__ring)->data_size); \ +#define data_addr_offset(__queue, __base, __i) \ +({ \ + (__base) + \ + ((__queue)->limit * (__queue)->desc_size) + \ + ((__i) * (__queue)->data_size); \ }) -static int rt2x00pci_alloc_dma(struct rt2x00_dev *rt2x00dev, - struct data_ring *ring) +#define data_dma_offset(__queue, __base, __i) \ +({ \ + (__base) + \ + ((__queue)->limit * (__queue)->desc_size) + \ + ((__i) * (__queue)->data_size); \ +}) + +static int rt2x00pci_alloc_queue_dma(struct rt2x00_dev *rt2x00dev, + struct data_queue *queue) { + struct pci_dev *pci_dev = rt2x00dev_pci(rt2x00dev); + struct queue_entry_priv_pci_tx *priv_tx; + void *data_addr; + dma_addr_t data_dma; unsigned int i; /* * Allocate DMA memory for descriptor and buffer. */ - ring->data_addr = pci_alloc_consistent(rt2x00dev_pci(rt2x00dev), - rt2x00_get_ring_size(ring), - &ring->data_dma); - if (!ring->data_addr) + data_addr = pci_alloc_consistent(pci_dev, dma_size(queue), &data_dma); + if (!data_addr) return -ENOMEM; /* - * Initialize all ring entries to contain valid - * addresses. + * Initialize all queue entries to contain valid addresses. */ - for (i = 0; i < ring->stats.limit; i++) { - ring->entry[i].priv = priv_offset(ring, i); - ring->entry[i].data_addr = data_addr_offset(ring, i); - ring->entry[i].data_dma = data_dma_offset(ring, i); + for (i = 0; i < queue->limit; i++) { + priv_tx = queue->entries[i].priv_data; + priv_tx->desc = priv_offset(queue, data_addr, i); + priv_tx->data = data_addr_offset(queue, data_addr, i); + priv_tx->dma = data_dma_offset(queue, data_dma, i); } return 0; } -static void rt2x00pci_free_dma(struct rt2x00_dev *rt2x00dev, - struct data_ring *ring) +static void rt2x00pci_free_queue_dma(struct rt2x00_dev *rt2x00dev, + struct data_queue *queue) { - if (ring->data_addr) - pci_free_consistent(rt2x00dev_pci(rt2x00dev), - rt2x00_get_ring_size(ring), - ring->data_addr, ring->data_dma); - ring->data_addr = NULL; + struct pci_dev *pci_dev = rt2x00dev_pci(rt2x00dev); + struct queue_entry_priv_pci_tx *priv_tx = queue->entries[0].priv_data; + + if (priv_tx->data) + pci_free_consistent(pci_dev, dma_size(queue), + priv_tx->data, priv_tx->dma); + priv_tx->data = NULL; } int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev) { struct pci_dev *pci_dev = rt2x00dev_pci(rt2x00dev); - struct data_ring *ring; + struct data_queue *queue; int status; /* * Allocate DMA */ - ring_for_each(rt2x00dev, ring) { - status = rt2x00pci_alloc_dma(rt2x00dev, ring); + queue_for_each(rt2x00dev, queue) { + status = rt2x00pci_alloc_queue_dma(rt2x00dev, queue); if (status) goto exit; } @@ -321,7 +334,7 @@ EXPORT_SYMBOL_GPL(rt2x00pci_initialize); void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev) { - struct data_ring *ring; + struct data_queue *queue; /* * Free irq line. @@ -331,8 +344,8 @@ void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev) /* * Free DMA */ - ring_for_each(rt2x00dev, ring) - rt2x00pci_free_dma(rt2x00dev, ring); + queue_for_each(rt2x00dev, queue) + rt2x00pci_free_queue_dma(rt2x00dev, queue); } EXPORT_SYMBOL_GPL(rt2x00pci_uninitialize); @@ -530,5 +543,5 @@ EXPORT_SYMBOL_GPL(rt2x00pci_resume); */ MODULE_AUTHOR(DRV_PROJECT); MODULE_VERSION(DRV_VERSION); -MODULE_DESCRIPTION("rt2x00 library"); +MODULE_DESCRIPTION("rt2x00 pci library"); MODULE_LICENSE("GPL"); diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.h b/drivers/net/wireless/rt2x00/rt2x00pci.h index 9ac560b87b2b..3b1597ffb4f2 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.h +++ b/drivers/net/wireless/rt2x00/rt2x00pci.h @@ -97,15 +97,54 @@ int rt2x00pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, * TX data handlers. */ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev, - struct data_ring *ring, struct sk_buff *skb, + struct data_queue *queue, struct sk_buff *skb, struct ieee80211_tx_control *control); -/* - * RX/TX data handlers. +/** + * struct queue_entry_priv_pci_rx: Per RX entry PCI specific information + * + * @desc: Pointer to device descriptor. + * @data: Pointer to device's entry memory. + * @dma: DMA pointer to &data. + */ +struct queue_entry_priv_pci_rx { + __le32 *desc; + + void *data; + dma_addr_t dma; +}; + +/** + * struct queue_entry_priv_pci_tx: Per TX entry PCI specific information + * + * @desc: Pointer to device descriptor + * @data: Pointer to device's entry memory. + * @dma: DMA pointer to &data. + * @control: mac80211 control structure used to transmit data. + */ +struct queue_entry_priv_pci_tx { + __le32 *desc; + + void *data; + dma_addr_t dma; + + struct ieee80211_tx_control control; +}; + +/** + * rt2x00pci_rxdone - Handle RX done events + * @rt2x00dev: Device pointer, see &struct rt2x00_dev. */ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev); -void rt2x00pci_txdone(struct rt2x00_dev *rt2x00dev, struct data_entry *entry, - const int tx_status, const int retry); + +/** + * rt2x00pci_txdone - Handle TX done events + * @rt2x00dev: Device pointer, see &struct rt2x00_dev. + * @entry: Entry which has completed the transmission of a frame. + * @desc: TX done descriptor + */ +void rt2x00pci_txdone(struct rt2x00_dev *rt2x00dev, struct queue_entry *entry, + struct txdone_entry_desc *desc); /* * Device initialization handlers. diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c new file mode 100644 index 000000000000..921eca35719d --- /dev/null +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -0,0 +1,291 @@ +/* + Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the + Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + Module: rt2x00lib + Abstract: rt2x00 queue specific routines. + */ + +#include +#include + +#include "rt2x00.h" +#include "rt2x00lib.h" + +struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev, + const enum ieee80211_tx_queue queue) +{ + int atim = test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags); + + if (queue < rt2x00dev->hw->queues && rt2x00dev->tx) + return &rt2x00dev->tx[queue]; + + if (!rt2x00dev->bcn) + return NULL; + + if (queue == IEEE80211_TX_QUEUE_BEACON) + return &rt2x00dev->bcn[0]; + else if (queue == IEEE80211_TX_QUEUE_AFTER_BEACON && atim) + return &rt2x00dev->bcn[1]; + + return NULL; +} +EXPORT_SYMBOL_GPL(rt2x00queue_get_queue); + +struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue, + enum queue_index index) +{ + struct queue_entry *entry; + + if (unlikely(index >= Q_INDEX_MAX)) { + ERROR(queue->rt2x00dev, + "Entry requested from invalid index type (%d)\n", index); + return NULL; + } + + spin_lock(&queue->lock); + + entry = &queue->entries[queue->index[index]]; + + spin_unlock(&queue->lock); + + return entry; +} +EXPORT_SYMBOL_GPL(rt2x00queue_get_entry); + +void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index) +{ + if (unlikely(index >= Q_INDEX_MAX)) { + ERROR(queue->rt2x00dev, + "Index change on invalid index type (%d)\n", index); + return; + } + + spin_lock(&queue->lock); + + queue->index[index]++; + if (queue->index[index] >= queue->limit) + queue->index[index] = 0; + + queue->length--; + queue->count += (index == Q_INDEX_DONE); + + spin_unlock(&queue->lock); +} +EXPORT_SYMBOL_GPL(rt2x00queue_index_inc); + +static void rt2x00queue_reset(struct data_queue *queue) +{ + spin_lock(&queue->lock); + + queue->count = 0; + queue->length = 0; + memset(queue->index, 0, sizeof(queue->index)); + + spin_unlock(&queue->lock); +} + +void rt2x00queue_init_rx(struct rt2x00_dev *rt2x00dev) +{ + struct data_queue *queue = rt2x00dev->rx; + unsigned int i; + + rt2x00queue_reset(queue); + + if (!rt2x00dev->ops->lib->init_rxentry) + return; + + for (i = 0; i < queue->limit; i++) + rt2x00dev->ops->lib->init_rxentry(rt2x00dev, + &queue->entries[i]); +} + +void rt2x00queue_init_tx(struct rt2x00_dev *rt2x00dev) +{ + struct data_queue *queue; + unsigned int i; + + txall_queue_for_each(rt2x00dev, queue) { + rt2x00queue_reset(queue); + + if (!rt2x00dev->ops->lib->init_txentry) + continue; + + for (i = 0; i < queue->limit; i++) + rt2x00dev->ops->lib->init_txentry(rt2x00dev, + &queue->entries[i]); + } +} + +static int rt2x00queue_alloc_entries(struct data_queue *queue, + const struct data_queue_desc *qdesc) +{ + struct queue_entry *entries; + unsigned int entry_size; + unsigned int i; + + rt2x00queue_reset(queue); + + queue->limit = qdesc->entry_num; + queue->data_size = qdesc->data_size; + queue->desc_size = qdesc->desc_size; + + /* + * Allocate all queue entries. + */ + entry_size = sizeof(*entries) + qdesc->priv_size; + entries = kzalloc(queue->limit * entry_size, GFP_KERNEL); + if (!entries) + return -ENOMEM; + +#define QUEUE_ENTRY_PRIV_OFFSET(__base, __index, __limit, __esize, __psize) \ + ( (__base) + ((__limit) * (__esize)) + ((__index) * (__psize)) ) + + for (i = 0; i < queue->limit; i++) { + entries[i].flags = 0; + entries[i].queue = queue; + entries[i].skb = NULL; + entries[i].entry_idx = i; + entries[i].priv_data = + QUEUE_ENTRY_PRIV_OFFSET(entries, i, queue->limit, + sizeof(*entries), qdesc->priv_size); + } + +#undef QUEUE_ENTRY_PRIV_OFFSET + + queue->entries = entries; + + return 0; +} + +int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev) +{ + struct data_queue *queue; + int status; + + + status = rt2x00queue_alloc_entries(rt2x00dev->rx, rt2x00dev->ops->rx); + if (status) + goto exit; + + tx_queue_for_each(rt2x00dev, queue) { + status = rt2x00queue_alloc_entries(queue, rt2x00dev->ops->tx); + if (status) + goto exit; + } + + status = rt2x00queue_alloc_entries(rt2x00dev->bcn, rt2x00dev->ops->bcn); + if (status) + goto exit; + + if (!test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags)) + return 0; + + status = rt2x00queue_alloc_entries(&rt2x00dev->bcn[1], + rt2x00dev->ops->atim); + if (status) + goto exit; + + return 0; + +exit: + ERROR(rt2x00dev, "Queue entries allocation failed.\n"); + + rt2x00queue_uninitialize(rt2x00dev); + + return status; +} + +void rt2x00queue_uninitialize(struct rt2x00_dev *rt2x00dev) +{ + struct data_queue *queue; + + queue_for_each(rt2x00dev, queue) { + kfree(queue->entries); + queue->entries = NULL; + } +} + +int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev) +{ + struct data_queue *queue; + enum data_queue_qid qid; + unsigned int req_atim = + !!test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags); + + /* + * We need the following queues: + * RX: 1 + * TX: hw->queues + * Beacon: 1 + * Atim: 1 (if required) + */ + rt2x00dev->data_queues = 2 + rt2x00dev->hw->queues + req_atim; + + queue = kzalloc(rt2x00dev->data_queues * sizeof(*queue), GFP_KERNEL); + if (!queue) { + ERROR(rt2x00dev, "Queue allocation failed.\n"); + return -ENOMEM; + } + + /* + * Initialize pointers + */ + rt2x00dev->rx = queue; + rt2x00dev->tx = &queue[1]; + rt2x00dev->bcn = &queue[1 + rt2x00dev->hw->queues]; + + /* + * Initialize queue parameters. + * RX: qid = QID_RX + * TX: qid = QID_AC_BE + index + * TX: cw_min: 2^5 = 32. + * TX: cw_max: 2^10 = 1024. + * BCN & Atim: qid = QID_MGMT + */ + qid = QID_AC_BE; + queue_for_each(rt2x00dev, queue) { + spin_lock_init(&queue->lock); + + queue->rt2x00dev = rt2x00dev; + queue->qid = qid++; + queue->aifs = 2; + queue->cw_min = 5; + queue->cw_max = 10; + } + + /* + * Fix non-TX data qid's + */ + rt2x00dev->rx->qid = QID_RX; + rt2x00dev->bcn[0].qid = QID_MGMT; + if (req_atim) + rt2x00dev->bcn[1].qid = QID_MGMT; + + return 0; +} + +void rt2x00queue_free(struct rt2x00_dev *rt2x00dev) +{ + kfree(rt2x00dev->rx); + rt2x00dev->rx = NULL; + rt2x00dev->tx = NULL; + rt2x00dev->bcn = NULL; +} diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h new file mode 100644 index 000000000000..507116c6c9fe --- /dev/null +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -0,0 +1,435 @@ +/* + Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the + Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + Module: rt2x00 + Abstract: rt2x00 queue datastructures and routines + */ + +#ifndef RT2X00QUEUE_H +#define RT2X00QUEUE_H + +#include + +/** + * DOC: Entrie frame size + * + * Ralink PCI devices demand the Frame size to be a multiple of 128 bytes, + * for USB devices this restriction does not apply, but the value of + * 2432 makes sense since it is big enough to contain the maximum fragment + * size according to the ieee802.11 specs. + */ +#define DATA_FRAME_SIZE 2432 +#define MGMT_FRAME_SIZE 256 + +/** + * DOC: Number of entries per queue + * + * After research it was concluded that 12 entries in a RX and TX + * queue would be sufficient. Although this is almost one third of + * the amount the legacy driver allocated, the queues aren't getting + * filled to the maximum even when working with the maximum rate. + * + * FIXME: For virtual interfaces we need a different number + * of beacons, since more interfaces require more beacons. + */ +#define RX_ENTRIES 12 +#define TX_ENTRIES 12 +#define BEACON_ENTRIES 1 +#define ATIM_ENTRIES 1 + +/** + * enum data_queue_qid: Queue identification + */ +enum data_queue_qid { + QID_AC_BE = 0, + QID_AC_BK = 1, + QID_AC_VI = 2, + QID_AC_VO = 3, + QID_HCCA = 4, + QID_MGMT = 13, + QID_RX = 14, + QID_OTHER = 15, +}; + +/** + * struct skb_frame_desc: Descriptor information for the skb buffer + * + * This structure is placed over the skb->cb array, this means that + * this structure should not exceed the size of that array (48 bytes). + * + * @flags: Frame flags. + * @frame_type: Frame type, see &enum rt2x00_dump_type. + * @data: Pointer to data part of frame (Start of ieee80211 header). + * @desc: Pointer to descriptor part of the frame. + * Note that this pointer could point to something outside + * of the scope of the skb->data pointer. + * @data_len: Length of the frame data. + * @desc_len: Length of the frame descriptor. + + * @entry: The entry to which this sk buffer belongs. + */ +struct skb_frame_desc { + unsigned int flags; + + unsigned int frame_type; + + void *data; + void *desc; + + unsigned int data_len; + unsigned int desc_len; + + struct queue_entry *entry; +}; + +static inline struct skb_frame_desc* get_skb_frame_desc(struct sk_buff *skb) +{ + BUILD_BUG_ON(sizeof(struct skb_frame_desc) > sizeof(skb->cb)); + return (struct skb_frame_desc *)&skb->cb[0]; +} + +/** + * struct rxdone_entry_desc: RX Entry descriptor + * + * Summary of information that has been read from the RX frame descriptor. + * + * @signal: Signal of the received frame. + * @rssi: RSSI of the received frame. + * @ofdm: Was frame send with an OFDM rate. + * @size: Data size of the received frame. + * @flags: MAC80211 receive flags (See &enum mac80211_rx_flags). + * @my_bss: Does this frame originate from device's BSS. + */ +struct rxdone_entry_desc { + int signal; + int rssi; + int ofdm; + int size; + int flags; + int my_bss; +}; + +/** + * struct txdone_entry_desc: TX done entry descriptor + * + * Summary of information that has been read from the TX frame descriptor + * after the device is done with transmission. + * + * @control: Control structure which was used to transmit the frame. + * @status: TX status (See &enum tx_status). + * @retry: Retry count. + */ +struct txdone_entry_desc { + struct ieee80211_tx_control *control; + int status; + int retry; +}; + +/** + * enum txentry_desc_flags: Status flags for TX entry descriptor + * + * @ENTRY_TXD_RTS_FRAME: This frame is a RTS frame. + * @ENTRY_TXD_OFDM_RATE: This frame is send out with an OFDM rate. + * @ENTRY_TXD_MORE_FRAG: This frame is followed by another fragment. + * @ENTRY_TXD_REQ_TIMESTAMP: Require timestamp to be inserted. + * @ENTRY_TXD_BURST: This frame belongs to the same burst event. + * @ENTRY_TXD_ACK: An ACK is required for this frame. + */ +enum txentry_desc_flags { + ENTRY_TXD_RTS_FRAME, + ENTRY_TXD_OFDM_RATE, + ENTRY_TXD_MORE_FRAG, + ENTRY_TXD_REQ_TIMESTAMP, + ENTRY_TXD_BURST, + ENTRY_TXD_ACK, +}; + +/** + * struct txentry_desc: TX Entry descriptor + * + * Summary of information for the frame descriptor before sending a TX frame. + * + * @flags: Descriptor flags (See &enum queue_entry_flags). + * @queue: Queue identification (See &enum data_queue_qid). + * @length_high: PLCP length high word. + * @length_low: PLCP length low word. + * @signal: PLCP signal. + * @service: PLCP service. + * @aifs: AIFS value. + * @ifs: IFS value. + * @cw_min: cwmin value. + * @cw_max: cwmax value. + */ +struct txentry_desc { + unsigned long flags; + + enum data_queue_qid queue; + + u16 length_high; + u16 length_low; + u16 signal; + u16 service; + + int aifs; + int ifs; + int cw_min; + int cw_max; +}; + +/** + * enum queue_entry_flags: Status flags for queue entry + * + * @ENTRY_BCN_ASSIGNED: This entry has been assigned to an interface. + * As long as this bit is set, this entry may only be touched + * through the interface structure. + * @ENTRY_OWNER_DEVICE_DATA: This entry is owned by the device for data + * transfer (either TX or RX depending on the queue). The entry should + * only be touched after the device has signaled it is done with it. + * @ENTRY_OWNER_DEVICE_CRYPTO: This entry is owned by the device for data + * encryption or decryption. The entry should only be touched after + * the device has signaled it is done with it. + */ + +enum queue_entry_flags { + ENTRY_BCN_ASSIGNED, + ENTRY_OWNER_DEVICE_DATA, + ENTRY_OWNER_DEVICE_CRYPTO, +}; + +/** + * struct queue_entry: Entry inside the &struct data_queue + * + * @flags: Entry flags, see &enum queue_entry_flags. + * @queue: The data queue (&struct data_queue) to which this entry belongs. + * @skb: The buffer which is currently being transmitted (for TX queue), + * or used to directly recieve data in (for RX queue). + * @entry_idx: The entry index number. + * @priv_data: Private data belonging to this queue entry. The pointer + * points to data specific to a particular driver and queue type. + */ +struct queue_entry { + unsigned long flags; + + struct data_queue *queue; + + struct sk_buff *skb; + + unsigned int entry_idx; + + void *priv_data; +}; + +/** + * enum queue_index: Queue index type + * + * @Q_INDEX: Index pointer to the current entry in the queue, if this entry is + * owned by the hardware then the queue is considered to be full. + * @Q_INDEX_DONE: Index pointer to the next entry which will be completed by + * the hardware and for which we need to run the txdone handler. If this + * entry is not owned by the hardware the queue is considered to be empty. + * @Q_INDEX_CRYPTO: Index pointer to the next entry which encryption/decription + * will be completed by the hardware next. + * @Q_INDEX_MAX: Keep last, used in &struct data_queue to determine the size + * of the index array. + */ +enum queue_index { + Q_INDEX, + Q_INDEX_DONE, + Q_INDEX_CRYPTO, + Q_INDEX_MAX, +}; + +/** + * struct data_queue: Data queue + * + * @rt2x00dev: Pointer to main &struct rt2x00dev where this queue belongs to. + * @entries: Base address of the &struct queue_entry which are + * part of this queue. + * @qid: The queue identification, see &enum data_queue_qid. + * @lock: Spinlock to protect index handling. Whenever @index, @index_done or + * @index_crypt needs to be changed this lock should be grabbed to prevent + * index corruption due to concurrency. + * @count: Number of frames handled in the queue. + * @limit: Maximum number of entries in the queue. + * @length: Number of frames in queue. + * @index: Index pointers to entry positions in the queue, + * use &enum queue_index to get a specific index field. + * @aifs: The aifs value for outgoing frames (field ignored in RX queue). + * @cw_min: The cw min value for outgoing frames (field ignored in RX queue). + * @cw_max: The cw max value for outgoing frames (field ignored in RX queue). + * @data_size: Maximum data size for the frames in this queue. + * @desc_size: Hardware descriptor size for the data in this queue. + */ +struct data_queue { + struct rt2x00_dev *rt2x00dev; + struct queue_entry *entries; + + enum data_queue_qid qid; + + spinlock_t lock; + unsigned int count; + unsigned short limit; + unsigned short length; + unsigned short index[Q_INDEX_MAX]; + + unsigned short aifs; + unsigned short cw_min; + unsigned short cw_max; + + unsigned short data_size; + unsigned short desc_size; +}; + +/** + * struct data_queue_desc: Data queue description + * + * The information in this structure is used by drivers + * to inform rt2x00lib about the creation of the data queue. + * + * @entry_num: Maximum number of entries for a queue. + * @data_size: Maximum data size for the frames in this queue. + * @desc_size: Hardware descriptor size for the data in this queue. + * @priv_size: Size of per-queue_entry private data. + */ +struct data_queue_desc { + unsigned short entry_num; + unsigned short data_size; + unsigned short desc_size; + unsigned short priv_size; +}; + +/** + * queue_end - Return pointer to the last queue (HELPER MACRO). + * @__dev: Pointer to &struct rt2x00_dev + * + * Using the base rx pointer and the maximum number of available queues, + * this macro will return the address of 1 position beyond the end of the + * queues array. + */ +#define queue_end(__dev) \ + &(__dev)->rx[(__dev)->data_queues] + +/** + * tx_queue_end - Return pointer to the last TX queue (HELPER MACRO). + * @__dev: Pointer to &struct rt2x00_dev + * + * Using the base tx pointer and the maximum number of available TX + * queues, this macro will return the address of 1 position beyond + * the end of the TX queue array. + */ +#define tx_queue_end(__dev) \ + &(__dev)->tx[(__dev)->hw->queues] + +/** + * queue_loop - Loop through the queues within a specific range (HELPER MACRO). + * @__entry: Pointer where the current queue entry will be stored in. + * @__start: Start queue pointer. + * @__end: End queue pointer. + * + * This macro will loop through all queues between &__start and &__end. + */ +#define queue_loop(__entry, __start, __end) \ + for ((__entry) = (__start); \ + prefetch(&(__entry)[1]), (__entry) != (__end); \ + (__entry) = &(__entry)[1]) + +/** + * queue_for_each - Loop through all queues + * @__dev: Pointer to &struct rt2x00_dev + * @__entry: Pointer where the current queue entry will be stored in. + * + * This macro will loop through all available queues. + */ +#define queue_for_each(__dev, __entry) \ + queue_loop(__entry, (__dev)->rx, queue_end(__dev)) + +/** + * tx_queue_for_each - Loop through the TX queues + * @__dev: Pointer to &struct rt2x00_dev + * @__entry: Pointer where the current queue entry will be stored in. + * + * This macro will loop through all TX related queues excluding + * the Beacon and Atim queues. + */ +#define tx_queue_for_each(__dev, __entry) \ + queue_loop(__entry, (__dev)->tx, tx_queue_end(__dev)) + +/** + * txall_queue_for_each - Loop through all TX related queues + * @__dev: Pointer to &struct rt2x00_dev + * @__entry: Pointer where the current queue entry will be stored in. + * + * This macro will loop through all TX related queues including + * the Beacon and Atim queues. + */ +#define txall_queue_for_each(__dev, __entry) \ + queue_loop(__entry, (__dev)->tx, queue_end(__dev)) + +/** + * rt2x00queue_empty - Check if the queue is empty. + * @queue: Queue to check if empty. + */ +static inline int rt2x00queue_empty(struct data_queue *queue) +{ + return queue->length == 0; +} + +/** + * rt2x00queue_full - Check if the queue is full. + * @queue: Queue to check if full. + */ +static inline int rt2x00queue_full(struct data_queue *queue) +{ + return queue->length == queue->limit; +} + +/** + * rt2x00queue_free - Check the number of available entries in queue. + * @queue: Queue to check. + */ +static inline int rt2x00queue_available(struct data_queue *queue) +{ + return queue->limit - queue->length; +} + +/** + * rt2x00_desc_read - Read a word from the hardware descriptor. + * @desc: Base descriptor address + * @word: Word index from where the descriptor should be read. + * @value: Address where the descriptor value should be written into. + */ +static inline void rt2x00_desc_read(__le32 *desc, const u8 word, u32 *value) +{ + *value = le32_to_cpu(desc[word]); +} + +/** + * rt2x00_desc_write - wrote a word to the hardware descriptor. + * @desc: Base descriptor address + * @word: Word index from where the descriptor should be written. + * @value: Value that should be written into the descriptor. + */ +static inline void rt2x00_desc_write(__le32 *desc, const u8 word, u32 value) +{ + desc[word] = cpu_to_le32(value); +} + +#endif /* RT2X00QUEUE_H */ diff --git a/drivers/net/wireless/rt2x00/rt2x00reg.h b/drivers/net/wireless/rt2x00/rt2x00reg.h index e99eab19e9d7..e0ebe51c082f 100644 --- a/drivers/net/wireless/rt2x00/rt2x00reg.h +++ b/drivers/net/wireless/rt2x00/rt2x00reg.h @@ -29,7 +29,7 @@ /* * TX result flags. */ -enum TX_STATUS { +enum tx_status { TX_SUCCESS = 0, TX_SUCCESS_RETRY = 1, TX_FAIL_RETRY = 2, diff --git a/drivers/net/wireless/rt2x00/rt2x00ring.h b/drivers/net/wireless/rt2x00/rt2x00ring.h deleted file mode 100644 index 764c2553d06c..000000000000 --- a/drivers/net/wireless/rt2x00/rt2x00ring.h +++ /dev/null @@ -1,290 +0,0 @@ -/* - Copyright (C) 2004 - 2008 rt2x00 SourceForge Project - - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the - Free Software Foundation, Inc., - 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* - Module: rt2x00 - Abstract: rt2x00 ring datastructures and routines - */ - -#ifndef RT2X00RING_H -#define RT2X00RING_H - -/* - * skb_desc - * Descriptor information for the skb buffer - */ -struct skb_desc { - unsigned int frame_type; - - unsigned int desc_len; - unsigned int data_len; - - void *desc; - void *data; - - struct data_ring *ring; - struct data_entry *entry; -}; - -static inline struct skb_desc* get_skb_desc(struct sk_buff *skb) -{ - return (struct skb_desc*)&skb->cb[0]; -} - -/* - * rxdata_entry_desc - * Summary of information that has been read from the - * RX frame descriptor. - */ -struct rxdata_entry_desc { - int signal; - int rssi; - int ofdm; - int size; - int flags; - int my_bss; -}; - -/* - * txdata_entry_desc - * Summary of information that should be written into the - * descriptor for sending a TX frame. - */ -struct txdata_entry_desc { - unsigned long flags; -#define ENTRY_TXDONE 1 -#define ENTRY_TXD_RTS_FRAME 2 -#define ENTRY_TXD_OFDM_RATE 3 -#define ENTRY_TXD_MORE_FRAG 4 -#define ENTRY_TXD_REQ_TIMESTAMP 5 -#define ENTRY_TXD_BURST 6 -#define ENTRY_TXD_ACK 7 - -/* - * Queue ID. ID's 0-4 are data TX rings - */ - int queue; -#define QUEUE_MGMT 13 -#define QUEUE_RX 14 -#define QUEUE_OTHER 15 - - /* - * PLCP values. - */ - u16 length_high; - u16 length_low; - u16 signal; - u16 service; - - /* - * Timing information - */ - int aifs; - int ifs; - int cw_min; - int cw_max; -}; - -/* - * data_entry - * The data ring is a list of data entries. - * Each entry holds a reference to the descriptor - * and the data buffer. For TX rings the reference to the - * sk_buff of the packet being transmitted is also stored here. - */ -struct data_entry { - /* - * Status flags - */ - unsigned long flags; -#define ENTRY_OWNER_NIC 1 - - /* - * Ring we belong to. - */ - struct data_ring *ring; - - /* - * sk_buff for the packet which is being transmitted - * in this entry (Only used with TX related rings). - */ - struct sk_buff *skb; - - /* - * Store a ieee80211_tx_status structure in each - * ring entry, this will optimize the txdone - * handler. - */ - struct ieee80211_tx_status tx_status; - - /* - * private pointer specific to driver. - */ - void *priv; - - /* - * Data address for this entry. - */ - void *data_addr; - dma_addr_t data_dma; - - /* - * Entry identification number (index). - */ - unsigned int entry_idx; -}; - -/* - * data_ring - * Data rings are used by the device to send and receive packets. - * The data_addr is the base address of the data memory. - * To determine at which point in the ring we are, - * have to use the rt2x00_ring_index_*() functions. - */ -struct data_ring { - /* - * Pointer to main rt2x00dev structure where this - * ring belongs to. - */ - struct rt2x00_dev *rt2x00dev; - - /* - * Base address for the device specific data entries. - */ - struct data_entry *entry; - - /* - * TX queue statistic info. - */ - struct ieee80211_tx_queue_stats_data stats; - - /* - * TX Queue parameters. - */ - struct ieee80211_tx_queue_params tx_params; - - /* - * Base address for data ring. - */ - dma_addr_t data_dma; - void *data_addr; - - /* - * Queue identification number: - * RX: 0 - * TX: IEEE80211_TX_* - */ - unsigned int queue_idx; - - /* - * Index variables. - */ - u16 index; - u16 index_done; - - /* - * Size of packet and descriptor in bytes. - */ - u16 data_size; - u16 desc_size; -}; - -/* - * Handlers to determine the address of the current device specific - * data entry, where either index or index_done points to. - */ -static inline struct data_entry *rt2x00_get_data_entry(struct data_ring *ring) -{ - return &ring->entry[ring->index]; -} - -static inline struct data_entry *rt2x00_get_data_entry_done(struct data_ring - *ring) -{ - return &ring->entry[ring->index_done]; -} - -/* - * Total ring memory - */ -static inline int rt2x00_get_ring_size(struct data_ring *ring) -{ - return ring->stats.limit * (ring->desc_size + ring->data_size); -} - -/* - * Ring index manipulation functions. - */ -static inline void rt2x00_ring_index_inc(struct data_ring *ring) -{ - ring->index++; - if (ring->index >= ring->stats.limit) - ring->index = 0; - ring->stats.len++; -} - -static inline void rt2x00_ring_index_done_inc(struct data_ring *ring) -{ - ring->index_done++; - if (ring->index_done >= ring->stats.limit) - ring->index_done = 0; - ring->stats.len--; - ring->stats.count++; -} - -static inline void rt2x00_ring_index_clear(struct data_ring *ring) -{ - ring->index = 0; - ring->index_done = 0; - ring->stats.len = 0; - ring->stats.count = 0; -} - -static inline int rt2x00_ring_empty(struct data_ring *ring) -{ - return ring->stats.len == 0; -} - -static inline int rt2x00_ring_full(struct data_ring *ring) -{ - return ring->stats.len == ring->stats.limit; -} - -static inline int rt2x00_ring_free(struct data_ring *ring) -{ - return ring->stats.limit - ring->stats.len; -} - -/* - * TX/RX Descriptor access functions. - */ -static inline void rt2x00_desc_read(__le32 *desc, - const u8 word, u32 *value) -{ - *value = le32_to_cpu(desc[word]); -} - -static inline void rt2x00_desc_write(__le32 *desc, - const u8 word, const u32 value) -{ - desc[word] = cpu_to_le32(value); -} - -#endif /* RT2X00RING_H */ diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 47cd0a5bf17c..fc606448908e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -40,8 +40,7 @@ int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev, void *buffer, const u16 buffer_length, const int timeout) { - struct usb_device *usb_dev = - interface_to_usbdev(rt2x00dev_usb(rt2x00dev)); + struct usb_device *usb_dev = rt2x00dev_usb_dev(rt2x00dev); int status; unsigned int i; unsigned int pipe = @@ -128,15 +127,15 @@ EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request_buff); */ static void rt2x00usb_interrupt_txdone(struct urb *urb) { - struct data_entry *entry = (struct data_entry *)urb->context; - struct data_ring *ring = entry->ring; - struct rt2x00_dev *rt2x00dev = ring->rt2x00dev; + struct queue_entry *entry = (struct queue_entry *)urb->context; + struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; + struct queue_entry_priv_usb_tx *priv_tx = entry->priv_data; + struct txdone_entry_desc txdesc; __le32 *txd = (__le32 *)entry->skb->data; u32 word; - int tx_status; if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) || - !__test_and_clear_bit(ENTRY_OWNER_NIC, &entry->flags)) + !__test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) return; rt2x00_desc_read(txd, 0, &word); @@ -144,45 +143,46 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb) /* * Remove the descriptor data from the buffer. */ - skb_pull(entry->skb, ring->desc_size); + skb_pull(entry->skb, entry->queue->desc_size); /* * Obtain the status about this packet. */ - tx_status = !urb->status ? TX_SUCCESS : TX_FAIL_RETRY; + txdesc.status = !urb->status ? TX_SUCCESS : TX_FAIL_RETRY; + txdesc.retry = 0; + txdesc.control = &priv_tx->control; - rt2x00lib_txdone(entry, tx_status, 0); + rt2x00lib_txdone(entry, &txdesc); /* * Make this entry available for reuse. */ entry->flags = 0; - rt2x00_ring_index_done_inc(entry->ring); + rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE); /* - * If the data ring was full before the txdone handler + * If the data queue was full before the txdone handler * we must make sure the packet queue in the mac80211 stack * is reenabled when the txdone handler has finished. */ - if (!rt2x00_ring_full(ring)) - ieee80211_wake_queue(rt2x00dev->hw, - entry->tx_status.control.queue); + if (!rt2x00queue_full(entry->queue)) + ieee80211_wake_queue(rt2x00dev->hw, priv_tx->control.queue); } int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev, - struct data_ring *ring, struct sk_buff *skb, + struct data_queue *queue, struct sk_buff *skb, struct ieee80211_tx_control *control) { - struct usb_device *usb_dev = - interface_to_usbdev(rt2x00dev_usb(rt2x00dev)); - struct data_entry *entry = rt2x00_get_data_entry(ring); - struct skb_desc *desc; + struct usb_device *usb_dev = rt2x00dev_usb_dev(rt2x00dev); + struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX); + struct queue_entry_priv_usb_tx *priv_tx = entry->priv_data; + struct skb_frame_desc *skbdesc; u32 length; - if (rt2x00_ring_full(ring)) + if (rt2x00queue_full(queue)) return -EINVAL; - if (test_bit(ENTRY_OWNER_NIC, &entry->flags)) { + if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) { ERROR(rt2x00dev, "Arrived at non-free entry in the non-full queue %d.\n" "Please file bug report to %s.\n", @@ -193,19 +193,19 @@ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev, /* * Add the descriptor in front of the skb. */ - skb_push(skb, ring->desc_size); - memset(skb->data, 0, ring->desc_size); + skb_push(skb, queue->desc_size); + memset(skb->data, 0, queue->desc_size); /* * Fill in skb descriptor */ - desc = get_skb_desc(skb); - desc->desc_len = ring->desc_size; - desc->data_len = skb->len - ring->desc_size; - desc->desc = skb->data; - desc->data = skb->data + ring->desc_size; - desc->ring = ring; - desc->entry = entry; + skbdesc = get_skb_frame_desc(skb); + memset(skbdesc, 0, sizeof(*skbdesc)); + skbdesc->data = skb->data + queue->desc_size; + skbdesc->data_len = queue->data_size; + skbdesc->desc = skb->data; + skbdesc->desc_len = queue->desc_size; + skbdesc->entry = entry; rt2x00lib_write_tx_desc(rt2x00dev, skb, control); @@ -219,12 +219,12 @@ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev, /* * Initialize URB and send the frame to the device. */ - __set_bit(ENTRY_OWNER_NIC, &entry->flags); - usb_fill_bulk_urb(entry->priv, usb_dev, usb_sndbulkpipe(usb_dev, 1), + __set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); + usb_fill_bulk_urb(priv_tx->urb, usb_dev, usb_sndbulkpipe(usb_dev, 1), skb->data, length, rt2x00usb_interrupt_txdone, entry); - usb_submit_urb(entry->priv, GFP_ATOMIC); + usb_submit_urb(priv_tx->urb, GFP_ATOMIC); - rt2x00_ring_index_inc(ring); + rt2x00queue_index_inc(queue, Q_INDEX); return 0; } @@ -233,20 +233,41 @@ EXPORT_SYMBOL_GPL(rt2x00usb_write_tx_data); /* * RX data handlers. */ +static struct sk_buff* rt2x00usb_alloc_rxskb(struct data_queue *queue) +{ + struct sk_buff *skb; + unsigned int frame_size; + + /* + * As alignment we use 2 and not NET_IP_ALIGN because we need + * to be sure we have 2 bytes room in the head. (NET_IP_ALIGN + * can be 0 on some hardware). We use these 2 bytes for frame + * alignment later, we assume that the chance that + * header_size % 4 == 2 is bigger then header_size % 2 == 0 + * and thus optimize alignment by reserving the 2 bytes in + * advance. + */ + frame_size = queue->data_size + queue->desc_size; + skb = dev_alloc_skb(frame_size + 2); + if (!skb) + return NULL; + + skb_reserve(skb, 2); + skb_put(skb, frame_size); + + return skb; +} + static void rt2x00usb_interrupt_rxdone(struct urb *urb) { - struct data_entry *entry = (struct data_entry *)urb->context; - struct data_ring *ring = entry->ring; - struct rt2x00_dev *rt2x00dev = ring->rt2x00dev; + struct queue_entry *entry = (struct queue_entry *)urb->context; + struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct sk_buff *skb; - struct ieee80211_hdr *hdr; - struct skb_desc *skbdesc; - struct rxdata_entry_desc desc; - int header_size; - int frame_size; + struct skb_frame_desc *skbdesc; + struct rxdone_entry_desc rxdesc; if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) || - !test_and_clear_bit(ENTRY_OWNER_NIC, &entry->flags)) + !test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) return; /* @@ -254,67 +275,32 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) * to be actually valid, or if the urb is signaling * a problem. */ - if (urb->actual_length < entry->ring->desc_size || urb->status) + if (urb->actual_length < entry->queue->desc_size || urb->status) goto skip_entry; /* * Fill in skb descriptor */ - skbdesc = get_skb_desc(entry->skb); - skbdesc->ring = ring; + skbdesc = get_skb_frame_desc(entry->skb); + memset(skbdesc, 0, sizeof(*skbdesc)); skbdesc->entry = entry; - memset(&desc, 0, sizeof(desc)); - rt2x00dev->ops->lib->fill_rxdone(entry, &desc); + memset(&rxdesc, 0, sizeof(rxdesc)); + rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc); /* * Allocate a new sk buffer to replace the current one. * If allocation fails, we should drop the current frame * so we can recycle the existing sk buffer for the new frame. - * As alignment we use 2 and not NET_IP_ALIGN because we need - * to be sure we have 2 bytes room in the head. (NET_IP_ALIGN - * can be 0 on some hardware). We use these 2 bytes for frame - * alignment later, we assume that the chance that - * header_size % 4 == 2 is bigger then header_size % 2 == 0 - * and thus optimize alignment by reserving the 2 bytes in - * advance. */ - frame_size = entry->ring->data_size + entry->ring->desc_size; - skb = dev_alloc_skb(frame_size + 2); + skb = rt2x00usb_alloc_rxskb(entry->queue); if (!skb) goto skip_entry; - skb_reserve(skb, 2); - skb_put(skb, frame_size); - - /* - * The data behind the ieee80211 header must be - * aligned on a 4 byte boundary. - */ - hdr = (struct ieee80211_hdr *)entry->skb->data; - header_size = - ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control)); - - if (header_size % 4 == 0) { - skb_push(entry->skb, 2); - memmove(entry->skb->data, entry->skb->data + 2, skb->len - 2); - } - - /* - * Trim the entire buffer down to only contain the valid frame data - * excluding the device descriptor. The position of the descriptor - * varies. This means that we should check where the descriptor is - * and decide if we need to pull the data pointer to exclude the - * device descriptor. - */ - if (skbdesc->data > skbdesc->desc) - skb_pull(entry->skb, skbdesc->desc_len); - skb_trim(entry->skb, desc.size); - /* * Send the frame to rt2x00lib for further processing. */ - rt2x00lib_rxdone(entry, entry->skb, &desc); + rt2x00lib_rxdone(entry, &rxdesc); /* * Replace current entry's skb with the newly allocated one, @@ -325,12 +311,12 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) urb->transfer_buffer_length = entry->skb->len; skip_entry: - if (test_bit(DEVICE_ENABLED_RADIO, &ring->rt2x00dev->flags)) { - __set_bit(ENTRY_OWNER_NIC, &entry->flags); + if (test_bit(DEVICE_ENABLED_RADIO, &entry->queue->rt2x00dev->flags)) { + __set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); usb_submit_urb(urb, GFP_ATOMIC); } - rt2x00_ring_index_inc(ring); + rt2x00queue_index_inc(entry->queue, Q_INDEX); } /* @@ -338,18 +324,27 @@ skip_entry: */ void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev) { - struct data_ring *ring; + struct queue_entry_priv_usb_rx *priv_rx; + struct queue_entry_priv_usb_tx *priv_tx; + struct data_queue *queue; unsigned int i; rt2x00usb_vendor_request_sw(rt2x00dev, USB_RX_CONTROL, 0x0000, 0x0000, REGISTER_TIMEOUT); /* - * Cancel all rings. + * Cancel all queues. */ - ring_for_each(rt2x00dev, ring) { - for (i = 0; i < ring->stats.limit; i++) - usb_kill_urb(ring->entry[i].priv); + for (i = 0; i < rt2x00dev->rx->limit; i++) { + priv_rx = rt2x00dev->rx->entries[i].priv_data; + usb_kill_urb(priv_rx->urb); + } + + txall_queue_for_each(rt2x00dev, queue) { + for (i = 0; i < queue->limit; i++) { + priv_tx = queue->entries[i].priv_data; + usb_kill_urb(priv_tx->urb); + } } } EXPORT_SYMBOL_GPL(rt2x00usb_disable_radio); @@ -358,64 +353,108 @@ EXPORT_SYMBOL_GPL(rt2x00usb_disable_radio); * Device initialization handlers. */ void rt2x00usb_init_rxentry(struct rt2x00_dev *rt2x00dev, - struct data_entry *entry) + struct queue_entry *entry) { - struct usb_device *usb_dev = - interface_to_usbdev(rt2x00dev_usb(rt2x00dev)); + struct usb_device *usb_dev = rt2x00dev_usb_dev(rt2x00dev); + struct queue_entry_priv_usb_rx *priv_rx = entry->priv_data; - usb_fill_bulk_urb(entry->priv, usb_dev, + usb_fill_bulk_urb(priv_rx->urb, usb_dev, usb_rcvbulkpipe(usb_dev, 1), entry->skb->data, entry->skb->len, rt2x00usb_interrupt_rxdone, entry); - __set_bit(ENTRY_OWNER_NIC, &entry->flags); - usb_submit_urb(entry->priv, GFP_ATOMIC); + __set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); + usb_submit_urb(priv_rx->urb, GFP_ATOMIC); } EXPORT_SYMBOL_GPL(rt2x00usb_init_rxentry); void rt2x00usb_init_txentry(struct rt2x00_dev *rt2x00dev, - struct data_entry *entry) + struct queue_entry *entry) { entry->flags = 0; } EXPORT_SYMBOL_GPL(rt2x00usb_init_txentry); static int rt2x00usb_alloc_urb(struct rt2x00_dev *rt2x00dev, - struct data_ring *ring) + struct data_queue *queue) { + struct queue_entry_priv_usb_rx *priv_rx; + struct queue_entry_priv_usb_tx *priv_tx; + struct queue_entry_priv_usb_bcn *priv_bcn; + struct urb *urb; + unsigned int guardian = + test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags); unsigned int i; /* * Allocate the URB's */ - for (i = 0; i < ring->stats.limit; i++) { - ring->entry[i].priv = usb_alloc_urb(0, GFP_KERNEL); - if (!ring->entry[i].priv) + for (i = 0; i < queue->limit; i++) { + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) return -ENOMEM; + + if (queue->qid == QID_RX) { + priv_rx = queue->entries[i].priv_data; + priv_rx->urb = urb; + } else if (queue->qid == QID_MGMT && guardian) { + priv_bcn = queue->entries[i].priv_data; + priv_bcn->urb = urb; + + urb = usb_alloc_urb(0, GFP_KERNEL); + if (!urb) + return -ENOMEM; + + priv_bcn->guardian_urb = urb; + } else { + priv_tx = queue->entries[i].priv_data; + priv_tx->urb = urb; + } } return 0; } static void rt2x00usb_free_urb(struct rt2x00_dev *rt2x00dev, - struct data_ring *ring) + struct data_queue *queue) { + struct queue_entry_priv_usb_rx *priv_rx; + struct queue_entry_priv_usb_tx *priv_tx; + struct queue_entry_priv_usb_bcn *priv_bcn; + struct urb *urb; + unsigned int guardian = + test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags); unsigned int i; - if (!ring->entry) + if (!queue->entries) return; - for (i = 0; i < ring->stats.limit; i++) { - usb_kill_urb(ring->entry[i].priv); - usb_free_urb(ring->entry[i].priv); - if (ring->entry[i].skb) - kfree_skb(ring->entry[i].skb); + for (i = 0; i < queue->limit; i++) { + if (queue->qid == QID_RX) { + priv_rx = queue->entries[i].priv_data; + urb = priv_rx->urb; + } else if (queue->qid == QID_MGMT && guardian) { + priv_bcn = queue->entries[i].priv_data; + + usb_kill_urb(priv_bcn->guardian_urb); + usb_free_urb(priv_bcn->guardian_urb); + + urb = priv_bcn->urb; + } else { + priv_tx = queue->entries[i].priv_data; + urb = priv_tx->urb; + } + + usb_kill_urb(urb); + usb_free_urb(urb); + if (queue->entries[i].skb) + kfree_skb(queue->entries[i].skb); } } int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev) { - struct data_ring *ring; + struct data_queue *queue; struct sk_buff *skb; unsigned int entry_size; unsigned int i; @@ -424,25 +463,22 @@ int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev) /* * Allocate DMA */ - ring_for_each(rt2x00dev, ring) { - status = rt2x00usb_alloc_urb(rt2x00dev, ring); + queue_for_each(rt2x00dev, queue) { + status = rt2x00usb_alloc_urb(rt2x00dev, queue); if (status) goto exit; } /* - * For the RX ring, skb's should be allocated. + * For the RX queue, skb's should be allocated. */ entry_size = rt2x00dev->rx->data_size + rt2x00dev->rx->desc_size; - for (i = 0; i < rt2x00dev->rx->stats.limit; i++) { - skb = dev_alloc_skb(NET_IP_ALIGN + entry_size); + for (i = 0; i < rt2x00dev->rx->limit; i++) { + skb = rt2x00usb_alloc_rxskb(rt2x00dev->rx); if (!skb) goto exit; - skb_reserve(skb, NET_IP_ALIGN); - skb_put(skb, entry_size); - - rt2x00dev->rx->entry[i].skb = skb; + rt2x00dev->rx->entries[i].skb = skb; } return 0; @@ -456,10 +492,10 @@ EXPORT_SYMBOL_GPL(rt2x00usb_initialize); void rt2x00usb_uninitialize(struct rt2x00_dev *rt2x00dev) { - struct data_ring *ring; + struct data_queue *queue; - ring_for_each(rt2x00dev, ring) - rt2x00usb_free_urb(rt2x00dev, ring); + queue_for_each(rt2x00dev, queue) + rt2x00usb_free_urb(rt2x00dev, queue); } EXPORT_SYMBOL_GPL(rt2x00usb_uninitialize); @@ -627,9 +663,9 @@ EXPORT_SYMBOL_GPL(rt2x00usb_resume); #endif /* CONFIG_PM */ /* - * rt2x00pci module information. + * rt2x00usb module information. */ MODULE_AUTHOR(DRV_PROJECT); MODULE_VERSION(DRV_VERSION); -MODULE_DESCRIPTION("rt2x00 library"); +MODULE_DESCRIPTION("rt2x00 usb library"); MODULE_LICENSE("GPL"); diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h index b5c1d176c481..af606638e227 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.h +++ b/drivers/net/wireless/rt2x00/rt2x00usb.h @@ -160,16 +160,58 @@ void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev); * TX data handlers. */ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev, - struct data_ring *ring, struct sk_buff *skb, + struct data_queue *queue, struct sk_buff *skb, struct ieee80211_tx_control *control); +/** + * struct queue_entry_priv_usb_rx: Per RX entry USB specific information + * + * @urb: Urb structure used for device communication. + */ +struct queue_entry_priv_usb_rx { + struct urb *urb; +}; + +/** + * struct queue_entry_priv_usb_tx: Per TX entry USB specific information + * + * @urb: Urb structure used for device communication. + * @control: mac80211 control structure used to transmit data. + */ +struct queue_entry_priv_usb_tx { + struct urb *urb; + + struct ieee80211_tx_control control; +}; + +/** + * struct queue_entry_priv_usb_tx: Per TX entry USB specific information + * + * The first section should match &struct queue_entry_priv_usb_tx exactly. + * rt2500usb can use this structure to send a guardian byte when working + * with beacons. + * + * @urb: Urb structure used for device communication. + * @control: mac80211 control structure used to transmit data. + * @guardian_data: Set to 0, used for sending the guardian data. + * @guardian_urb: Urb structure used to send the guardian data. + */ +struct queue_entry_priv_usb_bcn { + struct urb *urb; + + struct ieee80211_tx_control control; + + unsigned int guardian_data; + struct urb *guardian_urb; +}; + /* * Device initialization handlers. */ void rt2x00usb_init_rxentry(struct rt2x00_dev *rt2x00dev, - struct data_entry *entry); + struct queue_entry *entry); void rt2x00usb_init_txentry(struct rt2x00_dev *rt2x00dev, - struct data_entry *entry); + struct queue_entry *entry); int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev); void rt2x00usb_uninitialize(struct rt2x00_dev *rt2x00dev); diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 42cd1dc09164..547fa33e99dd 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -262,7 +262,7 @@ static int rt61pci_rfkill_poll(struct rt2x00_dev *rt2x00dev) u32 reg; rt2x00pci_register_read(rt2x00dev, MAC_CSR13, ®); - return rt2x00_get_field32(reg, MAC_CSR13_BIT5);; + return rt2x00_get_field32(reg, MAC_CSR13_BIT5); } #else #define rt61pci_rfkill_poll NULL @@ -990,49 +990,49 @@ static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev, void *data, } static void rt61pci_init_rxentry(struct rt2x00_dev *rt2x00dev, - struct data_entry *entry) + struct queue_entry *entry) { - __le32 *rxd = entry->priv; + struct queue_entry_priv_pci_rx *priv_rx = entry->priv_data; u32 word; - rt2x00_desc_read(rxd, 5, &word); - rt2x00_set_field32(&word, RXD_W5_BUFFER_PHYSICAL_ADDRESS, - entry->data_dma); - rt2x00_desc_write(rxd, 5, word); + rt2x00_desc_read(priv_rx->desc, 5, &word); + rt2x00_set_field32(&word, RXD_W5_BUFFER_PHYSICAL_ADDRESS, priv_rx->dma); + rt2x00_desc_write(priv_rx->desc, 5, word); - rt2x00_desc_read(rxd, 0, &word); + rt2x00_desc_read(priv_rx->desc, 0, &word); rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1); - rt2x00_desc_write(rxd, 0, word); + rt2x00_desc_write(priv_rx->desc, 0, word); } static void rt61pci_init_txentry(struct rt2x00_dev *rt2x00dev, - struct data_entry *entry) + struct queue_entry *entry) { - __le32 *txd = entry->priv; + struct queue_entry_priv_pci_tx *priv_tx = entry->priv_data; u32 word; - rt2x00_desc_read(txd, 1, &word); + rt2x00_desc_read(priv_tx->desc, 1, &word); rt2x00_set_field32(&word, TXD_W1_BUFFER_COUNT, 1); - rt2x00_desc_write(txd, 1, word); + rt2x00_desc_write(priv_tx->desc, 1, word); - rt2x00_desc_read(txd, 5, &word); - rt2x00_set_field32(&word, TXD_W5_PID_TYPE, entry->ring->queue_idx); + rt2x00_desc_read(priv_tx->desc, 5, &word); + rt2x00_set_field32(&word, TXD_W5_PID_TYPE, entry->queue->qid); rt2x00_set_field32(&word, TXD_W5_PID_SUBTYPE, entry->entry_idx); - rt2x00_desc_write(txd, 5, word); + rt2x00_desc_write(priv_tx->desc, 5, word); - rt2x00_desc_read(txd, 6, &word); - rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS, - entry->data_dma); - rt2x00_desc_write(txd, 6, word); + rt2x00_desc_read(priv_tx->desc, 6, &word); + rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS, priv_tx->dma); + rt2x00_desc_write(priv_tx->desc, 6, word); - rt2x00_desc_read(txd, 0, &word); + rt2x00_desc_read(priv_tx->desc, 0, &word); rt2x00_set_field32(&word, TXD_W0_VALID, 0); rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0); - rt2x00_desc_write(txd, 0, word); + rt2x00_desc_write(priv_tx->desc, 0, word); } -static int rt61pci_init_rings(struct rt2x00_dev *rt2x00dev) +static int rt61pci_init_queues(struct rt2x00_dev *rt2x00dev) { + struct queue_entry_priv_pci_rx *priv_rx; + struct queue_entry_priv_pci_tx *priv_tx; u32 reg; /* @@ -1040,59 +1040,50 @@ static int rt61pci_init_rings(struct rt2x00_dev *rt2x00dev) */ rt2x00pci_register_read(rt2x00dev, TX_RING_CSR0, ®); rt2x00_set_field32(®, TX_RING_CSR0_AC0_RING_SIZE, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].stats.limit); + rt2x00dev->tx[0].limit); rt2x00_set_field32(®, TX_RING_CSR0_AC1_RING_SIZE, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].stats.limit); + rt2x00dev->tx[1].limit); rt2x00_set_field32(®, TX_RING_CSR0_AC2_RING_SIZE, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA2].stats.limit); + rt2x00dev->tx[2].limit); rt2x00_set_field32(®, TX_RING_CSR0_AC3_RING_SIZE, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA3].stats.limit); + rt2x00dev->tx[3].limit); rt2x00pci_register_write(rt2x00dev, TX_RING_CSR0, reg); rt2x00pci_register_read(rt2x00dev, TX_RING_CSR1, ®); - rt2x00_set_field32(®, TX_RING_CSR1_MGMT_RING_SIZE, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA4].stats.limit); rt2x00_set_field32(®, TX_RING_CSR1_TXD_SIZE, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].desc_size / - 4); + rt2x00dev->tx[0].desc_size / 4); rt2x00pci_register_write(rt2x00dev, TX_RING_CSR1, reg); + priv_tx = rt2x00dev->tx[0].entries[0].priv_data; rt2x00pci_register_read(rt2x00dev, AC0_BASE_CSR, ®); - rt2x00_set_field32(®, AC0_BASE_CSR_RING_REGISTER, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA0].data_dma); + rt2x00_set_field32(®, AC0_BASE_CSR_RING_REGISTER, priv_tx->dma); rt2x00pci_register_write(rt2x00dev, AC0_BASE_CSR, reg); + priv_tx = rt2x00dev->tx[1].entries[0].priv_data; rt2x00pci_register_read(rt2x00dev, AC1_BASE_CSR, ®); - rt2x00_set_field32(®, AC1_BASE_CSR_RING_REGISTER, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA1].data_dma); + rt2x00_set_field32(®, AC1_BASE_CSR_RING_REGISTER, priv_tx->dma); rt2x00pci_register_write(rt2x00dev, AC1_BASE_CSR, reg); + priv_tx = rt2x00dev->tx[2].entries[0].priv_data; rt2x00pci_register_read(rt2x00dev, AC2_BASE_CSR, ®); - rt2x00_set_field32(®, AC2_BASE_CSR_RING_REGISTER, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA2].data_dma); + rt2x00_set_field32(®, AC2_BASE_CSR_RING_REGISTER, priv_tx->dma); rt2x00pci_register_write(rt2x00dev, AC2_BASE_CSR, reg); + priv_tx = rt2x00dev->tx[3].entries[0].priv_data; rt2x00pci_register_read(rt2x00dev, AC3_BASE_CSR, ®); - rt2x00_set_field32(®, AC3_BASE_CSR_RING_REGISTER, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA3].data_dma); + rt2x00_set_field32(®, AC3_BASE_CSR_RING_REGISTER, priv_tx->dma); rt2x00pci_register_write(rt2x00dev, AC3_BASE_CSR, reg); - rt2x00pci_register_read(rt2x00dev, MGMT_BASE_CSR, ®); - rt2x00_set_field32(®, MGMT_BASE_CSR_RING_REGISTER, - rt2x00dev->tx[IEEE80211_TX_QUEUE_DATA4].data_dma); - rt2x00pci_register_write(rt2x00dev, MGMT_BASE_CSR, reg); - rt2x00pci_register_read(rt2x00dev, RX_RING_CSR, ®); - rt2x00_set_field32(®, RX_RING_CSR_RING_SIZE, - rt2x00dev->rx->stats.limit); + rt2x00_set_field32(®, RX_RING_CSR_RING_SIZE, rt2x00dev->rx->limit); rt2x00_set_field32(®, RX_RING_CSR_RXD_SIZE, rt2x00dev->rx->desc_size / 4); rt2x00_set_field32(®, RX_RING_CSR_RXD_WRITEBACK_SIZE, 4); rt2x00pci_register_write(rt2x00dev, RX_RING_CSR, reg); + priv_rx = rt2x00dev->rx->entries[0].priv_data; rt2x00pci_register_read(rt2x00dev, RX_BASE_CSR, ®); - rt2x00_set_field32(®, RX_BASE_CSR_RING_REGISTER, - rt2x00dev->rx->data_dma); + rt2x00_set_field32(®, RX_BASE_CSR_RING_REGISTER, priv_rx->dma); rt2x00pci_register_write(rt2x00dev, RX_BASE_CSR, reg); rt2x00pci_register_read(rt2x00dev, TX_DMA_DST_CSR, ®); @@ -1108,7 +1099,7 @@ static int rt61pci_init_rings(struct rt2x00_dev *rt2x00dev) rt2x00_set_field32(®, LOAD_TX_RING_CSR_LOAD_TXD_AC1, 1); rt2x00_set_field32(®, LOAD_TX_RING_CSR_LOAD_TXD_AC2, 1); rt2x00_set_field32(®, LOAD_TX_RING_CSR_LOAD_TXD_AC3, 1); - rt2x00_set_field32(®, LOAD_TX_RING_CSR_LOAD_TXD_MGMT, 1); + rt2x00_set_field32(®, LOAD_TX_RING_CSR_LOAD_TXD_MGMT, 0); rt2x00pci_register_write(rt2x00dev, LOAD_TX_RING_CSR, reg); rt2x00pci_register_read(rt2x00dev, RX_CNTL_CSR, ®); @@ -1375,7 +1366,7 @@ static int rt61pci_enable_radio(struct rt2x00_dev *rt2x00dev) /* * Initialize all registers. */ - if (rt61pci_init_rings(rt2x00dev) || + if (rt61pci_init_queues(rt2x00dev) || rt61pci_init_registers(rt2x00dev) || rt61pci_init_bbp(rt2x00dev)) { ERROR(rt2x00dev, "Register initialization failed.\n"); @@ -1508,10 +1499,10 @@ static int rt61pci_set_device_state(struct rt2x00_dev *rt2x00dev, */ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb, - struct txdata_entry_desc *desc, + struct txentry_desc *txdesc, struct ieee80211_tx_control *control) { - struct skb_desc *skbdesc = get_skb_desc(skb); + struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); __le32 *txd = skbdesc->desc; u32 word; @@ -1519,19 +1510,19 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, * Start writing the descriptor words. */ rt2x00_desc_read(txd, 1, &word); - rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, desc->queue); - rt2x00_set_field32(&word, TXD_W1_AIFSN, desc->aifs); - rt2x00_set_field32(&word, TXD_W1_CWMIN, desc->cw_min); - rt2x00_set_field32(&word, TXD_W1_CWMAX, desc->cw_max); + rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, txdesc->queue); + rt2x00_set_field32(&word, TXD_W1_AIFSN, txdesc->aifs); + rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min); + rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max); rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, IEEE80211_HEADER); rt2x00_set_field32(&word, TXD_W1_HW_SEQUENCE, 1); rt2x00_desc_write(txd, 1, word); rt2x00_desc_read(txd, 2, &word); - rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, desc->signal); - rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, desc->service); - rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, desc->length_low); - rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, desc->length_high); + rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->signal); + rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->service); + rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, txdesc->length_low); + rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, txdesc->length_high); rt2x00_desc_write(txd, 2, word); rt2x00_desc_read(txd, 5, &word); @@ -1548,21 +1539,21 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 1); rt2x00_set_field32(&word, TXD_W0_VALID, 1); rt2x00_set_field32(&word, TXD_W0_MORE_FRAG, - test_bit(ENTRY_TXD_MORE_FRAG, &desc->flags)); + test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_ACK, - test_bit(ENTRY_TXD_ACK, &desc->flags)); + test_bit(ENTRY_TXD_ACK, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_TIMESTAMP, - test_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc->flags)); + test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_OFDM, - test_bit(ENTRY_TXD_OFDM_RATE, &desc->flags)); - rt2x00_set_field32(&word, TXD_W0_IFS, desc->ifs); + test_bit(ENTRY_TXD_OFDM_RATE, &txdesc->flags)); + rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs); rt2x00_set_field32(&word, TXD_W0_RETRY_MODE, !!(control->flags & IEEE80211_TXCTL_LONG_RETRY_LIMIT)); rt2x00_set_field32(&word, TXD_W0_TKIP_MIC, 0); rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skbdesc->data_len); rt2x00_set_field32(&word, TXD_W0_BURST, - test_bit(ENTRY_TXD_BURST, &desc->flags)); + test_bit(ENTRY_TXD_BURST, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE); rt2x00_desc_write(txd, 0, word); } @@ -1648,28 +1639,28 @@ static int rt61pci_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1) return rt2x00_get_field32(rxd_w1, RXD_W1_RSSI_AGC) * 2 - offset; } -static void rt61pci_fill_rxdone(struct data_entry *entry, - struct rxdata_entry_desc *desc) +static void rt61pci_fill_rxdone(struct queue_entry *entry, + struct rxdone_entry_desc *rxdesc) { - __le32 *rxd = entry->priv; + struct queue_entry_priv_pci_rx *priv_rx = entry->priv_data; u32 word0; u32 word1; - rt2x00_desc_read(rxd, 0, &word0); - rt2x00_desc_read(rxd, 1, &word1); + rt2x00_desc_read(priv_rx->desc, 0, &word0); + rt2x00_desc_read(priv_rx->desc, 1, &word1); - desc->flags = 0; + rxdesc->flags = 0; if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR)) - desc->flags |= RX_FLAG_FAILED_FCS_CRC; + rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; /* * Obtain the status about this packet. */ - desc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL); - desc->rssi = rt61pci_agc_to_rssi(entry->ring->rt2x00dev, word1); - desc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM); - desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); - desc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS); + rxdesc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL); + rxdesc->rssi = rt61pci_agc_to_rssi(entry->queue->rt2x00dev, word1); + rxdesc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM); + rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); + rxdesc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS); } /* @@ -1677,17 +1668,16 @@ static void rt61pci_fill_rxdone(struct data_entry *entry, */ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev) { - struct data_ring *ring; - struct data_entry *entry; - struct data_entry *entry_done; - __le32 *txd; + struct data_queue *queue; + struct queue_entry *entry; + struct queue_entry *entry_done; + struct queue_entry_priv_pci_tx *priv_tx; + struct txdone_entry_desc txdesc; u32 word; u32 reg; u32 old_reg; int type; int index; - int tx_status; - int retry; /* * During each loop we will compare the freshly read @@ -1710,11 +1700,11 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev) /* * Skip this entry when it contains an invalid - * ring identication number. + * queue identication number. */ type = rt2x00_get_field32(reg, STA_CSR4_PID_TYPE); - ring = rt2x00lib_get_ring(rt2x00dev, type); - if (unlikely(!ring)) + queue = rt2x00queue_get_queue(rt2x00dev, type); + if (unlikely(!queue)) continue; /* @@ -1722,36 +1712,40 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev) * index number. */ index = rt2x00_get_field32(reg, STA_CSR4_PID_SUBTYPE); - if (unlikely(index >= ring->stats.limit)) + if (unlikely(index >= queue->limit)) continue; - entry = &ring->entry[index]; - txd = entry->priv; - rt2x00_desc_read(txd, 0, &word); + entry = &queue->entries[index]; + priv_tx = entry->priv_data; + rt2x00_desc_read(priv_tx->desc, 0, &word); if (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) || !rt2x00_get_field32(word, TXD_W0_VALID)) return; - entry_done = rt2x00_get_data_entry_done(ring); + entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE); while (entry != entry_done) { - /* Catch up. Just report any entries we missed as - * failed. */ + /* Catch up. + * Just report any entries we missed as failed. + */ WARNING(rt2x00dev, - "TX status report missed for entry %p\n", - entry_done); - rt2x00pci_txdone(rt2x00dev, entry_done, TX_FAIL_OTHER, - 0); - entry_done = rt2x00_get_data_entry_done(ring); + "TX status report missed for entry %d\n", + entry_done->entry_idx); + + txdesc.status = TX_FAIL_OTHER; + txdesc.retry = 0; + + rt2x00pci_txdone(rt2x00dev, entry_done, &txdesc); + entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE); } /* * Obtain the status about this packet. */ - tx_status = rt2x00_get_field32(reg, STA_CSR4_TX_RESULT); - retry = rt2x00_get_field32(reg, STA_CSR4_RETRY_COUNT); + txdesc.status = rt2x00_get_field32(reg, STA_CSR4_TX_RESULT); + txdesc.retry = rt2x00_get_field32(reg, STA_CSR4_RETRY_COUNT); - rt2x00pci_txdone(rt2x00dev, entry, tx_status, retry); + rt2x00pci_txdone(rt2x00dev, entry, &txdesc); } } @@ -2381,9 +2375,9 @@ static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, struct ieee80211_tx_control *control) { struct rt2x00_dev *rt2x00dev = hw->priv; - struct skb_desc *desc; - struct data_ring *ring; - struct data_entry *entry; + struct skb_frame_desc *skbdesc; + struct data_queue *queue; + struct queue_entry *entry; /* * Just in case the ieee80211 doesn't set this, @@ -2391,15 +2385,15 @@ static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, * initialization. */ control->queue = IEEE80211_TX_QUEUE_BEACON; - ring = rt2x00lib_get_ring(rt2x00dev, control->queue); - entry = rt2x00_get_data_entry(ring); + queue = rt2x00queue_get_queue(rt2x00dev, control->queue); + entry = rt2x00queue_get_entry(queue, Q_INDEX); /* * We need to append the descriptor in front of the * beacon frame. */ - if (skb_headroom(skb) < TXD_DESC_SIZE) { - if (pskb_expand_head(skb, TXD_DESC_SIZE, 0, GFP_ATOMIC)) { + if (skb_headroom(skb) < queue->desc_size) { + if (pskb_expand_head(skb, queue->desc_size, 0, GFP_ATOMIC)) { dev_kfree_skb(skb); return -ENOMEM; } @@ -2408,19 +2402,19 @@ static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, /* * Add the descriptor in front of the skb. */ - skb_push(skb, ring->desc_size); - memset(skb->data, 0, ring->desc_size); + skb_push(skb, queue->desc_size); + memset(skb->data, 0, queue->desc_size); /* * Fill in skb descriptor */ - desc = get_skb_desc(skb); - desc->desc_len = ring->desc_size; - desc->data_len = skb->len - ring->desc_size; - desc->desc = skb->data; - desc->data = skb->data + ring->desc_size; - desc->ring = ring; - desc->entry = entry; + skbdesc = get_skb_frame_desc(skb); + memset(skbdesc, 0, sizeof(*skbdesc)); + skbdesc->data = skb->data + queue->desc_size; + skbdesc->data_len = queue->data_size; + skbdesc->desc = skb->data; + skbdesc->desc_len = queue->desc_size; + skbdesc->entry = entry; rt2x00lib_write_tx_desc(rt2x00dev, skb, control); @@ -2479,12 +2473,34 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { .config = rt61pci_config, }; +static const struct data_queue_desc rt61pci_queue_rx = { + .entry_num = RX_ENTRIES, + .data_size = DATA_FRAME_SIZE, + .desc_size = RXD_DESC_SIZE, + .priv_size = sizeof(struct queue_entry_priv_pci_rx), +}; + +static const struct data_queue_desc rt61pci_queue_tx = { + .entry_num = TX_ENTRIES, + .data_size = DATA_FRAME_SIZE, + .desc_size = TXD_DESC_SIZE, + .priv_size = sizeof(struct queue_entry_priv_pci_tx), +}; + +static const struct data_queue_desc rt61pci_queue_bcn = { + .entry_num = BEACON_ENTRIES, + .data_size = MGMT_FRAME_SIZE, + .desc_size = TXINFO_SIZE, + .priv_size = sizeof(struct queue_entry_priv_pci_tx), +}; + static const struct rt2x00_ops rt61pci_ops = { .name = KBUILD_MODNAME, - .rxd_size = RXD_DESC_SIZE, - .txd_size = TXD_DESC_SIZE, .eeprom_size = EEPROM_SIZE, .rf_size = RF_SIZE, + .rx = &rt61pci_queue_rx, + .tx = &rt61pci_queue_tx, + .bcn = &rt61pci_queue_bcn, .lib = &rt61pci_rt2x00_ops, .hw = &rt61pci_mac80211_ops, #ifdef CONFIG_RT2X00_LIB_DEBUGFS diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h index e4578fbdb361..10519f8c5783 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.h +++ b/drivers/net/wireless/rt2x00/rt61pci.h @@ -1247,6 +1247,7 @@ struct hw_pairwise_ta_entry { * DMA descriptor defines. */ #define TXD_DESC_SIZE ( 16 * sizeof(__le32) ) +#define TXINFO_SIZE ( 6 * sizeof(__le32) ) #define RXD_DESC_SIZE ( 16 * sizeof(__le32) ) /* diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 416e44943e71..4e6466b13af1 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -1234,10 +1234,10 @@ static int rt73usb_set_device_state(struct rt2x00_dev *rt2x00dev, */ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb, - struct txdata_entry_desc *desc, + struct txentry_desc *txdesc, struct ieee80211_tx_control *control) { - struct skb_desc *skbdesc = get_skb_desc(skb); + struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); __le32 *txd = skbdesc->desc; u32 word; @@ -1245,19 +1245,19 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, * Start writing the descriptor words. */ rt2x00_desc_read(txd, 1, &word); - rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, desc->queue); - rt2x00_set_field32(&word, TXD_W1_AIFSN, desc->aifs); - rt2x00_set_field32(&word, TXD_W1_CWMIN, desc->cw_min); - rt2x00_set_field32(&word, TXD_W1_CWMAX, desc->cw_max); + rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, txdesc->queue); + rt2x00_set_field32(&word, TXD_W1_AIFSN, txdesc->aifs); + rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min); + rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max); rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, IEEE80211_HEADER); rt2x00_set_field32(&word, TXD_W1_HW_SEQUENCE, 1); rt2x00_desc_write(txd, 1, word); rt2x00_desc_read(txd, 2, &word); - rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, desc->signal); - rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, desc->service); - rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, desc->length_low); - rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, desc->length_high); + rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->signal); + rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->service); + rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, txdesc->length_low); + rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, txdesc->length_high); rt2x00_desc_write(txd, 2, word); rt2x00_desc_read(txd, 5, &word); @@ -1268,24 +1268,24 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_desc_read(txd, 0, &word); rt2x00_set_field32(&word, TXD_W0_BURST, - test_bit(ENTRY_TXD_BURST, &desc->flags)); + test_bit(ENTRY_TXD_BURST, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_VALID, 1); rt2x00_set_field32(&word, TXD_W0_MORE_FRAG, - test_bit(ENTRY_TXD_MORE_FRAG, &desc->flags)); + test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_ACK, - test_bit(ENTRY_TXD_ACK, &desc->flags)); + test_bit(ENTRY_TXD_ACK, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_TIMESTAMP, - test_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc->flags)); + test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_OFDM, - test_bit(ENTRY_TXD_OFDM_RATE, &desc->flags)); - rt2x00_set_field32(&word, TXD_W0_IFS, desc->ifs); + test_bit(ENTRY_TXD_OFDM_RATE, &txdesc->flags)); + rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs); rt2x00_set_field32(&word, TXD_W0_RETRY_MODE, !!(control->flags & IEEE80211_TXCTL_LONG_RETRY_LIMIT)); rt2x00_set_field32(&word, TXD_W0_TKIP_MIC, 0); rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skbdesc->data_len); rt2x00_set_field32(&word, TXD_W0_BURST2, - test_bit(ENTRY_TXD_BURST, &desc->flags)); + test_bit(ENTRY_TXD_BURST, &txdesc->flags)); rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE); rt2x00_desc_write(txd, 0, word); } @@ -1377,37 +1377,57 @@ static int rt73usb_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1) return rt2x00_get_field32(rxd_w1, RXD_W1_RSSI_AGC) * 2 - offset; } -static void rt73usb_fill_rxdone(struct data_entry *entry, - struct rxdata_entry_desc *desc) +static void rt73usb_fill_rxdone(struct queue_entry *entry, + struct rxdone_entry_desc *rxdesc) { - struct skb_desc *skbdesc = get_skb_desc(entry->skb); + struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); __le32 *rxd = (__le32 *)entry->skb->data; + struct ieee80211_hdr *hdr = + (struct ieee80211_hdr *)entry->skb->data + entry->queue->desc_size; + int header_size = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control)); u32 word0; u32 word1; rt2x00_desc_read(rxd, 0, &word0); rt2x00_desc_read(rxd, 1, &word1); - desc->flags = 0; + rxdesc->flags = 0; if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR)) - desc->flags |= RX_FLAG_FAILED_FCS_CRC; + rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; /* * Obtain the status about this packet. */ - desc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL); - desc->rssi = rt73usb_agc_to_rssi(entry->ring->rt2x00dev, word1); - desc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM); - desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); - desc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS); + rxdesc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL); + rxdesc->rssi = rt73usb_agc_to_rssi(entry->queue->rt2x00dev, word1); + rxdesc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM); + rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); + rxdesc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS); + + /* + * The data behind the ieee80211 header must be + * aligned on a 4 byte boundary. + */ + if (header_size % 4 == 0) { + skb_push(entry->skb, 2); + memmove(entry->skb->data, entry->skb->data + 2, + entry->skb->len - 2); + } /* * Set descriptor and data pointer. */ + skbdesc->data = entry->skb->data + entry->queue->desc_size; + skbdesc->data_len = entry->queue->data_size; skbdesc->desc = entry->skb->data; - skbdesc->desc_len = entry->ring->desc_size; - skbdesc->data = entry->skb->data + entry->ring->desc_size; - skbdesc->data_len = desc->size; + skbdesc->desc_len = entry->queue->desc_size; + + /* + * Remove descriptor from skb buffer and trim the whole thing + * down to only contain data. + */ + skb_pull(entry->skb, skbdesc->desc_len); + skb_trim(entry->skb, rxdesc->size); } /* @@ -1967,9 +1987,9 @@ static int rt73usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, struct ieee80211_tx_control *control) { struct rt2x00_dev *rt2x00dev = hw->priv; - struct skb_desc *desc; - struct data_ring *ring; - struct data_entry *entry; + struct skb_frame_desc *skbdesc; + struct data_queue *queue; + struct queue_entry *entry; int timeout; /* @@ -1978,25 +1998,25 @@ static int rt73usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, * initialization. */ control->queue = IEEE80211_TX_QUEUE_BEACON; - ring = rt2x00lib_get_ring(rt2x00dev, control->queue); - entry = rt2x00_get_data_entry(ring); + queue = rt2x00queue_get_queue(rt2x00dev, control->queue); + entry = rt2x00queue_get_entry(queue, Q_INDEX); /* * Add the descriptor in front of the skb. */ - skb_push(skb, ring->desc_size); - memset(skb->data, 0, ring->desc_size); + skb_push(skb, queue->desc_size); + memset(skb->data, 0, queue->desc_size); /* * Fill in skb descriptor */ - desc = get_skb_desc(skb); - desc->desc_len = ring->desc_size; - desc->data_len = skb->len - ring->desc_size; - desc->desc = skb->data; - desc->data = skb->data + ring->desc_size; - desc->ring = ring; - desc->entry = entry; + skbdesc = get_skb_frame_desc(skb); + memset(skbdesc, 0, sizeof(*skbdesc)); + skbdesc->data = skb->data + queue->desc_size; + skbdesc->data_len = queue->data_size; + skbdesc->desc = skb->data; + skbdesc->desc_len = queue->desc_size; + skbdesc->entry = entry; rt2x00lib_write_tx_desc(rt2x00dev, skb, control); @@ -2057,12 +2077,34 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { .config = rt73usb_config, }; +static const struct data_queue_desc rt73usb_queue_rx = { + .entry_num = RX_ENTRIES, + .data_size = DATA_FRAME_SIZE, + .desc_size = RXD_DESC_SIZE, + .priv_size = sizeof(struct queue_entry_priv_usb_rx), +}; + +static const struct data_queue_desc rt73usb_queue_tx = { + .entry_num = TX_ENTRIES, + .data_size = DATA_FRAME_SIZE, + .desc_size = TXD_DESC_SIZE, + .priv_size = sizeof(struct queue_entry_priv_usb_tx), +}; + +static const struct data_queue_desc rt73usb_queue_bcn = { + .entry_num = BEACON_ENTRIES, + .data_size = MGMT_FRAME_SIZE, + .desc_size = TXINFO_SIZE, + .priv_size = sizeof(struct queue_entry_priv_usb_tx), +}; + static const struct rt2x00_ops rt73usb_ops = { .name = KBUILD_MODNAME, - .rxd_size = RXD_DESC_SIZE, - .txd_size = TXD_DESC_SIZE, .eeprom_size = EEPROM_SIZE, .rf_size = RF_SIZE, + .rx = &rt73usb_queue_rx, + .tx = &rt73usb_queue_tx, + .bcn = &rt73usb_queue_bcn, .lib = &rt73usb_rt2x00_ops, .hw = &rt73usb_mac80211_ops, #ifdef CONFIG_RT2X00_LIB_DEBUGFS diff --git a/drivers/net/wireless/rt2x00/rt73usb.h b/drivers/net/wireless/rt2x00/rt73usb.h index bc635908c470..da62b4f091a7 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.h +++ b/drivers/net/wireless/rt2x00/rt73usb.h @@ -867,6 +867,7 @@ struct hw_pairwise_ta_entry { * DMA descriptor defines. */ #define TXD_DESC_SIZE ( 6 * sizeof(__le32) ) +#define TXINFO_SIZE ( 6 * sizeof(__le32) ) #define RXD_DESC_SIZE ( 6 * sizeof(__le32) ) /* -- cgit v1.2.1 From d7bafff3f94efd850f8744d683e63812ff8d55c5 Mon Sep 17 00:00:00 2001 From: Adam Baker Date: Sun, 3 Feb 2008 15:46:24 +0100 Subject: rt2x00: don't write past the end when writing short descriptors on rt61 The space allocated in the skb for a descriptor is only 24 bytes when setting up beacons in rt61 so make sure we don't write to the descriptor words beyond that and corrupt the beacon packet. Signed-off-by: Adam Baker Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt61pci.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 547fa33e99dd..5e08541958cc 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -1531,9 +1531,11 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1); rt2x00_desc_write(txd, 5, word); - rt2x00_desc_read(txd, 11, &word); - rt2x00_set_field32(&word, TXD_W11_BUFFER_LENGTH0, skbdesc->data_len); - rt2x00_desc_write(txd, 11, word); + if (skbdesc->desc_len > TXINFO_SIZE) { + rt2x00_desc_read(txd, 11, &word); + rt2x00_set_field32(&word, TXD_W11_BUFFER_LENGTH0, skbdesc->data_len); + rt2x00_desc_write(txd, 11, word); + } rt2x00_desc_read(txd, 0, &word); rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 1); -- cgit v1.2.1 From 3b3618ad5117331b6fa7cafc41fc18935709e569 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 3 Feb 2008 15:47:30 +0100 Subject: rt2x00: Fix tx parameter initialization Check if the aifs, cw_min and cw_max are above 0 when determining if the default should be used. Tor aifs a negative number is used to determine if the default should be used or not. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00mac.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 411ed5d08598..380cc5b33131 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -396,17 +396,17 @@ int rt2x00mac_conf_tx(struct ieee80211_hw *hw, int queue_idx, * The passed variables are stored as real value ((2^n)-1). * Ralink registers require to know the bit number 'n'. */ - if (params->cw_min) + if (params->cw_min > 0) queue->cw_min = fls(params->cw_min); else queue->cw_min = 5; /* cw_min: 2^5 = 32. */ - if (params->cw_max) + if (params->cw_max > 0) queue->cw_max = fls(params->cw_max); else queue->cw_max = 10; /* cw_min: 2^10 = 1024. */ - if (params->aifs) + if (params->aifs >= 0) queue->aifs = params->aifs; else queue->aifs = 2; -- cgit v1.2.1 From adfdbb79c06154cd3cc7b5983106ace324aa3b02 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 3 Feb 2008 15:48:03 +0100 Subject: rt2x00: Enable master and adhoc mode again This will enable the creation of master mode and adhoc interfaces again. This does not mean the issues surrounding beaconing have been resolved, but this will make testing easier and perhaps we can discover which cards are actually working and which ones not. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00mac.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 380cc5b33131..f08c151ee4ba 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -164,14 +164,6 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, struct rt2x00_dev *rt2x00dev = hw->priv; struct interface *intf = &rt2x00dev->interface; - /* FIXME: Beaconing is broken in rt2x00. */ - if (conf->type == IEEE80211_IF_TYPE_IBSS || - conf->type == IEEE80211_IF_TYPE_AP) { - ERROR(rt2x00dev, - "rt2x00 does not support Adhoc or Master mode"); - return -EOPNOTSUPP; - } - /* * Don't allow interfaces to be added while * either the device has disappeared or when -- cgit v1.2.1 From 9404ef34e4747228717d6e22ce3827ed366ccf41 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 3 Feb 2008 15:48:38 +0100 Subject: rt2x00: Driver requiring firmware should select crc algo The driver should select what CRC algorithm is required when performing a checksum on the firmware. rt61pci & rt73usb require crc-itu-t rt2800pci & rt2800usb require crc-ccitt Legacy 2800pci/usb driver uses crc-itu-t + bit order reversion, but that is just inefficient especially since the end result is the same as a different algorithm which is also available as library. ;) Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/Kconfig | 1 + drivers/net/wireless/rt2x00/rt2x00.h | 2 ++ drivers/net/wireless/rt2x00/rt2x00dev.c | 8 ++---- drivers/net/wireless/rt2x00/rt2x00firmware.c | 41 ++++++++++++++++++++++------ drivers/net/wireless/rt2x00/rt61pci.c | 3 +- drivers/net/wireless/rt2x00/rt73usb.c | 3 +- 6 files changed, 42 insertions(+), 16 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index da05b1faf60d..28f3e5e94ab6 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig @@ -28,6 +28,7 @@ config RT2X00_LIB_USB config RT2X00_LIB_FIRMWARE boolean depends on RT2X00_LIB + select CRC_CCITT select CRC_ITU_T select FW_LOADER diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 7b67f9666c3b..6a25195816db 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -551,6 +551,8 @@ enum rt2x00_flags { * Driver features */ DRIVER_REQUIRE_FIRMWARE, + DRIVER_REQUIRE_FIRMWARE_CRC_ITU_T, + DRIVER_REQUIRE_FIRMWARE_CCITT, DRIVER_REQUIRE_BEACON_GUARD, DRIVER_REQUIRE_ATIM_QUEUE, diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 7620427887b6..bc07c56f89b3 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -1017,11 +1017,9 @@ int rt2x00lib_start(struct rt2x00_dev *rt2x00dev) * If this is the first interface which is added, * we should load the firmware now. */ - if (test_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags)) { - retval = rt2x00lib_load_firmware(rt2x00dev); - if (retval) - return retval; - } + retval = rt2x00lib_load_firmware(rt2x00dev); + if (retval) + return retval; /* * Initialize the device. diff --git a/drivers/net/wireless/rt2x00/rt2x00firmware.c b/drivers/net/wireless/rt2x00/rt2x00firmware.c index 442ff8047dce..4f9fe56f4f2e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00firmware.c +++ b/drivers/net/wireless/rt2x00/rt2x00firmware.c @@ -23,6 +23,7 @@ Abstract: rt2x00 firmware loading routines. */ +#include #include #include #include @@ -37,7 +38,6 @@ static int rt2x00lib_request_firmware(struct rt2x00_dev *rt2x00dev) char *fw_name; int retval; u16 crc; - u16 tmp; /* * Read correct firmware from harddisk. @@ -64,17 +64,37 @@ static int rt2x00lib_request_firmware(struct rt2x00_dev *rt2x00dev) } /* - * Validate the firmware using 16 bit CRC. - * The last 2 bytes of the firmware are the CRC - * so substract those 2 bytes from the CRC checksum, - * and set those 2 bytes to 0 when calculating CRC. + * Perform crc validation on the firmware. + * The last 2 bytes in the firmware array are the crc checksum itself, + * this means that we should never pass those 2 bytes to the crc + * algorithm. */ - tmp = 0; - crc = crc_itu_t(0, fw->data, fw->size - 2); - crc = crc_itu_t(crc, (u8 *)&tmp, 2); + if (test_bit(DRIVER_REQUIRE_FIRMWARE_CRC_ITU_T, &rt2x00dev->flags)) { + /* + * Use the crc itu-t algorithm. + * Use 0 for the last 2 bytes to complete the checksum. + */ + crc = crc_itu_t(0, fw->data, fw->size - 2); + crc = crc_itu_t_byte(crc, 0); + crc = crc_itu_t_byte(crc, 0); + } else if (test_bit(DRIVER_REQUIRE_FIRMWARE_CCITT, &rt2x00dev->flags)) { + /* + * Use the crc ccitt algorithm. + * This will return the same value as the legacy driver which + * used bit ordering reversion on the both the firmware bytes + * before input input as well as on the final output. + * Obviously using crc ccitt directly is much more efficient. + */ + crc = crc_ccitt(~0, fw->data, fw->size - 2); + } else { + ERROR(rt2x00dev, "No checksum algorithm selected " + "for firmware validation.\n"); + retval = -ENOENT; + goto exit; + } if (crc != (fw->data[fw->size - 2] << 8 | fw->data[fw->size - 1])) { - ERROR(rt2x00dev, "Firmware CRC error.\n"); + ERROR(rt2x00dev, "Firmware checksum error.\n"); retval = -ENOENT; goto exit; } @@ -96,6 +116,9 @@ int rt2x00lib_load_firmware(struct rt2x00_dev *rt2x00dev) { int retval; + if (!test_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags)) + return 0; + if (!rt2x00dev->fw) { retval = rt2x00lib_request_firmware(rt2x00dev); if (retval) diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 5e08541958cc..b5ab771bbac2 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -2258,9 +2258,10 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev) rt61pci_probe_hw_mode(rt2x00dev); /* - * This device requires firmware + * This device requires firmware. */ __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); + __set_bit(DRIVER_REQUIRE_FIRMWARE_CRC_ITU_T, &rt2x00dev->flags); /* * Set the rssi offset. diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 4e6466b13af1..8ebf3fed9815 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -1849,9 +1849,10 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev) rt73usb_probe_hw_mode(rt2x00dev); /* - * This device requires firmware + * This device requires firmware. */ __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); + __set_bit(DRIVER_REQUIRE_FIRMWARE_CRC_ITU_T, &rt2x00dev->flags); /* * Set the rssi offset. -- cgit v1.2.1 From 6bb40dd13b458beb55f5c60dba1cb28e814bd640 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 3 Feb 2008 15:49:59 +0100 Subject: rt2x00: Add per-interface structure Rework the interface handling. Delete the interface structure and replace it with a per-interface structure. This changes the way rt2x00 handles the active interface drastically. Copy ieee80211_bss_conf to the this rt2x00_intf structure during the bss_info_changed() callback function. This will allow us to reference it later, and removes the requirement for the device flag SHORT_PREAMBLE flag which is interface specific. Drivers receive the option to give the maximum number of virtual interfaces the device can handle. Virtual interface support: rt2400pci: 1 sta or 1 ap, * monitor interfaces rt2500pci: 1 sta or 1 ap, * monitor interfaces rt2500usb: 1 sta or 1 ap, * monitor interfaces rt61pci: 1 sta or 4 ap, * monitor interfaces rt73usb: 1 sta or 4 ap, * monitor interfaces At the moment none of the drivers support AP and STA interfaces simultaneously, this is a hardware limitation so future support will be very unlikely. Each interface structure receives its dedicated beacon entry, with this we can easily work with beaconing while multiple master mode interfaces are currently active. The configuration handlers for the MAC, BSSID and type are often called together since they all belong to the interface configuration. Merge the 3 configuration calls and cleanup the API between rt2x00lib and the drivers. While we are cleaning up the interface configuration anyway, we might as well clean up the configuration handler as well. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 84 ++++++------ drivers/net/wireless/rt2x00/rt2500pci.c | 98 +++++++------- drivers/net/wireless/rt2x00/rt2500usb.c | 207 ++++++++++++++++------------- drivers/net/wireless/rt2x00/rt2500usb.h | 1 + drivers/net/wireless/rt2x00/rt2x00.h | 113 +++++++++++----- drivers/net/wireless/rt2x00/rt2x00config.c | 119 ++++++++++------- drivers/net/wireless/rt2x00/rt2x00dev.c | 154 ++++++++++++++------- drivers/net/wireless/rt2x00/rt2x00lib.h | 10 +- drivers/net/wireless/rt2x00/rt2x00mac.c | 152 ++++++++++++++------- drivers/net/wireless/rt2x00/rt2x00pci.c | 32 ++--- drivers/net/wireless/rt2x00/rt2x00queue.h | 3 - drivers/net/wireless/rt2x00/rt61pci.c | 169 ++++++++++++----------- drivers/net/wireless/rt2x00/rt61pci.h | 18 ++- drivers/net/wireless/rt2x00/rt73usb.c | 179 ++++++++++++++----------- drivers/net/wireless/rt2x00/rt73usb.h | 17 ++- 15 files changed, 826 insertions(+), 530 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index fc161084a8d3..61766ed800e3 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -246,50 +246,50 @@ static int rt2400pci_rfkill_poll(struct rt2x00_dev *rt2x00dev) /* * Configuration handlers. */ -static void rt2400pci_config_mac_addr(struct rt2x00_dev *rt2x00dev, - __le32 *mac) +static void rt2400pci_config_intf(struct rt2x00_dev *rt2x00dev, + struct rt2x00_intf *intf, + struct rt2x00intf_conf *conf, + const unsigned int flags) { - rt2x00pci_register_multiwrite(rt2x00dev, CSR3, mac, - (2 * sizeof(__le32))); -} + unsigned int bcn_preload; + u32 reg; -static void rt2400pci_config_bssid(struct rt2x00_dev *rt2x00dev, - __le32 *bssid) -{ - rt2x00pci_register_multiwrite(rt2x00dev, CSR5, bssid, - (2 * sizeof(__le32))); -} + if (flags & CONFIG_UPDATE_TYPE) { + rt2x00pci_register_write(rt2x00dev, CSR14, 0); -static void rt2400pci_config_type(struct rt2x00_dev *rt2x00dev, const int type, - const int tsf_sync) -{ - u32 reg; + /* + * Enable beacon config + */ + bcn_preload = PREAMBLE + get_duration(IEEE80211_HEADER, 20); + rt2x00pci_register_read(rt2x00dev, BCNCSR1, ®); + rt2x00_set_field32(®, BCNCSR1_PRELOAD, bcn_preload); + rt2x00pci_register_write(rt2x00dev, BCNCSR1, reg); - rt2x00pci_register_write(rt2x00dev, CSR14, 0); + /* + * Enable synchronisation. + */ + rt2x00pci_register_read(rt2x00dev, CSR14, ®); + rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); + rt2x00_set_field32(®, CSR14_TBCN, + (conf->sync == TSF_SYNC_BEACON)); + rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); + rt2x00_set_field32(®, CSR14_TSF_SYNC, conf->sync); + rt2x00pci_register_write(rt2x00dev, CSR14, reg); + } - /* - * Enable beacon config - */ - rt2x00pci_register_read(rt2x00dev, BCNCSR1, ®); - rt2x00_set_field32(®, BCNCSR1_PRELOAD, - PREAMBLE + get_duration(IEEE80211_HEADER, 20)); - rt2x00pci_register_write(rt2x00dev, BCNCSR1, reg); + if (flags & CONFIG_UPDATE_MAC) + rt2x00pci_register_multiwrite(rt2x00dev, CSR3, + conf->mac, sizeof(conf->mac)); - /* - * Enable synchronisation. - */ - rt2x00pci_register_read(rt2x00dev, CSR14, ®); - rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); - rt2x00_set_field32(®, CSR14_TBCN, (tsf_sync == TSF_SYNC_BEACON)); - rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); - rt2x00_set_field32(®, CSR14_TSF_SYNC, tsf_sync); - rt2x00pci_register_write(rt2x00dev, CSR14, reg); + if (flags & CONFIG_UPDATE_BSSID) + rt2x00pci_register_multiwrite(rt2x00dev, CSR5, + conf->bssid, sizeof(conf->bssid)); } -static void rt2400pci_config_preamble(struct rt2x00_dev *rt2x00dev, - const int short_preamble, - const int ack_timeout, - const int ack_consume_time) +static int rt2400pci_config_preamble(struct rt2x00_dev *rt2x00dev, + const int short_preamble, + const int ack_timeout, + const int ack_consume_time) { int preamble_mask; u32 reg; @@ -327,6 +327,8 @@ static void rt2400pci_config_preamble(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(®, ARCSR5_SERVICE, 0x84); rt2x00_set_field32(®, ARCSR2_LENGTH, get_duration(ACK_SIZE, 110)); rt2x00pci_register_write(rt2x00dev, ARCSR5, reg); + + return 0; } static void rt2400pci_config_phymode(struct rt2x00_dev *rt2x00dev, @@ -481,8 +483,8 @@ static void rt2400pci_config_duration(struct rt2x00_dev *rt2x00dev, } static void rt2400pci_config(struct rt2x00_dev *rt2x00dev, - const unsigned int flags, - struct rt2x00lib_conf *libconf) + struct rt2x00lib_conf *libconf, + const unsigned int flags) { if (flags & CONFIG_UPDATE_PHYMODE) rt2400pci_config_phymode(rt2x00dev, libconf->basic_rates); @@ -1553,9 +1555,7 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { .write_tx_data = rt2x00pci_write_tx_data, .kick_tx_queue = rt2400pci_kick_tx_queue, .fill_rxdone = rt2400pci_fill_rxdone, - .config_mac_addr = rt2400pci_config_mac_addr, - .config_bssid = rt2400pci_config_bssid, - .config_type = rt2400pci_config_type, + .config_intf = rt2400pci_config_intf, .config_preamble = rt2400pci_config_preamble, .config = rt2400pci_config, }; @@ -1590,6 +1590,8 @@ static const struct data_queue_desc rt2400pci_queue_atim = { static const struct rt2x00_ops rt2400pci_ops = { .name = KBUILD_MODNAME, + .max_sta_intf = 1, + .max_ap_intf = 1, .eeprom_size = EEPROM_SIZE, .rf_size = RF_SIZE, .rx = &rt2400pci_queue_rx, diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 0a54b6512207..6a558bf74f11 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -246,53 +246,53 @@ static int rt2500pci_rfkill_poll(struct rt2x00_dev *rt2x00dev) /* * Configuration handlers. */ -static void rt2500pci_config_mac_addr(struct rt2x00_dev *rt2x00dev, - __le32 *mac) -{ - rt2x00pci_register_multiwrite(rt2x00dev, CSR3, mac, - (2 * sizeof(__le32))); -} - -static void rt2500pci_config_bssid(struct rt2x00_dev *rt2x00dev, - __le32 *bssid) -{ - rt2x00pci_register_multiwrite(rt2x00dev, CSR5, bssid, - (2 * sizeof(__le32))); -} - -static void rt2500pci_config_type(struct rt2x00_dev *rt2x00dev, const int type, - const int tsf_sync) +static void rt2500pci_config_intf(struct rt2x00_dev *rt2x00dev, + struct rt2x00_intf *intf, + struct rt2x00intf_conf *conf, + const unsigned int flags) { struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, IEEE80211_TX_QUEUE_BEACON); + unsigned int bcn_preload; u32 reg; - rt2x00pci_register_write(rt2x00dev, CSR14, 0); + if (flags & CONFIG_UPDATE_TYPE) { + rt2x00pci_register_write(rt2x00dev, CSR14, 0); - /* - * Enable beacon config - */ - rt2x00pci_register_read(rt2x00dev, BCNCSR1, ®); - rt2x00_set_field32(®, BCNCSR1_PRELOAD, - PREAMBLE + get_duration(IEEE80211_HEADER, 20)); - rt2x00_set_field32(®, BCNCSR1_BEACON_CWMIN, queue->cw_min); - rt2x00pci_register_write(rt2x00dev, BCNCSR1, reg); + /* + * Enable beacon config + */ + bcn_preload = PREAMBLE + get_duration(IEEE80211_HEADER, 20); + rt2x00pci_register_read(rt2x00dev, BCNCSR1, ®); + rt2x00_set_field32(®, BCNCSR1_PRELOAD, bcn_preload); + rt2x00_set_field32(®, BCNCSR1_BEACON_CWMIN, queue->cw_min); + rt2x00pci_register_write(rt2x00dev, BCNCSR1, reg); - /* - * Enable synchronisation. - */ - rt2x00pci_register_read(rt2x00dev, CSR14, ®); - rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); - rt2x00_set_field32(®, CSR14_TBCN, (tsf_sync == TSF_SYNC_BEACON)); - rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); - rt2x00_set_field32(®, CSR14_TSF_SYNC, tsf_sync); - rt2x00pci_register_write(rt2x00dev, CSR14, reg); + /* + * Enable synchronisation. + */ + rt2x00pci_register_read(rt2x00dev, CSR14, ®); + rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); + rt2x00_set_field32(®, CSR14_TBCN, + (conf->sync == TSF_SYNC_BEACON)); + rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); + rt2x00_set_field32(®, CSR14_TSF_SYNC, conf->sync); + rt2x00pci_register_write(rt2x00dev, CSR14, reg); + } + + if (flags & CONFIG_UPDATE_MAC) + rt2x00pci_register_multiwrite(rt2x00dev, CSR3, + conf->mac, sizeof(conf->mac)); + + if (flags & CONFIG_UPDATE_BSSID) + rt2x00pci_register_multiwrite(rt2x00dev, CSR5, + conf->bssid, sizeof(conf->bssid)); } -static void rt2500pci_config_preamble(struct rt2x00_dev *rt2x00dev, - const int short_preamble, - const int ack_timeout, - const int ack_consume_time) +static int rt2500pci_config_preamble(struct rt2x00_dev *rt2x00dev, + const int short_preamble, + const int ack_timeout, + const int ack_consume_time) { int preamble_mask; u32 reg; @@ -330,6 +330,8 @@ static void rt2500pci_config_preamble(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(®, ARCSR5_SERVICE, 0x84); rt2x00_set_field32(®, ARCSR2_LENGTH, get_duration(ACK_SIZE, 110)); rt2x00pci_register_write(rt2x00dev, ARCSR5, reg); + + return 0; } static void rt2500pci_config_phymode(struct rt2x00_dev *rt2x00dev, @@ -529,8 +531,8 @@ static void rt2500pci_config_duration(struct rt2x00_dev *rt2x00dev, } static void rt2500pci_config(struct rt2x00_dev *rt2x00dev, - const unsigned int flags, - struct rt2x00lib_conf *libconf) + struct rt2x00lib_conf *libconf, + const unsigned int flags) { if (flags & CONFIG_UPDATE_PHYMODE) rt2500pci_config_phymode(rt2x00dev, libconf->basic_rates); @@ -609,9 +611,10 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev) /* * To prevent collisions with MAC ASIC on chipsets * up to version C the link tuning should halt after 20 - * seconds. + * seconds while being associated. */ if (rt2x00_rev(&rt2x00dev->chip) < RT2560_VERSION_D && + rt2x00dev->intf_associated && rt2x00dev->link.count > 20) return; @@ -619,9 +622,12 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev) /* * Chipset versions C and lower should directly continue - * to the dynamic CCA tuning. + * to the dynamic CCA tuning. Chipset version D and higher + * should go straight to dynamic CCA tuning when they + * are not associated. */ - if (rt2x00_rev(&rt2x00dev->chip) < RT2560_VERSION_D) + if (rt2x00_rev(&rt2x00dev->chip) < RT2560_VERSION_D || + !rt2x00dev->intf_associated) goto dynamic_cca_tune; /* @@ -1861,9 +1867,7 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = { .write_tx_data = rt2x00pci_write_tx_data, .kick_tx_queue = rt2500pci_kick_tx_queue, .fill_rxdone = rt2500pci_fill_rxdone, - .config_mac_addr = rt2500pci_config_mac_addr, - .config_bssid = rt2500pci_config_bssid, - .config_type = rt2500pci_config_type, + .config_intf = rt2500pci_config_intf, .config_preamble = rt2500pci_config_preamble, .config = rt2500pci_config, }; @@ -1898,6 +1902,8 @@ static const struct data_queue_desc rt2500pci_queue_atim = { static const struct rt2x00_ops rt2500pci_ops = { .name = KBUILD_MODNAME, + .max_sta_intf = 1, + .max_ap_intf = 1, .eeprom_size = EEPROM_SIZE, .rf_size = RF_SIZE, .rx = &rt2500pci_queue_rx, diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index edc16a5fc754..31258ee24ee3 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -285,70 +285,65 @@ static const struct rt2x00debug rt2500usb_rt2x00debug = { /* * Configuration handlers. */ -static void rt2500usb_config_mac_addr(struct rt2x00_dev *rt2x00dev, - __le32 *mac) -{ - rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR2, mac, - (3 * sizeof(__le16))); -} - -static void rt2500usb_config_bssid(struct rt2x00_dev *rt2x00dev, - __le32 *bssid) -{ - rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR5, bssid, - (3 * sizeof(__le16))); -} - -static void rt2500usb_config_type(struct rt2x00_dev *rt2x00dev, const int type, - const int tsf_sync) +static void rt2500usb_config_intf(struct rt2x00_dev *rt2x00dev, + struct rt2x00_intf *intf, + struct rt2x00intf_conf *conf, + const unsigned int flags) { + unsigned int bcn_preload; u16 reg; - rt2500usb_register_write(rt2x00dev, TXRX_CSR19, 0); + if (flags & CONFIG_UPDATE_TYPE) { + rt2500usb_register_write(rt2x00dev, TXRX_CSR19, 0); - /* - * Enable beacon config - */ - rt2500usb_register_read(rt2x00dev, TXRX_CSR20, ®); - rt2x00_set_field16(®, TXRX_CSR20_OFFSET, - (PREAMBLE + get_duration(IEEE80211_HEADER, 20)) >> 6); - if (type == IEEE80211_IF_TYPE_STA) - rt2x00_set_field16(®, TXRX_CSR20_BCN_EXPECT_WINDOW, 0); - else - rt2x00_set_field16(®, TXRX_CSR20_BCN_EXPECT_WINDOW, 2); - rt2500usb_register_write(rt2x00dev, TXRX_CSR20, reg); + /* + * Enable beacon config + */ + bcn_preload = PREAMBLE + get_duration(IEEE80211_HEADER, 20); + rt2500usb_register_read(rt2x00dev, TXRX_CSR20, ®); + rt2x00_set_field16(®, TXRX_CSR20_OFFSET, bcn_preload >> 6); + rt2x00_set_field16(®, TXRX_CSR20_BCN_EXPECT_WINDOW, + 2 * (conf->type != IEEE80211_IF_TYPE_STA)); + rt2500usb_register_write(rt2x00dev, TXRX_CSR20, reg); - /* - * Enable synchronisation. - */ - rt2500usb_register_read(rt2x00dev, TXRX_CSR18, ®); - rt2x00_set_field16(®, TXRX_CSR18_OFFSET, 0); - rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg); + /* + * Enable synchronisation. + */ + rt2500usb_register_read(rt2x00dev, TXRX_CSR18, ®); + rt2x00_set_field16(®, TXRX_CSR18_OFFSET, 0); + rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg); + + rt2500usb_register_read(rt2x00dev, TXRX_CSR19, ®); + rt2x00_set_field16(®, TXRX_CSR19_TSF_COUNT, 1); + rt2x00_set_field16(®, TXRX_CSR19_TBCN, + (conf->sync == TSF_SYNC_BEACON)); + rt2x00_set_field16(®, TXRX_CSR19_BEACON_GEN, 0); + rt2x00_set_field16(®, TXRX_CSR19_TSF_SYNC, conf->sync); + rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); + } - rt2500usb_register_read(rt2x00dev, TXRX_CSR19, ®); - rt2x00_set_field16(®, TXRX_CSR19_TSF_COUNT, 1); - rt2x00_set_field16(®, TXRX_CSR19_TBCN, - (tsf_sync == TSF_SYNC_BEACON)); - rt2x00_set_field16(®, TXRX_CSR19_BEACON_GEN, 0); - rt2x00_set_field16(®, TXRX_CSR19_TSF_SYNC, tsf_sync); - rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); + if (flags & CONFIG_UPDATE_MAC) + rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR2, conf->mac, + (3 * sizeof(__le16))); + + if (flags & CONFIG_UPDATE_BSSID) + rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR5, conf->bssid, + (3 * sizeof(__le16))); } -static void rt2500usb_config_preamble(struct rt2x00_dev *rt2x00dev, - const int short_preamble, - const int ack_timeout, - const int ack_consume_time) +static int rt2500usb_config_preamble(struct rt2x00_dev *rt2x00dev, + const int short_preamble, + const int ack_timeout, + const int ack_consume_time) { u16 reg; /* - * When in atomic context, reschedule and let rt2x00lib - * call this function again. + * When in atomic context, we should let rt2x00lib + * try this configuration again later. */ - if (in_atomic()) { - queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->config_work); - return; - } + if (in_atomic()) + return -EAGAIN; rt2500usb_register_read(rt2x00dev, TXRX_CSR1, ®); rt2x00_set_field16(®, TXRX_CSR1_ACK_TIMEOUT, ack_timeout); @@ -358,6 +353,8 @@ static void rt2500usb_config_preamble(struct rt2x00_dev *rt2x00dev, rt2x00_set_field16(®, TXRX_CSR10_AUTORESPOND_PREAMBLE, !!short_preamble); rt2500usb_register_write(rt2x00dev, TXRX_CSR10, reg); + + return 0; } static void rt2500usb_config_phymode(struct rt2x00_dev *rt2x00dev, @@ -518,8 +515,8 @@ static void rt2500usb_config_duration(struct rt2x00_dev *rt2x00dev, } static void rt2500usb_config(struct rt2x00_dev *rt2x00dev, - const unsigned int flags, - struct rt2x00lib_conf *libconf) + struct rt2x00lib_conf *libconf, + const unsigned int flags) { if (flags & CONFIG_UPDATE_PHYMODE) rt2500usb_config_phymode(rt2x00dev, libconf->phymode, @@ -625,6 +622,24 @@ static void rt2500usb_link_tuner(struct rt2x00_dev *rt2x00dev) u8 up_bound; u8 low_bound; + /* + * Read current r17 value, as well as the sensitivity values + * for the r17 register. + */ + rt2500usb_bbp_read(rt2x00dev, 17, &r17); + rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R17, &r17_sens); + + rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_VGC, &vgc_bound); + up_bound = rt2x00_get_field16(vgc_bound, EEPROM_BBPTUNE_VGCUPPER); + low_bound = rt2x00_get_field16(vgc_bound, EEPROM_BBPTUNE_VGCLOWER); + + /* + * If we are not associated, we should go straight to the + * dynamic CCA tuning. + */ + if (!rt2x00dev->intf_associated) + goto dynamic_cca_tune; + /* * Determine the BBP tuning threshold and correctly * set BBP 24, 25 and 61. @@ -650,13 +665,6 @@ static void rt2500usb_link_tuner(struct rt2x00_dev *rt2x00dev) rt2500usb_bbp_write(rt2x00dev, 25, r25); rt2500usb_bbp_write(rt2x00dev, 61, r61); - /* - * Read current r17 value, as well as the sensitivity values - * for the r17 register. - */ - rt2500usb_bbp_read(rt2x00dev, 17, &r17); - rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R17, &r17_sens); - /* * A too low RSSI will cause too much false CCA which will * then corrupt the R17 tuning. To remidy this the tuning should @@ -692,14 +700,9 @@ static void rt2500usb_link_tuner(struct rt2x00_dev *rt2x00dev) * Leave short or middle distance condition, restore r17 * to the dynamic tuning range. */ - rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_VGC, &vgc_bound); - vgc_bound = rt2x00_get_field16(vgc_bound, EEPROM_BBPTUNE_VGCUPPER); - low_bound = 0x32; - if (rssi >= -77) - up_bound = vgc_bound; - else - up_bound = vgc_bound - (-77 - rssi); + if (rssi < -77) + up_bound -= (-77 - rssi); if (up_bound < low_bound) up_bound = low_bound; @@ -707,7 +710,16 @@ static void rt2500usb_link_tuner(struct rt2x00_dev *rt2x00dev) if (r17 > up_bound) { rt2500usb_bbp_write(rt2x00dev, 17, up_bound); rt2x00dev->link.vgc_level = up_bound; - } else if (rt2x00dev->link.qual.false_cca > 512 && r17 < up_bound) { + return; + } + +dynamic_cca_tune: + + /* + * R17 is inside the dynamic tuning range, + * start tuning the link based on the false cca counter. + */ + if (rt2x00dev->link.qual.false_cca > 512 && r17 < up_bound) { rt2500usb_bbp_write(rt2x00dev, 17, ++r17); rt2x00dev->link.vgc_level = r17; } else if (rt2x00dev->link.qual.false_cca < 100 && r17 > low_bound) { @@ -1203,6 +1215,7 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev) { u16 word; u8 *mac; + u8 bbp; rt2x00usb_eeprom_read(rt2x00dev, rt2x00dev->eeprom, EEPROM_SIZE); @@ -1257,9 +1270,17 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev) EEPROM(rt2x00dev, "BBPtune: 0x%04x\n", word); } + /* + * Switch lower vgc bound to current BBP R17 value, + * lower the value a bit for better quality. + */ + rt2500usb_bbp_read(rt2x00dev, 17, &bbp); + bbp -= 6; + rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_VGC, &word); if (word == 0xffff) { rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCUPPER, 0x40); + rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCLOWER, bbp); rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_VGC, word); EEPROM(rt2x00dev, "BBPtune vgc: 0x%04x\n", word); } @@ -1270,6 +1291,9 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev) rt2x00_set_field16(&word, EEPROM_BBPTUNE_R17_HIGH, 0x41); rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_R17, word); EEPROM(rt2x00dev, "BBPtune r17: 0x%04x\n", word); + } else { + rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCLOWER, bbp); + rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_VGC, word); } rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R24, &word); @@ -1705,40 +1729,40 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw, { struct rt2x00_dev *rt2x00dev = hw->priv; struct usb_device *usb_dev = rt2x00dev_usb_dev(rt2x00dev); + struct rt2x00_intf *intf = vif_to_intf(control->vif); struct queue_entry_priv_usb_bcn *priv_bcn; struct skb_frame_desc *skbdesc; - struct data_queue *queue; - struct queue_entry *entry; int pipe = usb_sndbulkpipe(usb_dev, 1); int length; - /* - * Just in case the ieee80211 doesn't set this, - * but we need this queue set for the descriptor - * initialization. - */ - control->queue = IEEE80211_TX_QUEUE_BEACON; - queue = rt2x00queue_get_queue(rt2x00dev, control->queue); - entry = rt2x00queue_get_entry(queue, Q_INDEX); - priv_bcn = entry->priv_data; + if (unlikely(!intf->beacon)) + return -ENOBUFS; + + priv_bcn = intf->beacon->priv_data; /* * Add the descriptor in front of the skb. */ - skb_push(skb, queue->desc_size); - memset(skb->data, 0, queue->desc_size); + skb_push(skb, intf->beacon->queue->desc_size); + memset(skb->data, 0, intf->beacon->queue->desc_size); /* * Fill in skb descriptor */ skbdesc = get_skb_frame_desc(skb); memset(skbdesc, 0, sizeof(*skbdesc)); - skbdesc->data = skb->data + queue->desc_size; - skbdesc->data_len = queue->data_size; + skbdesc->data = skb->data + intf->beacon->queue->desc_size; + skbdesc->data_len = skb->len - intf->beacon->queue->desc_size; skbdesc->desc = skb->data; - skbdesc->desc_len = queue->desc_size; - skbdesc->entry = entry; + skbdesc->desc_len = intf->beacon->queue->desc_size; + skbdesc->entry = intf->beacon; + /* + * Just in case mac80211 doesn't set this correctly, + * but we need this queue set for the descriptor + * initialization. + */ + control->queue = IEEE80211_TX_QUEUE_BEACON; rt2x00lib_write_tx_desc(rt2x00dev, skb, control); /* @@ -1749,7 +1773,8 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw, length = rt2500usb_get_tx_data_len(rt2x00dev, skb); usb_fill_bulk_urb(priv_bcn->urb, usb_dev, pipe, - skb->data, length, rt2500usb_beacondone, entry); + skb->data, length, rt2500usb_beacondone, + intf->beacon); /* * Second we need to create the guardian byte. @@ -1759,7 +1784,7 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw, priv_bcn->guardian_data = 0; usb_fill_bulk_urb(priv_bcn->guardian_urb, usb_dev, pipe, &priv_bcn->guardian_data, 1, rt2500usb_beacondone, - entry); + intf->beacon); /* * Send out the guardian byte. @@ -1769,7 +1794,7 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw, /* * Enable beacon generation. */ - rt2500usb_kick_tx_queue(rt2x00dev, IEEE80211_TX_QUEUE_BEACON); + rt2500usb_kick_tx_queue(rt2x00dev, control->queue); return 0; } @@ -1805,9 +1830,7 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { .get_tx_data_len = rt2500usb_get_tx_data_len, .kick_tx_queue = rt2500usb_kick_tx_queue, .fill_rxdone = rt2500usb_fill_rxdone, - .config_mac_addr = rt2500usb_config_mac_addr, - .config_bssid = rt2500usb_config_bssid, - .config_type = rt2500usb_config_type, + .config_intf = rt2500usb_config_intf, .config_preamble = rt2500usb_config_preamble, .config = rt2500usb_config, }; @@ -1842,6 +1865,8 @@ static const struct data_queue_desc rt2500usb_queue_atim = { static const struct rt2x00_ops rt2500usb_ops = { .name = KBUILD_MODNAME, + .max_sta_intf = 1, + .max_ap_intf = 1, .eeprom_size = EEPROM_SIZE, .rf_size = RF_SIZE, .rx = &rt2500usb_queue_rx, diff --git a/drivers/net/wireless/rt2x00/rt2500usb.h b/drivers/net/wireless/rt2x00/rt2500usb.h index e9f2cd90da58..23ba0c15741f 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.h +++ b/drivers/net/wireless/rt2x00/rt2500usb.h @@ -686,6 +686,7 @@ */ #define EEPROM_BBPTUNE_VGC 0x0034 #define EEPROM_BBPTUNE_VGCUPPER FIELD16(0x00ff) +#define EEPROM_BBPTUNE_VGCLOWER FIELD16(0xff00) /* * EEPROM BBP R17 Tuning. diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 6a25195816db..2363ca4903cc 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -343,20 +343,22 @@ static inline int rt2x00_update_ant_rssi(struct link *link, int rssi) /* * Interface structure - * Configuration details about the current interface. + * Per interface configuration details, this structure + * is allocated as the private data for ieee80211_vif. */ -struct interface { +struct rt2x00_intf { /* - * Interface identification. The value is assigned - * to us by the 80211 stack, and is used to request - * new beacons. + * All fields within the rt2x00_intf structure + * must be protected with a spinlock. */ - struct ieee80211_vif *id; + spinlock_t lock; /* - * Current working type (IEEE80211_IF_TYPE_*). + * BSS configuration. Copied from the structure + * passed to us through the bss_info_changed() + * callback funtion. */ - int type; + struct ieee80211_bss_conf conf; /* * MAC of the device. @@ -367,16 +369,25 @@ struct interface { * BBSID of the AP to associate with. */ u8 bssid[ETH_ALEN]; -}; -static inline int is_interface_present(struct interface *intf) -{ - return !!intf->id; -} + /* + * Entry in the beacon queue which belongs to + * this interface. Each interface has its own + * dedicated beacon entry. + */ + struct queue_entry *beacon; -static inline int is_interface_type(struct interface *intf, int type) + /* + * Actions that needed rescheduling. + */ + unsigned int delayed_flags; +#define DELAYED_UPDATE_BEACON 0x00000001 +#define DELAYED_CONFIG_PREAMBLE 0x00000002 +}; + +static inline struct rt2x00_intf* vif_to_intf(struct ieee80211_vif *vif) { - return intf->type == type; + return (struct rt2x00_intf *)vif->drv_priv; } /* @@ -429,6 +440,37 @@ struct rt2x00lib_conf { short eifs; }; +/* + * Configuration structure wrapper around the + * rt2x00 interface configuration handler. + */ +struct rt2x00intf_conf { + /* + * Interface type + */ + enum ieee80211_if_types type; + + /* + * TSF sync value, this is dependant on the operation type. + */ + enum tsf_sync sync; + + /* + * The MAC and BSSID addressess are simple array of bytes, + * these arrays are little endian, so when sending the addressess + * to the drivers, copy the it into a endian-signed variable. + * + * Note that all devices (except rt2500usb) have 32 bits + * register word sizes. This means that whatever variable we + * pass _must_ be a multiple of 32 bits. Otherwise the device + * might not accept what we are sending to it. + * This will also make it easier for the driver to write + * the data to the device. + */ + __le32 mac[2]; + __le32 bssid[2]; +}; + /* * rt2x00lib callback functions. */ @@ -495,16 +537,21 @@ struct rt2x00lib_ops { /* * Configuration handlers. */ - void (*config_mac_addr) (struct rt2x00_dev *rt2x00dev, __le32 *mac); - void (*config_bssid) (struct rt2x00_dev *rt2x00dev, __le32 *bssid); - void (*config_type) (struct rt2x00_dev *rt2x00dev, const int type, - const int tsf_sync); - void (*config_preamble) (struct rt2x00_dev *rt2x00dev, - const int short_preamble, - const int ack_timeout, - const int ack_consume_time); - void (*config) (struct rt2x00_dev *rt2x00dev, const unsigned int flags, - struct rt2x00lib_conf *libconf); + void (*config_intf) (struct rt2x00_dev *rt2x00dev, + struct rt2x00_intf *intf, + struct rt2x00intf_conf *conf, + const unsigned int flags); +#define CONFIG_UPDATE_TYPE ( 1 << 1 ) +#define CONFIG_UPDATE_MAC ( 1 << 2 ) +#define CONFIG_UPDATE_BSSID ( 1 << 3 ) + + int (*config_preamble) (struct rt2x00_dev *rt2x00dev, + const int short_preamble, + const int ack_timeout, + const int ack_consume_time); + void (*config) (struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_conf *libconf, + const unsigned int flags); #define CONFIG_UPDATE_PHYMODE ( 1 << 1 ) #define CONFIG_UPDATE_CHANNEL ( 1 << 2 ) #define CONFIG_UPDATE_TXPOWER ( 1 << 3 ) @@ -519,6 +566,8 @@ struct rt2x00lib_ops { */ struct rt2x00_ops { const char *name; + const unsigned int max_sta_intf; + const unsigned int max_ap_intf; const unsigned int eeprom_size; const unsigned int rf_size; const struct data_queue_desc *rx; @@ -550,6 +599,7 @@ enum rt2x00_flags { /* * Driver features */ + DRIVER_SUPPORT_MIXED_INTERFACES, DRIVER_REQUIRE_FIRMWARE, DRIVER_REQUIRE_FIRMWARE_CRC_ITU_T, DRIVER_REQUIRE_FIRMWARE_CCITT, @@ -566,7 +616,6 @@ enum rt2x00_flags { CONFIG_EXTERNAL_LNA_BG, CONFIG_DOUBLE_ANTENNA, CONFIG_DISABLE_LINK_TUNING, - CONFIG_SHORT_PREAMBLE, }; /* @@ -670,9 +719,14 @@ struct rt2x00_dev { unsigned int packet_filter; /* - * Interface configuration. + * Interface details: + * - Open ap interface count. + * - Open sta interface count. + * - Association count. */ - struct interface interface; + unsigned int intf_ap_count; + unsigned int intf_sta_count; + unsigned int intf_associated; /* * Link quality @@ -738,9 +792,8 @@ struct rt2x00_dev { /* * Scheduled work. */ - struct work_struct beacon_work; + struct work_struct intf_work; struct work_struct filter_work; - struct work_struct config_work; /* * Data queue arrays for RX, TX and Beacon. diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index c247ee77b3a3..20231e0c53fa 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -29,64 +29,89 @@ #include "rt2x00.h" #include "rt2x00lib.h" - -/* - * The MAC and BSSID addressess are simple array of bytes, - * these arrays are little endian, so when sending the addressess - * to the drivers, copy the it into a endian-signed variable. - * - * Note that all devices (except rt2500usb) have 32 bits - * register word sizes. This means that whatever variable we - * pass _must_ be a multiple of 32 bits. Otherwise the device - * might not accept what we are sending to it. - * This will also make it easier for the driver to write - * the data to the device. - * - * Also note that when NULL is passed as address the - * we will send 00:00:00:00:00 to the device to clear the address. - * This will prevent the device being confused when it wants - * to ACK frames or consideres itself associated. - */ -void rt2x00lib_config_mac_addr(struct rt2x00_dev *rt2x00dev, u8 *mac) +void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev, + struct rt2x00_intf *intf, + enum ieee80211_if_types type, + u8 *mac, u8 *bssid) { - __le32 reg[2]; - - memset(®, 0, sizeof(reg)); - if (mac) - memcpy(®, mac, ETH_ALEN); - - rt2x00dev->ops->lib->config_mac_addr(rt2x00dev, ®[0]); -} + struct rt2x00intf_conf conf; + unsigned int flags = 0; -void rt2x00lib_config_bssid(struct rt2x00_dev *rt2x00dev, u8 *bssid) -{ - __le32 reg[2]; - - memset(®, 0, sizeof(reg)); - if (bssid) - memcpy(®, bssid, ETH_ALEN); - - rt2x00dev->ops->lib->config_bssid(rt2x00dev, ®[0]); -} - -void rt2x00lib_config_type(struct rt2x00_dev *rt2x00dev, const int type) -{ - int tsf_sync; + conf.type = type; switch (type) { case IEEE80211_IF_TYPE_IBSS: case IEEE80211_IF_TYPE_AP: - tsf_sync = TSF_SYNC_BEACON; + conf.sync = TSF_SYNC_BEACON; break; case IEEE80211_IF_TYPE_STA: - tsf_sync = TSF_SYNC_INFRA; + conf.sync = TSF_SYNC_INFRA; break; default: - tsf_sync = TSF_SYNC_NONE; + conf.sync = TSF_SYNC_NONE; break; } - rt2x00dev->ops->lib->config_type(rt2x00dev, type, tsf_sync); + /* + * Note that when NULL is passed as address we will send + * 00:00:00:00:00 to the device to clear the address. + * This will prevent the device being confused when it wants + * to ACK frames or consideres itself associated. + */ + memset(&conf.mac, 0, sizeof(conf.mac)); + if (mac) + memcpy(&conf.mac, mac, ETH_ALEN); + + memset(&conf.bssid, 0, sizeof(conf.bssid)); + if (bssid) + memcpy(&conf.bssid, bssid, ETH_ALEN); + + flags |= CONFIG_UPDATE_TYPE; + if (mac || (!rt2x00dev->intf_ap_count && !rt2x00dev->intf_sta_count)) + flags |= CONFIG_UPDATE_MAC; + if (bssid || (!rt2x00dev->intf_ap_count && !rt2x00dev->intf_sta_count)) + flags |= CONFIG_UPDATE_BSSID; + + rt2x00dev->ops->lib->config_intf(rt2x00dev, intf, &conf, flags); +} + +void rt2x00lib_config_preamble(struct rt2x00_dev *rt2x00dev, + struct rt2x00_intf *intf, + const unsigned int short_preamble) +{ + int retval; + int ack_timeout; + int ack_consume_time; + + ack_timeout = PLCP + get_duration(ACK_SIZE, 10); + ack_consume_time = SIFS + PLCP + get_duration(ACK_SIZE, 10); + + if (rt2x00dev->hw->conf.flags & IEEE80211_CONF_SHORT_SLOT_TIME) + ack_timeout += SHORT_DIFS; + else + ack_timeout += DIFS; + + if (short_preamble) { + ack_timeout += SHORT_PREAMBLE; + ack_consume_time += SHORT_PREAMBLE; + } else { + ack_timeout += PREAMBLE; + ack_consume_time += PREAMBLE; + } + + retval = rt2x00dev->ops->lib->config_preamble(rt2x00dev, + short_preamble, + ack_timeout, + ack_consume_time); + + spin_lock(&intf->lock); + + if (retval) { + intf->delayed_flags |= DELAYED_CONFIG_PREAMBLE; + queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->intf_work); + } + + spin_unlock(&intf->lock); } void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, @@ -113,7 +138,7 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, * The latter is required since we need to recalibrate the * noise-sensitivity ratio for the new setup. */ - rt2x00dev->ops->lib->config(rt2x00dev, CONFIG_UPDATE_ANTENNA, &libconf); + rt2x00dev->ops->lib->config(rt2x00dev, &libconf, CONFIG_UPDATE_ANTENNA); rt2x00lib_reset_link_tuner(rt2x00dev); rt2x00dev->link.ant.active.rx = libconf.ant.rx; @@ -266,7 +291,7 @@ config: /* * Start configuration. */ - rt2x00dev->ops->lib->config(rt2x00dev, flags, &libconf); + rt2x00dev->ops->lib->config(rt2x00dev, &libconf, flags); /* * Some configuration changes affect the link quality diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index bc07c56f89b3..014c307c270c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -136,12 +136,10 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev) /* * Stop all scheduled work. */ - if (work_pending(&rt2x00dev->beacon_work)) - cancel_work_sync(&rt2x00dev->beacon_work); + if (work_pending(&rt2x00dev->intf_work)) + cancel_work_sync(&rt2x00dev->intf_work); if (work_pending(&rt2x00dev->filter_work)) cancel_work_sync(&rt2x00dev->filter_work); - if (work_pending(&rt2x00dev->config_work)) - cancel_work_sync(&rt2x00dev->config_work); /* * Stop the TX queues. @@ -173,7 +171,7 @@ void rt2x00lib_toggle_rx(struct rt2x00_dev *rt2x00dev, enum dev_state state) * When we are enabling the RX, we should also start the link tuner. */ if (state == STATE_RADIO_RX_ON && - is_interface_present(&rt2x00dev->interface)) + (rt2x00dev->intf_ap_count || rt2x00dev->intf_sta_count)) rt2x00lib_start_link_tuner(rt2x00dev); } @@ -401,10 +399,10 @@ static void rt2x00lib_packetfilter_scheduled(struct work_struct *work) unsigned int filter = rt2x00dev->packet_filter; /* - * Since we had stored the filter inside interface.filter, + * Since we had stored the filter inside rt2x00dev->packet_filter, * we should now clear that field. Otherwise the driver will * assume nothing has changed (*total_flags will be compared - * to interface.filter to determine if any action is required). + * to rt2x00dev->packet_filter to determine if any action is required). */ rt2x00dev->packet_filter = 0; @@ -412,41 +410,72 @@ static void rt2x00lib_packetfilter_scheduled(struct work_struct *work) filter, &filter, 0, NULL); } -static void rt2x00lib_configuration_scheduled(struct work_struct *work) +static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac, + struct ieee80211_vif *vif) { - struct rt2x00_dev *rt2x00dev = - container_of(work, struct rt2x00_dev, config_work); - struct ieee80211_bss_conf bss_conf; + struct rt2x00_dev *rt2x00dev = data; + struct rt2x00_intf *intf = vif_to_intf(vif); + struct sk_buff *skb; + struct ieee80211_tx_control control; + struct ieee80211_bss_conf conf; + int delayed_flags; + + /* + * Copy all data we need during this action under the protection + * of a spinlock. Otherwise race conditions might occur which results + * into an invalid configuration. + */ + spin_lock(&intf->lock); + + memcpy(&conf, &intf->conf, sizeof(conf)); + delayed_flags = intf->delayed_flags; + intf->delayed_flags = 0; + + spin_unlock(&intf->lock); + + if (delayed_flags & DELAYED_UPDATE_BEACON) { + skb = ieee80211_beacon_get(rt2x00dev->hw, vif, &control); + if (skb) { + rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw, skb, + &control); + dev_kfree_skb(skb); + } + } + + if (delayed_flags & DELAYED_CONFIG_PREAMBLE) + rt2x00lib_config_preamble(rt2x00dev, intf, + intf->conf.use_short_preamble); +} - bss_conf.use_short_preamble = - test_bit(CONFIG_SHORT_PREAMBLE, &rt2x00dev->flags); +static void rt2x00lib_intf_scheduled(struct work_struct *work) +{ + struct rt2x00_dev *rt2x00dev = + container_of(work, struct rt2x00_dev, intf_work); /* - * FIXME: shouldn't invoke it this way because all other contents - * of bss_conf is invalid. + * Iterate over each interface and perform the + * requested configurations. */ - rt2x00mac_bss_info_changed(rt2x00dev->hw, rt2x00dev->interface.id, - &bss_conf, BSS_CHANGED_ERP_PREAMBLE); + ieee80211_iterate_active_interfaces(rt2x00dev->hw, + rt2x00lib_intf_scheduled_iter, + rt2x00dev); } /* * Interrupt context handlers. */ -static void rt2x00lib_beacondone_scheduled(struct work_struct *work) +static void rt2x00lib_beacondone_iter(void *data, u8 *mac, + struct ieee80211_vif *vif) { - struct rt2x00_dev *rt2x00dev = - container_of(work, struct rt2x00_dev, beacon_work); - struct ieee80211_tx_control control; - struct sk_buff *skb; + struct rt2x00_intf *intf = vif_to_intf(vif); - skb = ieee80211_beacon_get(rt2x00dev->hw, - rt2x00dev->interface.id, &control); - if (!skb) + if (vif->type != IEEE80211_IF_TYPE_AP && + vif->type != IEEE80211_IF_TYPE_IBSS) return; - rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw, skb, &control); - - dev_kfree_skb(skb); + spin_lock(&intf->lock); + intf->delayed_flags |= DELAYED_UPDATE_BEACON; + spin_unlock(&intf->lock); } void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev) @@ -454,7 +483,11 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev) if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags)) return; - queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->beacon_work); + ieee80211_iterate_active_interfaces(rt2x00dev->hw, + rt2x00lib_beacondone_iter, + rt2x00dev); + + queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->intf_work); } EXPORT_SYMBOL_GPL(rt2x00lib_beacondone); @@ -1037,6 +1070,10 @@ int rt2x00lib_start(struct rt2x00_dev *rt2x00dev) return retval; } + rt2x00dev->intf_ap_count = 0; + rt2x00dev->intf_sta_count = 0; + rt2x00dev->intf_associated = 0; + __set_bit(DEVICE_STARTED, &rt2x00dev->flags); return 0; @@ -1053,6 +1090,10 @@ void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev) */ rt2x00lib_disable_radio(rt2x00dev); + rt2x00dev->intf_ap_count = 0; + rt2x00dev->intf_sta_count = 0; + rt2x00dev->intf_associated = 0; + __clear_bit(DEVICE_STARTED, &rt2x00dev->flags); } @@ -1063,6 +1104,12 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) { int retval = -ENOMEM; + /* + * Make room for rt2x00_intf inside the per-interface + * structure ieee80211_vif. + */ + rt2x00dev->hw->vif_data_size = sizeof(struct rt2x00_intf); + /* * Let the driver probe the device to detect the capabilities. */ @@ -1075,16 +1122,10 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) /* * Initialize configuration work. */ - INIT_WORK(&rt2x00dev->beacon_work, rt2x00lib_beacondone_scheduled); + INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled); INIT_WORK(&rt2x00dev->filter_work, rt2x00lib_packetfilter_scheduled); - INIT_WORK(&rt2x00dev->config_work, rt2x00lib_configuration_scheduled); INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00lib_link_tuner); - /* - * Reset current working type. - */ - rt2x00dev->interface.type = IEEE80211_IF_TYPE_INVALID; - /* * Allocate queue array. */ @@ -1203,9 +1244,30 @@ exit: } EXPORT_SYMBOL_GPL(rt2x00lib_suspend); +static void rt2x00lib_resume_intf(void *data, u8 *mac, + struct ieee80211_vif *vif) +{ + struct rt2x00_dev *rt2x00dev = data; + struct rt2x00_intf *intf = vif_to_intf(vif); + + spin_lock(&intf->lock); + + rt2x00lib_config_intf(rt2x00dev, intf, + vif->type, intf->mac, intf->bssid); + + + /* + * Master or Ad-hoc mode require a new beacon update. + */ + if (vif->type == IEEE80211_IF_TYPE_AP || + vif->type == IEEE80211_IF_TYPE_IBSS) + intf->delayed_flags |= DELAYED_UPDATE_BEACON; + + spin_unlock(&intf->lock); +} + int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev) { - struct interface *intf = &rt2x00dev->interface; int retval; NOTICE(rt2x00dev, "Waking up.\n"); @@ -1235,9 +1297,12 @@ int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev) if (!rt2x00dev->hw->conf.radio_enabled) rt2x00lib_disable_radio(rt2x00dev); - rt2x00lib_config_mac_addr(rt2x00dev, intf->mac); - rt2x00lib_config_bssid(rt2x00dev, intf->bssid); - rt2x00lib_config_type(rt2x00dev, intf->type); + /* + * Iterator over each active interface to + * reconfigure the hardware. + */ + ieee80211_iterate_active_interfaces(rt2x00dev->hw, + rt2x00lib_resume_intf, rt2x00dev); /* * We are ready again to receive requests from mac80211. @@ -1253,12 +1318,11 @@ int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev) ieee80211_start_queues(rt2x00dev->hw); /* - * When in Master or Ad-hoc mode, - * restart Beacon transmitting by faking a beacondone event. + * During interface iteration we might have changed the + * delayed_flags, time to handles the event by calling + * the work handler directly. */ - if (intf->type == IEEE80211_IF_TYPE_AP || - intf->type == IEEE80211_IF_TYPE_IBSS) - rt2x00lib_beacondone(rt2x00dev); + rt2x00lib_intf_scheduled(&rt2x00dev->intf_work); return 0; diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index 5c835f42a455..f6789fdaaf6e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -50,9 +50,13 @@ void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev); /* * Configuration handlers. */ -void rt2x00lib_config_mac_addr(struct rt2x00_dev *rt2x00dev, u8 *mac); -void rt2x00lib_config_bssid(struct rt2x00_dev *rt2x00dev, u8 *bssid); -void rt2x00lib_config_type(struct rt2x00_dev *rt2x00dev, const int type); +void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev, + struct rt2x00_intf *intf, + enum ieee80211_if_types type, + u8 *mac, u8 *bssid); +void rt2x00lib_config_preamble(struct rt2x00_dev *rt2x00dev, + struct rt2x00_intf *intf, + const unsigned int short_preamble); void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, enum antenna rx, enum antenna tx); void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index f08c151ee4ba..65a2bcd18aa1 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -52,11 +52,11 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev, skb_put(skb, size); if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) - ieee80211_ctstoself_get(rt2x00dev->hw, rt2x00dev->interface.id, + ieee80211_ctstoself_get(rt2x00dev->hw, control->vif, frag_skb->data, frag_skb->len, control, (struct ieee80211_cts *)(skb->data)); else - ieee80211_rts_get(rt2x00dev->hw, rt2x00dev->interface.id, + ieee80211_rts_get(rt2x00dev->hw, control->vif, frag_skb->data, frag_skb->len, control, (struct ieee80211_rts *)(skb->data)); @@ -162,19 +162,67 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_if_init_conf *conf) { struct rt2x00_dev *rt2x00dev = hw->priv; - struct interface *intf = &rt2x00dev->interface; + struct rt2x00_intf *intf = vif_to_intf(conf->vif); + struct data_queue *queue = + rt2x00queue_get_queue(rt2x00dev, IEEE80211_TX_QUEUE_BEACON); + struct queue_entry *entry = NULL; + unsigned int i; /* - * Don't allow interfaces to be added while - * either the device has disappeared or when - * another interface is already present. + * Don't allow interfaces to be added + * the device has disappeared. */ if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags) || - is_interface_present(intf)) + !test_bit(DEVICE_STARTED, &rt2x00dev->flags)) + return -ENODEV; + + /* + * When we don't support mixed interfaces (a combination + * of sta and ap virtual interfaces) then we can only + * add this interface when the rival interface count is 0. + */ + if (!test_bit(DRIVER_SUPPORT_MIXED_INTERFACES, &rt2x00dev->flags) && + ((conf->type == IEEE80211_IF_TYPE_AP && rt2x00dev->intf_sta_count) || + (conf->type != IEEE80211_IF_TYPE_AP && rt2x00dev->intf_ap_count))) + return -ENOBUFS; + + /* + * Check if we exceeded the maximum amount of supported interfaces. + */ + if ((conf->type == IEEE80211_IF_TYPE_AP && + rt2x00dev->intf_ap_count >= rt2x00dev->ops->max_ap_intf) || + (conf->type != IEEE80211_IF_TYPE_AP && + rt2x00dev->intf_sta_count >= rt2x00dev->ops->max_sta_intf)) + return -ENOBUFS; + + /* + * Loop through all beacon queues to find a free + * entry. Since there are as much beacon entries + * as the maximum interfaces, this search shouldn't + * fail. + */ + for (i = 0; i < queue->limit; i++) { + entry = &queue->entries[i]; + if (!__test_and_set_bit(ENTRY_BCN_ASSIGNED, &entry->flags)) + break; + } + + if (unlikely(i == queue->limit)) return -ENOBUFS; - intf->id = conf->vif; - intf->type = conf->type; + /* + * We are now absolutely sure the interface can be created, + * increase interface count and start initialization. + */ + + if (conf->type == IEEE80211_IF_TYPE_AP) + rt2x00dev->intf_ap_count++; + else + rt2x00dev->intf_sta_count++; + + spin_lock_init(&intf->lock); + intf->beacon = entry; + if (conf->type == IEEE80211_IF_TYPE_AP) memcpy(&intf->bssid, conf->mac_addr, ETH_ALEN); memcpy(&intf->mac, conf->mac_addr, ETH_ALEN); @@ -184,8 +232,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, * has been initialized. Otherwise the device can reset * the MAC registers. */ - rt2x00lib_config_mac_addr(rt2x00dev, intf->mac); - rt2x00lib_config_type(rt2x00dev, conf->type); + rt2x00lib_config_intf(rt2x00dev, intf, conf->type, intf->mac, NULL); return 0; } @@ -195,7 +242,7 @@ void rt2x00mac_remove_interface(struct ieee80211_hw *hw, struct ieee80211_if_init_conf *conf) { struct rt2x00_dev *rt2x00dev = hw->priv; - struct interface *intf = &rt2x00dev->interface; + struct rt2x00_intf *intf = vif_to_intf(conf->vif); /* * Don't allow interfaces to be remove while @@ -203,21 +250,27 @@ void rt2x00mac_remove_interface(struct ieee80211_hw *hw, * no interface is present. */ if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags) || - !is_interface_present(intf)) + (conf->type == IEEE80211_IF_TYPE_AP && !rt2x00dev->intf_ap_count) || + (conf->type != IEEE80211_IF_TYPE_AP && !rt2x00dev->intf_sta_count)) return; - intf->id = NULL; - intf->type = IEEE80211_IF_TYPE_INVALID; - memset(&intf->bssid, 0x00, ETH_ALEN); - memset(&intf->mac, 0x00, ETH_ALEN); + if (conf->type == IEEE80211_IF_TYPE_AP) + rt2x00dev->intf_ap_count--; + else + rt2x00dev->intf_sta_count--; + + /* + * Release beacon entry so it is available for + * new interfaces again. + */ + __clear_bit(ENTRY_BCN_ASSIGNED, &intf->beacon->flags); /* * Make sure the bssid and mac address registers * are cleared to prevent false ACKing of frames. */ - rt2x00lib_config_mac_addr(rt2x00dev, intf->mac); - rt2x00lib_config_bssid(rt2x00dev, intf->bssid); - rt2x00lib_config_type(rt2x00dev, intf->type); + rt2x00lib_config_intf(rt2x00dev, intf, + IEEE80211_IF_TYPE_INVALID, NULL, NULL); } EXPORT_SYMBOL_GPL(rt2x00mac_remove_interface); @@ -262,7 +315,7 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw, struct ieee80211_if_conf *conf) { struct rt2x00_dev *rt2x00dev = hw->priv; - struct interface *intf = &rt2x00dev->interface; + struct rt2x00_intf *intf = vif_to_intf(vif); int status; /* @@ -272,12 +325,7 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw, if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags)) return 0; - /* - * If the given type does not match the configured type, - * there has been a problem. - */ - if (conf->type != intf->type) - return -EINVAL; + spin_lock(&intf->lock); /* * If the interface does not work in master mode, @@ -286,7 +334,9 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw, */ if (conf->type != IEEE80211_IF_TYPE_AP) memcpy(&intf->bssid, conf->bssid, ETH_ALEN); - rt2x00lib_config_bssid(rt2x00dev, intf->bssid); + rt2x00lib_config_intf(rt2x00dev, intf, conf->type, NULL, intf->bssid); + + spin_unlock(&intf->lock); /* * We only need to initialize the beacon when master mode is enabled. @@ -342,35 +392,35 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, u32 changes) { struct rt2x00_dev *rt2x00dev = hw->priv; - int short_preamble; - int ack_timeout; - int ack_consume_time; - int difs; - int preamble; + struct rt2x00_intf *intf = vif_to_intf(vif); /* - * We only support changing preamble mode. + * When the association status has changed we must reset the link + * tuner counter. This is because some drivers determine if they + * should perform link tuning based on the number of seconds + * while associated or not associated. */ - if (!(changes & BSS_CHANGED_ERP_PREAMBLE)) - return; - - short_preamble = bss_conf->use_short_preamble; - preamble = bss_conf->use_short_preamble ? - SHORT_PREAMBLE : PREAMBLE; + if (changes & BSS_CHANGED_ASSOC) { + rt2x00dev->link.count = 0; - difs = (hw->conf.flags & IEEE80211_CONF_SHORT_SLOT_TIME) ? - SHORT_DIFS : DIFS; - ack_timeout = difs + PLCP + preamble + get_duration(ACK_SIZE, 10); - - ack_consume_time = SIFS + PLCP + preamble + get_duration(ACK_SIZE, 10); + if (bss_conf->assoc) + rt2x00dev->intf_associated++; + else + rt2x00dev->intf_associated--; + } - if (short_preamble) - __set_bit(CONFIG_SHORT_PREAMBLE, &rt2x00dev->flags); - else - __clear_bit(CONFIG_SHORT_PREAMBLE, &rt2x00dev->flags); + /* + * When the preamble mode has changed, we should perform additional + * configuration steps. For all other changes we are already done. + */ + if (changes & BSS_CHANGED_ERP_PREAMBLE) { + rt2x00lib_config_preamble(rt2x00dev, intf, + bss_conf->use_short_preamble); - rt2x00dev->ops->lib->config_preamble(rt2x00dev, short_preamble, - ack_timeout, ack_consume_time); + spin_lock(&intf->lock); + memcpy(&intf->conf, bss_conf, sizeof(*bss_conf)); + spin_unlock(&intf->lock); + } } EXPORT_SYMBOL_GPL(rt2x00mac_bss_info_changed); diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index 63cfe33e95da..764147dd5aea 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c @@ -38,20 +38,14 @@ int rt2x00pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, struct ieee80211_tx_control *control) { struct rt2x00_dev *rt2x00dev = hw->priv; + struct rt2x00_intf *intf = vif_to_intf(control->vif); struct queue_entry_priv_pci_tx *priv_tx; struct skb_frame_desc *skbdesc; - struct data_queue *queue; - struct queue_entry *entry; - /* - * Just in case mac80211 doesn't set this correctly, - * but we need this queue set for the descriptor - * initialization. - */ - control->queue = IEEE80211_TX_QUEUE_BEACON; - queue = rt2x00queue_get_queue(rt2x00dev, control->queue); - entry = rt2x00queue_get_entry(queue, Q_INDEX); - priv_tx = entry->priv_data; + if (unlikely(!intf->beacon)) + return -ENOBUFS; + + priv_tx = intf->beacon->priv_data; /* * Fill in skb descriptor @@ -59,17 +53,25 @@ int rt2x00pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, skbdesc = get_skb_frame_desc(skb); memset(skbdesc, 0, sizeof(*skbdesc)); skbdesc->data = skb->data; - skbdesc->data_len = queue->data_size; + skbdesc->data_len = skb->len; skbdesc->desc = priv_tx->desc; - skbdesc->desc_len = queue->desc_size; - skbdesc->entry = entry; + skbdesc->desc_len = intf->beacon->queue->desc_size; + skbdesc->entry = intf->beacon; - memcpy(priv_tx->data, skb->data, skb->len); + /* + * Just in case mac80211 doesn't set this correctly, + * but we need this queue set for the descriptor + * initialization. + */ + control->queue = IEEE80211_TX_QUEUE_BEACON; rt2x00lib_write_tx_desc(rt2x00dev, skb, control); /* * Enable beacon generation. + * Write entire beacon with descriptor to register, + * and kick the beacon generator. */ + memcpy(priv_tx->data, skb->data, skb->len); rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, control->queue); return 0; diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 507116c6c9fe..75af48eddc25 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -46,9 +46,6 @@ * queue would be sufficient. Although this is almost one third of * the amount the legacy driver allocated, the queues aren't getting * filled to the maximum even when working with the maximum rate. - * - * FIXME: For virtual interfaces we need a different number - * of beacons, since more interfaces require more beacons. */ #define RX_ENTRIES 12 #define TX_ENTRIES 12 diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index b5ab771bbac2..b432cc21d248 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -271,63 +271,60 @@ static int rt61pci_rfkill_poll(struct rt2x00_dev *rt2x00dev) /* * Configuration handlers. */ -static void rt61pci_config_mac_addr(struct rt2x00_dev *rt2x00dev, __le32 *mac) +static void rt61pci_config_intf(struct rt2x00_dev *rt2x00dev, + struct rt2x00_intf *intf, + struct rt2x00intf_conf *conf, + const unsigned int flags) { - u32 tmp; - - tmp = le32_to_cpu(mac[1]); - rt2x00_set_field32(&tmp, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff); - mac[1] = cpu_to_le32(tmp); - - rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR2, mac, - (2 * sizeof(__le32))); -} + unsigned int beacon_base; + u32 reg; -static void rt61pci_config_bssid(struct rt2x00_dev *rt2x00dev, __le32 *bssid) -{ - u32 tmp; + if (flags & CONFIG_UPDATE_TYPE) { + /* + * Clear current synchronisation setup. + * For the Beacon base registers we only need to clear + * the first byte since that byte contains the VALID and OWNER + * bits which (when set to 0) will invalidate the entire beacon. + */ + beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx); + rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, 0); + rt2x00pci_register_write(rt2x00dev, beacon_base, 0); - tmp = le32_to_cpu(bssid[1]); - rt2x00_set_field32(&tmp, MAC_CSR5_BSS_ID_MASK, 3); - bssid[1] = cpu_to_le32(tmp); + /* + * Enable synchronisation. + */ + rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); + rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); + rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, + (conf->sync == TSF_SYNC_BEACON)); + rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); + rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, conf->sync); + rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); + } - rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR4, bssid, - (2 * sizeof(__le32))); -} + if (flags & CONFIG_UPDATE_MAC) { + reg = le32_to_cpu(conf->mac[1]); + rt2x00_set_field32(®, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff); + conf->mac[1] = cpu_to_le32(reg); -static void rt61pci_config_type(struct rt2x00_dev *rt2x00dev, const int type, - const int tsf_sync) -{ - u32 reg; + rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR2, + conf->mac, sizeof(conf->mac)); + } - /* - * Clear current synchronisation setup. - * For the Beacon base registers we only need to clear - * the first byte since that byte contains the VALID and OWNER - * bits which (when set to 0) will invalidate the entire beacon. - */ - rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, 0); - rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE0, 0); - rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE1, 0); - rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE2, 0); - rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE3, 0); + if (flags & CONFIG_UPDATE_BSSID) { + reg = le32_to_cpu(conf->bssid[1]); + rt2x00_set_field32(®, MAC_CSR5_BSS_ID_MASK, 3); + conf->bssid[1] = cpu_to_le32(reg); - /* - * Enable synchronisation. - */ - rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); - rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); - rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, - (tsf_sync == TSF_SYNC_BEACON)); - rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); - rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, tsf_sync); - rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); + rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR4, + conf->bssid, sizeof(conf->bssid)); + } } -static void rt61pci_config_preamble(struct rt2x00_dev *rt2x00dev, - const int short_preamble, - const int ack_timeout, - const int ack_consume_time) +static int rt61pci_config_preamble(struct rt2x00_dev *rt2x00dev, + const int short_preamble, + const int ack_timeout, + const int ack_consume_time) { u32 reg; @@ -339,6 +336,8 @@ static void rt61pci_config_preamble(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_PREAMBLE, !!short_preamble); rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg); + + return 0; } static void rt61pci_config_phymode(struct rt2x00_dev *rt2x00dev, @@ -667,8 +666,8 @@ static void rt61pci_config_duration(struct rt2x00_dev *rt2x00dev, } static void rt61pci_config(struct rt2x00_dev *rt2x00dev, - const unsigned int flags, - struct rt2x00lib_conf *libconf) + struct rt2x00lib_conf *libconf, + const unsigned int flags) { if (flags & CONFIG_UPDATE_PHYMODE) rt61pci_config_phymode(rt2x00dev, libconf->basic_rates); @@ -815,6 +814,13 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev) } } + /* + * If we are not associated, we should go straight to the + * dynamic CCA tuning. + */ + if (!rt2x00dev->intf_associated) + goto dynamic_cca_tune; + /* * Special big-R17 for very short distance */ @@ -866,6 +872,8 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev) return; } +dynamic_cca_tune: + /* * r17 does not yet exceed upper limit, continue and base * the r17 tuning on the false CCA count. @@ -1214,6 +1222,17 @@ static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev) rt2x00_set_field32(®, AC_TXOP_CSR1_AC3_TX_OP, 48); rt2x00pci_register_write(rt2x00dev, AC_TXOP_CSR1, reg); + /* + * Clear all beacons + * For the Beacon base registers we only need to clear + * the first byte since that byte contains the VALID and OWNER + * bits which (when set to 0) will invalidate the entire beacon. + */ + rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE0, 0); + rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE1, 0); + rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE2, 0); + rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE3, 0); + /* * We must clear the error counters. * These registers are cleared on read, @@ -2378,25 +2397,20 @@ static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, struct ieee80211_tx_control *control) { struct rt2x00_dev *rt2x00dev = hw->priv; + struct rt2x00_intf *intf = vif_to_intf(control->vif); struct skb_frame_desc *skbdesc; - struct data_queue *queue; - struct queue_entry *entry; + unsigned int beacon_base; - /* - * Just in case the ieee80211 doesn't set this, - * but we need this queue set for the descriptor - * initialization. - */ - control->queue = IEEE80211_TX_QUEUE_BEACON; - queue = rt2x00queue_get_queue(rt2x00dev, control->queue); - entry = rt2x00queue_get_entry(queue, Q_INDEX); + if (unlikely(!intf->beacon)) + return -ENOBUFS; /* * We need to append the descriptor in front of the * beacon frame. */ - if (skb_headroom(skb) < queue->desc_size) { - if (pskb_expand_head(skb, queue->desc_size, 0, GFP_ATOMIC)) { + if (skb_headroom(skb) < intf->beacon->queue->desc_size) { + if (pskb_expand_head(skb, intf->beacon->queue->desc_size, + 0, GFP_ATOMIC)) { dev_kfree_skb(skb); return -ENOMEM; } @@ -2405,29 +2419,36 @@ static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, /* * Add the descriptor in front of the skb. */ - skb_push(skb, queue->desc_size); - memset(skb->data, 0, queue->desc_size); + skb_push(skb, intf->beacon->queue->desc_size); + memset(skb->data, 0, intf->beacon->queue->desc_size); /* * Fill in skb descriptor */ skbdesc = get_skb_frame_desc(skb); memset(skbdesc, 0, sizeof(*skbdesc)); - skbdesc->data = skb->data + queue->desc_size; - skbdesc->data_len = queue->data_size; + skbdesc->data = skb->data + intf->beacon->queue->desc_size; + skbdesc->data_len = skb->len - intf->beacon->queue->desc_size; skbdesc->desc = skb->data; - skbdesc->desc_len = queue->desc_size; - skbdesc->entry = entry; + skbdesc->desc_len = intf->beacon->queue->desc_size; + skbdesc->entry = intf->beacon; + /* + * Just in case the ieee80211 doesn't set this, + * but we need this queue set for the descriptor + * initialization. + */ + control->queue = IEEE80211_TX_QUEUE_BEACON; rt2x00lib_write_tx_desc(rt2x00dev, skb, control); /* * Write entire beacon with descriptor to register, * and kick the beacon generator. */ - rt2x00pci_register_multiwrite(rt2x00dev, HW_BEACON_BASE0, + beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx); + rt2x00pci_register_multiwrite(rt2x00dev, beacon_base, skb->data, skb->len); - rt61pci_kick_tx_queue(rt2x00dev, IEEE80211_TX_QUEUE_BEACON); + rt61pci_kick_tx_queue(rt2x00dev, control->queue); return 0; } @@ -2469,9 +2490,7 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { .write_tx_data = rt2x00pci_write_tx_data, .kick_tx_queue = rt61pci_kick_tx_queue, .fill_rxdone = rt61pci_fill_rxdone, - .config_mac_addr = rt61pci_config_mac_addr, - .config_bssid = rt61pci_config_bssid, - .config_type = rt61pci_config_type, + .config_intf = rt61pci_config_intf, .config_preamble = rt61pci_config_preamble, .config = rt61pci_config, }; @@ -2491,7 +2510,7 @@ static const struct data_queue_desc rt61pci_queue_tx = { }; static const struct data_queue_desc rt61pci_queue_bcn = { - .entry_num = BEACON_ENTRIES, + .entry_num = 4 * BEACON_ENTRIES, .data_size = MGMT_FRAME_SIZE, .desc_size = TXINFO_SIZE, .priv_size = sizeof(struct queue_entry_priv_pci_tx), @@ -2499,6 +2518,8 @@ static const struct data_queue_desc rt61pci_queue_bcn = { static const struct rt2x00_ops rt61pci_ops = { .name = KBUILD_MODNAME, + .max_sta_intf = 1, + .max_ap_intf = 4, .eeprom_size = EEPROM_SIZE, .rf_size = RF_SIZE, .rx = &rt61pci_queue_rx, diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h index 10519f8c5783..d291c0fe405c 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.h +++ b/drivers/net/wireless/rt2x00/rt61pci.h @@ -161,7 +161,9 @@ struct hw_pairwise_ta_entry { #define HW_BEACON_BASE1 0x2d00 #define HW_BEACON_BASE2 0x2e00 #define HW_BEACON_BASE3 0x2f00 -#define HW_BEACON_OFFSET 0x0100 + +#define HW_BEACON_OFFSET(__index) \ + ( HW_BEACON_BASE0 + (__index * 0x0100) ) /* * HOST-MCU shared memory. @@ -234,6 +236,11 @@ struct hw_pairwise_ta_entry { /* * MAC_CSR3: STA MAC register 1. + * UNICAST_TO_ME_MASK: + * Used to mask off bits from byte 5 of the MAC address + * to determine the UNICAST_TO_ME bit for RX frames. + * The full mask is complemented by BSS_ID_MASK: + * MASK = BSS_ID_MASK & UNICAST_TO_ME_MASK */ #define MAC_CSR3 0x300c #define MAC_CSR3_BYTE4 FIELD32(0x000000ff) @@ -251,7 +258,14 @@ struct hw_pairwise_ta_entry { /* * MAC_CSR5: BSSID register 1. - * BSS_ID_MASK: 3: one BSSID, 0: 4 BSSID, 2 or 1: 2 BSSID. + * BSS_ID_MASK: + * This mask is used to mask off bits 0 and 1 of byte 5 of the + * BSSID. This will make sure that those bits will be ignored + * when determining the MY_BSS of RX frames. + * 0: 1-BSSID mode (BSS index = 0) + * 1: 2-BSSID mode (BSS index: Byte5, bit 0) + * 2: 2-BSSID mode (BSS index: byte5, bit 1) + * 3: 4-BSSID mode (BSS index: byte5, bit 0 - 1) */ #define MAC_CSR5 0x3014 #define MAC_CSR5_BYTE4 FIELD32(0x000000ff) diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 8ebf3fed9815..7907fd0d4aa5 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -281,74 +281,69 @@ static const struct rt2x00debug rt73usb_rt2x00debug = { /* * Configuration handlers. */ -static void rt73usb_config_mac_addr(struct rt2x00_dev *rt2x00dev, __le32 *mac) +static void rt73usb_config_intf(struct rt2x00_dev *rt2x00dev, + struct rt2x00_intf *intf, + struct rt2x00intf_conf *conf, + const unsigned int flags) { - u32 tmp; - - tmp = le32_to_cpu(mac[1]); - rt2x00_set_field32(&tmp, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff); - mac[1] = cpu_to_le32(tmp); - - rt73usb_register_multiwrite(rt2x00dev, MAC_CSR2, mac, - (2 * sizeof(__le32))); -} + unsigned int beacon_base; + u32 reg; -static void rt73usb_config_bssid(struct rt2x00_dev *rt2x00dev, __le32 *bssid) -{ - u32 tmp; + if (flags & CONFIG_UPDATE_TYPE) { + /* + * Clear current synchronisation setup. + * For the Beacon base registers we only need to clear + * the first byte since that byte contains the VALID and OWNER + * bits which (when set to 0) will invalidate the entire beacon. + */ + beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx); + rt73usb_register_write(rt2x00dev, TXRX_CSR9, 0); + rt73usb_register_write(rt2x00dev, beacon_base, 0); - tmp = le32_to_cpu(bssid[1]); - rt2x00_set_field32(&tmp, MAC_CSR5_BSS_ID_MASK, 3); - bssid[1] = cpu_to_le32(tmp); + /* + * Enable synchronisation. + */ + rt73usb_register_read(rt2x00dev, TXRX_CSR9, ®); + rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); + rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, + (conf->sync == TSF_SYNC_BEACON)); + rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); + rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, conf->sync); + rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg); + } - rt73usb_register_multiwrite(rt2x00dev, MAC_CSR4, bssid, - (2 * sizeof(__le32))); -} + if (flags & CONFIG_UPDATE_MAC) { + reg = le32_to_cpu(conf->mac[1]); + rt2x00_set_field32(®, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff); + conf->mac[1] = cpu_to_le32(reg); -static void rt73usb_config_type(struct rt2x00_dev *rt2x00dev, const int type, - const int tsf_sync) -{ - u32 reg; + rt73usb_register_multiwrite(rt2x00dev, MAC_CSR2, + conf->mac, sizeof(conf->mac)); + } - /* - * Clear current synchronisation setup. - * For the Beacon base registers we only need to clear - * the first byte since that byte contains the VALID and OWNER - * bits which (when set to 0) will invalidate the entire beacon. - */ - rt73usb_register_write(rt2x00dev, TXRX_CSR9, 0); - rt73usb_register_write(rt2x00dev, HW_BEACON_BASE0, 0); - rt73usb_register_write(rt2x00dev, HW_BEACON_BASE1, 0); - rt73usb_register_write(rt2x00dev, HW_BEACON_BASE2, 0); - rt73usb_register_write(rt2x00dev, HW_BEACON_BASE3, 0); + if (flags & CONFIG_UPDATE_BSSID) { + reg = le32_to_cpu(conf->bssid[1]); + rt2x00_set_field32(®, MAC_CSR5_BSS_ID_MASK, 3); + conf->bssid[1] = cpu_to_le32(reg); - /* - * Enable synchronisation. - */ - rt73usb_register_read(rt2x00dev, TXRX_CSR9, ®); - rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); - rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, - (tsf_sync == TSF_SYNC_BEACON)); - rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); - rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, tsf_sync); - rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg); + rt73usb_register_multiwrite(rt2x00dev, MAC_CSR4, + conf->bssid, sizeof(conf->bssid)); + } } -static void rt73usb_config_preamble(struct rt2x00_dev *rt2x00dev, - const int short_preamble, - const int ack_timeout, - const int ack_consume_time) +static int rt73usb_config_preamble(struct rt2x00_dev *rt2x00dev, + const int short_preamble, + const int ack_timeout, + const int ack_consume_time) { u32 reg; /* - * When in atomic context, reschedule and let rt2x00lib - * call this function again. + * When in atomic context, we should let rt2x00lib + * try this configuration again later. */ - if (in_atomic()) { - queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->config_work); - return; - } + if (in_atomic()) + return -EAGAIN; rt73usb_register_read(rt2x00dev, TXRX_CSR0, ®); rt2x00_set_field32(®, TXRX_CSR0_RX_ACK_TIMEOUT, ack_timeout); @@ -358,6 +353,8 @@ static void rt73usb_config_preamble(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_PREAMBLE, !!short_preamble); rt73usb_register_write(rt2x00dev, TXRX_CSR4, reg); + + return 0; } static void rt73usb_config_phymode(struct rt2x00_dev *rt2x00dev, @@ -617,8 +614,8 @@ static void rt73usb_config_duration(struct rt2x00_dev *rt2x00dev, } static void rt73usb_config(struct rt2x00_dev *rt2x00dev, - const unsigned int flags, - struct rt2x00lib_conf *libconf) + struct rt2x00lib_conf *libconf, + const unsigned int flags) { if (flags & CONFIG_UPDATE_PHYMODE) rt73usb_config_phymode(rt2x00dev, libconf->basic_rates); @@ -765,6 +762,13 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev) } } + /* + * If we are not associated, we should go straight to the + * dynamic CCA tuning. + */ + if (!rt2x00dev->intf_associated) + goto dynamic_cca_tune; + /* * Special big-R17 for very short distance */ @@ -815,6 +819,8 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev) return; } +dynamic_cca_tune: + /* * r17 does not yet exceed upper limit, continue and base * the r17 tuning on the false CCA count. @@ -1020,6 +1026,17 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev) rt2x00_set_field32(®, MAC_CSR9_CW_SELECT, 0); rt73usb_register_write(rt2x00dev, MAC_CSR9, reg); + /* + * Clear all beacons + * For the Beacon base registers we only need to clear + * the first byte since that byte contains the VALID and OWNER + * bits which (when set to 0) will invalidate the entire beacon. + */ + rt73usb_register_write(rt2x00dev, HW_BEACON_BASE0, 0); + rt73usb_register_write(rt2x00dev, HW_BEACON_BASE1, 0); + rt73usb_register_write(rt2x00dev, HW_BEACON_BASE2, 0); + rt73usb_register_write(rt2x00dev, HW_BEACON_BASE3, 0); + /* * We must clear the error counters. * These registers are cleared on read, @@ -1985,52 +2002,52 @@ static void rt73usb_reset_tsf(struct ieee80211_hw *hw) } static int rt73usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, - struct ieee80211_tx_control *control) + struct ieee80211_tx_control *control) { struct rt2x00_dev *rt2x00dev = hw->priv; + struct rt2x00_intf *intf = vif_to_intf(control->vif); struct skb_frame_desc *skbdesc; - struct data_queue *queue; - struct queue_entry *entry; - int timeout; + unsigned int beacon_base; + unsigned int timeout; - /* - * Just in case the ieee80211 doesn't set this, - * but we need this queue set for the descriptor - * initialization. - */ - control->queue = IEEE80211_TX_QUEUE_BEACON; - queue = rt2x00queue_get_queue(rt2x00dev, control->queue); - entry = rt2x00queue_get_entry(queue, Q_INDEX); + if (unlikely(!intf->beacon)) + return -ENOBUFS; /* * Add the descriptor in front of the skb. */ - skb_push(skb, queue->desc_size); - memset(skb->data, 0, queue->desc_size); + skb_push(skb, intf->beacon->queue->desc_size); + memset(skb->data, 0, intf->beacon->queue->desc_size); /* * Fill in skb descriptor */ skbdesc = get_skb_frame_desc(skb); memset(skbdesc, 0, sizeof(*skbdesc)); - skbdesc->data = skb->data + queue->desc_size; - skbdesc->data_len = queue->data_size; + skbdesc->data = skb->data + intf->beacon->queue->desc_size; + skbdesc->data_len = skb->len - intf->beacon->queue->desc_size; skbdesc->desc = skb->data; - skbdesc->desc_len = queue->desc_size; - skbdesc->entry = entry; + skbdesc->desc_len = intf->beacon->queue->desc_size; + skbdesc->entry = intf->beacon; + /* + * Just in case the ieee80211 doesn't set this, + * but we need this queue set for the descriptor + * initialization. + */ + control->queue = IEEE80211_TX_QUEUE_BEACON; rt2x00lib_write_tx_desc(rt2x00dev, skb, control); /* * Write entire beacon with descriptor to register, * and kick the beacon generator. */ + beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx); timeout = REGISTER_TIMEOUT * (skb->len / sizeof(u32)); rt2x00usb_vendor_request(rt2x00dev, USB_MULTI_WRITE, - USB_VENDOR_REQUEST_OUT, - HW_BEACON_BASE0, 0x0000, + USB_VENDOR_REQUEST_OUT, beacon_base, 0, skb->data, skb->len, timeout); - rt73usb_kick_tx_queue(rt2x00dev, IEEE80211_TX_QUEUE_BEACON); + rt73usb_kick_tx_queue(rt2x00dev, control->queue); return 0; } @@ -2071,9 +2088,7 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { .get_tx_data_len = rt73usb_get_tx_data_len, .kick_tx_queue = rt73usb_kick_tx_queue, .fill_rxdone = rt73usb_fill_rxdone, - .config_mac_addr = rt73usb_config_mac_addr, - .config_bssid = rt73usb_config_bssid, - .config_type = rt73usb_config_type, + .config_intf = rt73usb_config_intf, .config_preamble = rt73usb_config_preamble, .config = rt73usb_config, }; @@ -2093,7 +2108,7 @@ static const struct data_queue_desc rt73usb_queue_tx = { }; static const struct data_queue_desc rt73usb_queue_bcn = { - .entry_num = BEACON_ENTRIES, + .entry_num = 4 * BEACON_ENTRIES, .data_size = MGMT_FRAME_SIZE, .desc_size = TXINFO_SIZE, .priv_size = sizeof(struct queue_entry_priv_usb_tx), @@ -2101,6 +2116,8 @@ static const struct data_queue_desc rt73usb_queue_bcn = { static const struct rt2x00_ops rt73usb_ops = { .name = KBUILD_MODNAME, + .max_sta_intf = 1, + .max_ap_intf = 4, .eeprom_size = EEPROM_SIZE, .rf_size = RF_SIZE, .rx = &rt73usb_queue_rx, diff --git a/drivers/net/wireless/rt2x00/rt73usb.h b/drivers/net/wireless/rt2x00/rt73usb.h index da62b4f091a7..3f9675655eb9 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.h +++ b/drivers/net/wireless/rt2x00/rt73usb.h @@ -114,6 +114,9 @@ struct hw_pairwise_ta_entry { #define HW_BEACON_BASE2 0x2600 #define HW_BEACON_BASE3 0x2700 +#define HW_BEACON_OFFSET(__index) \ + ( HW_BEACON_BASE0 + (__index * 0x0100) ) + /* * MAC Control/Status Registers(CSR). * Some values are set in TU, whereas 1 TU == 1024 us. @@ -146,6 +149,11 @@ struct hw_pairwise_ta_entry { /* * MAC_CSR3: STA MAC register 1. + * UNICAST_TO_ME_MASK: + * Used to mask off bits from byte 5 of the MAC address + * to determine the UNICAST_TO_ME bit for RX frames. + * The full mask is complemented by BSS_ID_MASK: + * MASK = BSS_ID_MASK & UNICAST_TO_ME_MASK */ #define MAC_CSR3 0x300c #define MAC_CSR3_BYTE4 FIELD32(0x000000ff) @@ -163,7 +171,14 @@ struct hw_pairwise_ta_entry { /* * MAC_CSR5: BSSID register 1. - * BSS_ID_MASK: 3: one BSSID, 0: 4 BSSID, 2 or 1: 2 BSSID. + * BSS_ID_MASK: + * This mask is used to mask off bits 0 and 1 of byte 5 of the + * BSSID. This will make sure that those bits will be ignored + * when determining the MY_BSS of RX frames. + * 0: 1-BSSID mode (BSS index = 0) + * 1: 2-BSSID mode (BSS index: Byte5, bit 0) + * 2: 2-BSSID mode (BSS index: byte5, bit 1) + * 3: 4-BSSID mode (BSS index: byte5, bit 0 - 1) */ #define MAC_CSR5 0x3014 #define MAC_CSR5_BYTE4 FIELD32(0x000000ff) -- cgit v1.2.1 From 871ff6ed64e17a785cb4d48f56beedff038cc42a Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 3 Feb 2008 15:51:47 +0100 Subject: rt2x00: Remove TX_MGMT queue usage rt73usb doesn't have a 5th queue, correctly initialize hw->queues rt61pci had a 5th queue but was removed recently, correctly initialize hw->queues and remove the last remnants. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt61pci.c | 5 +---- drivers/net/wireless/rt2x00/rt73usb.c | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index b432cc21d248..534e1647b7cf 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -1436,7 +1436,6 @@ static void rt61pci_disable_radio(struct rt2x00_dev *rt2x00dev) rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC1, 1); rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC2, 1); rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC3, 1); - rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_MGMT, 1); rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg); /* @@ -1611,8 +1610,6 @@ static void rt61pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, (queue == IEEE80211_TX_QUEUE_DATA2)); rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC3, (queue == IEEE80211_TX_QUEUE_DATA3)); - rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_MGMT, - (queue == IEEE80211_TX_QUEUE_DATA4)); rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg); } @@ -2212,7 +2209,7 @@ static void rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) rt2x00dev->hw->extra_tx_headroom = 0; rt2x00dev->hw->max_signal = MAX_SIGNAL; rt2x00dev->hw->max_rssi = MAX_RX_SSI; - rt2x00dev->hw->queues = 5; + rt2x00dev->hw->queues = 4; SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_pci(rt2x00dev)->dev); SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 7907fd0d4aa5..b519a4bfc212 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -1796,7 +1796,7 @@ static void rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) rt2x00dev->hw->extra_tx_headroom = TXD_DESC_SIZE; rt2x00dev->hw->max_signal = MAX_SIGNAL; rt2x00dev->hw->max_rssi = MAX_RX_SSI; - rt2x00dev->hw->queues = 5; + rt2x00dev->hw->queues = 4; SET_IEEE80211_DEV(rt2x00dev->hw, &rt2x00dev_usb(rt2x00dev)->dev); SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, -- cgit v1.2.1 From 091ed315ef77a4949a6ce22e43af15a504ada348 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 3 Feb 2008 15:52:21 +0100 Subject: rt2x00: Initialize QID from queue->qid The QID_MGMT is assigned to the beacon and atim queue during initialization. This means we don't need a seperate check in write_tx_desc().. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00dev.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 014c307c270c..1bc8c14e6aec 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -628,21 +628,11 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev, memset(&txdesc, 0, sizeof(txdesc)); + txdesc.queue = skbdesc->entry->queue->qid; txdesc.cw_min = skbdesc->entry->queue->cw_min; txdesc.cw_max = skbdesc->entry->queue->cw_max; txdesc.aifs = skbdesc->entry->queue->aifs; - /* - * Identify queue - */ - if (control->queue < rt2x00dev->hw->queues) - txdesc.queue = control->queue; - else if (control->queue == IEEE80211_TX_QUEUE_BEACON || - control->queue == IEEE80211_TX_QUEUE_AFTER_BEACON) - txdesc.queue = QID_MGMT; - else - txdesc.queue = QID_OTHER; - /* * Read required fields from ieee80211 header. */ -- cgit v1.2.1 From 5957da4c6e67a5447e75c2ad65252fdd5e22f9d0 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 3 Feb 2008 15:54:57 +0100 Subject: rt2x00: Move beacon and atim queue defines into rt2x00 As Johannes Berg indicated the BEACON and AFTER_BEACON queue indeces in mac80211 should be removed because they are too hardware specific. This patch adds the queue index defines into rt2x00queue.h and removes the dependency of the defines inside mac80211.h. Also move rt2x00pci_beacon_update() into rt2400pci and rt2500pci individually since it is no longer a generic function since rt61 and rt2800 no longer use that. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 53 ++++++++++++++++++++++++++--- drivers/net/wireless/rt2x00/rt2500pci.c | 55 +++++++++++++++++++++++++++---- drivers/net/wireless/rt2x00/rt2500usb.c | 12 +++---- drivers/net/wireless/rt2x00/rt2x00.h | 7 ++-- drivers/net/wireless/rt2x00/rt2x00dev.c | 2 +- drivers/net/wireless/rt2x00/rt2x00mac.c | 2 +- drivers/net/wireless/rt2x00/rt2x00pci.c | 47 -------------------------- drivers/net/wireless/rt2x00/rt2x00pci.h | 6 ---- drivers/net/wireless/rt2x00/rt2x00queue.c | 6 ++-- drivers/net/wireless/rt2x00/rt2x00queue.h | 15 +++++++++ drivers/net/wireless/rt2x00/rt61pci.c | 12 +++---- drivers/net/wireless/rt2x00/rt73usb.c | 12 +++---- 12 files changed, 139 insertions(+), 90 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 61766ed800e3..feb8c09a33ad 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1041,11 +1041,11 @@ static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, * TX data initialization */ static void rt2400pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, - unsigned int queue) + const unsigned int queue) { u32 reg; - if (queue == IEEE80211_TX_QUEUE_BEACON) { + if (queue == RT2X00_BCN_QUEUE_BEACON) { rt2x00pci_register_read(rt2x00dev, CSR14, ®); if (!rt2x00_get_field32(reg, CSR14_BEACON_GEN)) { rt2x00_set_field32(®, CSR14_BEACON_GEN, 1); @@ -1060,7 +1060,7 @@ static void rt2400pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(®, TXCSR0_KICK_TX, (queue == IEEE80211_TX_QUEUE_DATA1)); rt2x00_set_field32(®, TXCSR0_KICK_ATIM, - (queue == IEEE80211_TX_QUEUE_AFTER_BEACON)); + (queue == RT2X00_BCN_QUEUE_ATIM)); rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); } @@ -1165,7 +1165,7 @@ static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance) * 3 - Atim ring transmit done interrupt. */ if (rt2x00_get_field32(reg, CSR7_TXDONE_ATIMRING)) - rt2400pci_txdone(rt2x00dev, IEEE80211_TX_QUEUE_AFTER_BEACON); + rt2400pci_txdone(rt2x00dev, RT2X00_BCN_QUEUE_ATIM); /* * 4 - Priority ring transmit done interrupt. @@ -1510,6 +1510,49 @@ static void rt2400pci_reset_tsf(struct ieee80211_hw *hw) rt2x00pci_register_write(rt2x00dev, CSR17, 0); } +static int rt2400pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, + struct ieee80211_tx_control *control) +{ + struct rt2x00_dev *rt2x00dev = hw->priv; + struct rt2x00_intf *intf = vif_to_intf(control->vif); + struct queue_entry_priv_pci_tx *priv_tx; + struct skb_frame_desc *skbdesc; + + if (unlikely(!intf->beacon)) + return -ENOBUFS; + + priv_tx = intf->beacon->priv_data; + + /* + * Fill in skb descriptor + */ + skbdesc = get_skb_frame_desc(skb); + memset(skbdesc, 0, sizeof(*skbdesc)); + skbdesc->data = skb->data; + skbdesc->data_len = skb->len; + skbdesc->desc = priv_tx->desc; + skbdesc->desc_len = intf->beacon->queue->desc_size; + skbdesc->entry = intf->beacon; + + /* + * mac80211 doesn't provide the control->queue variable + * for beacons. Set our own queue identification so + * it can be used during descriptor initialization. + */ + control->queue = RT2X00_BCN_QUEUE_BEACON; + rt2x00lib_write_tx_desc(rt2x00dev, skb, control); + + /* + * Enable beacon generation. + * Write entire beacon with descriptor to register, + * and kick the beacon generator. + */ + memcpy(priv_tx->data, skb->data, skb->len); + rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, control->queue); + + return 0; +} + static int rt2400pci_tx_last_beacon(struct ieee80211_hw *hw) { struct rt2x00_dev *rt2x00dev = hw->priv; @@ -1535,7 +1578,7 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = { .get_tx_stats = rt2x00mac_get_tx_stats, .get_tsf = rt2400pci_get_tsf, .reset_tsf = rt2400pci_reset_tsf, - .beacon_update = rt2x00pci_beacon_update, + .beacon_update = rt2400pci_beacon_update, .tx_last_beacon = rt2400pci_tx_last_beacon, }; diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 6a558bf74f11..36c64f751b1d 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -252,7 +252,7 @@ static void rt2500pci_config_intf(struct rt2x00_dev *rt2x00dev, const unsigned int flags) { struct data_queue *queue = - rt2x00queue_get_queue(rt2x00dev, IEEE80211_TX_QUEUE_BEACON); + rt2x00queue_get_queue(rt2x00dev, RT2X00_BCN_QUEUE_BEACON); unsigned int bcn_preload; u32 reg; @@ -1195,11 +1195,11 @@ static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, * TX data initialization */ static void rt2500pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, - unsigned int queue) + const unsigned int queue) { u32 reg; - if (queue == IEEE80211_TX_QUEUE_BEACON) { + if (queue == RT2X00_BCN_QUEUE_BEACON) { rt2x00pci_register_read(rt2x00dev, CSR14, ®); if (!rt2x00_get_field32(reg, CSR14_BEACON_GEN)) { rt2x00_set_field32(®, CSR14_BEACON_GEN, 1); @@ -1214,7 +1214,7 @@ static void rt2500pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(®, TXCSR0_KICK_TX, (queue == IEEE80211_TX_QUEUE_DATA1)); rt2x00_set_field32(®, TXCSR0_KICK_ATIM, - (queue == IEEE80211_TX_QUEUE_AFTER_BEACON)); + (queue == RT2X00_BCN_QUEUE_ATIM)); rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); } @@ -1316,7 +1316,7 @@ static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance) * 3 - Atim ring transmit done interrupt. */ if (rt2x00_get_field32(reg, CSR7_TXDONE_ATIMRING)) - rt2500pci_txdone(rt2x00dev, IEEE80211_TX_QUEUE_AFTER_BEACON); + rt2500pci_txdone(rt2x00dev, RT2X00_BCN_QUEUE_ATIM); /* * 4 - Priority ring transmit done interrupt. @@ -1822,6 +1822,49 @@ static void rt2500pci_reset_tsf(struct ieee80211_hw *hw) rt2x00pci_register_write(rt2x00dev, CSR17, 0); } +static int rt2500pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, + struct ieee80211_tx_control *control) +{ + struct rt2x00_dev *rt2x00dev = hw->priv; + struct rt2x00_intf *intf = vif_to_intf(control->vif); + struct queue_entry_priv_pci_tx *priv_tx; + struct skb_frame_desc *skbdesc; + + if (unlikely(!intf->beacon)) + return -ENOBUFS; + + priv_tx = intf->beacon->priv_data; + + /* + * Fill in skb descriptor + */ + skbdesc = get_skb_frame_desc(skb); + memset(skbdesc, 0, sizeof(*skbdesc)); + skbdesc->data = skb->data; + skbdesc->data_len = skb->len; + skbdesc->desc = priv_tx->desc; + skbdesc->desc_len = intf->beacon->queue->desc_size; + skbdesc->entry = intf->beacon; + + /* + * mac80211 doesn't provide the control->queue variable + * for beacons. Set our own queue identification so + * it can be used during descriptor initialization. + */ + control->queue = RT2X00_BCN_QUEUE_BEACON; + rt2x00lib_write_tx_desc(rt2x00dev, skb, control); + + /* + * Enable beacon generation. + * Write entire beacon with descriptor to register, + * and kick the beacon generator. + */ + memcpy(priv_tx->data, skb->data, skb->len); + rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, control->queue); + + return 0; +} + static int rt2500pci_tx_last_beacon(struct ieee80211_hw *hw) { struct rt2x00_dev *rt2x00dev = hw->priv; @@ -1847,7 +1890,7 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = { .get_tx_stats = rt2x00mac_get_tx_stats, .get_tsf = rt2500pci_get_tsf, .reset_tsf = rt2500pci_reset_tsf, - .beacon_update = rt2x00pci_beacon_update, + .beacon_update = rt2500pci_beacon_update, .tx_last_beacon = rt2500pci_tx_last_beacon, }; diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 31258ee24ee3..38c968ee50f1 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1100,11 +1100,11 @@ static int rt2500usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev, * TX data initialization */ static void rt2500usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, - unsigned int queue) + const unsigned int queue) { u16 reg; - if (queue != IEEE80211_TX_QUEUE_BEACON) + if (queue != RT2X00_BCN_QUEUE_BEACON) return; rt2500usb_register_read(rt2x00dev, TXRX_CSR19, ®); @@ -1758,11 +1758,11 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw, skbdesc->entry = intf->beacon; /* - * Just in case mac80211 doesn't set this correctly, - * but we need this queue set for the descriptor - * initialization. + * mac80211 doesn't provide the control->queue variable + * for beacons. Set our own queue identification so + * it can be used during descriptor initialization. */ - control->queue = IEEE80211_TX_QUEUE_BEACON; + control->queue = RT2X00_BCN_QUEUE_BEACON; rt2x00lib_write_tx_desc(rt2x00dev, skb, control); /* diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 2363ca4903cc..b0e4ea7c9dca 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -526,7 +526,7 @@ struct rt2x00lib_ops { int (*get_tx_data_len) (struct rt2x00_dev *rt2x00dev, struct sk_buff *skb); void (*kick_tx_queue) (struct rt2x00_dev *rt2x00dev, - unsigned int queue); + const unsigned int queue); /* * RX control handlers @@ -906,10 +906,11 @@ static inline u16 get_duration_res(const unsigned int size, const u8 rate) /** * rt2x00queue_get_queue - Convert mac80211 queue index to rt2x00 queue * @rt2x00dev: Pointer to &struct rt2x00_dev. - * @queue: mac80211 queue index (see &enum ieee80211_tx_queue). + * @queue: mac80211/rt2x00 queue index + * (see &enum ieee80211_tx_queue and &enum rt2x00_bcn_queue). */ struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev, - const enum ieee80211_tx_queue queue); + const unsigned int queue); /** * rt2x00queue_get_entry - Get queue entry where the given index points to. diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 1bc8c14e6aec..0df8062b1a8e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -679,7 +679,7 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev, * Beacons and probe responses require the tsf timestamp * to be inserted into the frame. */ - if (control->queue == IEEE80211_TX_QUEUE_BEACON || + if (control->queue == RT2X00_BCN_QUEUE_BEACON || is_probe_resp(frame_control)) __set_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc.flags); diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 65a2bcd18aa1..8c24d3b36d28 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -164,7 +164,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, struct rt2x00_dev *rt2x00dev = hw->priv; struct rt2x00_intf *intf = vif_to_intf(conf->vif); struct data_queue *queue = - rt2x00queue_get_queue(rt2x00dev, IEEE80211_TX_QUEUE_BEACON); + rt2x00queue_get_queue(rt2x00dev, RT2X00_BCN_QUEUE_BEACON); struct queue_entry *entry = NULL; unsigned int i; diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index 764147dd5aea..275c8a1e6638 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c @@ -31,53 +31,6 @@ #include "rt2x00.h" #include "rt2x00pci.h" -/* - * Beacon handlers. - */ -int rt2x00pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, - struct ieee80211_tx_control *control) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - struct rt2x00_intf *intf = vif_to_intf(control->vif); - struct queue_entry_priv_pci_tx *priv_tx; - struct skb_frame_desc *skbdesc; - - if (unlikely(!intf->beacon)) - return -ENOBUFS; - - priv_tx = intf->beacon->priv_data; - - /* - * Fill in skb descriptor - */ - skbdesc = get_skb_frame_desc(skb); - memset(skbdesc, 0, sizeof(*skbdesc)); - skbdesc->data = skb->data; - skbdesc->data_len = skb->len; - skbdesc->desc = priv_tx->desc; - skbdesc->desc_len = intf->beacon->queue->desc_size; - skbdesc->entry = intf->beacon; - - /* - * Just in case mac80211 doesn't set this correctly, - * but we need this queue set for the descriptor - * initialization. - */ - control->queue = IEEE80211_TX_QUEUE_BEACON; - rt2x00lib_write_tx_desc(rt2x00dev, skb, control); - - /* - * Enable beacon generation. - * Write entire beacon with descriptor to register, - * and kick the beacon generator. - */ - memcpy(priv_tx->data, skb->data, skb->len); - rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, control->queue); - - return 0; -} -EXPORT_SYMBOL_GPL(rt2x00pci_beacon_update); - /* * TX data handlers. */ diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.h b/drivers/net/wireless/rt2x00/rt2x00pci.h index 3b1597ffb4f2..71335e16b058 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.h +++ b/drivers/net/wireless/rt2x00/rt2x00pci.h @@ -87,12 +87,6 @@ rt2x00pci_register_multiwrite(struct rt2x00_dev *rt2x00dev, memcpy_toio(rt2x00dev->csr_addr + offset, value, length); } -/* - * Beacon handlers. - */ -int rt2x00pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, - struct ieee80211_tx_control *control); - /* * TX data handlers. */ diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 921eca35719d..52bb57ddc05f 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -30,7 +30,7 @@ #include "rt2x00lib.h" struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev, - const enum ieee80211_tx_queue queue) + const unsigned int queue) { int atim = test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags); @@ -40,9 +40,9 @@ struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev, if (!rt2x00dev->bcn) return NULL; - if (queue == IEEE80211_TX_QUEUE_BEACON) + if (queue == RT2X00_BCN_QUEUE_BEACON) return &rt2x00dev->bcn[0]; - else if (queue == IEEE80211_TX_QUEUE_AFTER_BEACON && atim) + else if (queue == RT2X00_BCN_QUEUE_ATIM && atim) return &rt2x00dev->bcn[1]; return NULL; diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 75af48eddc25..956e0be8aadd 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -66,6 +66,21 @@ enum data_queue_qid { QID_OTHER = 15, }; +/** + * enum rt2x00_bcn_queue: Beacon queue index + * + * Start counting with a high offset, this because this enumeration + * supplements &enum ieee80211_tx_queue and we should prevent value + * conflicts. + * + * @RT2X00_BCN_QUEUE_BEACON: Beacon queue + * @RT2X00_BCN_QUEUE_ATIM: Atim queue (sends frame after beacon) + */ +enum rt2x00_bcn_queue { + RT2X00_BCN_QUEUE_BEACON = 100, + RT2X00_BCN_QUEUE_ATIM = 101, +}; + /** * struct skb_frame_desc: Descriptor information for the skb buffer * diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 534e1647b7cf..59e87a1d96a4 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -1582,11 +1582,11 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, * TX data initialization */ static void rt61pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, - unsigned int queue) + const unsigned int queue) { u32 reg; - if (queue == IEEE80211_TX_QUEUE_BEACON) { + if (queue == RT2X00_BCN_QUEUE_BEACON) { /* * For Wi-Fi faily generated beacons between participating * stations. Set TBTT phase adaptive adjustment step to 8us. @@ -2431,11 +2431,11 @@ static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, skbdesc->entry = intf->beacon; /* - * Just in case the ieee80211 doesn't set this, - * but we need this queue set for the descriptor - * initialization. + * mac80211 doesn't provide the control->queue variable + * for beacons. Set our own queue identification so + * it can be used during descriptor initialization. */ - control->queue = IEEE80211_TX_QUEUE_BEACON; + control->queue = RT2X00_BCN_QUEUE_BEACON; rt2x00lib_write_tx_desc(rt2x00dev, skb, control); /* diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index b519a4bfc212..4b5bde8b53de 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -1326,11 +1326,11 @@ static int rt73usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev, * TX data initialization */ static void rt73usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, - unsigned int queue) + const unsigned int queue) { u32 reg; - if (queue != IEEE80211_TX_QUEUE_BEACON) + if (queue != RT2X00_BCN_QUEUE_BEACON) return; /* @@ -2031,11 +2031,11 @@ static int rt73usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, skbdesc->entry = intf->beacon; /* - * Just in case the ieee80211 doesn't set this, - * but we need this queue set for the descriptor - * initialization. + * mac80211 doesn't provide the control->queue variable + * for beacons. Set our own queue identification so + * it can be used during descriptor initialization. */ - control->queue = IEEE80211_TX_QUEUE_BEACON; + control->queue = RT2X00_BCN_QUEUE_BEACON; rt2x00lib_write_tx_desc(rt2x00dev, skb, control); /* -- cgit v1.2.1 From 10b6b80145cc93887dd8aab99bfffa375e9add31 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 3 Feb 2008 15:55:21 +0100 Subject: rt2x00: Fix queue index handling When Q_INDEX is increased, the queue->length should be increased, only when Q_INDEX_DONE is increased should queue_length be descreased. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00queue.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 52bb57ddc05f..fde64ea3f4ef 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -84,8 +84,12 @@ void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index) if (queue->index[index] >= queue->limit) queue->index[index] = 0; - queue->length--; - queue->count += (index == Q_INDEX_DONE); + if (index == Q_INDEX) { + queue->length++; + } else if (index == Q_INDEX_DONE) { + queue->length--; + queue->count ++; + } spin_unlock(&queue->lock); } -- cgit v1.2.1 From 8318d78a44d49ac1edf2bdec7299de3617c4232e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 24 Jan 2008 19:38:38 +0100 Subject: cfg80211 API for channels/bitrates, mac80211 and driver conversion This patch creates new cfg80211 wiphy API for channel and bitrate registration and converts mac80211 and drivers to the new API. The old mac80211 API is completely ripped out. All drivers (except ath5k) are updated to the new API, in many cases I expect that optimisations can be done. Along with the regulatory code I've also ripped out the IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED flag, I believe it to be unnecessary if the hardware simply gives us whatever channels it wants to support and we then enable/disable them as required, which is pretty much required for travelling. Additionally, the patch adds proper "basic" rate handling for STA mode interface, AP mode interface will have to have new API added to allow userspace to set the basic rate set, currently it'll be empty... However, the basic rate handling will need to be moved to the BSS conf stuff. I do expect there to be bugs in this, especially wrt. transmit power handling where I'm basically clueless about how it should work. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/Kconfig | 1 + drivers/net/wireless/adm8211.c | 80 ++--- drivers/net/wireless/adm8211.h | 65 +--- drivers/net/wireless/b43/b43.h | 5 - drivers/net/wireless/b43/main.c | 119 +++---- drivers/net/wireless/b43/sysfs.c | 89 +----- drivers/net/wireless/b43/xmit.c | 81 ++--- drivers/net/wireless/b43legacy/b43legacy.h | 4 - drivers/net/wireless/b43legacy/main.c | 159 +++++----- drivers/net/wireless/b43legacy/xmit.c | 64 ++-- drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 88 +++--- drivers/net/wireless/iwlwifi/iwl-3945.c | 35 +-- drivers/net/wireless/iwlwifi/iwl-3945.h | 13 +- drivers/net/wireless/iwlwifi/iwl-4965-rs.c | 82 ++--- drivers/net/wireless/iwlwifi/iwl-4965.c | 43 ++- drivers/net/wireless/iwlwifi/iwl-4965.h | 16 +- drivers/net/wireless/iwlwifi/iwl3945-base.c | 445 ++++++++------------------- drivers/net/wireless/iwlwifi/iwl4965-base.c | 438 +++++++------------------- drivers/net/wireless/p54.h | 4 - drivers/net/wireless/p54common.c | 74 +++-- drivers/net/wireless/p54common.h | 75 ----- drivers/net/wireless/rt2x00/rt2x00.h | 11 +- drivers/net/wireless/rt2x00/rt2x00config.c | 33 +- drivers/net/wireless/rt2x00/rt2x00dev.c | 149 ++++----- drivers/net/wireless/rt2x00/rt61pci.c | 23 +- drivers/net/wireless/rt2x00/rt73usb.c | 23 +- drivers/net/wireless/rtl8180.h | 2 +- drivers/net/wireless/rtl8180_dev.c | 93 ++++-- drivers/net/wireless/rtl8180_grf5101.c | 5 +- drivers/net/wireless/rtl8180_max2820.c | 5 +- drivers/net/wireless/rtl8180_rtl8225.c | 15 +- drivers/net/wireless/rtl8180_sa2400.c | 5 +- drivers/net/wireless/rtl8187.h | 2 +- drivers/net/wireless/rtl8187_dev.c | 82 +++-- drivers/net/wireless/rtl8187_rtl8225.c | 15 +- drivers/net/wireless/rtl818x.h | 70 ----- drivers/net/wireless/zd1211rw/zd_chip.c | 15 +- drivers/net/wireless/zd1211rw/zd_ieee80211.c | 11 +- drivers/net/wireless/zd1211rw/zd_mac.c | 170 +++++----- drivers/net/wireless/zd1211rw/zd_mac.h | 2 +- 40 files changed, 1012 insertions(+), 1699 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 714a6ca30ad2..cd5fcc67e954 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -735,6 +735,7 @@ config P54_PCI config ATH5K tristate "Atheros 5xxx wireless cards support" depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL + depends on BROKEN ---help--- This module adds support for wireless adapters based on Atheros 5xxx chipset. diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c index 79796186713e..7d4218206c47 100644 --- a/drivers/net/wireless/adm8211.c +++ b/drivers/net/wireless/adm8211.c @@ -48,6 +48,32 @@ static struct pci_device_id adm8211_pci_id_table[] __devinitdata = { { 0 } }; +static struct ieee80211_rate adm8211_rates[] = { + { .bitrate = 10, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, + { .bitrate = 20, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, + { .bitrate = 55, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, + { .bitrate = 110, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, + { .bitrate = 220, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, /* XX ?? */ +}; + +static const struct ieee80211_channel adm8211_channels[] = { + { .center_freq = 2412}, + { .center_freq = 2417}, + { .center_freq = 2422}, + { .center_freq = 2427}, + { .center_freq = 2432}, + { .center_freq = 2437}, + { .center_freq = 2442}, + { .center_freq = 2447}, + { .center_freq = 2452}, + { .center_freq = 2457}, + { .center_freq = 2462}, + { .center_freq = 2467}, + { .center_freq = 2472}, + { .center_freq = 2484}, +}; + + static void adm8211_eeprom_register_read(struct eeprom_93cx6 *eeprom) { struct adm8211_priv *priv = eeprom->data; @@ -155,17 +181,17 @@ static int adm8211_read_eeprom(struct ieee80211_hw *dev) printk(KERN_DEBUG "%s (adm8211): Channel range: %d - %d\n", pci_name(priv->pdev), (int)chan_range.min, (int)chan_range.max); - priv->modes[0].num_channels = chan_range.max - chan_range.min + 1; - priv->modes[0].channels = priv->channels; + BUILD_BUG_ON(sizeof(priv->channels) != sizeof(adm8211_channels)); - memcpy(priv->channels, adm8211_channels, sizeof(adm8211_channels)); + memcpy(priv->channels, adm8211_channels, sizeof(priv->channels)); + priv->band.channels = priv->channels; + priv->band.n_channels = ARRAY_SIZE(adm8211_channels); + priv->band.bitrates = adm8211_rates; + priv->band.n_bitrates = ARRAY_SIZE(adm8211_rates); for (i = 1; i <= ARRAY_SIZE(adm8211_channels); i++) - if (i >= chan_range.min && i <= chan_range.max) - priv->channels[i - 1].flag = - IEEE80211_CHAN_W_SCAN | - IEEE80211_CHAN_W_ACTIVE_SCAN | - IEEE80211_CHAN_W_IBSS; + if (i < chan_range.min || i > chan_range.max) + priv->channels[i - 1].flags |= IEEE80211_CHAN_DISABLED; switch (priv->eeprom->specific_bbptype) { case ADM8211_BBP_RFMD3000: @@ -347,7 +373,6 @@ static void adm8211_interrupt_rci(struct ieee80211_hw *dev) unsigned int pktlen; struct sk_buff *skb, *newskb; unsigned int limit = priv->rx_ring_size; - static const u8 rate_tbl[] = {10, 20, 55, 110, 220}; u8 rssi, rate; while (!(priv->rx_ring[entry].status & cpu_to_le32(RDES0_STATUS_OWN))) { @@ -425,12 +450,10 @@ static void adm8211_interrupt_rci(struct ieee80211_hw *dev) else rx_status.ssi = 100 - rssi; - if (rate <= 4) - rx_status.rate = rate_tbl[rate]; + rx_status.rate_idx = rate; - rx_status.channel = priv->channel; - rx_status.freq = adm8211_channels[priv->channel - 1].freq; - rx_status.phymode = MODE_IEEE80211B; + rx_status.freq = adm8211_channels[priv->channel - 1].center_freq; + rx_status.band = IEEE80211_BAND_2GHZ; ieee80211_rx_irqsafe(dev, skb, &rx_status); } @@ -1054,7 +1077,7 @@ static int adm8211_set_rate(struct ieee80211_hw *dev) if (priv->pdev->revision != ADM8211_REV_BA) { rate_buf[0] = ARRAY_SIZE(adm8211_rates); for (i = 0; i < ARRAY_SIZE(adm8211_rates); i++) - rate_buf[i + 1] = (adm8211_rates[i].rate / 5) | 0x80; + rate_buf[i + 1] = (adm8211_rates[i].bitrate / 5) | 0x80; } else { /* workaround for rev BA specific bug */ rate_buf[0] = 0x04; @@ -1303,9 +1326,10 @@ static int adm8211_set_ssid(struct ieee80211_hw *dev, u8 *ssid, size_t ssid_len) static int adm8211_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf) { struct adm8211_priv *priv = dev->priv; + int channel = ieee80211_frequency_to_channel(conf->channel->center_freq); - if (conf->channel != priv->channel) { - priv->channel = conf->channel; + if (channel != priv->channel) { + priv->channel = channel; adm8211_rf_set_channel(dev, priv->channel); } @@ -1680,10 +1704,10 @@ static int adm8211_tx(struct ieee80211_hw *dev, struct sk_buff *skb, if (control->tx_rate < 0) { short_preamble = 1; - plcp_signal = -control->tx_rate; + plcp_signal = -control->tx_rate->bitrate; } else { short_preamble = 0; - plcp_signal = control->tx_rate; + plcp_signal = control->tx_rate->bitrate; } hdr = (struct ieee80211_hdr *)skb->data; @@ -1880,18 +1904,11 @@ static int __devinit adm8211_probe(struct pci_dev *pdev, SET_IEEE80211_PERM_ADDR(dev, perm_addr); dev->extra_tx_headroom = sizeof(struct adm8211_tx_hdr); - dev->flags = IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED; - /* IEEE80211_HW_RX_INCLUDES_FCS in promisc mode */ + /* dev->flags = IEEE80211_HW_RX_INCLUDES_FCS in promisc mode */ dev->channel_change_time = 1000; dev->max_rssi = 100; /* FIXME: find better value */ - priv->modes[0].mode = MODE_IEEE80211B; - /* channel info filled in by adm8211_read_eeprom */ - memcpy(priv->rates, adm8211_rates, sizeof(adm8211_rates)); - priv->modes[0].num_rates = ARRAY_SIZE(adm8211_rates); - priv->modes[0].rates = priv->rates; - dev->queues = 1; /* ADM8211C supports more, maybe ADM8211B too */ priv->retry_limit = 3; @@ -1917,14 +1934,7 @@ static int __devinit adm8211_probe(struct pci_dev *pdev, goto err_free_desc; } - priv->channel = priv->modes[0].channels[0].chan; - - err = ieee80211_register_hwmode(dev, &priv->modes[0]); - if (err) { - printk(KERN_ERR "%s (adm8211): Can't register hwmode\n", - pci_name(pdev)); - goto err_free_desc; - } + priv->channel = 1; err = ieee80211_register_hw(dev); if (err) { diff --git a/drivers/net/wireless/adm8211.h b/drivers/net/wireless/adm8211.h index ef326fed42e4..8d7c564b3b04 100644 --- a/drivers/net/wireless/adm8211.h +++ b/drivers/net/wireless/adm8211.h @@ -534,61 +534,6 @@ struct adm8211_eeprom { u8 cis_data[0]; /* 0x80, 384 bytes */ } __attribute__ ((packed)); -static const struct ieee80211_rate adm8211_rates[] = { - { .rate = 10, - .val = 10, - .val2 = -10, - .flags = IEEE80211_RATE_CCK_2 }, - { .rate = 20, - .val = 20, - .val2 = -20, - .flags = IEEE80211_RATE_CCK_2 }, - { .rate = 55, - .val = 55, - .val2 = -55, - .flags = IEEE80211_RATE_CCK_2 }, - { .rate = 110, - .val = 110, - .val2 = -110, - .flags = IEEE80211_RATE_CCK_2 } -}; - -struct ieee80211_chan_range { - u8 min; - u8 max; -}; - -static const struct ieee80211_channel adm8211_channels[] = { - { .chan = 1, - .freq = 2412}, - { .chan = 2, - .freq = 2417}, - { .chan = 3, - .freq = 2422}, - { .chan = 4, - .freq = 2427}, - { .chan = 5, - .freq = 2432}, - { .chan = 6, - .freq = 2437}, - { .chan = 7, - .freq = 2442}, - { .chan = 8, - .freq = 2447}, - { .chan = 9, - .freq = 2452}, - { .chan = 10, - .freq = 2457}, - { .chan = 11, - .freq = 2462}, - { .chan = 12, - .freq = 2467}, - { .chan = 13, - .freq = 2472}, - { .chan = 14, - .freq = 2484}, -}; - struct adm8211_priv { struct pci_dev *pdev; spinlock_t lock; @@ -603,9 +548,8 @@ struct adm8211_priv { unsigned int cur_tx, dirty_tx, cur_rx; struct ieee80211_low_level_stats stats; - struct ieee80211_hw_mode modes[1]; - struct ieee80211_channel channels[ARRAY_SIZE(adm8211_channels)]; - struct ieee80211_rate rates[ARRAY_SIZE(adm8211_rates)]; + struct ieee80211_supported_band band; + struct ieee80211_channel channels[14]; int mode; int channel; @@ -643,6 +587,11 @@ struct adm8211_priv { } transceiver_type; }; +struct ieee80211_chan_range { + u8 min; + u8 max; +}; + static const struct ieee80211_chan_range cranges[] = { {1, 11}, /* FCC */ {1, 11}, /* IC */ diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index f13346ba9dd2..3e40323cd43f 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -468,10 +468,6 @@ struct b43_phy { u8 possible_phymodes; /* GMODE bit enabled? */ bool gmode; - /* Possible ieee80211 subsystem hwmodes for this PHY. - * Which mode is selected, depends on thr GMODE enabled bit */ -#define B43_MAX_PHYHWMODES 2 - struct ieee80211_hw_mode hwmodes[B43_MAX_PHYHWMODES]; /* Analog Type */ u8 analog; @@ -727,7 +723,6 @@ struct b43_wldev { bool bad_frames_preempt; /* Use "Bad Frames Preemption" (default off) */ bool dfq_valid; /* Directed frame queue valid (IBSS PS mode, ATIM) */ - bool short_preamble; /* TRUE, if short preamble is enabled. */ bool short_slot; /* TRUE, if short slot timing is enabled. */ bool radio_hw_enable; /* saved state of radio hardware enabled state */ bool suspend_in_progress; /* TRUE, if we are in a suspend/resume cycle */ diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 51dfce16178a..017a041d07d0 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -96,25 +96,29 @@ MODULE_DEVICE_TABLE(ssb, b43_ssb_tbl); * data in there. This data is the same for all devices, so we don't * get concurrency issues */ #define RATETAB_ENT(_rateid, _flags) \ - { \ - .rate = B43_RATE_TO_BASE100KBPS(_rateid), \ - .val = (_rateid), \ - .val2 = (_rateid), \ - .flags = (_flags), \ + { \ + .bitrate = B43_RATE_TO_BASE100KBPS(_rateid), \ + .hw_value = (_rateid), \ + .flags = (_flags), \ } + +/* + * NOTE: When changing this, sync with xmit.c's + * b43_plcp_get_bitrate_idx_* functions! + */ static struct ieee80211_rate __b43_ratetable[] = { - RATETAB_ENT(B43_CCK_RATE_1MB, IEEE80211_RATE_CCK), - RATETAB_ENT(B43_CCK_RATE_2MB, IEEE80211_RATE_CCK_2), - RATETAB_ENT(B43_CCK_RATE_5MB, IEEE80211_RATE_CCK_2), - RATETAB_ENT(B43_CCK_RATE_11MB, IEEE80211_RATE_CCK_2), - RATETAB_ENT(B43_OFDM_RATE_6MB, IEEE80211_RATE_OFDM), - RATETAB_ENT(B43_OFDM_RATE_9MB, IEEE80211_RATE_OFDM), - RATETAB_ENT(B43_OFDM_RATE_12MB, IEEE80211_RATE_OFDM), - RATETAB_ENT(B43_OFDM_RATE_18MB, IEEE80211_RATE_OFDM), - RATETAB_ENT(B43_OFDM_RATE_24MB, IEEE80211_RATE_OFDM), - RATETAB_ENT(B43_OFDM_RATE_36MB, IEEE80211_RATE_OFDM), - RATETAB_ENT(B43_OFDM_RATE_48MB, IEEE80211_RATE_OFDM), - RATETAB_ENT(B43_OFDM_RATE_54MB, IEEE80211_RATE_OFDM), + RATETAB_ENT(B43_CCK_RATE_1MB, 0), + RATETAB_ENT(B43_CCK_RATE_2MB, IEEE80211_RATE_SHORT_PREAMBLE), + RATETAB_ENT(B43_CCK_RATE_5MB, IEEE80211_RATE_SHORT_PREAMBLE), + RATETAB_ENT(B43_CCK_RATE_11MB, IEEE80211_RATE_SHORT_PREAMBLE), + RATETAB_ENT(B43_OFDM_RATE_6MB, 0), + RATETAB_ENT(B43_OFDM_RATE_9MB, 0), + RATETAB_ENT(B43_OFDM_RATE_12MB, 0), + RATETAB_ENT(B43_OFDM_RATE_18MB, 0), + RATETAB_ENT(B43_OFDM_RATE_24MB, 0), + RATETAB_ENT(B43_OFDM_RATE_36MB, 0), + RATETAB_ENT(B43_OFDM_RATE_48MB, 0), + RATETAB_ENT(B43_OFDM_RATE_54MB, 0), }; #define b43_a_ratetable (__b43_ratetable + 4) @@ -126,14 +130,8 @@ static struct ieee80211_rate __b43_ratetable[] = { #define CHANTAB_ENT(_chanid, _freq) \ { \ - .chan = (_chanid), \ - .freq = (_freq), \ - .val = (_chanid), \ - .flag = IEEE80211_CHAN_W_SCAN | \ - IEEE80211_CHAN_W_ACTIVE_SCAN | \ - IEEE80211_CHAN_W_IBSS, \ - .power_level = 0xFF, \ - .antenna_max = 0xFF, \ + .center_freq = (_freq), \ + .hw_value = (_chanid), \ } static struct ieee80211_channel b43_2ghz_chantable[] = { CHANTAB_ENT(1, 2412), @@ -151,9 +149,8 @@ static struct ieee80211_channel b43_2ghz_chantable[] = { CHANTAB_ENT(13, 2472), CHANTAB_ENT(14, 2484), }; -#define b43_2ghz_chantable_size ARRAY_SIZE(b43_2ghz_chantable) -#if 0 +#ifdef NOTYET static struct ieee80211_channel b43_5ghz_chantable[] = { CHANTAB_ENT(36, 5180), CHANTAB_ENT(40, 5200), @@ -169,9 +166,22 @@ static struct ieee80211_channel b43_5ghz_chantable[] = { CHANTAB_ENT(161, 5805), CHANTAB_ENT(165, 5825), }; -#define b43_5ghz_chantable_size ARRAY_SIZE(b43_5ghz_chantable) + +static struct ieee80211_supported_band b43_band_5GHz = { + .channels = b43_5ghz_chantable, + .n_channels = ARRAY_SIZE(b43_5ghz_chantable), + .bitrates = b43_a_ratetable, + .n_bitrates = b43_a_ratetable_size, +}; #endif +static struct ieee80211_supported_band b43_band_2GHz = { + .channels = b43_2ghz_chantable, + .n_channels = ARRAY_SIZE(b43_2ghz_chantable), + .bitrates = b43_g_ratetable, + .n_bitrates = b43_g_ratetable_size, +}; + static void b43_wireless_core_exit(struct b43_wldev *dev); static int b43_wireless_core_init(struct b43_wldev *dev); static void b43_wireless_core_stop(struct b43_wldev *dev); @@ -1222,17 +1232,18 @@ static void b43_write_beacon_template(struct b43_wldev *dev, } static void b43_write_probe_resp_plcp(struct b43_wldev *dev, - u16 shm_offset, u16 size, u8 rate) + u16 shm_offset, u16 size, + struct ieee80211_rate *rate) { struct b43_plcp_hdr4 plcp; u32 tmp; __le16 dur; plcp.data = 0; - b43_generate_plcp_hdr(&plcp, size + FCS_LEN, rate); + b43_generate_plcp_hdr(&plcp, size + FCS_LEN, rate->hw_value); dur = ieee80211_generic_frame_duration(dev->wl->hw, dev->wl->vif, size, - B43_RATE_TO_BASE100KBPS(rate)); + rate); /* Write PLCP in two parts and timing for packet transfer */ tmp = le32_to_cpu(plcp.data); b43_shm_write16(dev, B43_SHM_SHARED, shm_offset, tmp & 0xFFFF); @@ -1247,7 +1258,8 @@ static void b43_write_probe_resp_plcp(struct b43_wldev *dev, * 3) Stripping TIM */ static const u8 * b43_generate_probe_resp(struct b43_wldev *dev, - u16 *dest_size, u8 rate) + u16 *dest_size, + struct ieee80211_rate *rate) { const u8 *src_data; u8 *dest_data; @@ -1292,7 +1304,7 @@ static const u8 * b43_generate_probe_resp(struct b43_wldev *dev, IEEE80211_STYPE_PROBE_RESP); dur = ieee80211_generic_frame_duration(dev->wl->hw, dev->wl->vif, *dest_size, - B43_RATE_TO_BASE100KBPS(rate)); + rate); hdr->duration_id = dur; return dest_data; @@ -1300,7 +1312,8 @@ static const u8 * b43_generate_probe_resp(struct b43_wldev *dev, static void b43_write_probe_resp_template(struct b43_wldev *dev, u16 ram_offset, - u16 shm_size_offset, u8 rate) + u16 shm_size_offset, + struct ieee80211_rate *rate) { const u8 *probe_resp_data; u16 size; @@ -1313,14 +1326,15 @@ static void b43_write_probe_resp_template(struct b43_wldev *dev, /* Looks like PLCP headers plus packet timings are stored for * all possible basic rates */ - b43_write_probe_resp_plcp(dev, 0x31A, size, B43_CCK_RATE_1MB); - b43_write_probe_resp_plcp(dev, 0x32C, size, B43_CCK_RATE_2MB); - b43_write_probe_resp_plcp(dev, 0x33E, size, B43_CCK_RATE_5MB); - b43_write_probe_resp_plcp(dev, 0x350, size, B43_CCK_RATE_11MB); + b43_write_probe_resp_plcp(dev, 0x31A, size, &b43_b_ratetable[0]); + b43_write_probe_resp_plcp(dev, 0x32C, size, &b43_b_ratetable[1]); + b43_write_probe_resp_plcp(dev, 0x33E, size, &b43_b_ratetable[2]); + b43_write_probe_resp_plcp(dev, 0x350, size, &b43_b_ratetable[3]); size = min((size_t) size, 0x200 - sizeof(struct b43_plcp_hdr6)); b43_write_template_common(dev, probe_resp_data, - size, ram_offset, shm_size_offset, rate); + size, ram_offset, shm_size_offset, + rate->hw_value); kfree(probe_resp_data); } @@ -1388,7 +1402,7 @@ static void handle_irq_beacon(struct b43_wldev *dev) b43_write_beacon_template(dev, 0x68, 0x18, B43_CCK_RATE_1MB); b43_write_probe_resp_template(dev, 0x268, 0x4A, - B43_CCK_RATE_11MB); + &__b43_ratetable[3]); wl->beacon0_uploaded = 1; } cmd |= B43_MACCMD_BEACON0_VALID; @@ -2830,14 +2844,11 @@ static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) mutex_lock(&wl->mutex); /* Switch the PHY mode (if necessary). */ - switch (conf->phymode) { - case MODE_IEEE80211A: + switch (conf->channel->band) { + case IEEE80211_BAND_5GHZ: new_phymode = B43_PHYMODE_A; break; - case MODE_IEEE80211B: - new_phymode = B43_PHYMODE_B; - break; - case MODE_IEEE80211G: + case IEEE80211_BAND_2GHZ: new_phymode = B43_PHYMODE_G; break; default: @@ -2863,8 +2874,8 @@ static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) /* Switch to the requested channel. * The firmware takes care of races with the TX handler. */ - if (conf->channel_val != phy->channel) - b43_radio_selectchannel(dev, conf->channel_val, 0); + if (conf->channel->hw_value != phy->channel) + b43_radio_selectchannel(dev, conf->channel->hw_value, 0); /* Enable/Disable ShortSlot timing. */ if ((!!(conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME)) != @@ -3810,9 +3821,7 @@ static int b43_setup_modes(struct b43_wldev *dev, bool have_2ghz_phy, bool have_5ghz_phy) { struct ieee80211_hw *hw = dev->wl->hw; - struct ieee80211_hw_mode *mode; struct b43_phy *phy = &dev->phy; - int err; /* XXX: This function will go away soon, when mac80211 * band stuff is rewritten. So this is just a hack. @@ -3821,15 +3830,7 @@ static int b43_setup_modes(struct b43_wldev *dev, * This assumption is OK, as any B, N or A PHY will already * have died a horrible sanity check death earlier. */ - mode = &phy->hwmodes[0]; - mode->mode = MODE_IEEE80211G; - mode->num_channels = b43_2ghz_chantable_size; - mode->channels = b43_2ghz_chantable; - mode->num_rates = b43_g_ratetable_size; - mode->rates = b43_g_ratetable; - err = ieee80211_register_hwmode(hw, mode); - if (err) - return err; + hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &b43_band_2GHz; phy->possible_phymodes |= B43_PHYMODE_G; return 0; diff --git a/drivers/net/wireless/b43/sysfs.c b/drivers/net/wireless/b43/sysfs.c index f4faff6a7d6c..275095b8cbe7 100644 --- a/drivers/net/wireless/b43/sysfs.c +++ b/drivers/net/wireless/b43/sysfs.c @@ -47,29 +47,6 @@ static int get_integer(const char *buf, size_t count) return ret; } -static int get_boolean(const char *buf, size_t count) -{ - if (count != 0) { - if (buf[0] == '1') - return 1; - if (buf[0] == '0') - return 0; - if (count >= 4 && memcmp(buf, "true", 4) == 0) - return 1; - if (count >= 5 && memcmp(buf, "false", 5) == 0) - return 0; - if (count >= 3 && memcmp(buf, "yes", 3) == 0) - return 1; - if (count >= 2 && memcmp(buf, "no", 2) == 0) - return 0; - if (count >= 2 && memcmp(buf, "on", 2) == 0) - return 1; - if (count >= 3 && memcmp(buf, "off", 3) == 0) - return 0; - } - return -EINVAL; -} - static ssize_t b43_attr_interfmode_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -155,82 +132,18 @@ static ssize_t b43_attr_interfmode_store(struct device *dev, static DEVICE_ATTR(interference, 0644, b43_attr_interfmode_show, b43_attr_interfmode_store); -static ssize_t b43_attr_preamble_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct b43_wldev *wldev = dev_to_b43_wldev(dev); - ssize_t count; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - mutex_lock(&wldev->wl->mutex); - - if (wldev->short_preamble) - count = - snprintf(buf, PAGE_SIZE, "1 (Short Preamble enabled)\n"); - else - count = - snprintf(buf, PAGE_SIZE, "0 (Short Preamble disabled)\n"); - - mutex_unlock(&wldev->wl->mutex); - - return count; -} - -static ssize_t b43_attr_preamble_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct b43_wldev *wldev = dev_to_b43_wldev(dev); - unsigned long flags; - int value; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - value = get_boolean(buf, count); - if (value < 0) - return value; - mutex_lock(&wldev->wl->mutex); - spin_lock_irqsave(&wldev->wl->irq_lock, flags); - - wldev->short_preamble = !!value; - - spin_unlock_irqrestore(&wldev->wl->irq_lock, flags); - mutex_unlock(&wldev->wl->mutex); - - return count; -} - -static DEVICE_ATTR(shortpreamble, 0644, - b43_attr_preamble_show, b43_attr_preamble_store); - int b43_sysfs_register(struct b43_wldev *wldev) { struct device *dev = wldev->dev->dev; - int err; B43_WARN_ON(b43_status(wldev) != B43_STAT_INITIALIZED); - err = device_create_file(dev, &dev_attr_interference); - if (err) - goto out; - err = device_create_file(dev, &dev_attr_shortpreamble); - if (err) - goto err_remove_interfmode; - - out: - return err; - err_remove_interfmode: - device_remove_file(dev, &dev_attr_interference); - goto out; + return device_create_file(dev, &dev_attr_interference); } void b43_sysfs_unregister(struct b43_wldev *wldev) { struct device *dev = wldev->dev->dev; - device_remove_file(dev, &dev_attr_shortpreamble); device_remove_file(dev, &dev_attr_interference); } diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index 7caa26eb4105..4014b6c8272b 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c @@ -32,46 +32,48 @@ #include "dma.h" -/* Extract the bitrate out of a CCK PLCP header. */ -static u8 b43_plcp_get_bitrate_cck(struct b43_plcp_hdr6 *plcp) +/* Extract the bitrate index out of a CCK PLCP header. */ +static int b43_plcp_get_bitrate_idx_cck(struct b43_plcp_hdr6 *plcp) { switch (plcp->raw[0]) { case 0x0A: - return B43_CCK_RATE_1MB; + return 0; case 0x14: - return B43_CCK_RATE_2MB; + return 1; case 0x37: - return B43_CCK_RATE_5MB; + return 2; case 0x6E: - return B43_CCK_RATE_11MB; + return 3; } B43_WARN_ON(1); - return 0; + return -1; } -/* Extract the bitrate out of an OFDM PLCP header. */ -static u8 b43_plcp_get_bitrate_ofdm(struct b43_plcp_hdr6 *plcp) +/* Extract the bitrate index out of an OFDM PLCP header. */ +static u8 b43_plcp_get_bitrate_idx_ofdm(struct b43_plcp_hdr6 *plcp, bool aphy) { + int base = aphy ? 0 : 4; + switch (plcp->raw[0] & 0xF) { case 0xB: - return B43_OFDM_RATE_6MB; + return base + 0; case 0xF: - return B43_OFDM_RATE_9MB; + return base + 1; case 0xA: - return B43_OFDM_RATE_12MB; + return base + 2; case 0xE: - return B43_OFDM_RATE_18MB; + return base + 3; case 0x9: - return B43_OFDM_RATE_24MB; + return base + 4; case 0xD: - return B43_OFDM_RATE_36MB; + return base + 5; case 0x8: - return B43_OFDM_RATE_48MB; + return base + 6; case 0xC: - return B43_OFDM_RATE_54MB; + return base + 7; } B43_WARN_ON(1); - return 0; + return -1; } u8 b43_plcp_get_ratecode_cck(const u8 bitrate) @@ -191,6 +193,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, (const struct ieee80211_hdr *)fragment_data; int use_encryption = (!(txctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT)); u16 fctl = le16_to_cpu(wlhdr->frame_control); + struct ieee80211_rate *fbrate; u8 rate, rate_fb; int rate_ofdm, rate_fb_ofdm; unsigned int plcp_fragment_len; @@ -200,9 +203,11 @@ int b43_generate_txhdr(struct b43_wldev *dev, memset(txhdr, 0, sizeof(*txhdr)); - rate = txctl->tx_rate; + WARN_ON(!txctl->tx_rate); + rate = txctl->tx_rate ? txctl->tx_rate->hw_value : B43_CCK_RATE_1MB; rate_ofdm = b43_is_ofdm_rate(rate); - rate_fb = (txctl->alt_retry_rate == -1) ? rate : txctl->alt_retry_rate; + fbrate = txctl->alt_retry_rate ? : txctl->tx_rate; + rate_fb = fbrate->hw_value; rate_fb_ofdm = b43_is_ofdm_rate(rate_fb); if (rate_ofdm) @@ -221,11 +226,10 @@ int b43_generate_txhdr(struct b43_wldev *dev, * use the original dur_id field. */ txhdr->dur_fb = wlhdr->duration_id; } else { - int fbrate_base100kbps = B43_RATE_TO_BASE100KBPS(rate_fb); txhdr->dur_fb = ieee80211_generic_frame_duration(dev->wl->hw, txctl->vif, fragment_len, - fbrate_base100kbps); + fbrate); } plcp_fragment_len = fragment_len + FCS_LEN; @@ -287,7 +291,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, phy_ctl |= B43_TXH_PHY_ENC_OFDM; else phy_ctl |= B43_TXH_PHY_ENC_CCK; - if (dev->short_preamble) + if (txctl->flags & IEEE80211_TXCTL_SHORT_PREAMBLE) phy_ctl |= B43_TXH_PHY_SHORTPRMBL; switch (b43_ieee80211_antenna_sanitize(dev, txctl->antenna_sel_tx)) { @@ -332,7 +336,8 @@ int b43_generate_txhdr(struct b43_wldev *dev, int rts_rate_ofdm, rts_rate_fb_ofdm; struct b43_plcp_hdr6 *plcp; - rts_rate = txctl->rts_cts_rate; + WARN_ON(!txctl->rts_cts_rate); + rts_rate = txctl->rts_cts_rate ? txctl->rts_cts_rate->hw_value : B43_CCK_RATE_1MB; rts_rate_ofdm = b43_is_ofdm_rate(rts_rate); rts_rate_fb = b43_calc_fallback_rate(rts_rate); rts_rate_fb_ofdm = b43_is_ofdm_rate(rts_rate_fb); @@ -506,6 +511,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) u16 phystat0, phystat3, chanstat, mactime; u32 macstat; u16 chanid; + u16 phytype; u8 jssi; int padding; @@ -518,6 +524,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) macstat = le32_to_cpu(rxhdr->mac_status); mactime = le16_to_cpu(rxhdr->mac_time); chanstat = le16_to_cpu(rxhdr->channel); + phytype = chanstat & B43_RX_CHAN_PHYTYPE; if (macstat & B43_RX_MAC_FCSERR) dev->wl->ieee_stats.dot11FCSErrorCount++; @@ -575,9 +582,10 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) /* the next line looks wrong, but is what mac80211 wants */ status.signal = (jssi * 100) / B43_RX_MAX_SSI; if (phystat0 & B43_RX_PHYST0_OFDM) - status.rate = b43_plcp_get_bitrate_ofdm(plcp); + status.rate_idx = b43_plcp_get_bitrate_idx_ofdm(plcp, + phytype == B43_PHYTYPE_A); else - status.rate = b43_plcp_get_bitrate_cck(plcp); + status.rate_idx = b43_plcp_get_bitrate_idx_cck(plcp); status.antenna = !!(phystat0 & B43_RX_PHYST0_ANT); /* @@ -601,29 +609,28 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) chanid = (chanstat & B43_RX_CHAN_ID) >> B43_RX_CHAN_ID_SHIFT; switch (chanstat & B43_RX_CHAN_PHYTYPE) { case B43_PHYTYPE_A: - status.phymode = MODE_IEEE80211A; + status.band = IEEE80211_BAND_5GHZ; B43_WARN_ON(1); /* FIXME: We don't really know which value the "chanid" contains. * So the following assignment might be wrong. */ - status.channel = chanid; - status.freq = b43_channel_to_freq_5ghz(status.channel); + status.freq = b43_channel_to_freq_5ghz(chanid); break; case B43_PHYTYPE_G: - status.phymode = MODE_IEEE80211G; + status.band = IEEE80211_BAND_2GHZ; /* chanid is the radio channel cookie value as used * to tune the radio. */ status.freq = chanid + 2400; - status.channel = b43_freq_to_channel_2ghz(status.freq); break; case B43_PHYTYPE_N: - status.phymode = 0xDEAD /*FIXME MODE_IEEE80211N*/; /* chanid is the SHM channel cookie. Which is the plain * channel number in b43. */ - status.channel = chanid; - if (chanstat & B43_RX_CHAN_5GHZ) - status.freq = b43_freq_to_channel_5ghz(status.freq); - else - status.freq = b43_freq_to_channel_2ghz(status.freq); + if (chanstat & B43_RX_CHAN_5GHZ) { + status.band = IEEE80211_BAND_5GHZ; + status.freq = b43_freq_to_channel_5ghz(chanid); + } else { + status.band = IEEE80211_BAND_2GHZ; + status.freq = b43_freq_to_channel_2ghz(chanid); + } break; default: B43_WARN_ON(1); diff --git a/drivers/net/wireless/b43legacy/b43legacy.h b/drivers/net/wireless/b43legacy/b43legacy.h index 93d45b71799a..5f217d6d2e6a 100644 --- a/drivers/net/wireless/b43legacy/b43legacy.h +++ b/drivers/net/wireless/b43legacy/b43legacy.h @@ -392,10 +392,6 @@ struct b43legacy_phy { u8 possible_phymodes; /* GMODE bit enabled in MACCTL? */ bool gmode; - /* Possible ieee80211 subsystem hwmodes for this PHY. - * Which mode is selected, depends on thr GMODE enabled bit */ -#define B43legacy_MAX_PHYHWMODES 2 - struct ieee80211_hw_mode hwmodes[B43legacy_MAX_PHYHWMODES]; /* Analog Type */ u8 analog; diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index c39de422e220..d2a72a2cd178 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -95,28 +95,29 @@ MODULE_DEVICE_TABLE(ssb, b43legacy_ssb_tbl); * data in there. This data is the same for all devices, so we don't * get concurrency issues */ #define RATETAB_ENT(_rateid, _flags) \ - { \ - .rate = B43legacy_RATE_TO_100KBPS(_rateid), \ - .val = (_rateid), \ - .val2 = (_rateid), \ - .flags = (_flags), \ + { \ + .bitrate = B43legacy_RATE_TO_100KBPS(_rateid), \ + .hw_value = (_rateid), \ + .flags = (_flags), \ } +/* + * NOTE: When changing this, sync with xmit.c's + * b43legacy_plcp_get_bitrate_idx_* functions! + */ static struct ieee80211_rate __b43legacy_ratetable[] = { - RATETAB_ENT(B43legacy_CCK_RATE_1MB, IEEE80211_RATE_CCK), - RATETAB_ENT(B43legacy_CCK_RATE_2MB, IEEE80211_RATE_CCK_2), - RATETAB_ENT(B43legacy_CCK_RATE_5MB, IEEE80211_RATE_CCK_2), - RATETAB_ENT(B43legacy_CCK_RATE_11MB, IEEE80211_RATE_CCK_2), - RATETAB_ENT(B43legacy_OFDM_RATE_6MB, IEEE80211_RATE_OFDM), - RATETAB_ENT(B43legacy_OFDM_RATE_9MB, IEEE80211_RATE_OFDM), - RATETAB_ENT(B43legacy_OFDM_RATE_12MB, IEEE80211_RATE_OFDM), - RATETAB_ENT(B43legacy_OFDM_RATE_18MB, IEEE80211_RATE_OFDM), - RATETAB_ENT(B43legacy_OFDM_RATE_24MB, IEEE80211_RATE_OFDM), - RATETAB_ENT(B43legacy_OFDM_RATE_36MB, IEEE80211_RATE_OFDM), - RATETAB_ENT(B43legacy_OFDM_RATE_48MB, IEEE80211_RATE_OFDM), - RATETAB_ENT(B43legacy_OFDM_RATE_54MB, IEEE80211_RATE_OFDM), + RATETAB_ENT(B43legacy_CCK_RATE_1MB, 0), + RATETAB_ENT(B43legacy_CCK_RATE_2MB, IEEE80211_RATE_SHORT_PREAMBLE), + RATETAB_ENT(B43legacy_CCK_RATE_5MB, IEEE80211_RATE_SHORT_PREAMBLE), + RATETAB_ENT(B43legacy_CCK_RATE_11MB, IEEE80211_RATE_SHORT_PREAMBLE), + RATETAB_ENT(B43legacy_OFDM_RATE_6MB, 0), + RATETAB_ENT(B43legacy_OFDM_RATE_9MB, 0), + RATETAB_ENT(B43legacy_OFDM_RATE_12MB, 0), + RATETAB_ENT(B43legacy_OFDM_RATE_18MB, 0), + RATETAB_ENT(B43legacy_OFDM_RATE_24MB, 0), + RATETAB_ENT(B43legacy_OFDM_RATE_36MB, 0), + RATETAB_ENT(B43legacy_OFDM_RATE_48MB, 0), + RATETAB_ENT(B43legacy_OFDM_RATE_54MB, 0), }; -#define b43legacy_a_ratetable (__b43legacy_ratetable + 4) -#define b43legacy_a_ratetable_size 8 #define b43legacy_b_ratetable (__b43legacy_ratetable + 0) #define b43legacy_b_ratetable_size 4 #define b43legacy_g_ratetable (__b43legacy_ratetable + 0) @@ -124,14 +125,8 @@ static struct ieee80211_rate __b43legacy_ratetable[] = { #define CHANTAB_ENT(_chanid, _freq) \ { \ - .chan = (_chanid), \ - .freq = (_freq), \ - .val = (_chanid), \ - .flag = IEEE80211_CHAN_W_SCAN | \ - IEEE80211_CHAN_W_ACTIVE_SCAN | \ - IEEE80211_CHAN_W_IBSS, \ - .power_level = 0x0A, \ - .antenna_max = 0xFF, \ + .center_freq = (_freq), \ + .hw_value = (_chanid), \ } static struct ieee80211_channel b43legacy_bg_chantable[] = { CHANTAB_ENT(1, 2412), @@ -149,7 +144,20 @@ static struct ieee80211_channel b43legacy_bg_chantable[] = { CHANTAB_ENT(13, 2472), CHANTAB_ENT(14, 2484), }; -#define b43legacy_bg_chantable_size ARRAY_SIZE(b43legacy_bg_chantable) + +static struct ieee80211_supported_band b43legacy_band_2GHz_BPHY = { + .channels = b43legacy_bg_chantable, + .n_channels = ARRAY_SIZE(b43legacy_bg_chantable), + .bitrates = b43legacy_b_ratetable, + .n_bitrates = b43legacy_b_ratetable_size, +}; + +static struct ieee80211_supported_band b43legacy_band_2GHz_GPHY = { + .channels = b43legacy_bg_chantable, + .n_channels = ARRAY_SIZE(b43legacy_bg_chantable), + .bitrates = b43legacy_g_ratetable, + .n_bitrates = b43legacy_g_ratetable_size, +}; static void b43legacy_wireless_core_exit(struct b43legacy_wldev *dev); static int b43legacy_wireless_core_init(struct b43legacy_wldev *dev); @@ -969,18 +977,18 @@ static void b43legacy_write_beacon_template(struct b43legacy_wldev *dev, static void b43legacy_write_probe_resp_plcp(struct b43legacy_wldev *dev, u16 shm_offset, u16 size, - u8 rate) + struct ieee80211_rate *rate) { struct b43legacy_plcp_hdr4 plcp; u32 tmp; __le16 dur; plcp.data = 0; - b43legacy_generate_plcp_hdr(&plcp, size + FCS_LEN, rate); + b43legacy_generate_plcp_hdr(&plcp, size + FCS_LEN, rate->bitrate); dur = ieee80211_generic_frame_duration(dev->wl->hw, dev->wl->vif, size, - B43legacy_RATE_TO_100KBPS(rate)); + rate); /* Write PLCP in two parts and timing for packet transfer */ tmp = le32_to_cpu(plcp.data); b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, shm_offset, @@ -998,7 +1006,8 @@ static void b43legacy_write_probe_resp_plcp(struct b43legacy_wldev *dev, * 3) Stripping TIM */ static u8 *b43legacy_generate_probe_resp(struct b43legacy_wldev *dev, - u16 *dest_size, u8 rate) + u16 *dest_size, + struct ieee80211_rate *rate) { const u8 *src_data; u8 *dest_data; @@ -1046,7 +1055,7 @@ static u8 *b43legacy_generate_probe_resp(struct b43legacy_wldev *dev, dur = ieee80211_generic_frame_duration(dev->wl->hw, dev->wl->vif, *dest_size, - B43legacy_RATE_TO_100KBPS(rate)); + rate); hdr->duration_id = dur; return dest_data; @@ -1054,7 +1063,8 @@ static u8 *b43legacy_generate_probe_resp(struct b43legacy_wldev *dev, static void b43legacy_write_probe_resp_template(struct b43legacy_wldev *dev, u16 ram_offset, - u16 shm_size_offset, u8 rate) + u16 shm_size_offset, + struct ieee80211_rate *rate) { u8 *probe_resp_data; u16 size; @@ -1069,19 +1079,19 @@ static void b43legacy_write_probe_resp_template(struct b43legacy_wldev *dev, * all possible basic rates */ b43legacy_write_probe_resp_plcp(dev, 0x31A, size, - B43legacy_CCK_RATE_1MB); + &b43legacy_b_ratetable[0]); b43legacy_write_probe_resp_plcp(dev, 0x32C, size, - B43legacy_CCK_RATE_2MB); + &b43legacy_b_ratetable[1]); b43legacy_write_probe_resp_plcp(dev, 0x33E, size, - B43legacy_CCK_RATE_5MB); + &b43legacy_b_ratetable[2]); b43legacy_write_probe_resp_plcp(dev, 0x350, size, - B43legacy_CCK_RATE_11MB); + &b43legacy_b_ratetable[3]); size = min((size_t)size, 0x200 - sizeof(struct b43legacy_plcp_hdr6)); b43legacy_write_template_common(dev, probe_resp_data, size, ram_offset, - shm_size_offset, rate); + shm_size_offset, rate->bitrate); kfree(probe_resp_data); } @@ -1106,7 +1116,7 @@ static void b43legacy_update_templates(struct b43legacy_wldev *dev) b43legacy_write_beacon_template(dev, 0x468, 0x1A, B43legacy_CCK_RATE_1MB); b43legacy_write_probe_resp_template(dev, 0x268, 0x4A, - B43legacy_CCK_RATE_11MB); + &b43legacy_b_ratetable[0]); status = b43legacy_read32(dev, B43legacy_MMIO_MACCMD); status |= 0x03; @@ -2550,14 +2560,16 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw, antenna_rx = b43legacy_antenna_from_ieee80211(conf->antenna_sel_rx); mutex_lock(&wl->mutex); + dev = wl->current_dev; + phy = &dev->phy; /* Switch the PHY mode (if necessary). */ - switch (conf->phymode) { - case MODE_IEEE80211B: - new_phymode = B43legacy_PHYMODE_B; - break; - case MODE_IEEE80211G: - new_phymode = B43legacy_PHYMODE_G; + switch (conf->channel->band) { + case IEEE80211_BAND_2GHZ: + if (phy->type == B43legacy_PHYTYPE_B) + new_phymode = B43legacy_PHYMODE_B; + else + new_phymode = B43legacy_PHYMODE_G; break; default: B43legacy_WARN_ON(1); @@ -2565,8 +2577,6 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw, err = b43legacy_switch_phymode(wl, new_phymode); if (err) goto out_unlock_mutex; - dev = wl->current_dev; - phy = &dev->phy; /* Disable IRQs while reconfiguring the device. * This makes it possible to drop the spinlock throughout @@ -2582,8 +2592,8 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw, /* Switch to the requested channel. * The firmware takes care of races with the TX handler. */ - if (conf->channel_val != phy->channel) - b43legacy_radio_selectchannel(dev, conf->channel_val, 0); + if (conf->channel->hw_value != phy->channel) + b43legacy_radio_selectchannel(dev, conf->channel->hw_value, 0); /* Enable/Disable ShortSlot timing. */ if ((!!(conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME)) @@ -3398,48 +3408,19 @@ static int b43legacy_setup_modes(struct b43legacy_wldev *dev, int have_gphy) { struct ieee80211_hw *hw = dev->wl->hw; - struct ieee80211_hw_mode *mode; struct b43legacy_phy *phy = &dev->phy; - int cnt = 0; - int err; phy->possible_phymodes = 0; - for (; 1; cnt++) { - if (have_bphy) { - B43legacy_WARN_ON(cnt >= B43legacy_MAX_PHYHWMODES); - mode = &phy->hwmodes[cnt]; - - mode->mode = MODE_IEEE80211B; - mode->num_channels = b43legacy_bg_chantable_size; - mode->channels = b43legacy_bg_chantable; - mode->num_rates = b43legacy_b_ratetable_size; - mode->rates = b43legacy_b_ratetable; - err = ieee80211_register_hwmode(hw, mode); - if (err) - return err; - - phy->possible_phymodes |= B43legacy_PHYMODE_B; - have_bphy = 0; - continue; - } - if (have_gphy) { - B43legacy_WARN_ON(cnt >= B43legacy_MAX_PHYHWMODES); - mode = &phy->hwmodes[cnt]; - - mode->mode = MODE_IEEE80211G; - mode->num_channels = b43legacy_bg_chantable_size; - mode->channels = b43legacy_bg_chantable; - mode->num_rates = b43legacy_g_ratetable_size; - mode->rates = b43legacy_g_ratetable; - err = ieee80211_register_hwmode(hw, mode); - if (err) - return err; - - phy->possible_phymodes |= B43legacy_PHYMODE_G; - have_gphy = 0; - continue; - } - break; + if (have_bphy) { + hw->wiphy->bands[IEEE80211_BAND_2GHZ] = + &b43legacy_band_2GHz_BPHY; + phy->possible_phymodes |= B43legacy_PHYMODE_B; + } + + if (have_gphy) { + hw->wiphy->bands[IEEE80211_BAND_2GHZ] = + &b43legacy_band_2GHz_GPHY; + phy->possible_phymodes |= B43legacy_PHYMODE_G; } return 0; diff --git a/drivers/net/wireless/b43legacy/xmit.c b/drivers/net/wireless/b43legacy/xmit.c index d84408a82db9..47e130e9fdf2 100644 --- a/drivers/net/wireless/b43legacy/xmit.c +++ b/drivers/net/wireless/b43legacy/xmit.c @@ -37,45 +37,48 @@ /* Extract the bitrate out of a CCK PLCP header. */ -static u8 b43legacy_plcp_get_bitrate_cck(struct b43legacy_plcp_hdr6 *plcp) +static u8 b43legacy_plcp_get_bitrate_idx_cck(struct b43legacy_plcp_hdr6 *plcp) { switch (plcp->raw[0]) { case 0x0A: - return B43legacy_CCK_RATE_1MB; + return 0; case 0x14: - return B43legacy_CCK_RATE_2MB; + return 1; case 0x37: - return B43legacy_CCK_RATE_5MB; + return 2; case 0x6E: - return B43legacy_CCK_RATE_11MB; + return 3; } B43legacy_BUG_ON(1); - return 0; + return -1; } /* Extract the bitrate out of an OFDM PLCP header. */ -static u8 b43legacy_plcp_get_bitrate_ofdm(struct b43legacy_plcp_hdr6 *plcp) +static u8 b43legacy_plcp_get_bitrate_idx_ofdm(struct b43legacy_plcp_hdr6 *plcp, + bool aphy) { + int base = aphy ? 0 : 4; + switch (plcp->raw[0] & 0xF) { case 0xB: - return B43legacy_OFDM_RATE_6MB; + return base + 0; case 0xF: - return B43legacy_OFDM_RATE_9MB; + return base + 1; case 0xA: - return B43legacy_OFDM_RATE_12MB; + return base + 2; case 0xE: - return B43legacy_OFDM_RATE_18MB; + return base + 3; case 0x9: - return B43legacy_OFDM_RATE_24MB; + return base + 4; case 0xD: - return B43legacy_OFDM_RATE_36MB; + return base + 5; case 0x8: - return B43legacy_OFDM_RATE_48MB; + return base + 6; case 0xC: - return B43legacy_OFDM_RATE_54MB; + return base + 7; } B43legacy_BUG_ON(1); - return 0; + return -1; } u8 b43legacy_plcp_get_ratecode_cck(const u8 bitrate) @@ -192,7 +195,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev, int use_encryption = (!(txctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT)); u16 fctl; u8 rate; - u8 rate_fb; + struct ieee80211_rate *rate_fb; int rate_ofdm; int rate_fb_ofdm; unsigned int plcp_fragment_len; @@ -204,16 +207,16 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev, memset(txhdr, 0, sizeof(*txhdr)); - rate = txctl->tx_rate; + rate = txctl->tx_rate->hw_value; rate_ofdm = b43legacy_is_ofdm_rate(rate); - rate_fb = (txctl->alt_retry_rate == -1) ? rate : txctl->alt_retry_rate; - rate_fb_ofdm = b43legacy_is_ofdm_rate(rate_fb); + rate_fb = txctl->alt_retry_rate ? : txctl->tx_rate; + rate_fb_ofdm = b43legacy_is_ofdm_rate(rate_fb->hw_value); txhdr->mac_frame_ctl = wlhdr->frame_control; memcpy(txhdr->tx_receiver, wlhdr->addr1, 6); /* Calculate duration for fallback rate */ - if ((rate_fb == rate) || + if ((rate_fb->hw_value == rate) || (wlhdr->duration_id & cpu_to_le16(0x8000)) || (wlhdr->duration_id == cpu_to_le16(0))) { /* If the fallback rate equals the normal rate or the @@ -221,11 +224,10 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev, * use the original dur_id field. */ txhdr->dur_fb = wlhdr->duration_id; } else { - int fbrate_base100kbps = B43legacy_RATE_TO_100KBPS(rate_fb); txhdr->dur_fb = ieee80211_generic_frame_duration(dev->wl->hw, txctl->vif, fragment_len, - fbrate_base100kbps); + rate_fb); } plcp_fragment_len = fragment_len + FCS_LEN; @@ -266,7 +268,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev, rate); b43legacy_generate_plcp_hdr((struct b43legacy_plcp_hdr4 *) (&txhdr->plcp_fb), plcp_fragment_len, - rate_fb); + rate_fb->hw_value); /* PHY TX Control word */ if (rate_ofdm) @@ -310,7 +312,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev, int rts_rate_ofdm; int rts_rate_fb_ofdm; - rts_rate = txctl->rts_cts_rate; + rts_rate = txctl->rts_cts_rate->hw_value; rts_rate_ofdm = b43legacy_is_ofdm_rate(rts_rate); rts_rate_fb = b43legacy_calc_fallback_rate(rts_rate); rts_rate_fb_ofdm = b43legacy_is_ofdm_rate(rts_rate_fb); @@ -536,10 +538,11 @@ void b43legacy_rx(struct b43legacy_wldev *dev, (phystat3 & B43legacy_RX_PHYST3_TRSTATE)); status.noise = dev->stats.link_noise; status.signal = (jssi * 100) / B43legacy_RX_MAX_SSI; + /* change to support A PHY */ if (phystat0 & B43legacy_RX_PHYST0_OFDM) - status.rate = b43legacy_plcp_get_bitrate_ofdm(plcp); + status.rate_idx = b43legacy_plcp_get_bitrate_idx_ofdm(plcp, false); else - status.rate = b43legacy_plcp_get_bitrate_cck(plcp); + status.rate_idx = b43legacy_plcp_get_bitrate_idx_cck(plcp); status.antenna = !!(phystat0 & B43legacy_RX_PHYST0_ANT); /* @@ -564,14 +567,9 @@ void b43legacy_rx(struct b43legacy_wldev *dev, B43legacy_RX_CHAN_ID_SHIFT; switch (chanstat & B43legacy_RX_CHAN_PHYTYPE) { case B43legacy_PHYTYPE_B: - status.phymode = MODE_IEEE80211B; - status.freq = chanid + 2400; - status.channel = b43legacy_freq_to_channel_bg(chanid + 2400); - break; case B43legacy_PHYTYPE_G: - status.phymode = MODE_IEEE80211G; + status.band = IEEE80211_BAND_2GHZ; status.freq = chanid + 2400; - status.channel = b43legacy_freq_to_channel_bg(chanid + 2400); break; default: b43legacywarn(dev->wl, "Unexpected value for chanstat (0x%X)\n", diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index 80d31ae51e77..f018ce464d97 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -100,14 +100,6 @@ static struct iwl3945_tpt_entry iwl3945_tpt_table_a[] = { {-89, IWL_RATE_6M_INDEX} }; -static struct iwl3945_tpt_entry iwl3945_tpt_table_b[] = { - {-86, IWL_RATE_11M_INDEX}, - {-88, IWL_RATE_5M_INDEX}, - {-90, IWL_RATE_2M_INDEX}, - {-92, IWL_RATE_1M_INDEX} - -}; - static struct iwl3945_tpt_entry iwl3945_tpt_table_g[] = { {-60, IWL_RATE_54M_INDEX}, {-64, IWL_RATE_48M_INDEX}, @@ -129,7 +121,7 @@ static struct iwl3945_tpt_entry iwl3945_tpt_table_g[] = { #define IWL_RATE_MIN_SUCCESS_TH 8 #define IWL_RATE_DECREASE_TH 1920 -static u8 iwl3945_get_rate_index_by_rssi(s32 rssi, u8 mode) +static u8 iwl3945_get_rate_index_by_rssi(s32 rssi, enum ieee80211_band band) { u32 index = 0; u32 table_size = 0; @@ -138,21 +130,19 @@ static u8 iwl3945_get_rate_index_by_rssi(s32 rssi, u8 mode) if ((rssi < IWL_MIN_RSSI_VAL) || (rssi > IWL_MAX_RSSI_VAL)) rssi = IWL_MIN_RSSI_VAL; - switch (mode) { - case MODE_IEEE80211G: + switch (band) { + case IEEE80211_BAND_2GHZ: tpt_table = iwl3945_tpt_table_g; table_size = ARRAY_SIZE(iwl3945_tpt_table_g); break; - case MODE_IEEE80211A: + case IEEE80211_BAND_5GHZ: tpt_table = iwl3945_tpt_table_a; table_size = ARRAY_SIZE(iwl3945_tpt_table_a); break; default: - case MODE_IEEE80211B: - tpt_table = iwl3945_tpt_table_b; - table_size = ARRAY_SIZE(iwl3945_tpt_table_b); + BUG(); break; } @@ -340,17 +330,17 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, * after assoc.. */ for (i = IWL_RATE_COUNT - 1; i >= 0; i--) { - if (sta->supp_rates & (1 << i)) { - sta->txrate = i; + if (sta->supp_rates[local->hw.conf.channel->band] & (1 << i)) { + sta->txrate_idx = i; break; } } - sta->last_txrate = sta->txrate; + sta->last_txrate_idx = sta->txrate_idx; - /* For MODE_IEEE80211A mode it start at IWL_FIRST_OFDM_RATE */ - if (local->hw.conf.phymode == MODE_IEEE80211A) - sta->last_txrate += IWL_FIRST_OFDM_RATE; + /* For 5 GHz band it start at IWL_FIRST_OFDM_RATE */ + if (local->hw.conf.channel->band == IEEE80211_BAND_5GHZ) + sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; IWL_DEBUG_RATE("leave\n"); } @@ -429,17 +419,19 @@ static int rs_adjust_next_rate(struct iwl3945_priv *priv, int rate) { int next_rate = iwl3945_get_prev_ieee_rate(rate); - switch (priv->phymode) { - case MODE_IEEE80211A: + switch (priv->band) { + case IEEE80211_BAND_5GHZ: if (rate == IWL_RATE_12M_INDEX) next_rate = IWL_RATE_9M_INDEX; else if (rate == IWL_RATE_6M_INDEX) next_rate = IWL_RATE_6M_INDEX; break; +/* XXX cannot be invoked in current mac80211 so not a regression case MODE_IEEE80211B: if (rate == IWL_RATE_11M_INDEX_TABLE) next_rate = IWL_RATE_5M_INDEX_TABLE; break; + */ default: break; } @@ -465,15 +457,17 @@ static void rs_tx_status(void *priv_rate, struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_rate; struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct iwl3945_rs_sta *rs_sta; + struct ieee80211_supported_band *sband; + + sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; IWL_DEBUG_RATE("enter\n"); retries = tx_resp->retry_count; - first_index = tx_resp->control.tx_rate; + first_index = &sband->bitrates[0] - tx_resp->control.tx_rate; if ((first_index < 0) || (first_index >= IWL_RATE_COUNT)) { - IWL_DEBUG_RATE("leave: Rate out of bounds: %0x for %d\n", - tx_resp->control.tx_rate, first_index); + IWL_DEBUG_RATE("leave: Rate out of bounds: %d\n", first_index); return; } @@ -561,14 +555,14 @@ static void rs_tx_status(void *priv_rate, } static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta, - u8 index, u16 rate_mask, int phymode) + u8 index, u16 rate_mask, enum ieee80211_band band) { u8 high = IWL_RATE_INVALID; u8 low = IWL_RATE_INVALID; /* 802.11A walks to the next literal adjacent rate in * the rate table */ - if (unlikely(phymode == MODE_IEEE80211A)) { + if (unlikely(band == IEEE80211_BAND_5GHZ)) { int i; u32 mask; @@ -639,7 +633,8 @@ static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta, * */ static void rs_get_rate(void *priv_rate, struct net_device *dev, - struct ieee80211_hw_mode *mode, struct sk_buff *skb, + struct ieee80211_supported_band *band, + struct sk_buff *skb, struct rate_selection *sel) { u8 low = IWL_RATE_INVALID; @@ -672,16 +667,16 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, is_multicast_ether_addr(hdr->addr1) || !sta || !sta->rate_ctrl_priv) { IWL_DEBUG_RATE("leave: No STA priv data to update!\n"); - sel->rate = rate_lowest(local, local->oper_hw_mode, sta); + sel->rate = rate_lowest(local, band, sta); if (sta) sta_info_put(sta); return; } - rate_mask = sta->supp_rates; - index = min(sta->last_txrate & 0xffff, IWL_RATE_COUNT - 1); + rate_mask = sta->supp_rates[band->band]; + index = min(sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT - 1); - if (priv->phymode == (u8) MODE_IEEE80211A) + if (priv->band == IEEE80211_BAND_5GHZ) rate_mask = rate_mask << IWL_FIRST_OFDM_RATE; rs_sta = (void *)sta->rate_ctrl_priv; @@ -732,7 +727,7 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, current_tpt = window->average_tpt; high_low = iwl3945_get_adjacent_rate(rs_sta, index, rate_mask, - local->hw.conf.phymode); + band->band); low = high_low & 0xff; high = (high_low >> 8) & 0xff; @@ -810,11 +805,11 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, out: - sta->last_txrate = index; - if (priv->phymode == (u8) MODE_IEEE80211A) - sta->txrate = sta->last_txrate - IWL_FIRST_OFDM_RATE; + sta->last_txrate_idx = index; + if (priv->band == IEEE80211_BAND_5GHZ) + sta->txrate_idx = sta->last_txrate_idx - IWL_FIRST_OFDM_RATE; else - sta->txrate = sta->last_txrate; + sta->txrate_idx = sta->last_txrate_idx; sta_info_put(sta); @@ -945,8 +940,9 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) spin_lock_irqsave(&rs_sta->lock, flags); rs_sta->tgg = 0; - switch (priv->phymode) { - case MODE_IEEE80211G: + switch (priv->band) { + case IEEE80211_BAND_2GHZ: + /* TODO: this always does G, not a regression */ if (priv->active_rxon.flags & RXON_FLG_TGG_PROTECT_MSK) { rs_sta->tgg = 1; rs_sta->expected_tpt = iwl3945_expected_tpt_g_prot; @@ -954,14 +950,11 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) rs_sta->expected_tpt = iwl3945_expected_tpt_g; break; - case MODE_IEEE80211A: + case IEEE80211_BAND_5GHZ: rs_sta->expected_tpt = iwl3945_expected_tpt_a; break; - - default: - IWL_WARNING("Invalid phymode. Defaulting to 802.11b\n"); - case MODE_IEEE80211B: - rs_sta->expected_tpt = iwl3945_expected_tpt_b; + case IEEE80211_NUM_BANDS: + BUG(); break; } @@ -974,8 +967,7 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) IWL_DEBUG(IWL_DL_INFO | IWL_DL_RATE, "Network RSSI: %d\n", rssi); - rs_sta->start_rate = - iwl3945_get_rate_index_by_rssi(rssi, priv->phymode); + rs_sta->start_rate = iwl3945_get_rate_index_by_rssi(rssi, priv->band); IWL_DEBUG_RATE("leave: rssi %d assign rate index: " "%d (plcp 0x%x)\n", rssi, rs_sta->start_rate, diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 8d4d91d35fd2..50d927bb2170 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -247,7 +247,7 @@ static void iwl3945_add_radiotap(struct iwl3945_priv *priv, * the information provided in the skb from the hardware */ s8 signal = stats->ssi; s8 noise = 0; - int rate = stats->rate; + int rate = stats->rate_idx; u64 tsf = stats->mactime; __le16 phy_flags_hw = rx_hdr->phy_flags; @@ -315,7 +315,6 @@ static void iwl3945_add_radiotap(struct iwl3945_priv *priv, IEEE80211_CHAN_2GHZ), &iwl3945_rt->rt_chbitmask); - rate = iwl3945_rate_index_from_plcp(rate); if (rate == -1) iwl3945_rt->rt_rate = 0; else @@ -387,11 +386,10 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv, struct ieee80211_rx_status stats = { .mactime = le64_to_cpu(rx_end->timestamp), .freq = ieee80211chan2mhz(le16_to_cpu(rx_hdr->channel)), - .channel = le16_to_cpu(rx_hdr->channel), - .phymode = (rx_hdr->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? - MODE_IEEE80211G : MODE_IEEE80211A, + .band = (rx_hdr->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? + IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ, .antenna = 0, - .rate = rx_hdr->rate, + .rate_idx = iwl3945_rate_index_from_plcp(rx_hdr->rate), .flag = 0, }; u8 network_packet; @@ -450,8 +448,6 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv, stats.ssi, stats.noise, stats.signal, rx_stats_sig_avg, rx_stats_noise_diff); - stats.freq = ieee80211chan2mhz(stats.channel); - /* can be covered by iwl3945_report_frame() in most cases */ /* IWL_DEBUG_RX("RX status: 0x%08X\n", rx_end->status); */ @@ -464,8 +460,9 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv, IWL_DEBUG_STATS ("[%c] %d RSSI: %d Signal: %u, Noise: %u, Rate: %u\n", network_packet ? '*' : ' ', - stats.channel, stats.ssi, stats.ssi, - stats.ssi, stats.rate); + le16_to_cpu(rx_hdr->channel), + stats.ssi, stats.ssi, + stats.ssi, stats.rate_idx); if (iwl3945_debug_level & (IWL_DL_RX)) /* Set "1" to report good data frames in groups of 100 */ @@ -689,7 +686,7 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl3945_priv *priv, struct ieee80211_hdr *hdr, int sta_id, int tx_id) { unsigned long flags; - u16 rate_index = min(ctrl->tx_rate & 0xffff, IWL_RATE_COUNT - 1); + u16 rate_index = min(ctrl->tx_rate->hw_value & 0xffff, IWL_RATE_COUNT - 1); u16 rate_mask; int rate; u8 rts_retry_limit; @@ -1552,14 +1549,14 @@ int iwl3945_hw_reg_send_txpower(struct iwl3945_priv *priv) .channel = priv->active_rxon.channel, }; - txpower.band = (priv->phymode == MODE_IEEE80211A) ? 0 : 1; + txpower.band = (priv->band == IEEE80211_BAND_5GHZ) ? 0 : 1; ch_info = iwl3945_get_channel_info(priv, - priv->phymode, + priv->band, le16_to_cpu(priv->active_rxon.channel)); if (!ch_info) { IWL_ERROR ("Failed to get channel info for channel %d [%d]\n", - le16_to_cpu(priv->active_rxon.channel), priv->phymode); + le16_to_cpu(priv->active_rxon.channel), priv->band); return -EINVAL; } @@ -2241,8 +2238,8 @@ int iwl3945_init_hw_rate_table(struct iwl3945_priv *priv) table[index].next_rate_index = iwl3945_rates[prev_index].table_rs_index; } - switch (priv->phymode) { - case MODE_IEEE80211A: + switch (priv->band) { + case IEEE80211_BAND_5GHZ: IWL_DEBUG_RATE("Select A mode rate scale\n"); /* If one of the following CCK rates is used, * have it fall back to the 6M OFDM rate */ @@ -2257,8 +2254,8 @@ int iwl3945_init_hw_rate_table(struct iwl3945_priv *priv) iwl3945_rates[IWL_FIRST_OFDM_RATE].table_rs_index; break; - case MODE_IEEE80211B: - IWL_DEBUG_RATE("Select B mode rate scale\n"); + case IEEE80211_BAND_2GHZ: + IWL_DEBUG_RATE("Select B/G mode rate scale\n"); /* If an OFDM rate is used, have it fall back to the * 1M CCK rates */ for (i = IWL_RATE_6M_INDEX_TABLE; i <= IWL_RATE_54M_INDEX_TABLE; i++) @@ -2269,7 +2266,7 @@ int iwl3945_init_hw_rate_table(struct iwl3945_priv *priv) break; default: - IWL_DEBUG_RATE("Select G mode rate scale\n"); + WARN_ON(1); break; } diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 1da14f9bbe0f..1beb5b676797 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -195,7 +195,7 @@ struct iwl3945_channel_info { u8 group_index; /* 0-4, maps channel to group1/2/3/4/5 */ u8 band_index; /* 0-4, maps channel to band1/2/3/4/5 */ - u8 phymode; /* MODE_IEEE80211{A,B,G} */ + enum ieee80211_band band; /* Radio/DSP gain settings for each "normal" data Tx rate. * These include, in addition to RF and DSP gain, a few fields for @@ -699,14 +699,14 @@ struct iwl3945_priv { struct list_head free_frames; int frames_count; - u8 phymode; + enum ieee80211_band band; int alloc_rxb_skb; bool add_radiotap; void (*rx_handlers[REPLY_MAX])(struct iwl3945_priv *priv, struct iwl3945_rx_mem_buffer *rxb); - const struct ieee80211_hw_mode *modes; + struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; #ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT /* spectrum measurement report caching */ @@ -937,13 +937,12 @@ static inline int is_channel_radar(const struct iwl3945_channel_info *ch_info) static inline u8 is_channel_a_band(const struct iwl3945_channel_info *ch_info) { - return ch_info->phymode == MODE_IEEE80211A; + return ch_info->band == IEEE80211_BAND_5GHZ; } static inline u8 is_channel_bg_band(const struct iwl3945_channel_info *ch_info) { - return ((ch_info->phymode == MODE_IEEE80211B) || - (ch_info->phymode == MODE_IEEE80211G)); + return ch_info->band == IEEE80211_BAND_2GHZ; } static inline int is_channel_passive(const struct iwl3945_channel_info *ch) @@ -967,7 +966,7 @@ static inline int iwl3945_rate_index_from_plcp(int plcp) } extern const struct iwl3945_channel_info *iwl3945_get_channel_info( - const struct iwl3945_priv *priv, int phymode, u16 channel); + const struct iwl3945_priv *priv, enum ieee80211_band band, u16 channel); /* Requires full declaration of iwl3945_priv before including */ #include "iwl-3945-io.h" diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c index 660671f17a3b..48a6a85355ec 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c @@ -139,7 +139,7 @@ struct iwl4965_lq_sta { u8 valid_antenna; u8 is_green; u8 is_dup; - u8 phymode; + enum ieee80211_band band; u8 ibss_sta_added; /* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */ @@ -563,7 +563,8 @@ static void rs_mcs_from_tbl(struct iwl4965_rate *mcs_rate, * fill "search" or "active" tx mode table. */ static int rs_get_tbl_info_from_mcs(const struct iwl4965_rate *mcs_rate, - int phymode, struct iwl4965_scale_tbl_info *tbl, + enum ieee80211_band band, + struct iwl4965_scale_tbl_info *tbl, int *rate_idx) { int index; @@ -588,7 +589,7 @@ static int rs_get_tbl_info_from_mcs(const struct iwl4965_rate *mcs_rate, tbl->lq_type = LQ_NONE; else { - if (phymode == MODE_IEEE80211A) + if (band == IEEE80211_BAND_5GHZ) tbl->lq_type = LQ_A; else tbl->lq_type = LQ_G; @@ -766,7 +767,7 @@ static void rs_get_lower_rate(struct iwl4965_lq_sta *lq_sta, if (!is_legacy(tbl->lq_type) && (!ht_possible || !scale_index)) { switch_to_legacy = 1; scale_index = rs_ht_to_legacy[scale_index]; - if (lq_sta->phymode == MODE_IEEE80211A) + if (lq_sta->band == IEEE80211_BAND_5GHZ) tbl->lq_type = LQ_A; else tbl->lq_type = LQ_G; @@ -784,7 +785,7 @@ static void rs_get_lower_rate(struct iwl4965_lq_sta *lq_sta, /* Mask with station rate restriction */ if (is_legacy(tbl->lq_type)) { /* supp_rates has no CCK bits in A mode */ - if (lq_sta->phymode == (u8) MODE_IEEE80211A) + if (lq_sta->band == IEEE80211_BAND_5GHZ) rate_mask = (u16)(rate_mask & (lq_sta->supp_rates << IWL_FIRST_OFDM_RATE)); else @@ -883,9 +884,9 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, search_win = (struct iwl4965_rate_scale_data *) &(search_tbl->win[0]); - tx_mcs.rate_n_flags = tx_resp->control.tx_rate; + tx_mcs.rate_n_flags = tx_resp->control.tx_rate->hw_value; - rs_get_tbl_info_from_mcs(&tx_mcs, priv->phymode, + rs_get_tbl_info_from_mcs(&tx_mcs, priv->band, &tbl_type, &rs_index); if ((rs_index < 0) || (rs_index >= IWL_RATE_COUNT)) { IWL_DEBUG_RATE("bad rate index at: %d rate 0x%X\n", @@ -918,7 +919,7 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, * Each tx attempt steps one entry deeper in the rate table. */ tx_mcs.rate_n_flags = le32_to_cpu(table->rs_table[index].rate_n_flags); - rs_get_tbl_info_from_mcs(&tx_mcs, priv->phymode, + rs_get_tbl_info_from_mcs(&tx_mcs, priv->band, &tbl_type, &rs_index); /* If type matches "search" table, @@ -959,12 +960,12 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, * else look up the rate that was, finally, successful. */ if (!tx_resp->retry_count) - tx_mcs.rate_n_flags = tx_resp->control.tx_rate; + tx_mcs.rate_n_flags = tx_resp->control.tx_rate->hw_value; else tx_mcs.rate_n_flags = le32_to_cpu(table->rs_table[index].rate_n_flags); - rs_get_tbl_info_from_mcs(&tx_mcs, priv->phymode, + rs_get_tbl_info_from_mcs(&tx_mcs, priv->band, &tbl_type, &rs_index); /* Update frame history window with "success" if Tx got ACKed ... */ @@ -1801,7 +1802,7 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv, is_green = lq_sta->is_green; /* current tx rate */ - index = sta->last_txrate; + index = sta->last_txrate_idx; IWL_DEBUG_RATE("Rate scale index %d for type %d\n", index, tbl->lq_type); @@ -1814,7 +1815,7 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv, /* mask with station rate restriction */ if (is_legacy(tbl->lq_type)) { - if (lq_sta->phymode == (u8) MODE_IEEE80211A) + if (lq_sta->band == IEEE80211_BAND_5GHZ) /* supp_rates has no CCK bits in A mode */ rate_scale_index_msk = (u16) (rate_mask & (lq_sta->supp_rates << IWL_FIRST_OFDM_RATE)); @@ -2134,15 +2135,15 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv, out: rs_mcs_from_tbl(&tbl->current_rate, tbl, index, is_green); i = index; - sta->last_txrate = i; + sta->last_txrate_idx = i; - /* sta->txrate is an index to A mode rates which start + /* sta->txrate_idx is an index to A mode rates which start * at IWL_FIRST_OFDM_RATE */ - if (lq_sta->phymode == (u8) MODE_IEEE80211A) - sta->txrate = i - IWL_FIRST_OFDM_RATE; + if (lq_sta->band == IEEE80211_BAND_5GHZ) + sta->txrate_idx = i - IWL_FIRST_OFDM_RATE; else - sta->txrate = i; + sta->txrate_idx = i; return; } @@ -2164,7 +2165,7 @@ static void rs_initialize_lq(struct iwl4965_priv *priv, goto out; lq_sta = (struct iwl4965_lq_sta *)sta->rate_ctrl_priv; - i = sta->last_txrate; + i = sta->last_txrate_idx; if ((lq_sta->lq.sta_id == 0xff) && (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)) @@ -2188,7 +2189,7 @@ static void rs_initialize_lq(struct iwl4965_priv *priv, mcs_rate.rate_n_flags |= RATE_MCS_CCK_MSK; tbl->antenna_type = ANT_AUX; - rs_get_tbl_info_from_mcs(&mcs_rate, priv->phymode, tbl, &rate_idx); + rs_get_tbl_info_from_mcs(&mcs_rate, priv->band, tbl, &rate_idx); if (!rs_is_ant_connected(priv->valid_antenna, tbl->antenna_type)) rs_toggle_antenna(&mcs_rate, tbl); @@ -2202,7 +2203,8 @@ static void rs_initialize_lq(struct iwl4965_priv *priv, } static void rs_get_rate(void *priv_rate, struct net_device *dev, - struct ieee80211_hw_mode *mode, struct sk_buff *skb, + struct ieee80211_supported_band *sband, + struct sk_buff *skb, struct rate_selection *sel) { @@ -2224,14 +2226,14 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, fc = le16_to_cpu(hdr->frame_control); if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1) || !sta || !sta->rate_ctrl_priv) { - sel->rate = rate_lowest(local, local->oper_hw_mode, sta); + sel->rate = rate_lowest(local, sband, sta); if (sta) sta_info_put(sta); return; } lq_sta = (struct iwl4965_lq_sta *)sta->rate_ctrl_priv; - i = sta->last_txrate; + i = sta->last_txrate_idx; if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) && !lq_sta->ibss_sta_added) { @@ -2256,7 +2258,7 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, done: if ((i < 0) || (i > IWL_RATE_COUNT)) { - sel->rate = rate_lowest(local, local->oper_hw_mode, sta); + sel->rate = rate_lowest(local, sband, sta); return; } sta_info_put(sta); @@ -2291,13 +2293,15 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, { int i, j; struct ieee80211_conf *conf = &local->hw.conf; - struct ieee80211_hw_mode *mode = local->oper_hw_mode; + struct ieee80211_supported_band *sband; struct iwl4965_priv *priv = (struct iwl4965_priv *)priv_rate; struct iwl4965_lq_sta *lq_sta = priv_sta; + sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; + lq_sta->flush_timer = 0; - lq_sta->supp_rates = sta->supp_rates; - sta->txrate = 3; + lq_sta->supp_rates = sta->supp_rates[sband->band]; + sta->txrate_idx = 3; for (j = 0; j < LQ_SIZE; j++) for (i = 0; i < IWL_RATE_COUNT; i++) rs_rate_scale_clear_window(&(lq_sta->lq_info[j].win[i])); @@ -2332,15 +2336,15 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, } /* Find highest tx rate supported by hardware and destination station */ - for (i = 0; i < mode->num_rates; i++) { - if ((sta->supp_rates & BIT(i)) && - (mode->rates[i].flags & IEEE80211_RATE_SUPPORTED)) - sta->txrate = i; - } - sta->last_txrate = sta->txrate; + for (i = 0; i < sband->n_bitrates; i++) + if (sta->supp_rates[sband->band] & BIT(i)) + sta->txrate_idx = i; + + sta->last_txrate_idx = sta->txrate_idx; + /* WTF is with this bogus comment? A doesn't have cck rates */ /* For MODE_IEEE80211A, cck rates are at end of rate table */ - if (local->hw.conf.phymode == MODE_IEEE80211A) - sta->last_txrate += IWL_FIRST_OFDM_RATE; + if (local->hw.conf.channel->band == IEEE80211_BAND_5GHZ) + sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; lq_sta->is_dup = 0; lq_sta->valid_antenna = priv->valid_antenna; @@ -2349,7 +2353,7 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, lq_sta->active_rate = priv->active_rate; lq_sta->active_rate &= ~(0x1000); lq_sta->active_rate_basic = priv->active_rate_basic; - lq_sta->phymode = priv->phymode; + lq_sta->band = priv->band; #ifdef CONFIG_IWL4965_HT /* * active_siso_rate mask includes 9 MBits (bit 5), and CCK (bits 0-3), @@ -2401,7 +2405,7 @@ static void rs_fill_link_cmd(struct iwl4965_lq_sta *lq_sta, rs_dbgfs_set_mcs(lq_sta, tx_mcs, index); /* Interpret rate_n_flags */ - rs_get_tbl_info_from_mcs(tx_mcs, lq_sta->phymode, + rs_get_tbl_info_from_mcs(tx_mcs, lq_sta->band, &tbl_type, &rate_idx); /* How many times should we repeat the initial rate? */ @@ -2455,7 +2459,7 @@ static void rs_fill_link_cmd(struct iwl4965_lq_sta *lq_sta, index++; } - rs_get_tbl_info_from_mcs(&new_rate, lq_sta->phymode, &tbl_type, + rs_get_tbl_info_from_mcs(&new_rate, lq_sta->band, &tbl_type, &rate_idx); /* Indicate to uCode which entries might be MIMO. @@ -2542,7 +2546,7 @@ static void rs_dbgfs_set_mcs(struct iwl4965_lq_sta *lq_sta, { u32 base_rate; - if (lq_sta->phymode == (u8) MODE_IEEE80211A) + if (lq_sta->band == IEEE80211_BAND_5GHZ) base_rate = 0x800D; else base_rate = 0x820A; @@ -2802,7 +2806,7 @@ int iwl4965_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id) cnt += sprintf(&buf[cnt], "\nrate scale type %d antenna %d " "active_search %d rate index %d\n", lq_type, antenna, - lq_sta->search_better_tbl, sta->last_txrate); + lq_sta->search_better_tbl, sta->last_txrate_idx); sta_info_put(sta); return cnt; diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 0bded8570275..a89439320498 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -339,14 +339,15 @@ static int iwl4965_kw_alloc(struct iwl4965_priv *priv) * * Does not set up a command, or touch hardware. */ -int iwl4965_set_fat_chan_info(struct iwl4965_priv *priv, int phymode, u16 channel, +int iwl4965_set_fat_chan_info(struct iwl4965_priv *priv, + enum ieee80211_band band, u16 channel, const struct iwl4965_eeprom_channel *eeprom_ch, u8 fat_extension_channel) { struct iwl4965_channel_info *ch_info; ch_info = (struct iwl4965_channel_info *) - iwl4965_get_channel_info(priv, phymode, channel); + iwl4965_get_channel_info(priv, band, channel); if (!is_channel_valid(ch_info)) return -1; @@ -1939,11 +1940,12 @@ static s32 iwl4965_get_voltage_compensation(s32 eeprom_voltage, } static const struct iwl4965_channel_info * -iwl4965_get_channel_txpower_info(struct iwl4965_priv *priv, u8 phymode, u16 channel) +iwl4965_get_channel_txpower_info(struct iwl4965_priv *priv, + enum ieee80211_band band, u16 channel) { const struct iwl4965_channel_info *ch_info; - ch_info = iwl4965_get_channel_info(priv, phymode, channel); + ch_info = iwl4965_get_channel_info(priv, band, channel); if (!is_channel_valid(ch_info)) return NULL; @@ -2392,7 +2394,7 @@ static int iwl4965_fill_txpower_tbl(struct iwl4965_priv *priv, u8 band, u16 chan /* Get current (RXON) channel, band, width */ ch_info = - iwl4965_get_channel_txpower_info(priv, priv->phymode, channel); + iwl4965_get_channel_txpower_info(priv, priv->band, channel); IWL_DEBUG_TXPOWER("chan %d band %d is_fat %d\n", channel, band, is_fat); @@ -2619,8 +2621,7 @@ int iwl4965_hw_reg_send_txpower(struct iwl4965_priv *priv) return -EAGAIN; } - band = ((priv->phymode == MODE_IEEE80211B) || - (priv->phymode == MODE_IEEE80211G)); + band = priv->band == IEEE80211_BAND_2GHZ; is_fat = is_fat_channel(priv->active_rxon.flags); @@ -2650,10 +2651,9 @@ int iwl4965_hw_channel_switch(struct iwl4965_priv *priv, u16 channel) struct iwl4965_channel_switch_cmd cmd = { 0 }; const struct iwl4965_channel_info *ch_info; - band = ((priv->phymode == MODE_IEEE80211B) || - (priv->phymode == MODE_IEEE80211G)); + band = priv->band == IEEE80211_BAND_2GHZ; - ch_info = iwl4965_get_channel_info(priv, priv->phymode, channel); + ch_info = iwl4965_get_channel_info(priv, priv->band, channel); is_fat = is_fat_channel(priv->staging_rxon.flags); @@ -2698,7 +2698,7 @@ void iwl4965_hw_build_tx_cmd_rate(struct iwl4965_priv *priv, u16 fc = le16_to_cpu(hdr->frame_control); u8 rate_plcp; u16 rate_flags = 0; - int rate_idx = min(ctrl->tx_rate & 0xffff, IWL_RATE_COUNT - 1); + int rate_idx = min(ctrl->tx_rate->hw_value & 0xffff, IWL_RATE_COUNT - 1); rate_plcp = iwl4965_rates[rate_idx].plcp; @@ -3178,7 +3178,7 @@ static void iwl4965_add_radiotap(struct iwl4965_priv *priv, { s8 signal = stats->ssi; s8 noise = 0; - int rate = stats->rate; + int rate = stats->rate_idx; u64 tsf = stats->mactime; __le16 phy_flags_hw = rx_start->phy_flags; struct iwl4965_rt_rx_hdr { @@ -3246,7 +3246,6 @@ static void iwl4965_add_radiotap(struct iwl4965_priv *priv, IEEE80211_CHAN_2GHZ), &iwl4965_rt->rt_chbitmask); - rate = iwl4965_rate_index_from_plcp(rate); if (rate == -1) iwl4965_rt->rt_rate = 0; else @@ -3542,12 +3541,13 @@ static void iwl4965_rx_reply_rx(struct iwl4965_priv *priv, u16 fc; struct ieee80211_rx_status stats = { .mactime = le64_to_cpu(rx_start->timestamp), - .channel = le16_to_cpu(rx_start->channel), - .phymode = + .freq = ieee80211chan2mhz(le16_to_cpu(rx_start->channel)), + .band = (rx_start->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? - MODE_IEEE80211G : MODE_IEEE80211A, + IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ, .antenna = 0, - .rate = iwl4965_hw_get_rate(rx_start->rate_n_flags), + .rate_idx = iwl4965_hw_get_rate( + le32_to_cpu(rx_start->rate_n_flags)), .flag = 0, }; u8 network_packet; @@ -3598,8 +3598,6 @@ static void iwl4965_rx_reply_rx(struct iwl4965_priv *priv, priv->ucode_beacon_time = le32_to_cpu(rx_start->beacon_time_stamp); - stats.freq = ieee80211chan2mhz(stats.channel); - /* Find max signal strength (dBm) among 3 antenna/receiver chains */ stats.ssi = iwl4965_calc_rssi(rx_start); @@ -4185,7 +4183,7 @@ void iwl4965_add_station(struct iwl4965_priv *priv, const u8 *addr, int is_ap) * all the way down to 1M in IEEE order, and then spin on 1M */ if (is_ap) r = IWL_RATE_54M_INDEX; - else if (priv->phymode == MODE_IEEE80211A) + else if (priv->band == IEEE80211_BAND_5GHZ) r = IWL_RATE_6M_INDEX; else r = IWL_RATE_1M_INDEX; @@ -4218,12 +4216,13 @@ void iwl4965_add_station(struct iwl4965_priv *priv, const u8 *addr, int is_ap) #ifdef CONFIG_IWL4965_HT -static u8 iwl4965_is_channel_extension(struct iwl4965_priv *priv, int phymode, +static u8 iwl4965_is_channel_extension(struct iwl4965_priv *priv, + enum ieee80211_band band, u16 channel, u8 extension_chan_offset) { const struct iwl4965_channel_info *ch_info; - ch_info = iwl4965_get_channel_info(priv, phymode, channel); + ch_info = iwl4965_get_channel_info(priv, band, channel); if (!is_channel_valid(ch_info)) return 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index de5c1bf8fc42..cb8f7f2a8d48 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -206,7 +206,7 @@ struct iwl4965_channel_info { u8 group_index; /* 0-4, maps channel to group1/2/3/4/5 */ u8 band_index; /* 0-4, maps channel to band1/2/3/4/5 */ - u8 phymode; /* MODE_IEEE80211{A,B,G} */ + enum ieee80211_band band; /* Radio/DSP gain settings for each "normal" data Tx rate. * These include, in addition to RF and DSP gain, a few fields for @@ -764,7 +764,8 @@ extern void iwl4965_update_rate_scaling(struct iwl4965_priv *priv, u8 mode); extern void iwl4965_chain_noise_reset(struct iwl4965_priv *priv); extern void iwl4965_init_sensitivity(struct iwl4965_priv *priv, u8 flags, u8 force); -extern int iwl4965_set_fat_chan_info(struct iwl4965_priv *priv, int phymode, +extern int iwl4965_set_fat_chan_info(struct iwl4965_priv *priv, + enum ieee80211_band band, u16 channel, const struct iwl4965_eeprom_channel *eeprom_ch, u8 fat_extension_channel); @@ -977,14 +978,14 @@ struct iwl4965_priv { struct list_head free_frames; int frames_count; - u8 phymode; + enum ieee80211_band band; int alloc_rxb_skb; bool add_radiotap; void (*rx_handlers[REPLY_MAX])(struct iwl4965_priv *priv, struct iwl4965_rx_mem_buffer *rxb); - const struct ieee80211_hw_mode *modes; + struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; #ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT /* spectrum measurement report caching */ @@ -1243,13 +1244,12 @@ static inline int is_channel_radar(const struct iwl4965_channel_info *ch_info) static inline u8 is_channel_a_band(const struct iwl4965_channel_info *ch_info) { - return ch_info->phymode == MODE_IEEE80211A; + return ch_info->band == IEEE80211_BAND_5GHZ; } static inline u8 is_channel_bg_band(const struct iwl4965_channel_info *ch_info) { - return ((ch_info->phymode == MODE_IEEE80211B) || - (ch_info->phymode == MODE_IEEE80211G)); + return ch_info->band == IEEE80211_BAND_2GHZ; } static inline int is_channel_passive(const struct iwl4965_channel_info *ch) @@ -1263,7 +1263,7 @@ static inline int is_channel_ibss(const struct iwl4965_channel_info *ch) } extern const struct iwl4965_channel_info *iwl4965_get_channel_info( - const struct iwl4965_priv *priv, int phymode, u16 channel); + const struct iwl4965_priv *priv, enum ieee80211_band band, u16 channel); /* Requires full declaration of iwl4965_priv before including */ #include "iwl-4965-io.h" diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 40b71bc2c4a4..57a1d70f2abf 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -116,16 +116,10 @@ static __le16 *ieee80211_get_qos_ctrl(struct ieee80211_hdr *hdr) return NULL; } -static const struct ieee80211_hw_mode *iwl3945_get_hw_mode( - struct iwl3945_priv *priv, int mode) +static const struct ieee80211_supported_band *iwl3945_get_band( + struct iwl3945_priv *priv, enum ieee80211_band band) { - int i; - - for (i = 0; i < 3; i++) - if (priv->modes[i].mode == mode) - return &priv->modes[i]; - - return NULL; + return priv->hw->wiphy->bands[band]; } static int iwl3945_is_empty_essid(const char *essid, int essid_len) @@ -547,7 +541,7 @@ u8 iwl3945_add_station(struct iwl3945_priv *priv, const u8 *addr, int is_ap, u8 station->sta.sta.sta_id = index; station->sta.station_flags = 0; - if (priv->phymode == MODE_IEEE80211A) + if (priv->band == IEEE80211_BAND_5GHZ) rate = IWL_RATE_6M_PLCP; else rate = IWL_RATE_1M_PLCP; @@ -894,35 +888,37 @@ int iwl3945_send_statistics_request(struct iwl3945_priv *priv) /** * iwl3945_set_rxon_channel - Set the phymode and channel values in staging RXON - * @phymode: MODE_IEEE80211A sets to 5.2GHz; all else set to 2.4GHz - * @channel: Any channel valid for the requested phymode + * @band: 2.4 or 5 GHz band + * @channel: Any channel valid for the requested band - * In addition to setting the staging RXON, priv->phymode is also set. + * In addition to setting the staging RXON, priv->band is also set. * * NOTE: Does not commit to the hardware; it sets appropriate bit fields - * in the staging RXON flag structure based on the phymode + * in the staging RXON flag structure based on the band */ -static int iwl3945_set_rxon_channel(struct iwl3945_priv *priv, u8 phymode, u16 channel) +static int iwl3945_set_rxon_channel(struct iwl3945_priv *priv, + enum ieee80211_band band, + u16 channel) { - if (!iwl3945_get_channel_info(priv, phymode, channel)) { + if (!iwl3945_get_channel_info(priv, band, channel)) { IWL_DEBUG_INFO("Could not set channel to %d [%d]\n", - channel, phymode); + channel, band); return -EINVAL; } if ((le16_to_cpu(priv->staging_rxon.channel) == channel) && - (priv->phymode == phymode)) + (priv->band == band)) return 0; priv->staging_rxon.channel = cpu_to_le16(channel); - if (phymode == MODE_IEEE80211A) + if (band == IEEE80211_BAND_5GHZ) priv->staging_rxon.flags &= ~RXON_FLG_BAND_24G_MSK; else priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK; - priv->phymode = phymode; + priv->band = band; - IWL_DEBUG_INFO("Staging channel set to %d [%d]\n", channel, phymode); + IWL_DEBUG_INFO("Staging channel set to %d [%d]\n", channel, band); return 0; } @@ -1210,8 +1206,7 @@ static int iwl3945_commit_rxon(struct iwl3945_priv *priv) return -EIO; } - /* Init the hardware's rate fallback order based on the - * phymode */ + /* Init the hardware's rate fallback order based on the band */ rc = iwl3945_init_hw_rate_table(priv); if (rc) { IWL_ERROR("Error setting HW rate table: %02X\n", rc); @@ -2461,9 +2456,10 @@ static int iwl3945_set_rxon_hwcrypto(struct iwl3945_priv *priv, int hw_decrypt) return 0; } -static void iwl3945_set_flags_for_phymode(struct iwl3945_priv *priv, u8 phymode) +static void iwl3945_set_flags_for_phymode(struct iwl3945_priv *priv, + enum ieee80211_band band) { - if (phymode == MODE_IEEE80211A) { + if (band == IEEE80211_BAND_5GHZ) { priv->staging_rxon.flags &= ~(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_CCK_MSK); @@ -2526,7 +2522,7 @@ static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv) priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; #endif - ch_info = iwl3945_get_channel_info(priv, priv->phymode, + ch_info = iwl3945_get_channel_info(priv, priv->band, le16_to_cpu(priv->staging_rxon.channel)); if (!ch_info) @@ -2542,11 +2538,11 @@ static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv) priv->staging_rxon.channel = cpu_to_le16(ch_info->channel); if (is_channel_a_band(ch_info)) - priv->phymode = MODE_IEEE80211A; + priv->band = IEEE80211_BAND_5GHZ; else - priv->phymode = MODE_IEEE80211G; + priv->band = IEEE80211_BAND_2GHZ; - iwl3945_set_flags_for_phymode(priv, priv->phymode); + iwl3945_set_flags_for_phymode(priv, priv->band); priv->staging_rxon.ofdm_basic_rates = (IWL_OFDM_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; @@ -2560,7 +2556,7 @@ static int iwl3945_set_mode(struct iwl3945_priv *priv, int mode) const struct iwl3945_channel_info *ch_info; ch_info = iwl3945_get_channel_info(priv, - priv->phymode, + priv->band, le16_to_cpu(priv->staging_rxon.channel)); if (!ch_info || !is_channel_ibss(ch_info)) { @@ -2792,7 +2788,7 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, goto drop_unlock; } - if ((ctl->tx_rate & 0xFF) == IWL_INVALID_RATE) { + if ((ctl->tx_rate->hw_value & 0xFF) == IWL_INVALID_RATE) { IWL_ERROR("ERROR: No TX rate available.\n"); goto drop_unlock; } @@ -2992,12 +2988,12 @@ drop: static void iwl3945_set_rate(struct iwl3945_priv *priv) { - const struct ieee80211_hw_mode *hw = NULL; + const struct ieee80211_supported_band *sband = NULL; struct ieee80211_rate *rate; int i; - hw = iwl3945_get_hw_mode(priv, priv->phymode); - if (!hw) { + sband = iwl3945_get_band(priv, priv->band); + if (!sband) { IWL_ERROR("Failed to set rate: unable to get hw mode\n"); return; } @@ -3005,24 +3001,17 @@ static void iwl3945_set_rate(struct iwl3945_priv *priv) priv->active_rate = 0; priv->active_rate_basic = 0; - IWL_DEBUG_RATE("Setting rates for 802.11%c\n", - hw->mode == MODE_IEEE80211A ? - 'a' : ((hw->mode == MODE_IEEE80211B) ? 'b' : 'g')); - - for (i = 0; i < hw->num_rates; i++) { - rate = &(hw->rates[i]); - if ((rate->val < IWL_RATE_COUNT) && - (rate->flags & IEEE80211_RATE_SUPPORTED)) { - IWL_DEBUG_RATE("Adding rate index %d (plcp %d)%s\n", - rate->val, iwl3945_rates[rate->val].plcp, - (rate->flags & IEEE80211_RATE_BASIC) ? - "*" : ""); - priv->active_rate |= (1 << rate->val); - if (rate->flags & IEEE80211_RATE_BASIC) - priv->active_rate_basic |= (1 << rate->val); - } else - IWL_DEBUG_RATE("Not adding rate %d (plcp %d)\n", - rate->val, iwl3945_rates[rate->val].plcp); + IWL_DEBUG_RATE("Setting rates for %s GHz\n", + sband->band == IEEE80211_BAND_2GHZ ? "2.4" : "5"); + + for (i = 0; i < sband->n_bitrates; i++) { + rate = &sband->bitrates[i]; + if ((rate->hw_value < IWL_RATE_COUNT) && + !(rate->flags & IEEE80211_CHAN_DISABLED)) { + IWL_DEBUG_RATE("Adding rate index %d (plcp %d)\n", + rate->hw_value, iwl3945_rates[rate->hw_value].plcp); + priv->active_rate |= (1 << rate->hw_value); + } } IWL_DEBUG_RATE("Set active_rate = %0x, active_rate_basic = %0x\n", @@ -3436,8 +3425,6 @@ static void iwl3945_rx_reply_tx(struct iwl3945_priv *priv, tx_status->flags = iwl3945_is_tx_success(status) ? IEEE80211_TX_STATUS_ACK : 0; - tx_status->control.tx_rate = iwl3945_rate_index_from_plcp(tx_resp->rate); - IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) plcp rate %d retries %d\n", txq_id, iwl3945_get_tx_fail_reason(status), status, tx_resp->rate, tx_resp->failure_frame); @@ -5026,24 +5013,24 @@ static void iwl3945_init_band_reference(const struct iwl3945_priv *priv, int ban * Based on band and channel number. */ const struct iwl3945_channel_info *iwl3945_get_channel_info(const struct iwl3945_priv *priv, - int phymode, u16 channel) + enum ieee80211_band band, u16 channel) { int i; - switch (phymode) { - case MODE_IEEE80211A: + switch (band) { + case IEEE80211_BAND_5GHZ: for (i = 14; i < priv->channel_count; i++) { if (priv->channel_info[i].channel == channel) return &priv->channel_info[i]; } break; - case MODE_IEEE80211B: - case MODE_IEEE80211G: + case IEEE80211_BAND_2GHZ: if (channel >= 1 && channel <= 14) return &priv->channel_info[channel - 1]; break; - + case IEEE80211_NUM_BANDS: + WARN_ON(1); } return NULL; @@ -5106,8 +5093,8 @@ static int iwl3945_init_channel_map(struct iwl3945_priv *priv) /* Loop through each band adding each of the channels */ for (ch = 0; ch < eeprom_ch_count; ch++) { ch_info->channel = eeprom_ch_index[ch]; - ch_info->phymode = (band == 1) ? MODE_IEEE80211B : - MODE_IEEE80211A; + ch_info->band = (band == 1) ? IEEE80211_BAND_2GHZ : + IEEE80211_BAND_5GHZ; /* permanently store EEPROM's channel regulatory flags * and max power in channel info database. */ @@ -5203,18 +5190,20 @@ static void iwl3945_free_channel_map(struct iwl3945_priv *priv) #define IWL_PASSIVE_DWELL_BASE (100) #define IWL_CHANNEL_TUNE_TIME 5 -static inline u16 iwl3945_get_active_dwell_time(struct iwl3945_priv *priv, int phymode) +static inline u16 iwl3945_get_active_dwell_time(struct iwl3945_priv *priv, + enum ieee80211_band band) { - if (phymode == MODE_IEEE80211A) + if (band == IEEE80211_BAND_5GHZ) return IWL_ACTIVE_DWELL_TIME_52; else return IWL_ACTIVE_DWELL_TIME_24; } -static u16 iwl3945_get_passive_dwell_time(struct iwl3945_priv *priv, int phymode) +static u16 iwl3945_get_passive_dwell_time(struct iwl3945_priv *priv, + enum ieee80211_band band) { - u16 active = iwl3945_get_active_dwell_time(priv, phymode); - u16 passive = (phymode != MODE_IEEE80211A) ? + u16 active = iwl3945_get_active_dwell_time(priv, band); + u16 passive = (band == IEEE80211_BAND_2GHZ) ? IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 : IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52; @@ -5234,28 +5223,29 @@ static u16 iwl3945_get_passive_dwell_time(struct iwl3945_priv *priv, int phymode return passive; } -static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv, int phymode, +static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv, + enum ieee80211_band band, u8 is_active, u8 direct_mask, struct iwl3945_scan_channel *scan_ch) { const struct ieee80211_channel *channels = NULL; - const struct ieee80211_hw_mode *hw_mode; + const struct ieee80211_supported_band *sband; const struct iwl3945_channel_info *ch_info; u16 passive_dwell = 0; u16 active_dwell = 0; int added, i; - hw_mode = iwl3945_get_hw_mode(priv, phymode); - if (!hw_mode) + sband = iwl3945_get_band(priv, band); + if (!sband) return 0; - channels = hw_mode->channels; + channels = sband->channels; - active_dwell = iwl3945_get_active_dwell_time(priv, phymode); - passive_dwell = iwl3945_get_passive_dwell_time(priv, phymode); + active_dwell = iwl3945_get_active_dwell_time(priv, band); + passive_dwell = iwl3945_get_passive_dwell_time(priv, band); - for (i = 0, added = 0; i < hw_mode->num_channels; i++) { - if (channels[i].chan == + for (i = 0, added = 0; i < sband->n_channels; i++) { + if (channels[i].hw_value == le16_to_cpu(priv->active_rxon.channel)) { if (iwl3945_is_associated(priv)) { IWL_DEBUG_SCAN @@ -5266,9 +5256,9 @@ static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv, int phymode, } else if (priv->only_active_channel) continue; - scan_ch->channel = channels[i].chan; + scan_ch->channel = channels[i].hw_value; - ch_info = iwl3945_get_channel_info(priv, phymode, scan_ch->channel); + ch_info = iwl3945_get_channel_info(priv, band, scan_ch->channel); if (!is_channel_valid(ch_info)) { IWL_DEBUG_SCAN("Channel %d is INVALID for this SKU.\n", scan_ch->channel); @@ -5276,7 +5266,7 @@ static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv, int phymode, } if (!is_active || is_channel_passive(ch_info) || - !(channels[i].flag & IEEE80211_CHAN_W_ACTIVE_SCAN)) + (channels[i].flags & IEEE80211_CHAN_PASSIVE_SCAN)) scan_ch->type = 0; /* passive */ else scan_ch->type = 1; /* active */ @@ -5295,7 +5285,7 @@ static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv, int phymode, /* scan_pwr_info->tpc.dsp_atten; */ /*scan_pwr_info->tpc.tx_gain; */ - if (phymode == MODE_IEEE80211A) + if (band == IEEE80211_BAND_5GHZ) scan_ch->tpc.tx_gain = ((1 << 5) | (3 << 3)) | 3; else { scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3)); @@ -5319,41 +5309,23 @@ static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv, int phymode, return added; } -static void iwl3945_reset_channel_flag(struct iwl3945_priv *priv) -{ - int i, j; - for (i = 0; i < 3; i++) { - struct ieee80211_hw_mode *hw_mode = (void *)&priv->modes[i]; - for (j = 0; j < hw_mode->num_channels; j++) - hw_mode->channels[j].flag = hw_mode->channels[j].val; - } -} - static void iwl3945_init_hw_rates(struct iwl3945_priv *priv, struct ieee80211_rate *rates) { int i; for (i = 0; i < IWL_RATE_COUNT; i++) { - rates[i].rate = iwl3945_rates[i].ieee * 5; - rates[i].val = i; /* Rate scaling will work on indexes */ - rates[i].val2 = i; - rates[i].flags = IEEE80211_RATE_SUPPORTED; - /* Only OFDM have the bits-per-symbol set */ - if ((i <= IWL_LAST_OFDM_RATE) && (i >= IWL_FIRST_OFDM_RATE)) - rates[i].flags |= IEEE80211_RATE_OFDM; - else { + rates[i].bitrate = iwl3945_rates[i].ieee * 5; + rates[i].hw_value = i; /* Rate scaling will work on indexes */ + rates[i].hw_value_short = i; + rates[i].flags = 0; + if ((i > IWL_LAST_OFDM_RATE) || (i < IWL_FIRST_OFDM_RATE)) { /* - * If CCK 1M then set rate flag to CCK else CCK_2 - * which is CCK | PREAMBLE2 + * If CCK != 1M then set short preamble rate flag. */ rates[i].flags |= (iwl3945_rates[i].plcp == 10) ? - IEEE80211_RATE_CCK : IEEE80211_RATE_CCK_2; + 0 : IEEE80211_RATE_SHORT_PREAMBLE; } - - /* Set up which ones are basic rates... */ - if (IWL_BASIC_RATES_MASK & (1 << i)) - rates[i].flags |= IEEE80211_RATE_BASIC; } } @@ -5363,67 +5335,41 @@ static void iwl3945_init_hw_rates(struct iwl3945_priv *priv, static int iwl3945_init_geos(struct iwl3945_priv *priv) { struct iwl3945_channel_info *ch; - struct ieee80211_hw_mode *modes; + struct ieee80211_supported_band *band; struct ieee80211_channel *channels; struct ieee80211_channel *geo_ch; struct ieee80211_rate *rates; int i = 0; - enum { - A = 0, - B = 1, - G = 2, - }; - int mode_count = 3; - if (priv->modes) { + if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates || + priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) { IWL_DEBUG_INFO("Geography modes already initialized.\n"); set_bit(STATUS_GEO_CONFIGURED, &priv->status); return 0; } - modes = kzalloc(sizeof(struct ieee80211_hw_mode) * mode_count, - GFP_KERNEL); - if (!modes) - return -ENOMEM; - channels = kzalloc(sizeof(struct ieee80211_channel) * priv->channel_count, GFP_KERNEL); - if (!channels) { - kfree(modes); + if (!channels) return -ENOMEM; - } rates = kzalloc((sizeof(struct ieee80211_rate) * (IWL_MAX_RATES + 1)), GFP_KERNEL); if (!rates) { - kfree(modes); kfree(channels); return -ENOMEM; } - /* 0 = 802.11a - * 1 = 802.11b - * 2 = 802.11g - */ - /* 5.2GHz channels start after the 2.4GHz channels */ - modes[A].mode = MODE_IEEE80211A; - modes[A].channels = &channels[ARRAY_SIZE(iwl3945_eeprom_band_1)]; - modes[A].rates = &rates[4]; - modes[A].num_rates = 8; /* just OFDM */ - modes[A].num_channels = 0; - - modes[B].mode = MODE_IEEE80211B; - modes[B].channels = channels; - modes[B].rates = rates; - modes[B].num_rates = 4; /* just CCK */ - modes[B].num_channels = 0; - - modes[G].mode = MODE_IEEE80211G; - modes[G].channels = channels; - modes[G].rates = rates; - modes[G].num_rates = 12; /* OFDM & CCK */ - modes[G].num_channels = 0; + band = &priv->bands[IEEE80211_BAND_5GHZ]; + band->channels = &channels[ARRAY_SIZE(iwl3945_eeprom_band_1)]; + band->bitrates = &rates[4]; + band->n_bitrates = 8; /* just OFDM */ + + band = &priv->bands[IEEE80211_BAND_2GHZ]; + band->channels = channels; + band->bitrates = rates; + band->n_bitrates = 12; /* OFDM & CCK */ priv->ieee_channels = channels; priv->ieee_rates = rates; @@ -5442,37 +5388,32 @@ static int iwl3945_init_geos(struct iwl3945_priv *priv) } if (is_channel_a_band(ch)) - geo_ch = &modes[A].channels[modes[A].num_channels++]; - else { - geo_ch = &modes[B].channels[modes[B].num_channels++]; - modes[G].num_channels++; - } + geo_ch = &priv->bands[IEEE80211_BAND_5GHZ].channels[priv->bands[IEEE80211_BAND_5GHZ].n_channels++]; + else + geo_ch = &priv->bands[IEEE80211_BAND_2GHZ].channels[priv->bands[IEEE80211_BAND_2GHZ].n_channels++]; - geo_ch->freq = ieee80211chan2mhz(ch->channel); - geo_ch->chan = ch->channel; - geo_ch->power_level = ch->max_power_avg; - geo_ch->antenna_max = 0xff; + geo_ch->center_freq = ieee80211chan2mhz(ch->channel); + geo_ch->max_power = ch->max_power_avg; + geo_ch->max_antenna_gain = 0xff; if (is_channel_valid(ch)) { - geo_ch->flag = IEEE80211_CHAN_W_SCAN; - if (ch->flags & EEPROM_CHANNEL_IBSS) - geo_ch->flag |= IEEE80211_CHAN_W_IBSS; + if (!(ch->flags & EEPROM_CHANNEL_IBSS)) + geo_ch->flags |= IEEE80211_CHAN_NO_IBSS; - if (ch->flags & EEPROM_CHANNEL_ACTIVE) - geo_ch->flag |= IEEE80211_CHAN_W_ACTIVE_SCAN; + if (!(ch->flags & EEPROM_CHANNEL_ACTIVE)) + geo_ch->flags |= IEEE80211_CHAN_PASSIVE_SCAN; if (ch->flags & EEPROM_CHANNEL_RADAR) - geo_ch->flag |= IEEE80211_CHAN_W_RADAR_DETECT; + geo_ch->flags |= IEEE80211_CHAN_RADAR; if (ch->max_power_avg > priv->max_channel_txpower_limit) priv->max_channel_txpower_limit = ch->max_power_avg; - } - - geo_ch->val = geo_ch->flag; + } else + geo_ch->flags |= IEEE80211_CHAN_DISABLED; } - if ((modes[A].num_channels == 0) && priv->is_abg) { + if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) && priv->is_abg) { printk(KERN_INFO DRV_NAME ": Incorrectly detected BG card as ABG. Please send " "your PCI ID 0x%04X:0x%04X to maintainer.\n", @@ -5482,24 +5423,12 @@ static int iwl3945_init_geos(struct iwl3945_priv *priv) printk(KERN_INFO DRV_NAME ": Tunable channels: %d 802.11bg, %d 802.11a channels\n", - modes[G].num_channels, modes[A].num_channels); + priv->bands[IEEE80211_BAND_2GHZ].n_channels, + priv->bands[IEEE80211_BAND_5GHZ].n_channels); - /* - * NOTE: We register these in preference of order -- the - * stack doesn't currently (as of 7.0.6 / Apr 24 '07) pick - * a phymode based on rates or AP capabilities but seems to - * configure it purely on if the channel being configured - * is supported by a mode -- and the first match is taken - */ - - if (modes[G].num_channels) - ieee80211_register_hwmode(priv->hw, &modes[G]); - if (modes[B].num_channels) - ieee80211_register_hwmode(priv->hw, &modes[B]); - if (modes[A].num_channels) - ieee80211_register_hwmode(priv->hw, &modes[A]); + priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->bands[IEEE80211_BAND_2GHZ]; + priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &priv->bands[IEEE80211_BAND_5GHZ]; - priv->modes = modes; set_bit(STATUS_GEO_CONFIGURED, &priv->status); return 0; @@ -5510,7 +5439,6 @@ static int iwl3945_init_geos(struct iwl3945_priv *priv) */ static void iwl3945_free_geos(struct iwl3945_priv *priv) { - kfree(priv->modes); kfree(priv->ieee_channels); kfree(priv->ieee_rates); clear_bit(STATUS_GEO_CONFIGURED, &priv->status); @@ -6519,7 +6447,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data) struct iwl3945_scan_cmd *scan; struct ieee80211_conf *conf = NULL; u8 direct_mask; - int phymode; + enum ieee80211_band band; conf = ieee80211_get_hw_conf(priv->hw); @@ -6651,13 +6579,13 @@ static void iwl3945_bg_request_scan(struct work_struct *data) scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK; scan->tx_cmd.rate = IWL_RATE_1M_PLCP; scan->good_CRC_th = 0; - phymode = MODE_IEEE80211G; + band = IEEE80211_BAND_2GHZ; break; case 1: scan->tx_cmd.rate = IWL_RATE_6M_PLCP; scan->good_CRC_th = IWL_GOOD_CRC_TH; - phymode = MODE_IEEE80211A; + band = IEEE80211_BAND_5GHZ; break; default: @@ -6680,7 +6608,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data) scan->channel_count = iwl3945_get_channels_for_scan( - priv, phymode, 1, /* active */ + priv, band, 1, /* active */ direct_mask, (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]); @@ -6825,7 +6753,7 @@ static void iwl3945_bg_post_associate(struct work_struct *data) iwl3945_add_station(priv, iwl3945_broadcast_addr, 0, 0); iwl3945_add_station(priv, priv->bssid, 0, 0); iwl3945_sync_sta(priv, IWL_STA_ID, - (priv->phymode == MODE_IEEE80211A)? + (priv->band == IEEE80211_BAND_5GHZ) ? IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP, CMD_ASYNC); iwl3945_rate_scale_init(priv->hw, IWL_STA_ID); @@ -7020,7 +6948,7 @@ static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb, } IWL_DEBUG_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len, - ctl->tx_rate); + ctl->tx_rate->bitrate); if (iwl3945_tx_skb(priv, skb, ctl)) dev_kfree_skb_any(skb); @@ -7079,7 +7007,7 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co int ret = 0; mutex_lock(&priv->mutex); - IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel); + IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel->hw_value); priv->add_radiotap = !!(conf->flags & IEEE80211_CONF_RADIOTAP); @@ -7099,19 +7027,20 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co spin_lock_irqsave(&priv->lock, flags); - ch_info = iwl3945_get_channel_info(priv, conf->phymode, conf->channel); + ch_info = iwl3945_get_channel_info(priv, conf->channel->band, + conf->channel->hw_value); if (!is_channel_valid(ch_info)) { IWL_DEBUG_SCAN("Channel %d [%d] is INVALID for this SKU.\n", - conf->channel, conf->phymode); + conf->channel->hw_value, conf->channel->band); IWL_DEBUG_MAC80211("leave - invalid channel\n"); spin_unlock_irqrestore(&priv->lock, flags); ret = -EINVAL; goto out; } - iwl3945_set_rxon_channel(priv, conf->phymode, conf->channel); + iwl3945_set_rxon_channel(priv, conf->channel->band, conf->channel->hw_value); - iwl3945_set_flags_for_phymode(priv, conf->phymode); + iwl3945_set_flags_for_phymode(priv, conf->channel->band); /* The list of supported rates and rate mask can be different * for each phymode; since the phymode may have changed, reset @@ -7892,65 +7821,6 @@ static ssize_t store_filter_flags(struct device *d, static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags, store_filter_flags); -static ssize_t show_tune(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data; - - return sprintf(buf, "0x%04X\n", - (priv->phymode << 8) | - le16_to_cpu(priv->active_rxon.channel)); -} - -static void iwl3945_set_flags_for_phymode(struct iwl3945_priv *priv, u8 phymode); - -static ssize_t store_tune(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data; - char *p = (char *)buf; - u16 tune = simple_strtoul(p, &p, 0); - u8 phymode = (tune >> 8) & 0xff; - u16 channel = tune & 0xff; - - IWL_DEBUG_INFO("Tune request to:%d channel:%d\n", phymode, channel); - - mutex_lock(&priv->mutex); - if ((le16_to_cpu(priv->staging_rxon.channel) != channel) || - (priv->phymode != phymode)) { - const struct iwl3945_channel_info *ch_info; - - ch_info = iwl3945_get_channel_info(priv, phymode, channel); - if (!ch_info) { - IWL_WARNING("Requested invalid phymode/channel " - "combination: %d %d\n", phymode, channel); - mutex_unlock(&priv->mutex); - return -EINVAL; - } - - /* Cancel any currently running scans... */ - if (iwl3945_scan_cancel_timeout(priv, 100)) - IWL_WARNING("Could not cancel scan.\n"); - else { - IWL_DEBUG_INFO("Committing phymode and " - "rxon.channel = %d %d\n", - phymode, channel); - - iwl3945_set_rxon_channel(priv, phymode, channel); - iwl3945_set_flags_for_phymode(priv, phymode); - - iwl3945_set_rate(priv); - iwl3945_commit_rxon(priv); - } - } - mutex_unlock(&priv->mutex); - - return count; -} - -static DEVICE_ATTR(tune, S_IWUSR | S_IRUGO, show_tune, store_tune); - #ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT static ssize_t show_measurement(struct device *d, @@ -8165,73 +8035,8 @@ static DEVICE_ATTR(power_level, S_IWUSR | S_IRUSR, show_power_level, static ssize_t show_channels(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl3945_priv *priv = dev_get_drvdata(d); - int len = 0, i; - struct ieee80211_channel *channels = NULL; - const struct ieee80211_hw_mode *hw_mode = NULL; - int count = 0; - - if (!iwl3945_is_ready(priv)) - return -EAGAIN; - - hw_mode = iwl3945_get_hw_mode(priv, MODE_IEEE80211G); - if (!hw_mode) - hw_mode = iwl3945_get_hw_mode(priv, MODE_IEEE80211B); - if (hw_mode) { - channels = hw_mode->channels; - count = hw_mode->num_channels; - } - - len += - sprintf(&buf[len], - "Displaying %d channels in 2.4GHz band " - "(802.11bg):\n", count); - - for (i = 0; i < count; i++) - len += sprintf(&buf[len], "%d: %ddBm: BSS%s%s, %s.\n", - channels[i].chan, - channels[i].power_level, - channels[i]. - flag & IEEE80211_CHAN_W_RADAR_DETECT ? - " (IEEE 802.11h required)" : "", - (!(channels[i].flag & IEEE80211_CHAN_W_IBSS) - || (channels[i]. - flag & - IEEE80211_CHAN_W_RADAR_DETECT)) ? "" : - ", IBSS", - channels[i]. - flag & IEEE80211_CHAN_W_ACTIVE_SCAN ? - "active/passive" : "passive only"); - - hw_mode = iwl3945_get_hw_mode(priv, MODE_IEEE80211A); - if (hw_mode) { - channels = hw_mode->channels; - count = hw_mode->num_channels; - } else { - channels = NULL; - count = 0; - } - - len += sprintf(&buf[len], "Displaying %d channels in 5.2GHz band " - "(802.11a):\n", count); - - for (i = 0; i < count; i++) - len += sprintf(&buf[len], "%d: %ddBm: BSS%s%s, %s.\n", - channels[i].chan, - channels[i].power_level, - channels[i]. - flag & IEEE80211_CHAN_W_RADAR_DETECT ? - " (IEEE 802.11h required)" : "", - (!(channels[i].flag & IEEE80211_CHAN_W_IBSS) - || (channels[i]. - flag & - IEEE80211_CHAN_W_RADAR_DETECT)) ? "" : - ", IBSS", - channels[i]. - flag & IEEE80211_CHAN_W_ACTIVE_SCAN ? - "active/passive" : "passive only"); - - return len; + /* all this shit doesn't belong into sysfs anyway */ + return 0; } static DEVICE_ATTR(channels, S_IRUSR, show_channels, NULL); @@ -8411,7 +8216,6 @@ static struct attribute *iwl3945_sysfs_entries[] = { &dev_attr_statistics.attr, &dev_attr_status.attr, &dev_attr_temperature.attr, - &dev_attr_tune.attr, &dev_attr_tx_power.attr, NULL @@ -8532,7 +8336,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e priv->data_retry_limit = -1; priv->ieee_channels = NULL; priv->ieee_rates = NULL; - priv->phymode = -1; + priv->band = IEEE80211_BAND_2GHZ; err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); if (!err) @@ -8614,7 +8418,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e priv->qos_data.qos_cap.val = 0; #endif /* CONFIG_IWL3945_QOS */ - iwl3945_set_rxon_channel(priv, MODE_IEEE80211G, 6); + iwl3945_set_rxon_channel(priv, IEEE80211_BAND_2GHZ, 6); iwl3945_setup_deferred_work(priv); iwl3945_setup_rx_handlers(priv); @@ -8665,7 +8469,6 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e IWL_ERROR("initializing geos failed: %d\n", err); goto out_free_channel_map; } - iwl3945_reset_channel_flag(priv); iwl3945_rate_control_register(priv->hw); err = ieee80211_register_hw(priv->hw); diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 5f38fc585eda..6de969de4c84 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -115,16 +115,10 @@ __le16 *ieee80211_get_qos_ctrl(struct ieee80211_hdr *hdr) return NULL; } -static const struct ieee80211_hw_mode *iwl4965_get_hw_mode( - struct iwl4965_priv *priv, int mode) +static const struct ieee80211_supported_band *iwl4965_get_hw_mode( + struct iwl4965_priv *priv, enum ieee80211_band band) { - int i; - - for (i = 0; i < 3; i++) - if (priv->modes[i].mode == mode) - return &priv->modes[i]; - - return NULL; + return priv->hw->wiphy->bands[band]; } static int iwl4965_is_empty_essid(const char *essid, int essid_len) @@ -937,28 +931,29 @@ static int iwl4965_rxon_add_station(struct iwl4965_priv *priv, * NOTE: Does not commit to the hardware; it sets appropriate bit fields * in the staging RXON flag structure based on the phymode */ -static int iwl4965_set_rxon_channel(struct iwl4965_priv *priv, u8 phymode, +static int iwl4965_set_rxon_channel(struct iwl4965_priv *priv, + enum ieee80211_band band, u16 channel) { - if (!iwl4965_get_channel_info(priv, phymode, channel)) { + if (!iwl4965_get_channel_info(priv, band, channel)) { IWL_DEBUG_INFO("Could not set channel to %d [%d]\n", - channel, phymode); + channel, band); return -EINVAL; } if ((le16_to_cpu(priv->staging_rxon.channel) == channel) && - (priv->phymode == phymode)) + (priv->band == band)) return 0; priv->staging_rxon.channel = cpu_to_le16(channel); - if (phymode == MODE_IEEE80211A) + if (band == IEEE80211_BAND_5GHZ) priv->staging_rxon.flags &= ~RXON_FLG_BAND_24G_MSK; else priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK; - priv->phymode = phymode; + priv->band = band; - IWL_DEBUG_INFO("Staging channel set to %d [%d]\n", channel, phymode); + IWL_DEBUG_INFO("Staging channel set to %d [%d]\n", channel, band); return 0; } @@ -2571,9 +2566,10 @@ static int iwl4965_set_rxon_hwcrypto(struct iwl4965_priv *priv, int hw_decrypt) return 0; } -static void iwl4965_set_flags_for_phymode(struct iwl4965_priv *priv, u8 phymode) +static void iwl4965_set_flags_for_phymode(struct iwl4965_priv *priv, + enum ieee80211_band band) { - if (phymode == MODE_IEEE80211A) { + if (band == IEEE80211_BAND_5GHZ) { priv->staging_rxon.flags &= ~(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_CCK_MSK); @@ -2636,7 +2632,7 @@ static void iwl4965_connection_init_rx_config(struct iwl4965_priv *priv) priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; #endif - ch_info = iwl4965_get_channel_info(priv, priv->phymode, + ch_info = iwl4965_get_channel_info(priv, priv->band, le16_to_cpu(priv->staging_rxon.channel)); if (!ch_info) @@ -2651,12 +2647,9 @@ static void iwl4965_connection_init_rx_config(struct iwl4965_priv *priv) ch_info = &priv->channel_info[0]; priv->staging_rxon.channel = cpu_to_le16(ch_info->channel); - if (is_channel_a_band(ch_info)) - priv->phymode = MODE_IEEE80211A; - else - priv->phymode = MODE_IEEE80211G; + priv->band = ch_info->band; - iwl4965_set_flags_for_phymode(priv, priv->phymode); + iwl4965_set_flags_for_phymode(priv, priv->band); priv->staging_rxon.ofdm_basic_rates = (IWL_OFDM_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; @@ -2678,7 +2671,7 @@ static int iwl4965_set_mode(struct iwl4965_priv *priv, int mode) const struct iwl4965_channel_info *ch_info; ch_info = iwl4965_get_channel_info(priv, - priv->phymode, + priv->band, le16_to_cpu(priv->staging_rxon.channel)); if (!ch_info || !is_channel_ibss(ch_info)) { @@ -2918,7 +2911,7 @@ static int iwl4965_tx_skb(struct iwl4965_priv *priv, goto drop_unlock; } - if ((ctl->tx_rate & 0xFF) == IWL_INVALID_RATE) { + if ((ctl->tx_rate->hw_value & 0xFF) == IWL_INVALID_RATE) { IWL_ERROR("ERROR: No TX rate available.\n"); goto drop_unlock; } @@ -3125,11 +3118,11 @@ drop: static void iwl4965_set_rate(struct iwl4965_priv *priv) { - const struct ieee80211_hw_mode *hw = NULL; + const struct ieee80211_supported_band *hw = NULL; struct ieee80211_rate *rate; int i; - hw = iwl4965_get_hw_mode(priv, priv->phymode); + hw = iwl4965_get_hw_mode(priv, priv->band); if (!hw) { IWL_ERROR("Failed to set rate: unable to get hw mode\n"); return; @@ -3138,24 +3131,10 @@ static void iwl4965_set_rate(struct iwl4965_priv *priv) priv->active_rate = 0; priv->active_rate_basic = 0; - IWL_DEBUG_RATE("Setting rates for 802.11%c\n", - hw->mode == MODE_IEEE80211A ? - 'a' : ((hw->mode == MODE_IEEE80211B) ? 'b' : 'g')); - - for (i = 0; i < hw->num_rates; i++) { - rate = &(hw->rates[i]); - if ((rate->val < IWL_RATE_COUNT) && - (rate->flags & IEEE80211_RATE_SUPPORTED)) { - IWL_DEBUG_RATE("Adding rate index %d (plcp %d)%s\n", - rate->val, iwl4965_rates[rate->val].plcp, - (rate->flags & IEEE80211_RATE_BASIC) ? - "*" : ""); - priv->active_rate |= (1 << rate->val); - if (rate->flags & IEEE80211_RATE_BASIC) - priv->active_rate_basic |= (1 << rate->val); - } else - IWL_DEBUG_RATE("Not adding rate %d (plcp %d)\n", - rate->val, iwl4965_rates[rate->val].plcp); + for (i = 0; i < hw->n_bitrates; i++) { + rate = &(hw->bitrates[i]); + if (rate->hw_value < IWL_RATE_COUNT) + priv->active_rate |= (1 << rate->hw_value); } IWL_DEBUG_RATE("Set active_rate = %0x, active_rate_basic = %0x\n", @@ -3775,9 +3754,6 @@ static void iwl4965_rx_reply_tx(struct iwl4965_priv *priv, tx_status->flags = iwl4965_is_tx_success(status) ? IEEE80211_TX_STATUS_ACK : 0; - tx_status->control.tx_rate = - iwl4965_hw_get_rate_n_flags(tx_resp->rate_n_flags); - IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) rate_n_flags 0x%x " "retries %d\n", txq_id, iwl4965_get_tx_fail_reason(status), status, le32_to_cpu(tx_resp->rate_n_flags), @@ -5419,24 +5395,23 @@ static void iwl4965_init_band_reference(const struct iwl4965_priv *priv, * Based on band and channel number. */ const struct iwl4965_channel_info *iwl4965_get_channel_info(const struct iwl4965_priv *priv, - int phymode, u16 channel) + enum ieee80211_band band, u16 channel) { int i; - switch (phymode) { - case MODE_IEEE80211A: + switch (band) { + case IEEE80211_BAND_5GHZ: for (i = 14; i < priv->channel_count; i++) { if (priv->channel_info[i].channel == channel) return &priv->channel_info[i]; } break; - - case MODE_IEEE80211B: - case MODE_IEEE80211G: + case IEEE80211_BAND_2GHZ: if (channel >= 1 && channel <= 14) return &priv->channel_info[channel - 1]; break; - + default: + BUG(); } return NULL; @@ -5499,8 +5474,8 @@ static int iwl4965_init_channel_map(struct iwl4965_priv *priv) /* Loop through each band adding each of the channels */ for (ch = 0; ch < eeprom_ch_count; ch++) { ch_info->channel = eeprom_ch_index[ch]; - ch_info->phymode = (band == 1) ? MODE_IEEE80211B : - MODE_IEEE80211A; + ch_info->band = (band == 1) ? IEEE80211_BAND_2GHZ : + IEEE80211_BAND_5GHZ; /* permanently store EEPROM's channel regulatory flags * and max power in channel info database. */ @@ -5559,14 +5534,14 @@ static int iwl4965_init_channel_map(struct iwl4965_priv *priv) /* Two additional EEPROM bands for 2.4 and 5 GHz FAT channels */ for (band = 6; band <= 7; band++) { - int phymode; + enum ieee80211_band ieeeband; u8 fat_extension_chan; iwl4965_init_band_reference(priv, band, &eeprom_ch_count, &eeprom_ch_info, &eeprom_ch_index); /* EEPROM band 6 is 2.4, band 7 is 5 GHz */ - phymode = (band == 6) ? MODE_IEEE80211B : MODE_IEEE80211A; + ieeeband = (band == 6) ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; /* Loop through each band adding each of the channels */ for (ch = 0; ch < eeprom_ch_count; ch++) { @@ -5580,13 +5555,13 @@ static int iwl4965_init_channel_map(struct iwl4965_priv *priv) fat_extension_chan = HT_IE_EXT_CHANNEL_ABOVE; /* Set up driver's info for lower half */ - iwl4965_set_fat_chan_info(priv, phymode, + iwl4965_set_fat_chan_info(priv, ieeeband, eeprom_ch_index[ch], &(eeprom_ch_info[ch]), fat_extension_chan); /* Set up driver's info for upper half */ - iwl4965_set_fat_chan_info(priv, phymode, + iwl4965_set_fat_chan_info(priv, ieeeband, (eeprom_ch_index[ch] + 4), &(eeprom_ch_info[ch]), HT_IE_EXT_CHANNEL_BELOW); @@ -5628,18 +5603,20 @@ static void iwl4965_free_channel_map(struct iwl4965_priv *priv) #define IWL_PASSIVE_DWELL_BASE (100) #define IWL_CHANNEL_TUNE_TIME 5 -static inline u16 iwl4965_get_active_dwell_time(struct iwl4965_priv *priv, int phymode) +static inline u16 iwl4965_get_active_dwell_time(struct iwl4965_priv *priv, + enum ieee80211_band band) { - if (phymode == MODE_IEEE80211A) + if (band == IEEE80211_BAND_5GHZ) return IWL_ACTIVE_DWELL_TIME_52; else return IWL_ACTIVE_DWELL_TIME_24; } -static u16 iwl4965_get_passive_dwell_time(struct iwl4965_priv *priv, int phymode) +static u16 iwl4965_get_passive_dwell_time(struct iwl4965_priv *priv, + enum ieee80211_band band) { - u16 active = iwl4965_get_active_dwell_time(priv, phymode); - u16 passive = (phymode != MODE_IEEE80211A) ? + u16 active = iwl4965_get_active_dwell_time(priv, band); + u16 passive = (band != IEEE80211_BAND_5GHZ) ? IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 : IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52; @@ -5659,28 +5636,29 @@ static u16 iwl4965_get_passive_dwell_time(struct iwl4965_priv *priv, int phymode return passive; } -static int iwl4965_get_channels_for_scan(struct iwl4965_priv *priv, int phymode, +static int iwl4965_get_channels_for_scan(struct iwl4965_priv *priv, + enum ieee80211_band band, u8 is_active, u8 direct_mask, struct iwl4965_scan_channel *scan_ch) { const struct ieee80211_channel *channels = NULL; - const struct ieee80211_hw_mode *hw_mode; + const struct ieee80211_supported_band *sband; const struct iwl4965_channel_info *ch_info; u16 passive_dwell = 0; u16 active_dwell = 0; int added, i; - hw_mode = iwl4965_get_hw_mode(priv, phymode); - if (!hw_mode) + sband = iwl4965_get_hw_mode(priv, band); + if (!sband) return 0; - channels = hw_mode->channels; + channels = sband->channels; - active_dwell = iwl4965_get_active_dwell_time(priv, phymode); - passive_dwell = iwl4965_get_passive_dwell_time(priv, phymode); + active_dwell = iwl4965_get_active_dwell_time(priv, band); + passive_dwell = iwl4965_get_passive_dwell_time(priv, band); - for (i = 0, added = 0; i < hw_mode->num_channels; i++) { - if (channels[i].chan == + for (i = 0, added = 0; i < sband->n_channels; i++) { + if (ieee80211_frequency_to_channel(channels[i].center_freq) == le16_to_cpu(priv->active_rxon.channel)) { if (iwl4965_is_associated(priv)) { IWL_DEBUG_SCAN @@ -5691,9 +5669,9 @@ static int iwl4965_get_channels_for_scan(struct iwl4965_priv *priv, int phymode, } else if (priv->only_active_channel) continue; - scan_ch->channel = channels[i].chan; + scan_ch->channel = ieee80211_frequency_to_channel(channels[i].center_freq); - ch_info = iwl4965_get_channel_info(priv, phymode, + ch_info = iwl4965_get_channel_info(priv, band, scan_ch->channel); if (!is_channel_valid(ch_info)) { IWL_DEBUG_SCAN("Channel %d is INVALID for this SKU.\n", @@ -5702,7 +5680,7 @@ static int iwl4965_get_channels_for_scan(struct iwl4965_priv *priv, int phymode, } if (!is_active || is_channel_passive(ch_info) || - !(channels[i].flag & IEEE80211_CHAN_W_ACTIVE_SCAN)) + (channels[i].flags & IEEE80211_CHAN_PASSIVE_SCAN)) scan_ch->type = 0; /* passive */ else scan_ch->type = 1; /* active */ @@ -5721,7 +5699,7 @@ static int iwl4965_get_channels_for_scan(struct iwl4965_priv *priv, int phymode, /* scan_pwr_info->tpc.dsp_atten; */ /*scan_pwr_info->tpc.tx_gain; */ - if (phymode == MODE_IEEE80211A) + if (band == IEEE80211_BAND_5GHZ) scan_ch->tpc.tx_gain = ((1 << 5) | (3 << 3)) | 3; else { scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3)); @@ -5745,41 +5723,23 @@ static int iwl4965_get_channels_for_scan(struct iwl4965_priv *priv, int phymode, return added; } -static void iwl4965_reset_channel_flag(struct iwl4965_priv *priv) -{ - int i, j; - for (i = 0; i < 3; i++) { - struct ieee80211_hw_mode *hw_mode = (void *)&priv->modes[i]; - for (j = 0; j < hw_mode->num_channels; j++) - hw_mode->channels[j].flag = hw_mode->channels[j].val; - } -} - static void iwl4965_init_hw_rates(struct iwl4965_priv *priv, struct ieee80211_rate *rates) { int i; for (i = 0; i < IWL_RATE_COUNT; i++) { - rates[i].rate = iwl4965_rates[i].ieee * 5; - rates[i].val = i; /* Rate scaling will work on indexes */ - rates[i].val2 = i; - rates[i].flags = IEEE80211_RATE_SUPPORTED; - /* Only OFDM have the bits-per-symbol set */ - if ((i <= IWL_LAST_OFDM_RATE) && (i >= IWL_FIRST_OFDM_RATE)) - rates[i].flags |= IEEE80211_RATE_OFDM; - else { + rates[i].bitrate = iwl4965_rates[i].ieee * 5; + rates[i].hw_value = i; /* Rate scaling will work on indexes */ + rates[i].hw_value_short = i; + rates[i].flags = 0; + if ((i > IWL_LAST_OFDM_RATE) || (i < IWL_FIRST_OFDM_RATE)) { /* - * If CCK 1M then set rate flag to CCK else CCK_2 - * which is CCK | PREAMBLE2 + * If CCK != 1M then set short preamble rate flag. */ rates[i].flags |= (iwl4965_rates[i].plcp == 10) ? - IEEE80211_RATE_CCK : IEEE80211_RATE_CCK_2; + 0 : IEEE80211_RATE_SHORT_PREAMBLE; } - - /* Set up which ones are basic rates... */ - if (IWL_BASIC_RATES_MASK & (1 << i)) - rates[i].flags |= IEEE80211_RATE_BASIC; } } @@ -5789,74 +5749,47 @@ static void iwl4965_init_hw_rates(struct iwl4965_priv *priv, static int iwl4965_init_geos(struct iwl4965_priv *priv) { struct iwl4965_channel_info *ch; - struct ieee80211_hw_mode *modes; + struct ieee80211_supported_band *band; struct ieee80211_channel *channels; struct ieee80211_channel *geo_ch; struct ieee80211_rate *rates; int i = 0; - enum { - A = 0, - B = 1, - G = 2, - }; - int mode_count = 3; - if (priv->modes) { + if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates || + priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) { IWL_DEBUG_INFO("Geography modes already initialized.\n"); set_bit(STATUS_GEO_CONFIGURED, &priv->status); return 0; } - modes = kzalloc(sizeof(struct ieee80211_hw_mode) * mode_count, - GFP_KERNEL); - if (!modes) - return -ENOMEM; - channels = kzalloc(sizeof(struct ieee80211_channel) * priv->channel_count, GFP_KERNEL); - if (!channels) { - kfree(modes); + if (!channels) return -ENOMEM; - } rates = kzalloc((sizeof(struct ieee80211_rate) * (IWL_MAX_RATES + 1)), GFP_KERNEL); if (!rates) { - kfree(modes); kfree(channels); return -ENOMEM; } - /* 0 = 802.11a - * 1 = 802.11b - * 2 = 802.11g - */ - /* 5.2GHz channels start after the 2.4GHz channels */ - modes[A].mode = MODE_IEEE80211A; - modes[A].channels = &channels[ARRAY_SIZE(iwl4965_eeprom_band_1)]; - modes[A].rates = rates; - modes[A].num_rates = 8; /* just OFDM */ - modes[A].rates = &rates[4]; - modes[A].num_channels = 0; #ifdef CONFIG_IWL4965_HT iwl4965_init_ht_hw_capab(&modes[A].ht_info, MODE_IEEE80211A); #endif - - modes[B].mode = MODE_IEEE80211B; - modes[B].channels = channels; - modes[B].rates = rates; - modes[B].num_rates = 4; /* just CCK */ - modes[B].num_channels = 0; - - modes[G].mode = MODE_IEEE80211G; - modes[G].channels = channels; - modes[G].rates = rates; - modes[G].num_rates = 12; /* OFDM & CCK */ - modes[G].num_channels = 0; #ifdef CONFIG_IWL4965_HT iwl4965_init_ht_hw_capab(&modes[G].ht_info, MODE_IEEE80211G); #endif + band = &priv->bands[IEEE80211_BAND_5GHZ]; + band->channels = &channels[ARRAY_SIZE(iwl4965_eeprom_band_1)]; + band->bitrates = &rates[4]; + band->n_bitrates = 8; /* just OFDM */ + + band = &priv->bands[IEEE80211_BAND_2GHZ]; + band->channels = channels; + band->bitrates = rates; + band->n_bitrates = 12; /* OFDM & CCK */ priv->ieee_channels = channels; priv->ieee_rates = rates; @@ -5875,37 +5808,32 @@ static int iwl4965_init_geos(struct iwl4965_priv *priv) } if (is_channel_a_band(ch)) { - geo_ch = &modes[A].channels[modes[A].num_channels++]; - } else { - geo_ch = &modes[B].channels[modes[B].num_channels++]; - modes[G].num_channels++; - } + geo_ch = &priv->bands[IEEE80211_BAND_5GHZ].channels[priv->bands[IEEE80211_BAND_5GHZ].n_channels++]; + } else + geo_ch = &priv->bands[IEEE80211_BAND_2GHZ].channels[priv->bands[IEEE80211_BAND_2GHZ].n_channels++]; - geo_ch->freq = ieee80211chan2mhz(ch->channel); - geo_ch->chan = ch->channel; - geo_ch->power_level = ch->max_power_avg; - geo_ch->antenna_max = 0xff; + geo_ch->center_freq = ieee80211chan2mhz(ch->channel); + geo_ch->max_power = ch->max_power_avg; + geo_ch->max_antenna_gain = 0xff; if (is_channel_valid(ch)) { - geo_ch->flag = IEEE80211_CHAN_W_SCAN; - if (ch->flags & EEPROM_CHANNEL_IBSS) - geo_ch->flag |= IEEE80211_CHAN_W_IBSS; + if (!(ch->flags & EEPROM_CHANNEL_IBSS)) + geo_ch->flags |= IEEE80211_CHAN_NO_IBSS; - if (ch->flags & EEPROM_CHANNEL_ACTIVE) - geo_ch->flag |= IEEE80211_CHAN_W_ACTIVE_SCAN; + if (!(ch->flags & EEPROM_CHANNEL_ACTIVE)) + geo_ch->flags |= IEEE80211_CHAN_PASSIVE_SCAN; if (ch->flags & EEPROM_CHANNEL_RADAR) - geo_ch->flag |= IEEE80211_CHAN_W_RADAR_DETECT; + geo_ch->flags |= IEEE80211_CHAN_RADAR; if (ch->max_power_avg > priv->max_channel_txpower_limit) priv->max_channel_txpower_limit = ch->max_power_avg; - } - - geo_ch->val = geo_ch->flag; + } else + geo_ch->flags |= IEEE80211_CHAN_DISABLED; } - if ((modes[A].num_channels == 0) && priv->is_abg) { + if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) && priv->is_abg) { printk(KERN_INFO DRV_NAME ": Incorrectly detected BG card as ABG. Please send " "your PCI ID 0x%04X:0x%04X to maintainer.\n", @@ -5915,24 +5843,12 @@ static int iwl4965_init_geos(struct iwl4965_priv *priv) printk(KERN_INFO DRV_NAME ": Tunable channels: %d 802.11bg, %d 802.11a channels\n", - modes[G].num_channels, modes[A].num_channels); - - /* - * NOTE: We register these in preference of order -- the - * stack doesn't currently (as of 7.0.6 / Apr 24 '07) pick - * a phymode based on rates or AP capabilities but seems to - * configure it purely on if the channel being configured - * is supported by a mode -- and the first match is taken - */ + priv->bands[IEEE80211_BAND_2GHZ].n_channels, + priv->bands[IEEE80211_BAND_5GHZ].n_channels); - if (modes[G].num_channels) - ieee80211_register_hwmode(priv->hw, &modes[G]); - if (modes[B].num_channels) - ieee80211_register_hwmode(priv->hw, &modes[B]); - if (modes[A].num_channels) - ieee80211_register_hwmode(priv->hw, &modes[A]); + priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->bands[IEEE80211_BAND_2GHZ]; + priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &priv->bands[IEEE80211_BAND_5GHZ]; - priv->modes = modes; set_bit(STATUS_GEO_CONFIGURED, &priv->status); return 0; @@ -5943,7 +5859,6 @@ static int iwl4965_init_geos(struct iwl4965_priv *priv) */ static void iwl4965_free_geos(struct iwl4965_priv *priv) { - kfree(priv->modes); kfree(priv->ieee_channels); kfree(priv->ieee_rates); clear_bit(STATUS_GEO_CONFIGURED, &priv->status); @@ -6945,7 +6860,7 @@ static void iwl4965_bg_request_scan(struct work_struct *data) struct iwl4965_scan_cmd *scan; struct ieee80211_conf *conf = NULL; u8 direct_mask; - int phymode; + enum ieee80211_band band; conf = ieee80211_get_hw_conf(priv->hw); @@ -7075,7 +6990,7 @@ static void iwl4965_bg_request_scan(struct work_struct *data) RATE_MCS_ANT_B_MSK|RATE_MCS_CCK_MSK); scan->good_CRC_th = 0; - phymode = MODE_IEEE80211G; + band = IEEE80211_BAND_2GHZ; break; case 1: @@ -7083,7 +6998,7 @@ static void iwl4965_bg_request_scan(struct work_struct *data) iwl4965_hw_set_rate_n_flags(IWL_RATE_6M_PLCP, RATE_MCS_ANT_B_MSK); scan->good_CRC_th = IWL_GOOD_CRC_TH; - phymode = MODE_IEEE80211A; + band = IEEE80211_BAND_5GHZ; break; default: @@ -7113,7 +7028,7 @@ static void iwl4965_bg_request_scan(struct work_struct *data) scan->channel_count = iwl4965_get_channels_for_scan( - priv, phymode, 1, /* active */ + priv, band, 1, /* active */ direct_mask, (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]); @@ -7463,7 +7378,7 @@ static int iwl4965_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb, } IWL_DEBUG_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len, - ctl->tx_rate); + ctl->tx_rate->bitrate); if (iwl4965_tx_skb(priv, skb, ctl)) dev_kfree_skb_any(skb); @@ -7522,7 +7437,7 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co int ret = 0; mutex_lock(&priv->mutex); - IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel); + IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel->hw_value); priv->add_radiotap = !!(conf->flags & IEEE80211_CONF_RADIOTAP); @@ -7542,10 +7457,9 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co spin_lock_irqsave(&priv->lock, flags); - ch_info = iwl4965_get_channel_info(priv, conf->phymode, conf->channel); + ch_info = iwl4965_get_channel_info(priv, conf->channel->band, + ieee80211_frequency_to_channel(conf->channel->center_freq)); if (!is_channel_valid(ch_info)) { - IWL_DEBUG_SCAN("Channel %d [%d] is INVALID for this SKU.\n", - conf->channel, conf->phymode); IWL_DEBUG_MAC80211("leave - invalid channel\n"); spin_unlock_irqrestore(&priv->lock, flags); ret = -EINVAL; @@ -7564,12 +7478,13 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co priv->staging_rxon.flags = 0; #endif /* CONFIG_IWL4965_HT */ - iwl4965_set_rxon_channel(priv, conf->phymode, conf->channel); + iwl4965_set_rxon_channel(priv, conf->channel->band, + ieee80211_frequency_to_channel(conf->channel->center_freq)); - iwl4965_set_flags_for_phymode(priv, conf->phymode); + iwl4965_set_flags_for_phymode(priv, conf->channel->band); /* The list of supported rates and rate mask can be different - * for each phymode; since the phymode may have changed, reset + * for each band; since the band may have changed, reset * the rate mask to what mac80211 lists */ iwl4965_set_rate(priv); @@ -7839,7 +7754,7 @@ static void iwl4965_bss_info_changed(struct ieee80211_hw *hw, } if (changes & BSS_CHANGED_ERP_CTS_PROT) { - if (bss_conf->use_cts_prot && (priv->phymode != MODE_IEEE80211A)) + if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ)) priv->staging_rxon.flags |= RXON_FLG_TGG_PROTECT_MSK; else priv->staging_rxon.flags &= ~RXON_FLG_TGG_PROTECT_MSK; @@ -8277,7 +8192,6 @@ static void iwl4965_set_ht_capab(struct ieee80211_hw *hw, u8 use_current_config) { struct ieee80211_conf *conf = &hw->conf; - struct ieee80211_hw_mode *mode = conf->mode; if (use_current_config) { ht_cap->cap_info = cpu_to_le16(conf->ht_conf.cap); @@ -8488,65 +8402,6 @@ static ssize_t store_filter_flags(struct device *d, static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags, store_filter_flags); -static ssize_t show_tune(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data; - - return sprintf(buf, "0x%04X\n", - (priv->phymode << 8) | - le16_to_cpu(priv->active_rxon.channel)); -} - -static void iwl4965_set_flags_for_phymode(struct iwl4965_priv *priv, u8 phymode); - -static ssize_t store_tune(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data; - char *p = (char *)buf; - u16 tune = simple_strtoul(p, &p, 0); - u8 phymode = (tune >> 8) & 0xff; - u16 channel = tune & 0xff; - - IWL_DEBUG_INFO("Tune request to:%d channel:%d\n", phymode, channel); - - mutex_lock(&priv->mutex); - if ((le16_to_cpu(priv->staging_rxon.channel) != channel) || - (priv->phymode != phymode)) { - const struct iwl4965_channel_info *ch_info; - - ch_info = iwl4965_get_channel_info(priv, phymode, channel); - if (!ch_info) { - IWL_WARNING("Requested invalid phymode/channel " - "combination: %d %d\n", phymode, channel); - mutex_unlock(&priv->mutex); - return -EINVAL; - } - - /* Cancel any currently running scans... */ - if (iwl4965_scan_cancel_timeout(priv, 100)) - IWL_WARNING("Could not cancel scan.\n"); - else { - IWL_DEBUG_INFO("Committing phymode and " - "rxon.channel = %d %d\n", - phymode, channel); - - iwl4965_set_rxon_channel(priv, phymode, channel); - iwl4965_set_flags_for_phymode(priv, phymode); - - iwl4965_set_rate(priv); - iwl4965_commit_rxon(priv); - } - } - mutex_unlock(&priv->mutex); - - return count; -} - -static DEVICE_ATTR(tune, S_IWUSR | S_IRUGO, show_tune, store_tune); - #ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT static ssize_t show_measurement(struct device *d, @@ -8736,73 +8591,8 @@ static DEVICE_ATTR(power_level, S_IWUSR | S_IRUSR, show_power_level, static ssize_t show_channels(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl4965_priv *priv = dev_get_drvdata(d); - int len = 0, i; - struct ieee80211_channel *channels = NULL; - const struct ieee80211_hw_mode *hw_mode = NULL; - int count = 0; - - if (!iwl4965_is_ready(priv)) - return -EAGAIN; - - hw_mode = iwl4965_get_hw_mode(priv, MODE_IEEE80211G); - if (!hw_mode) - hw_mode = iwl4965_get_hw_mode(priv, MODE_IEEE80211B); - if (hw_mode) { - channels = hw_mode->channels; - count = hw_mode->num_channels; - } - - len += - sprintf(&buf[len], - "Displaying %d channels in 2.4GHz band " - "(802.11bg):\n", count); - - for (i = 0; i < count; i++) - len += sprintf(&buf[len], "%d: %ddBm: BSS%s%s, %s.\n", - channels[i].chan, - channels[i].power_level, - channels[i]. - flag & IEEE80211_CHAN_W_RADAR_DETECT ? - " (IEEE 802.11h required)" : "", - (!(channels[i].flag & IEEE80211_CHAN_W_IBSS) - || (channels[i]. - flag & - IEEE80211_CHAN_W_RADAR_DETECT)) ? "" : - ", IBSS", - channels[i]. - flag & IEEE80211_CHAN_W_ACTIVE_SCAN ? - "active/passive" : "passive only"); - - hw_mode = iwl4965_get_hw_mode(priv, MODE_IEEE80211A); - if (hw_mode) { - channels = hw_mode->channels; - count = hw_mode->num_channels; - } else { - channels = NULL; - count = 0; - } - - len += sprintf(&buf[len], "Displaying %d channels in 5.2GHz band " - "(802.11a):\n", count); - - for (i = 0; i < count; i++) - len += sprintf(&buf[len], "%d: %ddBm: BSS%s%s, %s.\n", - channels[i].chan, - channels[i].power_level, - channels[i]. - flag & IEEE80211_CHAN_W_RADAR_DETECT ? - " (IEEE 802.11h required)" : "", - (!(channels[i].flag & IEEE80211_CHAN_W_IBSS) - || (channels[i]. - flag & - IEEE80211_CHAN_W_RADAR_DETECT)) ? "" : - ", IBSS", - channels[i]. - flag & IEEE80211_CHAN_W_ACTIVE_SCAN ? - "active/passive" : "passive only"); - - return len; + /* all this shit doesn't belong into sysfs anyway */ + return 0; } static DEVICE_ATTR(channels, S_IRUSR, show_channels, NULL); @@ -8981,7 +8771,6 @@ static struct attribute *iwl4965_sysfs_entries[] = { &dev_attr_statistics.attr, &dev_attr_status.attr, &dev_attr_temperature.attr, - &dev_attr_tune.attr, &dev_attr_tx_power.attr, NULL @@ -9109,7 +8898,7 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e priv->data_retry_limit = -1; priv->ieee_channels = NULL; priv->ieee_rates = NULL; - priv->phymode = -1; + priv->band = IEEE80211_BAND_2GHZ; err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); if (!err) @@ -9175,7 +8964,7 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e priv->qos_data.qos_cap.val = 0; #endif /* CONFIG_IWL4965_QOS */ - iwl4965_set_rxon_channel(priv, MODE_IEEE80211G, 6); + iwl4965_set_rxon_channel(priv, IEEE80211_BAND_2GHZ, 6); iwl4965_setup_deferred_work(priv); iwl4965_setup_rx_handlers(priv); @@ -9226,7 +9015,6 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e IWL_ERROR("initializing geos failed: %d\n", err); goto out_free_channel_map; } - iwl4965_reset_channel_flag(priv); iwl4965_rate_control_register(priv->hw); err = ieee80211_register_hw(priv->hw); diff --git a/drivers/net/wireless/p54.h b/drivers/net/wireless/p54.h index 744c866066c5..06d2c67f4c81 100644 --- a/drivers/net/wireless/p54.h +++ b/drivers/net/wireless/p54.h @@ -64,10 +64,6 @@ struct p54_common { unsigned int tx_hdr_len; void *cached_vdcf; unsigned int fw_var; - /* FIXME: this channels/modes/rates stuff sucks */ - struct ieee80211_channel channels[14]; - struct ieee80211_rate rates[12]; - struct ieee80211_hw_mode modes[2]; struct ieee80211_tx_queue_stats tx_stats; }; diff --git a/drivers/net/wireless/p54common.c b/drivers/net/wireless/p54common.c index 5cda49aff3a8..218ff7770ef6 100644 --- a/drivers/net/wireless/p54common.c +++ b/drivers/net/wireless/p54common.c @@ -27,6 +27,46 @@ MODULE_DESCRIPTION("Softmac Prism54 common code"); MODULE_LICENSE("GPL"); MODULE_ALIAS("prism54common"); +static struct ieee80211_rate p54_rates[] = { + { .bitrate = 10, .hw_value = 0, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, + { .bitrate = 20, .hw_value = 1, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, + { .bitrate = 55, .hw_value = 2, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, + { .bitrate = 110, .hw_value = 3, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, + { .bitrate = 60, .hw_value = 4, }, + { .bitrate = 90, .hw_value = 5, }, + { .bitrate = 120, .hw_value = 6, }, + { .bitrate = 180, .hw_value = 7, }, + { .bitrate = 240, .hw_value = 8, }, + { .bitrate = 360, .hw_value = 9, }, + { .bitrate = 480, .hw_value = 10, }, + { .bitrate = 540, .hw_value = 11, }, +}; + +static struct ieee80211_channel p54_channels[] = { + { .center_freq = 2412, .hw_value = 1, }, + { .center_freq = 2417, .hw_value = 2, }, + { .center_freq = 2422, .hw_value = 3, }, + { .center_freq = 2427, .hw_value = 4, }, + { .center_freq = 2432, .hw_value = 5, }, + { .center_freq = 2437, .hw_value = 6, }, + { .center_freq = 2442, .hw_value = 7, }, + { .center_freq = 2447, .hw_value = 8, }, + { .center_freq = 2452, .hw_value = 9, }, + { .center_freq = 2457, .hw_value = 10, }, + { .center_freq = 2462, .hw_value = 11, }, + { .center_freq = 2467, .hw_value = 12, }, + { .center_freq = 2472, .hw_value = 13, }, + { .center_freq = 2484, .hw_value = 14, }, +}; + +struct ieee80211_supported_band band_2GHz = { + .channels = p54_channels, + .n_channels = ARRAY_SIZE(p54_channels), + .bitrates = p54_rates, + .n_bitrates = ARRAY_SIZE(p54_rates), +}; + + void p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw) { struct p54_common *priv = dev->priv; @@ -308,10 +348,10 @@ static void p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb) u16 freq = le16_to_cpu(hdr->freq); rx_status.ssi = hdr->rssi; - rx_status.rate = hdr->rate & 0x1f; /* report short preambles & CCK too */ - rx_status.channel = freq == 2484 ? 14 : (freq - 2407)/5; + /* XX correct? */ + rx_status.rate_idx = hdr->rate & 0xf; rx_status.freq = freq; - rx_status.phymode = MODE_IEEE80211G; + rx_status.band = IEEE80211_BAND_2GHZ; rx_status.antenna = hdr->antenna; rx_status.mactime = le64_to_cpu(hdr->timestamp); rx_status.flag |= RX_FLAG_TSFT; @@ -547,7 +587,9 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb, txhdr->padding2 = 0; /* TODO: add support for alternate retry TX rates */ - rate = control->tx_rate; + rate = control->tx_rate->hw_value; + if (control->flags & IEEE80211_TXCTL_SHORT_PREAMBLE) + rate |= 0x10; if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS) rate |= 0x40; else if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) @@ -849,7 +891,7 @@ static int p54_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf) { int ret; - ret = p54_set_freq(dev, cpu_to_le16(conf->freq)); + ret = p54_set_freq(dev, cpu_to_le16(conf->channel->center_freq)); p54_set_vdcf(dev); return ret; } @@ -944,7 +986,6 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len) { struct ieee80211_hw *dev; struct p54_common *priv; - int i; dev = ieee80211_alloc_hw(priv_data_len, &p54_ops); if (!dev) @@ -953,18 +994,7 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len) priv = dev->priv; priv->mode = IEEE80211_IF_TYPE_INVALID; skb_queue_head_init(&priv->tx_queue); - memcpy(priv->channels, p54_channels, sizeof(p54_channels)); - memcpy(priv->rates, p54_rates, sizeof(p54_rates)); - priv->modes[1].mode = MODE_IEEE80211B; - priv->modes[1].num_rates = 4; - priv->modes[1].rates = priv->rates; - priv->modes[1].num_channels = ARRAY_SIZE(p54_channels); - priv->modes[1].channels = priv->channels; - priv->modes[0].mode = MODE_IEEE80211G; - priv->modes[0].num_rates = ARRAY_SIZE(p54_rates); - priv->modes[0].rates = priv->rates; - priv->modes[0].num_channels = ARRAY_SIZE(p54_channels); - priv->modes[0].channels = priv->channels; + dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &band_2GHz; dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | /* not sure */ IEEE80211_HW_RX_INCLUDES_FCS; dev->channel_change_time = 1000; /* TODO: find actual value */ @@ -986,14 +1016,6 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len) p54_init_vdcf(dev); - for (i = 0; i < 2; i++) { - if (ieee80211_register_hwmode(dev, &priv->modes[i])) { - kfree(priv->cached_vdcf); - ieee80211_free_hw(dev); - return NULL; - } - } - return dev; } EXPORT_SYMBOL_GPL(p54_init_common); diff --git a/drivers/net/wireless/p54common.h b/drivers/net/wireless/p54common.h index a721334e20d9..dc9f4cef585e 100644 --- a/drivers/net/wireless/p54common.h +++ b/drivers/net/wireless/p54common.h @@ -251,79 +251,4 @@ struct p54_tx_control_vdcf { __le16 frameburst; } __attribute__ ((packed)); -static const struct ieee80211_rate p54_rates[] = { - { .rate = 10, - .val = 0, - .val2 = 0x10, - .flags = IEEE80211_RATE_CCK_2 }, - { .rate = 20, - .val = 1, - .val2 = 0x11, - .flags = IEEE80211_RATE_CCK_2 }, - { .rate = 55, - .val = 2, - .val2 = 0x12, - .flags = IEEE80211_RATE_CCK_2 }, - { .rate = 110, - .val = 3, - .val2 = 0x13, - .flags = IEEE80211_RATE_CCK_2 }, - { .rate = 60, - .val = 4, - .flags = IEEE80211_RATE_OFDM }, - { .rate = 90, - .val = 5, - .flags = IEEE80211_RATE_OFDM }, - { .rate = 120, - .val = 6, - .flags = IEEE80211_RATE_OFDM }, - { .rate = 180, - .val = 7, - .flags = IEEE80211_RATE_OFDM }, - { .rate = 240, - .val = 8, - .flags = IEEE80211_RATE_OFDM }, - { .rate = 360, - .val = 9, - .flags = IEEE80211_RATE_OFDM }, - { .rate = 480, - .val = 10, - .flags = IEEE80211_RATE_OFDM }, - { .rate = 540, - .val = 11, - .flags = IEEE80211_RATE_OFDM }, -}; - -// TODO: just generate this.. -static const struct ieee80211_channel p54_channels[] = { - { .chan = 1, - .freq = 2412}, - { .chan = 2, - .freq = 2417}, - { .chan = 3, - .freq = 2422}, - { .chan = 4, - .freq = 2427}, - { .chan = 5, - .freq = 2432}, - { .chan = 6, - .freq = 2437}, - { .chan = 7, - .freq = 2442}, - { .chan = 8, - .freq = 2447}, - { .chan = 9, - .freq = 2452}, - { .chan = 10, - .freq = 2457}, - { .chan = 11, - .freq = 2462}, - { .chan = 12, - .freq = 2467}, - { .chan = 13, - .freq = 2472}, - { .chan = 14, - .freq = 2484} -}; - #endif /* PRISM54COMMON_H */ diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index b0e4ea7c9dca..4fa762bdb734 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -390,6 +390,10 @@ static inline struct rt2x00_intf* vif_to_intf(struct ieee80211_vif *vif) return (struct rt2x00_intf *)vif->drv_priv; } +#define HWMODE_B 0 +#define HWMODE_G 1 +#define HWMODE_A 2 + /* * Details about the supported modes, rates and channels * of a particular chipset. This is used by rt2x00lib @@ -644,11 +648,8 @@ struct rt2x00_dev { * IEEE80211 control structure. */ struct ieee80211_hw *hw; - struct ieee80211_hw_mode *hwmodes; - unsigned int curr_hwmode; -#define HWMODE_B 0 -#define HWMODE_G 1 -#define HWMODE_A 2 + struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; + enum ieee80211_band curr_band; /* * rfkill structure for RF state switching support. diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index 20231e0c53fa..9fba485a40ac 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -152,7 +152,7 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, struct ieee80211_conf *conf, const int force_config) { struct rt2x00lib_conf libconf; - struct ieee80211_hw_mode *mode; + struct ieee80211_supported_band *band; struct ieee80211_rate *rate; struct antenna_setup *default_ant = &rt2x00dev->default_ant; struct antenna_setup *active_ant = &rt2x00dev->link.ant.active; @@ -172,9 +172,9 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, * Check which configuration options have been * updated and should be send to the device. */ - if (rt2x00dev->rx_status.phymode != conf->phymode) + if (rt2x00dev->rx_status.band != conf->channel->band) flags |= CONFIG_UPDATE_PHYMODE; - if (rt2x00dev->rx_status.channel != conf->channel) + if (rt2x00dev->rx_status.freq != conf->channel->center_freq) flags |= CONFIG_UPDATE_CHANNEL; if (rt2x00dev->tx_power != conf->power_level) flags |= CONFIG_UPDATE_TXPOWER; @@ -229,33 +229,31 @@ config: memset(&libconf, 0, sizeof(libconf)); if (flags & CONFIG_UPDATE_PHYMODE) { - switch (conf->phymode) { - case MODE_IEEE80211A: + switch (conf->channel->band) { + case IEEE80211_BAND_5GHZ: libconf.phymode = HWMODE_A; break; - case MODE_IEEE80211B: - libconf.phymode = HWMODE_B; - break; - case MODE_IEEE80211G: + case IEEE80211_BAND_2GHZ: + /* Uh oh. what about B? */ libconf.phymode = HWMODE_G; break; default: ERROR(rt2x00dev, "Attempt to configure unsupported mode (%d)" - "Defaulting to 802.11b", conf->phymode); + "Defaulting to 802.11b", conf->channel->band); libconf.phymode = HWMODE_B; } - mode = &rt2x00dev->hwmodes[libconf.phymode]; - rate = &mode->rates[mode->num_rates - 1]; + band = &rt2x00dev->bands[conf->channel->band]; + rate = &band->bitrates[band->n_bitrates - 1]; libconf.basic_rates = - DEVICE_GET_RATE_FIELD(rate->val, RATEMASK) & DEV_BASIC_RATEMASK; + DEVICE_GET_RATE_FIELD(rate->hw_value, RATEMASK) & DEV_BASIC_RATEMASK; } if (flags & CONFIG_UPDATE_CHANNEL) { memcpy(&libconf.rf, - &rt2x00dev->spec.channels[conf->channel_val], + &rt2x00dev->spec.channels[conf->channel->hw_value], sizeof(libconf.rf)); } @@ -301,12 +299,11 @@ config: rt2x00lib_reset_link_tuner(rt2x00dev); if (flags & CONFIG_UPDATE_PHYMODE) { - rt2x00dev->curr_hwmode = libconf.phymode; - rt2x00dev->rx_status.phymode = conf->phymode; + rt2x00dev->curr_band = conf->channel->band; + rt2x00dev->rx_status.band = conf->channel->band; } - rt2x00dev->rx_status.freq = conf->freq; - rt2x00dev->rx_status.channel = conf->channel; + rt2x00dev->rx_status.freq = conf->channel->center_freq; rt2x00dev->tx_power = conf->power_level; if (flags & CONFIG_UPDATE_ANTENNA) { diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 0df8062b1a8e..83a72ae36638 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -550,19 +550,19 @@ void rt2x00lib_rxdone(struct queue_entry *entry, { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status; - struct ieee80211_hw_mode *mode; + struct ieee80211_supported_band *sband; struct ieee80211_rate *rate; struct ieee80211_hdr *hdr; unsigned int i; - int val = 0; + int val = 0, idx = -1; u16 fc; /* * Update RX statistics. */ - mode = &rt2x00dev->hwmodes[rt2x00dev->curr_hwmode]; - for (i = 0; i < mode->num_rates; i++) { - rate = &mode->rates[i]; + sband = &rt2x00dev->bands[rt2x00dev->curr_band]; + for (i = 0; i < sband->n_bitrates; i++) { + rate = &sband->bitrates[i]; /* * When frame was received with an OFDM bitrate, @@ -570,12 +570,12 @@ void rt2x00lib_rxdone(struct queue_entry *entry, * a CCK bitrate the signal is the rate in 0.5kbit/s. */ if (!rxdesc->ofdm) - val = DEVICE_GET_RATE_FIELD(rate->val, RATE); + val = DEVICE_GET_RATE_FIELD(rate->hw_value, RATE); else - val = DEVICE_GET_RATE_FIELD(rate->val, PLCP); + val = DEVICE_GET_RATE_FIELD(rate->hw_value, PLCP); if (val == rxdesc->signal) { - val = rate->val; + idx = i; break; } } @@ -590,7 +590,7 @@ void rt2x00lib_rxdone(struct queue_entry *entry, rt2x00dev->link.qual.rx_success++; - rx_status->rate = val; + rx_status->rate_idx = idx; rx_status->signal = rt2x00lib_calculate_link_signal(rt2x00dev, rxdesc->rssi); rx_status->ssi = rxdesc->rssi; @@ -639,7 +639,7 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev, frame_control = le16_to_cpu(ieee80211hdr->frame_control); seq_ctrl = le16_to_cpu(ieee80211hdr->seq_ctrl); - tx_rate = control->tx_rate; + tx_rate = control->tx_rate->hw_value; /* * Check whether this frame is to be acked @@ -658,7 +658,7 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev, } else __clear_bit(ENTRY_TXD_ACK, &txdesc.flags); if (control->rts_cts_rate) - tx_rate = control->rts_cts_rate; + tx_rate = control->rts_cts_rate->hw_value; } /* @@ -760,54 +760,45 @@ static void rt2x00lib_channel(struct ieee80211_channel *entry, const int channel, const int tx_power, const int value) { - entry->chan = channel; if (channel <= 14) - entry->freq = 2407 + (5 * channel); + entry->center_freq = 2407 + (5 * channel); else - entry->freq = 5000 + (5 * channel); - entry->val = value; - entry->flag = - IEEE80211_CHAN_W_IBSS | - IEEE80211_CHAN_W_ACTIVE_SCAN | - IEEE80211_CHAN_W_SCAN; - entry->power_level = tx_power; - entry->antenna_max = 0xff; + entry->center_freq = 5000 + (5 * channel); + entry->hw_value = value; + entry->max_power = tx_power; + entry->max_antenna_gain = 0xff; } static void rt2x00lib_rate(struct ieee80211_rate *entry, const int rate, const int mask, const int plcp, const int flags) { - entry->rate = rate; - entry->val = + entry->bitrate = rate; + entry->hw_value = DEVICE_SET_RATE_FIELD(rate, RATE) | DEVICE_SET_RATE_FIELD(mask, RATEMASK) | DEVICE_SET_RATE_FIELD(plcp, PLCP); entry->flags = flags; - entry->val2 = entry->val; - if (entry->flags & IEEE80211_RATE_PREAMBLE2) - entry->val2 |= DEVICE_SET_RATE_FIELD(1, PREAMBLE); - entry->min_rssi_ack = 0; - entry->min_rssi_ack_delta = 0; + entry->hw_value_short = entry->hw_value; + if (entry->flags & IEEE80211_RATE_SHORT_PREAMBLE) + entry->hw_value_short |= DEVICE_SET_RATE_FIELD(1, PREAMBLE); } static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev, struct hw_mode_spec *spec) { struct ieee80211_hw *hw = rt2x00dev->hw; - struct ieee80211_hw_mode *hwmodes; + struct ieee80211_supported_band *sbands; struct ieee80211_channel *channels; struct ieee80211_rate *rates; unsigned int i; unsigned char tx_power; - hwmodes = kzalloc(sizeof(*hwmodes) * spec->num_modes, GFP_KERNEL); - if (!hwmodes) - goto exit; + sbands = &rt2x00dev->bands[0]; channels = kzalloc(sizeof(*channels) * spec->num_channels, GFP_KERNEL); if (!channels) - goto exit_free_modes; + return -ENOMEM; rates = kzalloc(sizeof(*rates) * spec->num_rates, GFP_KERNEL); if (!rates) @@ -817,31 +808,31 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev, * Initialize Rate list. */ rt2x00lib_rate(&rates[0], 10, DEV_RATEMASK_1MB, - 0x00, IEEE80211_RATE_CCK); + 0x00, 0); rt2x00lib_rate(&rates[1], 20, DEV_RATEMASK_2MB, - 0x01, IEEE80211_RATE_CCK_2); + 0x01, IEEE80211_RATE_SHORT_PREAMBLE); rt2x00lib_rate(&rates[2], 55, DEV_RATEMASK_5_5MB, - 0x02, IEEE80211_RATE_CCK_2); + 0x02, IEEE80211_RATE_SHORT_PREAMBLE); rt2x00lib_rate(&rates[3], 110, DEV_RATEMASK_11MB, - 0x03, IEEE80211_RATE_CCK_2); + 0x03, IEEE80211_RATE_SHORT_PREAMBLE); if (spec->num_rates > 4) { rt2x00lib_rate(&rates[4], 60, DEV_RATEMASK_6MB, - 0x0b, IEEE80211_RATE_OFDM); + 0x0b, 0); rt2x00lib_rate(&rates[5], 90, DEV_RATEMASK_9MB, - 0x0f, IEEE80211_RATE_OFDM); + 0x0f, 0); rt2x00lib_rate(&rates[6], 120, DEV_RATEMASK_12MB, - 0x0a, IEEE80211_RATE_OFDM); + 0x0a, 0); rt2x00lib_rate(&rates[7], 180, DEV_RATEMASK_18MB, - 0x0e, IEEE80211_RATE_OFDM); + 0x0e, 0); rt2x00lib_rate(&rates[8], 240, DEV_RATEMASK_24MB, - 0x09, IEEE80211_RATE_OFDM); + 0x09, 0); rt2x00lib_rate(&rates[9], 360, DEV_RATEMASK_36MB, - 0x0d, IEEE80211_RATE_OFDM); + 0x0d, 0); rt2x00lib_rate(&rates[10], 480, DEV_RATEMASK_48MB, - 0x08, IEEE80211_RATE_OFDM); + 0x08, 0); rt2x00lib_rate(&rates[11], 540, DEV_RATEMASK_54MB, - 0x0c, IEEE80211_RATE_OFDM); + 0x0c, 0); } /* @@ -862,27 +853,27 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev, /* * Intitialize 802.11b * Rates: CCK. - * Channels: OFDM. + * Channels: 2.4 GHz */ if (spec->num_modes > HWMODE_B) { - hwmodes[HWMODE_B].mode = MODE_IEEE80211B; - hwmodes[HWMODE_B].num_channels = 14; - hwmodes[HWMODE_B].num_rates = 4; - hwmodes[HWMODE_B].channels = channels; - hwmodes[HWMODE_B].rates = rates; + sbands[IEEE80211_BAND_2GHZ].n_channels = 14; + sbands[IEEE80211_BAND_2GHZ].n_bitrates = 4; + sbands[IEEE80211_BAND_2GHZ].channels = channels; + sbands[IEEE80211_BAND_2GHZ].bitrates = rates; + hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &rt2x00dev->bands[IEEE80211_BAND_2GHZ]; } /* * Intitialize 802.11g * Rates: CCK, OFDM. - * Channels: OFDM. + * Channels: 2.4 GHz */ if (spec->num_modes > HWMODE_G) { - hwmodes[HWMODE_G].mode = MODE_IEEE80211G; - hwmodes[HWMODE_G].num_channels = 14; - hwmodes[HWMODE_G].num_rates = spec->num_rates; - hwmodes[HWMODE_G].channels = channels; - hwmodes[HWMODE_G].rates = rates; + sbands[IEEE80211_BAND_2GHZ].n_channels = 14; + sbands[IEEE80211_BAND_2GHZ].n_bitrates = spec->num_rates; + sbands[IEEE80211_BAND_2GHZ].channels = channels; + sbands[IEEE80211_BAND_2GHZ].bitrates = rates; + hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &rt2x00dev->bands[IEEE80211_BAND_2GHZ]; } /* @@ -891,39 +882,17 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev, * Channels: OFDM, UNII, HiperLAN2. */ if (spec->num_modes > HWMODE_A) { - hwmodes[HWMODE_A].mode = MODE_IEEE80211A; - hwmodes[HWMODE_A].num_channels = spec->num_channels - 14; - hwmodes[HWMODE_A].num_rates = spec->num_rates - 4; - hwmodes[HWMODE_A].channels = &channels[14]; - hwmodes[HWMODE_A].rates = &rates[4]; + sbands[IEEE80211_BAND_5GHZ].n_channels = spec->num_channels - 14; + sbands[IEEE80211_BAND_5GHZ].n_bitrates = spec->num_rates - 4; + sbands[IEEE80211_BAND_5GHZ].channels = &channels[14]; + sbands[IEEE80211_BAND_5GHZ].bitrates = &rates[4]; + hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &rt2x00dev->bands[IEEE80211_BAND_5GHZ]; } - if (spec->num_modes > HWMODE_G && - ieee80211_register_hwmode(hw, &hwmodes[HWMODE_G])) - goto exit_free_rates; - - if (spec->num_modes > HWMODE_B && - ieee80211_register_hwmode(hw, &hwmodes[HWMODE_B])) - goto exit_free_rates; - - if (spec->num_modes > HWMODE_A && - ieee80211_register_hwmode(hw, &hwmodes[HWMODE_A])) - goto exit_free_rates; - - rt2x00dev->hwmodes = hwmodes; - return 0; -exit_free_rates: - kfree(rates); - -exit_free_channels: + exit_free_channels: kfree(channels); - -exit_free_modes: - kfree(hwmodes); - -exit: ERROR(rt2x00dev, "Allocation ieee80211 modes failed.\n"); return -ENOMEM; } @@ -933,11 +902,11 @@ static void rt2x00lib_remove_hw(struct rt2x00_dev *rt2x00dev) if (test_bit(DEVICE_REGISTERED_HW, &rt2x00dev->flags)) ieee80211_unregister_hw(rt2x00dev->hw); - if (likely(rt2x00dev->hwmodes)) { - kfree(rt2x00dev->hwmodes->channels); - kfree(rt2x00dev->hwmodes->rates); - kfree(rt2x00dev->hwmodes); - rt2x00dev->hwmodes = NULL; + if (likely(rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ])) { + kfree(rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ]->channels); + kfree(rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ]->bitrates); + rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = NULL; + rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL; } } diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 59e87a1d96a4..1dd30510ed1e 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -426,12 +426,12 @@ static void rt61pci_config_antenna_5x(struct rt2x00_dev *rt2x00dev, case ANTENNA_HW_DIVERSITY: rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2); rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, - (rt2x00dev->curr_hwmode != HWMODE_A)); + (rt2x00dev->curr_band != IEEE80211_BAND_5GHZ)); break; case ANTENNA_A: rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1); rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0); - if (rt2x00dev->curr_hwmode == HWMODE_A) + if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0); else rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3); @@ -446,7 +446,7 @@ static void rt61pci_config_antenna_5x(struct rt2x00_dev *rt2x00dev, case ANTENNA_B: rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1); rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0); - if (rt2x00dev->curr_hwmode == HWMODE_A) + if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3); else rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0); @@ -602,7 +602,7 @@ static void rt61pci_config_antenna(struct rt2x00_dev *rt2x00dev, unsigned int i; u32 reg; - if (rt2x00dev->curr_hwmode == HWMODE_A) { + if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { sel = antenna_sel_a; lna = test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags); } else { @@ -616,10 +616,9 @@ static void rt61pci_config_antenna(struct rt2x00_dev *rt2x00dev, rt2x00pci_register_read(rt2x00dev, PHY_CSR0, ®); rt2x00_set_field32(®, PHY_CSR0_PA_PE_BG, - (rt2x00dev->curr_hwmode == HWMODE_B || - rt2x00dev->curr_hwmode == HWMODE_G)); + rt2x00dev->curr_band == IEEE80211_BAND_2GHZ); rt2x00_set_field32(®, PHY_CSR0_PA_PE_A, - (rt2x00dev->curr_hwmode == HWMODE_A)); + rt2x00dev->curr_band == IEEE80211_BAND_5GHZ); rt2x00pci_register_write(rt2x00dev, PHY_CSR0, reg); @@ -698,9 +697,9 @@ static void rt61pci_enable_led(struct rt2x00_dev *rt2x00dev) rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_RADIO_STATUS, 1); rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_A_STATUS, - (rt2x00dev->rx_status.phymode == MODE_IEEE80211A)); + rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ); rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_BG_STATUS, - (rt2x00dev->rx_status.phymode != MODE_IEEE80211A)); + rt2x00dev->rx_status.band != IEEE80211_BAND_5GHZ); arg0 = rt2x00dev->led_reg & 0xff; arg1 = (rt2x00dev->led_reg >> 8) & 0xff; @@ -798,7 +797,7 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev) /* * Determine r17 bounds. */ - if (rt2x00dev->rx_status.phymode == MODE_IEEE80211A) { + if (rt2x00dev->rx_status.band == IEEE80211_BAND_2GHZ) { low_bound = 0x28; up_bound = 0x48; if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) { @@ -1544,8 +1543,10 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_desc_write(txd, 2, word); rt2x00_desc_read(txd, 5, &word); +/* XXX: removed for now rt2x00_set_field32(&word, TXD_W5_TX_POWER, TXPOWER_TO_DEV(control->power_level)); + */ rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1); rt2x00_desc_write(txd, 5, word); @@ -1637,7 +1638,7 @@ static int rt61pci_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1) return 0; } - if (rt2x00dev->rx_status.phymode == MODE_IEEE80211A) { + if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) { if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) offset += 14; diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 4b5bde8b53de..9cbc879da037 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -439,13 +439,13 @@ static void rt73usb_config_antenna_5x(struct rt2x00_dev *rt2x00dev, case ANTENNA_HW_DIVERSITY: rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2); temp = !test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags) - && (rt2x00dev->curr_hwmode != HWMODE_A); + && (rt2x00dev->curr_band != IEEE80211_BAND_5GHZ); rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, temp); break; case ANTENNA_A: rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1); rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0); - if (rt2x00dev->curr_hwmode == HWMODE_A) + if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0); else rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3); @@ -460,7 +460,7 @@ static void rt73usb_config_antenna_5x(struct rt2x00_dev *rt2x00dev, case ANTENNA_B: rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1); rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0); - if (rt2x00dev->curr_hwmode == HWMODE_A) + if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3); else rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0); @@ -555,7 +555,7 @@ static void rt73usb_config_antenna(struct rt2x00_dev *rt2x00dev, unsigned int i; u32 reg; - if (rt2x00dev->curr_hwmode == HWMODE_A) { + if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { sel = antenna_sel_a; lna = test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags); } else { @@ -569,10 +569,9 @@ static void rt73usb_config_antenna(struct rt2x00_dev *rt2x00dev, rt73usb_register_read(rt2x00dev, PHY_CSR0, ®); rt2x00_set_field32(®, PHY_CSR0_PA_PE_BG, - (rt2x00dev->curr_hwmode == HWMODE_B || - rt2x00dev->curr_hwmode == HWMODE_G)); + (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ)); rt2x00_set_field32(®, PHY_CSR0_PA_PE_A, - (rt2x00dev->curr_hwmode == HWMODE_A)); + (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ)); rt73usb_register_write(rt2x00dev, PHY_CSR0, reg); @@ -644,9 +643,9 @@ static void rt73usb_enable_led(struct rt2x00_dev *rt2x00dev) rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_RADIO_STATUS, 1); rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_A_STATUS, - (rt2x00dev->rx_status.phymode == MODE_IEEE80211A)); + (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ)); rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_BG_STATUS, - (rt2x00dev->rx_status.phymode != MODE_IEEE80211A)); + (rt2x00dev->rx_status.band != IEEE80211_BAND_5GHZ)); rt2x00usb_vendor_request_sw(rt2x00dev, USB_LED_CONTROL, 0x0000, rt2x00dev->led_reg, REGISTER_TIMEOUT); @@ -736,7 +735,7 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev) /* * Determine r17 bounds. */ - if (rt2x00dev->rx_status.phymode == MODE_IEEE80211A) { + if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) { low_bound = 0x28; up_bound = 0x48; @@ -1278,8 +1277,10 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_desc_write(txd, 2, word); rt2x00_desc_read(txd, 5, &word); +/* XXX: removed for now rt2x00_set_field32(&word, TXD_W5_TX_POWER, TXPOWER_TO_DEV(control->power_level)); + */ rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1); rt2x00_desc_write(txd, 5, word); @@ -1370,7 +1371,7 @@ static int rt73usb_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1) return 0; } - if (rt2x00dev->rx_status.phymode == MODE_IEEE80211A) { + if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) { if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) { if (lna == 3 || lna == 2) offset += 10; diff --git a/drivers/net/wireless/rtl8180.h b/drivers/net/wireless/rtl8180.h index 2cbfe3c8081f..082a11f93beb 100644 --- a/drivers/net/wireless/rtl8180.h +++ b/drivers/net/wireless/rtl8180.h @@ -102,7 +102,7 @@ struct rtl8180_priv { struct rtl8180_tx_ring tx_ring[4]; struct ieee80211_channel channels[14]; struct ieee80211_rate rates[12]; - struct ieee80211_hw_mode modes[2]; + struct ieee80211_supported_band band; struct pci_dev *pdev; u32 rx_conf; diff --git a/drivers/net/wireless/rtl8180_dev.c b/drivers/net/wireless/rtl8180_dev.c index 5e9a8ace0d81..d0928c91c21c 100644 --- a/drivers/net/wireless/rtl8180_dev.c +++ b/drivers/net/wireless/rtl8180_dev.c @@ -49,6 +49,41 @@ static struct pci_device_id rtl8180_table[] __devinitdata = { MODULE_DEVICE_TABLE(pci, rtl8180_table); +static const struct ieee80211_rate rtl818x_rates[] = { + { .bitrate = 10, .hw_value = 0, }, + { .bitrate = 20, .hw_value = 1, }, + { .bitrate = 55, .hw_value = 2, }, + { .bitrate = 110, .hw_value = 3, }, + { .bitrate = 60, .hw_value = 4, }, + { .bitrate = 90, .hw_value = 5, }, + { .bitrate = 120, .hw_value = 6, }, + { .bitrate = 180, .hw_value = 7, }, + { .bitrate = 240, .hw_value = 8, }, + { .bitrate = 360, .hw_value = 9, }, + { .bitrate = 480, .hw_value = 10, }, + { .bitrate = 540, .hw_value = 11, }, +}; + +static const struct ieee80211_channel rtl818x_channels[] = { + { .center_freq = 2412 }, + { .center_freq = 2417 }, + { .center_freq = 2422 }, + { .center_freq = 2427 }, + { .center_freq = 2432 }, + { .center_freq = 2437 }, + { .center_freq = 2442 }, + { .center_freq = 2447 }, + { .center_freq = 2452 }, + { .center_freq = 2457 }, + { .center_freq = 2462 }, + { .center_freq = 2467 }, + { .center_freq = 2472 }, + { .center_freq = 2484 }, +}; + + + + void rtl8180_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data) { struct rtl8180_priv *priv = dev->priv; @@ -99,10 +134,10 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev) /* TODO: improve signal/rssi reporting */ rx_status.signal = flags2 & 0xFF; rx_status.ssi = (flags2 >> 8) & 0x7F; - rx_status.rate = (flags >> 20) & 0xF; - rx_status.freq = dev->conf.freq; - rx_status.channel = dev->conf.channel; - rx_status.phymode = dev->conf.phymode; + /* XXX: is this correct? */ + rx_status.rate_idx = (flags >> 20) & 0xF; + rx_status.freq = dev->conf.channel->center_freq; + rx_status.band = dev->conf.channel->band; rx_status.mactime = le64_to_cpu(entry->tsft); rx_status.flag |= RX_FLAG_TSFT; if (flags & RTL8180_RX_DESC_FLAG_CRC32_ERR) @@ -223,8 +258,9 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb, skb->len, PCI_DMA_TODEVICE); tx_flags = RTL8180_TX_DESC_FLAG_OWN | RTL8180_TX_DESC_FLAG_FS | - RTL8180_TX_DESC_FLAG_LS | (control->tx_rate << 24) | - (control->rts_cts_rate << 19) | skb->len; + RTL8180_TX_DESC_FLAG_LS | + (control->tx_rate->hw_value << 24) | + (control->rts_cts_rate->hw_value << 19) | skb->len; if (priv->r8185) tx_flags |= RTL8180_TX_DESC_FLAG_DMA | @@ -246,9 +282,9 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb, unsigned int remainder; plcp_len = DIV_ROUND_UP(16 * (skb->len + 4), - (control->rate->rate * 2) / 10); + (control->tx_rate->bitrate * 2) / 10); remainder = (16 * (skb->len + 4)) % - ((control->rate->rate * 2) / 10); + ((control->tx_rate->bitrate * 2) / 10); if (remainder > 0 && remainder <= 6) plcp_len |= 1 << 15; } @@ -261,8 +297,8 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb, entry->plcp_len = cpu_to_le16(plcp_len); entry->tx_buf = cpu_to_le32(mapping); entry->frame_len = cpu_to_le32(skb->len); - entry->flags2 = control->alt_retry_rate != -1 ? - control->alt_retry_rate << 4 : 0; + entry->flags2 = control->alt_retry_rate != NULL ? + control->alt_retry_rate->bitrate << 4 : 0; entry->retry_limit = control->retry_limit; entry->flags = cpu_to_le32(tx_flags); __skb_queue_tail(&ring->queue, skb); @@ -838,19 +874,19 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev, goto err_free_dev; } + BUILD_BUG_ON(sizeof(priv->channels) != sizeof(rtl818x_channels)); + BUILD_BUG_ON(sizeof(priv->rates) != sizeof(rtl818x_rates)); + memcpy(priv->channels, rtl818x_channels, sizeof(rtl818x_channels)); memcpy(priv->rates, rtl818x_rates, sizeof(rtl818x_rates)); - priv->modes[0].mode = MODE_IEEE80211G; - priv->modes[0].num_rates = ARRAY_SIZE(rtl818x_rates); - priv->modes[0].rates = priv->rates; - priv->modes[0].num_channels = ARRAY_SIZE(rtl818x_channels); - priv->modes[0].channels = priv->channels; - priv->modes[1].mode = MODE_IEEE80211B; - priv->modes[1].num_rates = 4; - priv->modes[1].rates = priv->rates; - priv->modes[1].num_channels = ARRAY_SIZE(rtl818x_channels); - priv->modes[1].channels = priv->channels; - priv->mode = IEEE80211_IF_TYPE_INVALID; + + priv->band.band = IEEE80211_BAND_2GHZ; + priv->band.channels = priv->channels; + priv->band.n_channels = ARRAY_SIZE(rtl818x_channels); + priv->band.bitrates = priv->rates; + priv->band.n_bitrates = 4; + dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; + dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | IEEE80211_HW_RX_INCLUDES_FCS; dev->queues = 1; @@ -879,15 +915,10 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev, priv->r8185 = reg & RTL818X_TX_CONF_R8185_ABC; if (priv->r8185) { - if ((err = ieee80211_register_hwmode(dev, &priv->modes[0]))) - goto err_iounmap; - + priv->band.n_bitrates = ARRAY_SIZE(rtl818x_rates); pci_try_set_mwi(pdev); } - if ((err = ieee80211_register_hwmode(dev, &priv->modes[1]))) - goto err_iounmap; - eeprom.data = dev; eeprom.register_read = rtl8180_eeprom_register_read; eeprom.register_write = rtl8180_eeprom_register_write; @@ -950,8 +981,8 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev, for (i = 0; i < 14; i += 2) { u16 txpwr; eeprom_93cx6_read(&eeprom, 0x10 + (i >> 1), &txpwr); - priv->channels[i].val = txpwr & 0xFF; - priv->channels[i + 1].val = txpwr >> 8; + priv->channels[i].hw_value = txpwr & 0xFF; + priv->channels[i + 1].hw_value = txpwr >> 8; } /* OFDM TX power */ @@ -959,8 +990,8 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev, for (i = 0; i < 14; i += 2) { u16 txpwr; eeprom_93cx6_read(&eeprom, 0x20 + (i >> 1), &txpwr); - priv->channels[i].val |= (txpwr & 0xFF) << 8; - priv->channels[i + 1].val |= txpwr & 0xFF00; + priv->channels[i].hw_value |= (txpwr & 0xFF) << 8; + priv->channels[i + 1].hw_value |= txpwr & 0xFF00; } } diff --git a/drivers/net/wireless/rtl8180_grf5101.c b/drivers/net/wireless/rtl8180_grf5101.c index 8293e19c4c59..5d47935dbac3 100644 --- a/drivers/net/wireless/rtl8180_grf5101.c +++ b/drivers/net/wireless/rtl8180_grf5101.c @@ -73,8 +73,9 @@ static void grf5101_rf_set_channel(struct ieee80211_hw *dev, struct ieee80211_conf *conf) { struct rtl8180_priv *priv = dev->priv; - u32 txpw = priv->channels[conf->channel - 1].val & 0xFF; - u32 chan = conf->channel - 1; + int channel = ieee80211_frequency_to_channel(conf->channel->center_freq); + u32 txpw = priv->channels[channel - 1].hw_value & 0xFF; + u32 chan = channel - 1; /* set TX power */ write_grf5101(dev, 0x15, 0x0); diff --git a/drivers/net/wireless/rtl8180_max2820.c b/drivers/net/wireless/rtl8180_max2820.c index 98fe9fd64968..a34dfd382b6d 100644 --- a/drivers/net/wireless/rtl8180_max2820.c +++ b/drivers/net/wireless/rtl8180_max2820.c @@ -78,8 +78,9 @@ static void max2820_rf_set_channel(struct ieee80211_hw *dev, struct ieee80211_conf *conf) { struct rtl8180_priv *priv = dev->priv; - unsigned int chan_idx = conf ? conf->channel - 1 : 0; - u32 txpw = priv->channels[chan_idx].val & 0xFF; + int channel = ieee80211_frequency_to_channel(conf->channel->center_freq); + unsigned int chan_idx = channel - 1; + u32 txpw = priv->channels[chan_idx].hw_value & 0xFF; u32 chan = max2820_chan[chan_idx]; /* While philips SA2400 drive the PA bias from diff --git a/drivers/net/wireless/rtl8180_rtl8225.c b/drivers/net/wireless/rtl8180_rtl8225.c index ef3832bee85c..cd22781728a9 100644 --- a/drivers/net/wireless/rtl8180_rtl8225.c +++ b/drivers/net/wireless/rtl8180_rtl8225.c @@ -261,8 +261,8 @@ static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel) u32 reg; int i; - cck_power = priv->channels[channel - 1].val & 0xFF; - ofdm_power = priv->channels[channel - 1].val >> 8; + cck_power = priv->channels[channel - 1].hw_value & 0xFF; + ofdm_power = priv->channels[channel - 1].hw_value >> 8; cck_power = min(cck_power, (u8)35); ofdm_power = min(ofdm_power, (u8)35); @@ -476,8 +476,8 @@ static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel) const u8 *tmp; int i; - cck_power = priv->channels[channel - 1].val & 0xFF; - ofdm_power = priv->channels[channel - 1].val >> 8; + cck_power = priv->channels[channel - 1].hw_value & 0xFF; + ofdm_power = priv->channels[channel - 1].hw_value >> 8; if (channel == 14) tmp = rtl8225z2_tx_power_cck_ch14; @@ -716,13 +716,14 @@ static void rtl8225_rf_set_channel(struct ieee80211_hw *dev, struct ieee80211_conf *conf) { struct rtl8180_priv *priv = dev->priv; + int chan = ieee80211_frequency_to_channel(conf->channel->center_freq); if (priv->rf->init == rtl8225_rf_init) - rtl8225_rf_set_tx_power(dev, conf->channel); + rtl8225_rf_set_tx_power(dev, chan); else - rtl8225z2_rf_set_tx_power(dev, conf->channel); + rtl8225z2_rf_set_tx_power(dev, chan); - rtl8225_write(dev, 0x7, rtl8225_chan[conf->channel - 1]); + rtl8225_write(dev, 0x7, rtl8225_chan[chan - 1]); msleep(10); if (conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME) { diff --git a/drivers/net/wireless/rtl8180_sa2400.c b/drivers/net/wireless/rtl8180_sa2400.c index e08ace7b1cb7..0311b4ea124c 100644 --- a/drivers/net/wireless/rtl8180_sa2400.c +++ b/drivers/net/wireless/rtl8180_sa2400.c @@ -80,8 +80,9 @@ static void sa2400_rf_set_channel(struct ieee80211_hw *dev, struct ieee80211_conf *conf) { struct rtl8180_priv *priv = dev->priv; - u32 txpw = priv->channels[conf->channel - 1].val & 0xFF; - u32 chan = sa2400_chan[conf->channel - 1]; + int channel = ieee80211_frequency_to_channel(conf->channel->center_freq); + u32 txpw = priv->channels[channel - 1].hw_value & 0xFF; + u32 chan = sa2400_chan[channel - 1]; write_sa2400(dev, 7, txpw); diff --git a/drivers/net/wireless/rtl8187.h b/drivers/net/wireless/rtl8187.h index 8680a0b6433c..076d88b6db0e 100644 --- a/drivers/net/wireless/rtl8187.h +++ b/drivers/net/wireless/rtl8187.h @@ -71,7 +71,7 @@ struct rtl8187_priv { /* rtl8187 specific */ struct ieee80211_channel channels[14]; struct ieee80211_rate rates[12]; - struct ieee80211_hw_mode modes[2]; + struct ieee80211_supported_band band; struct usb_device *udev; u32 rx_conf; u16 txpwr_base; diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c index f44505994a0e..6ef67990692d 100644 --- a/drivers/net/wireless/rtl8187_dev.c +++ b/drivers/net/wireless/rtl8187_dev.c @@ -45,6 +45,38 @@ static struct usb_device_id rtl8187_table[] __devinitdata = { MODULE_DEVICE_TABLE(usb, rtl8187_table); +static const struct ieee80211_rate rtl818x_rates[] = { + { .bitrate = 10, .hw_value = 0, }, + { .bitrate = 20, .hw_value = 1, }, + { .bitrate = 55, .hw_value = 2, }, + { .bitrate = 110, .hw_value = 3, }, + { .bitrate = 60, .hw_value = 4, }, + { .bitrate = 90, .hw_value = 5, }, + { .bitrate = 120, .hw_value = 6, }, + { .bitrate = 180, .hw_value = 7, }, + { .bitrate = 240, .hw_value = 8, }, + { .bitrate = 360, .hw_value = 9, }, + { .bitrate = 480, .hw_value = 10, }, + { .bitrate = 540, .hw_value = 11, }, +}; + +static const struct ieee80211_channel rtl818x_channels[] = { + { .center_freq = 2412 }, + { .center_freq = 2417 }, + { .center_freq = 2422 }, + { .center_freq = 2427 }, + { .center_freq = 2432 }, + { .center_freq = 2437 }, + { .center_freq = 2442 }, + { .center_freq = 2447 }, + { .center_freq = 2452 }, + { .center_freq = 2457 }, + { .center_freq = 2462 }, + { .center_freq = 2467 }, + { .center_freq = 2472 }, + { .center_freq = 2484 }, +}; + static void rtl8187_iowrite_async_cb(struct urb *urb) { kfree(urb->context); @@ -146,8 +178,8 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb, flags = skb->len; flags |= RTL8187_TX_FLAG_NO_ENCRYPT; - flags |= control->rts_cts_rate << 19; - flags |= control->tx_rate << 24; + flags |= control->rts_cts_rate->hw_value << 19; + flags |= control->tx_rate->hw_value << 24; if (ieee80211_get_morefrag((struct ieee80211_hdr *)skb->data)) flags |= RTL8187_TX_FLAG_MORE_FRAG; if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS) { @@ -225,10 +257,9 @@ static void rtl8187_rx_cb(struct urb *urb) rx_status.antenna = (hdr->signal >> 7) & 1; rx_status.signal = 64 - min(hdr->noise, (u8)64); rx_status.ssi = signal; - rx_status.rate = rate; - rx_status.freq = dev->conf.freq; - rx_status.channel = dev->conf.channel; - rx_status.phymode = dev->conf.phymode; + 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)) @@ -682,19 +713,22 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, usb_get_dev(udev); skb_queue_head_init(&priv->rx_queue); + + BUILD_BUG_ON(sizeof(priv->channels) != sizeof(rtl818x_channels)); + BUILD_BUG_ON(sizeof(priv->rates) != sizeof(rtl818x_rates)); + memcpy(priv->channels, rtl818x_channels, sizeof(rtl818x_channels)); memcpy(priv->rates, rtl818x_rates, sizeof(rtl818x_rates)); priv->map = (struct rtl818x_csr *)0xFF00; - priv->modes[0].mode = MODE_IEEE80211G; - priv->modes[0].num_rates = ARRAY_SIZE(rtl818x_rates); - priv->modes[0].rates = priv->rates; - priv->modes[0].num_channels = ARRAY_SIZE(rtl818x_channels); - priv->modes[0].channels = priv->channels; - priv->modes[1].mode = MODE_IEEE80211B; - priv->modes[1].num_rates = 4; - priv->modes[1].rates = priv->rates; - priv->modes[1].num_channels = ARRAY_SIZE(rtl818x_channels); - priv->modes[1].channels = priv->channels; + + priv->band.band = IEEE80211_BAND_2GHZ; + priv->band.channels = priv->channels; + priv->band.n_channels = ARRAY_SIZE(rtl818x_channels); + priv->band.bitrates = priv->rates; + priv->band.n_bitrates = ARRAY_SIZE(rtl818x_rates); + dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; + + priv->mode = IEEE80211_IF_TYPE_MNTR; dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | IEEE80211_HW_RX_INCLUDES_FCS; @@ -703,10 +737,6 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, dev->max_rssi = 65; dev->max_signal = 64; - for (i = 0; i < 2; i++) - if ((err = ieee80211_register_hwmode(dev, &priv->modes[i]))) - goto err_free_dev; - eeprom.data = dev; eeprom.register_read = rtl8187_eeprom_register_read; eeprom.register_write = rtl8187_eeprom_register_write; @@ -730,20 +760,20 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, for (i = 0; i < 3; i++) { eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_1 + i, &txpwr); - (*channel++).val = txpwr & 0xFF; - (*channel++).val = txpwr >> 8; + (*channel++).hw_value = txpwr & 0xFF; + (*channel++).hw_value = txpwr >> 8; } for (i = 0; i < 2; i++) { eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_4 + i, &txpwr); - (*channel++).val = txpwr & 0xFF; - (*channel++).val = txpwr >> 8; + (*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, &txpwr); - (*channel++).val = txpwr & 0xFF; - (*channel++).val = txpwr >> 8; + (*channel++).hw_value = txpwr & 0xFF; + (*channel++).hw_value = txpwr >> 8; } eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_BASE, diff --git a/drivers/net/wireless/rtl8187_rtl8225.c b/drivers/net/wireless/rtl8187_rtl8225.c index b713de17ba0a..9146387b4c5e 100644 --- a/drivers/net/wireless/rtl8187_rtl8225.c +++ b/drivers/net/wireless/rtl8187_rtl8225.c @@ -283,8 +283,8 @@ static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel) u32 reg; int i; - cck_power = priv->channels[channel - 1].val & 0xF; - ofdm_power = priv->channels[channel - 1].val >> 4; + cck_power = priv->channels[channel - 1].hw_value & 0xF; + ofdm_power = priv->channels[channel - 1].hw_value >> 4; cck_power = min(cck_power, (u8)11); ofdm_power = min(ofdm_power, (u8)35); @@ -500,8 +500,8 @@ static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel) u32 reg; int i; - cck_power = priv->channels[channel - 1].val & 0xF; - ofdm_power = priv->channels[channel - 1].val >> 4; + cck_power = priv->channels[channel - 1].hw_value & 0xF; + ofdm_power = priv->channels[channel - 1].hw_value >> 4; cck_power = min(cck_power, (u8)15); cck_power += priv->txpwr_base & 0xF; @@ -735,13 +735,14 @@ static void rtl8225_rf_set_channel(struct ieee80211_hw *dev, struct ieee80211_conf *conf) { struct rtl8187_priv *priv = dev->priv; + int chan = ieee80211_frequency_to_channel(conf->channel->center_freq); if (priv->rf->init == rtl8225_rf_init) - rtl8225_rf_set_tx_power(dev, conf->channel); + rtl8225_rf_set_tx_power(dev, chan); else - rtl8225z2_rf_set_tx_power(dev, conf->channel); + rtl8225z2_rf_set_tx_power(dev, chan); - rtl8225_write(dev, 0x7, rtl8225_chan[conf->channel - 1]); + rtl8225_write(dev, 0x7, rtl8225_chan[chan - 1]); msleep(10); } diff --git a/drivers/net/wireless/rtl818x.h b/drivers/net/wireless/rtl818x.h index 1e7d6f8278d7..4f7d38f506eb 100644 --- a/drivers/net/wireless/rtl818x.h +++ b/drivers/net/wireless/rtl818x.h @@ -175,74 +175,4 @@ struct rtl818x_rf_ops { void (*set_chan)(struct ieee80211_hw *, struct ieee80211_conf *); }; -static const struct ieee80211_rate rtl818x_rates[] = { - { .rate = 10, - .val = 0, - .flags = IEEE80211_RATE_CCK }, - { .rate = 20, - .val = 1, - .flags = IEEE80211_RATE_CCK }, - { .rate = 55, - .val = 2, - .flags = IEEE80211_RATE_CCK }, - { .rate = 110, - .val = 3, - .flags = IEEE80211_RATE_CCK }, - { .rate = 60, - .val = 4, - .flags = IEEE80211_RATE_OFDM }, - { .rate = 90, - .val = 5, - .flags = IEEE80211_RATE_OFDM }, - { .rate = 120, - .val = 6, - .flags = IEEE80211_RATE_OFDM }, - { .rate = 180, - .val = 7, - .flags = IEEE80211_RATE_OFDM }, - { .rate = 240, - .val = 8, - .flags = IEEE80211_RATE_OFDM }, - { .rate = 360, - .val = 9, - .flags = IEEE80211_RATE_OFDM }, - { .rate = 480, - .val = 10, - .flags = IEEE80211_RATE_OFDM }, - { .rate = 540, - .val = 11, - .flags = IEEE80211_RATE_OFDM }, -}; - -static const struct ieee80211_channel rtl818x_channels[] = { - { .chan = 1, - .freq = 2412}, - { .chan = 2, - .freq = 2417}, - { .chan = 3, - .freq = 2422}, - { .chan = 4, - .freq = 2427}, - { .chan = 5, - .freq = 2432}, - { .chan = 6, - .freq = 2437}, - { .chan = 7, - .freq = 2442}, - { .chan = 8, - .freq = 2447}, - { .chan = 9, - .freq = 2452}, - { .chan = 10, - .freq = 2457}, - { .chan = 11, - .freq = 2462}, - { .chan = 12, - .freq = 2467}, - { .chan = 13, - .freq = 2472}, - { .chan = 14, - .freq = 2484} -}; - #endif /* RTL818X_H */ diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c index 99e5b03b3f51..e3fba6f09455 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.c +++ b/drivers/net/wireless/zd1211rw/zd_chip.c @@ -986,7 +986,7 @@ static int print_fw_version(struct zd_chip *chip) return 0; } -static int set_mandatory_rates(struct zd_chip *chip, int mode) +static int set_mandatory_rates(struct zd_chip *chip, int gmode) { u32 rates; ZD_ASSERT(mutex_is_locked(&chip->mutex)); @@ -994,17 +994,12 @@ static int set_mandatory_rates(struct zd_chip *chip, int mode) * that the device is supporting. Until further notice we should try * to support 802.11g also for full speed USB. */ - switch (mode) { - case MODE_IEEE80211B: + if (!gmode) rates = CR_RATE_1M|CR_RATE_2M|CR_RATE_5_5M|CR_RATE_11M; - break; - case MODE_IEEE80211G: + else rates = CR_RATE_1M|CR_RATE_2M|CR_RATE_5_5M|CR_RATE_11M| CR_RATE_6M|CR_RATE_12M|CR_RATE_24M; - break; - default: - return -EINVAL; - } + return zd_iowrite32_locked(chip, rates, CR_MANDATORY_RATE_TBL); } @@ -1108,7 +1103,7 @@ int zd_chip_init_hw(struct zd_chip *chip) * It might be discussed, whether we should suppport pure b mode for * full speed USB. */ - r = set_mandatory_rates(chip, MODE_IEEE80211G); + r = set_mandatory_rates(chip, 1); if (r) goto out; /* Disabling interrupts is certainly a smart thing here. diff --git a/drivers/net/wireless/zd1211rw/zd_ieee80211.c b/drivers/net/wireless/zd1211rw/zd_ieee80211.c index 7c277ec43f79..d8dc41ec0e5d 100644 --- a/drivers/net/wireless/zd1211rw/zd_ieee80211.c +++ b/drivers/net/wireless/zd1211rw/zd_ieee80211.c @@ -65,16 +65,14 @@ static const struct channel_range *zd_channel_range(u8 regdomain) static void unmask_bg_channels(struct ieee80211_hw *hw, const struct channel_range *range, - struct ieee80211_hw_mode *mode) + struct ieee80211_supported_band *sband) { u8 channel; for (channel = range->start; channel < range->end; channel++) { struct ieee80211_channel *chan = - &mode->channels[CHAN_TO_IDX(channel)]; - chan->flag |= IEEE80211_CHAN_W_SCAN | - IEEE80211_CHAN_W_ACTIVE_SCAN | - IEEE80211_CHAN_W_IBSS; + &sband->channels[CHAN_TO_IDX(channel)]; + chan->flags = 0; } } @@ -97,7 +95,6 @@ void zd_geo_init(struct ieee80211_hw *hw, u8 regdomain) range = zd_channel_range(ZD_REGDOMAIN_FCC); } - unmask_bg_channels(hw, range, &mac->modes[0]); - unmask_bg_channels(hw, range, &mac->modes[1]); + unmask_bg_channels(hw, range, &mac->band); } diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index 76ef2d83919d..21b653458831 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -34,76 +34,61 @@ /* This table contains the hardware specific values for the modulation rates. */ static const struct ieee80211_rate zd_rates[] = { - { .rate = 10, - .val = ZD_CCK_RATE_1M, - .flags = IEEE80211_RATE_CCK }, - { .rate = 20, - .val = ZD_CCK_RATE_2M, - .val2 = ZD_CCK_RATE_2M | ZD_CCK_PREA_SHORT, - .flags = IEEE80211_RATE_CCK_2 }, - { .rate = 55, - .val = ZD_CCK_RATE_5_5M, - .val2 = ZD_CCK_RATE_5_5M | ZD_CCK_PREA_SHORT, - .flags = IEEE80211_RATE_CCK_2 }, - { .rate = 110, - .val = ZD_CCK_RATE_11M, - .val2 = ZD_CCK_RATE_11M | ZD_CCK_PREA_SHORT, - .flags = IEEE80211_RATE_CCK_2 }, - { .rate = 60, - .val = ZD_OFDM_RATE_6M, - .flags = IEEE80211_RATE_OFDM }, - { .rate = 90, - .val = ZD_OFDM_RATE_9M, - .flags = IEEE80211_RATE_OFDM }, - { .rate = 120, - .val = ZD_OFDM_RATE_12M, - .flags = IEEE80211_RATE_OFDM }, - { .rate = 180, - .val = ZD_OFDM_RATE_18M, - .flags = IEEE80211_RATE_OFDM }, - { .rate = 240, - .val = ZD_OFDM_RATE_24M, - .flags = IEEE80211_RATE_OFDM }, - { .rate = 360, - .val = ZD_OFDM_RATE_36M, - .flags = IEEE80211_RATE_OFDM }, - { .rate = 480, - .val = ZD_OFDM_RATE_48M, - .flags = IEEE80211_RATE_OFDM }, - { .rate = 540, - .val = ZD_OFDM_RATE_54M, - .flags = IEEE80211_RATE_OFDM }, + { .bitrate = 10, + .hw_value = ZD_CCK_RATE_1M, }, + { .bitrate = 20, + .hw_value = ZD_CCK_RATE_2M, + .hw_value_short = ZD_CCK_RATE_2M | ZD_CCK_PREA_SHORT, + .flags = IEEE80211_RATE_SHORT_PREAMBLE }, + { .bitrate = 55, + .hw_value = ZD_CCK_RATE_5_5M, + .hw_value_short = ZD_CCK_RATE_5_5M | ZD_CCK_PREA_SHORT, + .flags = IEEE80211_RATE_SHORT_PREAMBLE }, + { .bitrate = 110, + .hw_value = ZD_CCK_RATE_11M, + .hw_value_short = ZD_CCK_RATE_11M | ZD_CCK_PREA_SHORT, + .flags = IEEE80211_RATE_SHORT_PREAMBLE }, + { .bitrate = 60, + .hw_value = ZD_OFDM_RATE_6M, + .flags = 0 }, + { .bitrate = 90, + .hw_value = ZD_OFDM_RATE_9M, + .flags = 0 }, + { .bitrate = 120, + .hw_value = ZD_OFDM_RATE_12M, + .flags = 0 }, + { .bitrate = 180, + .hw_value = ZD_OFDM_RATE_18M, + .flags = 0 }, + { .bitrate = 240, + .hw_value = ZD_OFDM_RATE_24M, + .flags = 0 }, + { .bitrate = 360, + .hw_value = ZD_OFDM_RATE_36M, + .flags = 0 }, + { .bitrate = 480, + .hw_value = ZD_OFDM_RATE_48M, + .flags = 0 }, + { .bitrate = 540, + .hw_value = ZD_OFDM_RATE_54M, + .flags = 0 }, }; static const struct ieee80211_channel zd_channels[] = { - { .chan = 1, - .freq = 2412}, - { .chan = 2, - .freq = 2417}, - { .chan = 3, - .freq = 2422}, - { .chan = 4, - .freq = 2427}, - { .chan = 5, - .freq = 2432}, - { .chan = 6, - .freq = 2437}, - { .chan = 7, - .freq = 2442}, - { .chan = 8, - .freq = 2447}, - { .chan = 9, - .freq = 2452}, - { .chan = 10, - .freq = 2457}, - { .chan = 11, - .freq = 2462}, - { .chan = 12, - .freq = 2467}, - { .chan = 13, - .freq = 2472}, - { .chan = 14, - .freq = 2484} + { .center_freq = 2412, .hw_value = 1 }, + { .center_freq = 2417, .hw_value = 2 }, + { .center_freq = 2422, .hw_value = 3 }, + { .center_freq = 2427, .hw_value = 4 }, + { .center_freq = 2432, .hw_value = 5 }, + { .center_freq = 2437, .hw_value = 6 }, + { .center_freq = 2442, .hw_value = 7 }, + { .center_freq = 2447, .hw_value = 8 }, + { .center_freq = 2452, .hw_value = 9 }, + { .center_freq = 2457, .hw_value = 10 }, + { .center_freq = 2462, .hw_value = 11 }, + { .center_freq = 2467, .hw_value = 12 }, + { .center_freq = 2472, .hw_value = 13 }, + { .center_freq = 2484, .hw_value = 14 }, }; static void housekeeping_init(struct zd_mac *mac); @@ -503,7 +488,9 @@ static int fill_ctrlset(struct zd_mac *mac, ZD_ASSERT(frag_len <= 0xffff); - cs->modulation = control->tx_rate; + cs->modulation = control->tx_rate->hw_value; + if (control->flags & IEEE80211_TXCTL_SHORT_PREAMBLE) + cs->modulation = control->tx_rate->hw_value_short; cs->tx_length = cpu_to_le16(frag_len); @@ -631,6 +618,8 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length) int bad_frame = 0; u16 fc; bool is_qos, is_4addr, need_padding; + int i; + u8 rate; if (length < ZD_PLCP_HEADER_SIZE + 10 /* IEEE80211_1ADDR_LEN */ + FCS_LEN + sizeof(struct rx_status)) @@ -660,14 +649,19 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length) } } - stats.channel = _zd_chip_get_channel(&mac->chip); - stats.freq = zd_channels[stats.channel - 1].freq; - stats.phymode = MODE_IEEE80211G; + stats.freq = zd_channels[_zd_chip_get_channel(&mac->chip) - 1].center_freq; + stats.band = IEEE80211_BAND_2GHZ; stats.ssi = status->signal_strength; stats.signal = zd_rx_qual_percent(buffer, length - sizeof(struct rx_status), status); - stats.rate = zd_rx_rate(buffer, status); + + rate = zd_rx_rate(buffer, status); + + /* todo: return index in the big switches in zd_rx_rate instead */ + for (i = 0; i < mac->band.n_bitrates; i++) + if (rate == mac->band.bitrates[i].hw_value) + stats.rate_idx = i; length -= ZD_PLCP_HEADER_SIZE + sizeof(struct rx_status); buffer += ZD_PLCP_HEADER_SIZE; @@ -736,7 +730,7 @@ static void zd_op_remove_interface(struct ieee80211_hw *hw, static int zd_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) { struct zd_mac *mac = zd_hw_mac(hw); - return zd_chip_set_channel(&mac->chip, conf->channel); + return zd_chip_set_channel(&mac->chip, conf->channel->hw_value); } static int zd_op_config_interface(struct ieee80211_hw *hw, @@ -894,7 +888,6 @@ struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf) { struct zd_mac *mac; struct ieee80211_hw *hw; - int i; hw = ieee80211_alloc_hw(sizeof(struct zd_mac), &zd_ops); if (!hw) { @@ -912,19 +905,14 @@ struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf) memcpy(mac->channels, zd_channels, sizeof(zd_channels)); memcpy(mac->rates, zd_rates, sizeof(zd_rates)); - mac->modes[0].mode = MODE_IEEE80211G; - mac->modes[0].num_rates = ARRAY_SIZE(zd_rates); - mac->modes[0].rates = mac->rates; - mac->modes[0].num_channels = ARRAY_SIZE(zd_channels); - mac->modes[0].channels = mac->channels; - mac->modes[1].mode = MODE_IEEE80211B; - mac->modes[1].num_rates = 4; - mac->modes[1].rates = mac->rates; - mac->modes[1].num_channels = ARRAY_SIZE(zd_channels); - mac->modes[1].channels = mac->channels; - - hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | - IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED; + mac->band.n_bitrates = ARRAY_SIZE(zd_rates); + mac->band.bitrates = mac->rates; + mac->band.n_channels = ARRAY_SIZE(zd_channels); + mac->band.channels = mac->channels; + + hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &mac->band; + + hw->flags = IEEE80211_HW_RX_INCLUDES_FCS; hw->max_rssi = 100; hw->max_signal = 100; @@ -933,14 +921,6 @@ struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf) skb_queue_head_init(&mac->ack_wait_queue); - for (i = 0; i < 2; i++) { - if (ieee80211_register_hwmode(hw, &mac->modes[i])) { - dev_dbg_f(&intf->dev, "cannot register hwmode\n"); - ieee80211_free_hw(hw); - return NULL; - } - } - zd_chip_init(&mac->chip, hw, intf); housekeeping_init(mac); INIT_WORK(&mac->set_multicast_hash_work, set_multicast_hash_handler); diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h index 2dde108df767..67dea9739c8f 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.h +++ b/drivers/net/wireless/zd1211rw/zd_mac.h @@ -185,7 +185,7 @@ struct zd_mac { struct sk_buff_head ack_wait_queue; struct ieee80211_channel channels[14]; struct ieee80211_rate rates[12]; - struct ieee80211_hw_mode modes[2]; + struct ieee80211_supported_band band; /* Short preamble (used for RTS/CTS) */ unsigned int short_preamble:1; -- cgit v1.2.1 From 7b72304d864ed281547341a49495a6eb3770681b Mon Sep 17 00:00:00 2001 From: Mohamed Abbas Date: Thu, 31 Jan 2008 21:46:40 -0800 Subject: iwlwifi: initialize ieee80211_channel->hw_value hw_value is being used uninitialized. fix it. Signed-off-by: Mohamed Abbas Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl3945-base.c | 1 + drivers/net/wireless/iwlwifi/iwl4965-base.c | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 57a1d70f2abf..41b45a2778bd 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -5395,6 +5395,7 @@ static int iwl3945_init_geos(struct iwl3945_priv *priv) geo_ch->center_freq = ieee80211chan2mhz(ch->channel); geo_ch->max_power = ch->max_power_avg; geo_ch->max_antenna_gain = 0xff; + geo_ch->hw_value = ch->channel; if (is_channel_valid(ch)) { if (!(ch->flags & EEPROM_CHANNEL_IBSS)) diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 6de969de4c84..933e0d44f69f 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -5815,6 +5815,7 @@ static int iwl4965_init_geos(struct iwl4965_priv *priv) geo_ch->center_freq = ieee80211chan2mhz(ch->channel); geo_ch->max_power = ch->max_power_avg; geo_ch->max_antenna_gain = 0xff; + geo_ch->hw_value = ch->channel; if (is_channel_valid(ch)) { if (!(ch->flags & EEPROM_CHANNEL_IBSS)) -- cgit v1.2.1 From 2c28b36275b53cfe380566c1810b3f500f7f4b5b Mon Sep 17 00:00:00 2001 From: Mohamed Abbas Date: Thu, 31 Jan 2008 21:46:41 -0800 Subject: iwlwifi: set rate_idx correctly from plcp rate_idx is derived from plcp information Signed-off-by: Mohamed Abbas Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index a89439320498..886a4b86605c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -3546,7 +3546,7 @@ static void iwl4965_rx_reply_rx(struct iwl4965_priv *priv, (rx_start->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ, .antenna = 0, - .rate_idx = iwl4965_hw_get_rate( + .rate_idx = iwl4965_rate_index_from_plcp( le32_to_cpu(rx_start->rate_n_flags)), .flag = 0, }; -- cgit v1.2.1 From d8ee398d183df36083e41e9162b0cf014f38f482 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Sun, 3 Feb 2008 21:51:04 -0500 Subject: ath5k: Port to new bitrate/channel API Author: Nick Kossifidis Tested on 5211, 5213+5112, 5213A+2112A and it wors fine. Also i figured out a way to process rate vallue found on status descriptors, it's still buggy but we are getting closer (i think it improved stability a little). Changes to hw.c, initvals.c, phy.c Changes-licensed-under: ISC Changes to ath5k.h, base.c, base.h Changes-licensed-under: 3-Clause-BSD Acked-by: Jiri Slaby Signed-off-by: Nick Kossifidis Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/Kconfig | 1 - drivers/net/wireless/ath5k/Makefile | 2 +- drivers/net/wireless/ath5k/ath5k.h | 100 +++++----- drivers/net/wireless/ath5k/base.c | 346 +++++++++++++++++++--------------- drivers/net/wireless/ath5k/base.h | 14 +- drivers/net/wireless/ath5k/hw.c | 170 +++++------------ drivers/net/wireless/ath5k/initvals.c | 2 +- drivers/net/wireless/ath5k/phy.c | 66 +++---- 8 files changed, 329 insertions(+), 372 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index cd5fcc67e954..714a6ca30ad2 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -735,7 +735,6 @@ config P54_PCI config ATH5K tristate "Atheros 5xxx wireless cards support" depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL - depends on BROKEN ---help--- This module adds support for wireless adapters based on Atheros 5xxx chipset. diff --git a/drivers/net/wireless/ath5k/Makefile b/drivers/net/wireless/ath5k/Makefile index 321641f99e13..ada1095d4ef1 100644 --- a/drivers/net/wireless/ath5k/Makefile +++ b/drivers/net/wireless/ath5k/Makefile @@ -1,2 +1,2 @@ -ath5k-objs = base.o hw.o regdom.o initvals.o phy.o debug.o +ath5k-objs = base.o hw.o initvals.o phy.o debug.o obj-$(CONFIG_ATH5K) += ath5k.o diff --git a/drivers/net/wireless/ath5k/ath5k.h b/drivers/net/wireless/ath5k/ath5k.h index 69dea3392612..9ea8c549b781 100644 --- a/drivers/net/wireless/ath5k/ath5k.h +++ b/drivers/net/wireless/ath5k/ath5k.h @@ -30,7 +30,6 @@ #include #include "hw.h" -#include "regdom.h" /* PCI IDs */ #define PCI_DEVICE_ID_ATHEROS_AR5210 0x0007 /* AR5210 */ @@ -251,18 +250,20 @@ struct ath5k_srev_name { */ #define MODULATION_TURBO 0x00000080 -enum ath5k_vendor_mode { - MODE_ATHEROS_TURBO = NUM_IEEE80211_MODES+1, - MODE_ATHEROS_TURBOG +enum ath5k_driver_mode { + AR5K_MODE_11A = 0, + AR5K_MODE_11A_TURBO = 1, + AR5K_MODE_11B = 2, + AR5K_MODE_11G = 3, + AR5K_MODE_11G_TURBO = 4, + AR5K_MODE_XR = 0, + AR5K_MODE_MAX = 5 }; -/* Number of supported mac80211 enum ieee80211_phymode modes by this driver */ -#define NUM_DRIVER_MODES 3 - /* adding this flag to rate_code enables short preamble, see ar5212_reg.h */ #define AR5K_SET_SHORT_PREAMBLE 0x04 -#define HAS_SHPREAMBLE(_ix) (rt->rates[_ix].modulation == IEEE80211_RATE_CCK_2) +#define HAS_SHPREAMBLE(_ix) (rt->rates[_ix].modulation == IEEE80211_RATE_SHORT_PREAMBLE) #define SHPREAMBLE_FLAG(_ix) (HAS_SHPREAMBLE(_ix) ? AR5K_SET_SHORT_PREAMBLE : 0) /****************\ @@ -560,8 +561,8 @@ struct ath5k_desc { * Used internaly in OpenHAL (ar5211.c/ar5212.c * for reset_tx_queue). Also see struct struct ieee80211_channel. */ -#define IS_CHAN_XR(_c) ((_c.val & CHANNEL_XR) != 0) -#define IS_CHAN_B(_c) ((_c.val & CHANNEL_B) != 0) +#define IS_CHAN_XR(_c) ((_c.hw_value & CHANNEL_XR) != 0) +#define IS_CHAN_B(_c) ((_c.hw_value & CHANNEL_B) != 0) /* * The following structure will be used to map 2GHz channels to @@ -584,7 +585,7 @@ struct ath5k_athchan_2ghz { /** * struct ath5k_rate - rate structure - * @valid: is this a valid rate for the current mode + * @valid: is this a valid rate for rate control (remove) * @modulation: respective mac80211 modulation * @rate_kbps: rate in kbit/s * @rate_code: hardware rate value, used in &struct ath5k_desc, on RX on @@ -643,47 +644,48 @@ struct ath5k_rate_table { /* * Rate tables... + * TODO: CLEAN THIS !!! */ #define AR5K_RATES_11A { 8, { \ 255, 255, 255, 255, 255, 255, 255, 255, 6, 4, 2, 0, \ 7, 5, 3, 1, 255, 255, 255, 255, 255, 255, 255, 255, \ 255, 255, 255, 255, 255, 255, 255, 255 }, { \ - { 1, IEEE80211_RATE_OFDM, 6000, 11, 140, 0 }, \ - { 1, IEEE80211_RATE_OFDM, 9000, 15, 18, 0 }, \ - { 1, IEEE80211_RATE_OFDM, 12000, 10, 152, 2 }, \ - { 1, IEEE80211_RATE_OFDM, 18000, 14, 36, 2 }, \ - { 1, IEEE80211_RATE_OFDM, 24000, 9, 176, 4 }, \ - { 1, IEEE80211_RATE_OFDM, 36000, 13, 72, 4 }, \ - { 1, IEEE80211_RATE_OFDM, 48000, 8, 96, 4 }, \ - { 1, IEEE80211_RATE_OFDM, 54000, 12, 108, 4 } } \ + { 1, 0, 6000, 11, 140, 0 }, \ + { 1, 0, 9000, 15, 18, 0 }, \ + { 1, 0, 12000, 10, 152, 2 }, \ + { 1, 0, 18000, 14, 36, 2 }, \ + { 1, 0, 24000, 9, 176, 4 }, \ + { 1, 0, 36000, 13, 72, 4 }, \ + { 1, 0, 48000, 8, 96, 4 }, \ + { 1, 0, 54000, 12, 108, 4 } } \ } #define AR5K_RATES_11B { 4, { \ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, \ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, \ 3, 2, 1, 0, 255, 255, 255, 255 }, { \ - { 1, IEEE80211_RATE_CCK, 1000, 27, 130, 0 }, \ - { 1, IEEE80211_RATE_CCK_2, 2000, 26, 132, 1 }, \ - { 1, IEEE80211_RATE_CCK_2, 5500, 25, 139, 1 }, \ - { 1, IEEE80211_RATE_CCK_2, 11000, 24, 150, 1 } } \ + { 1, 0, 1000, 27, 130, 0 }, \ + { 1, IEEE80211_RATE_SHORT_PREAMBLE, 2000, 26, 132, 1 }, \ + { 1, IEEE80211_RATE_SHORT_PREAMBLE, 5500, 25, 139, 1 }, \ + { 1, IEEE80211_RATE_SHORT_PREAMBLE, 11000, 24, 150, 1 } } \ } #define AR5K_RATES_11G { 12, { \ 255, 255, 255, 255, 255, 255, 255, 255, 10, 8, 6, 4, \ 11, 9, 7, 5, 255, 255, 255, 255, 255, 255, 255, 255, \ 3, 2, 1, 0, 255, 255, 255, 255 }, { \ - { 1, IEEE80211_RATE_CCK, 1000, 27, 2, 0 }, \ - { 1, IEEE80211_RATE_CCK_2, 2000, 26, 4, 1 }, \ - { 1, IEEE80211_RATE_CCK_2, 5500, 25, 11, 1 }, \ - { 1, IEEE80211_RATE_CCK_2, 11000, 24, 22, 1 }, \ - { 0, IEEE80211_RATE_OFDM, 6000, 11, 12, 4 }, \ - { 0, IEEE80211_RATE_OFDM, 9000, 15, 18, 4 }, \ - { 1, IEEE80211_RATE_OFDM, 12000, 10, 24, 6 }, \ - { 1, IEEE80211_RATE_OFDM, 18000, 14, 36, 6 }, \ - { 1, IEEE80211_RATE_OFDM, 24000, 9, 48, 8 }, \ - { 1, IEEE80211_RATE_OFDM, 36000, 13, 72, 8 }, \ - { 1, IEEE80211_RATE_OFDM, 48000, 8, 96, 8 }, \ - { 1, IEEE80211_RATE_OFDM, 54000, 12, 108, 8 } } \ + { 1, 0, 1000, 27, 2, 0 }, \ + { 1, IEEE80211_RATE_SHORT_PREAMBLE, 2000, 26, 4, 1 }, \ + { 1, IEEE80211_RATE_SHORT_PREAMBLE, 5500, 25, 11, 1 }, \ + { 1, IEEE80211_RATE_SHORT_PREAMBLE, 11000, 24, 22, 1 }, \ + { 0, 0, 6000, 11, 12, 4 }, \ + { 0, 0, 9000, 15, 18, 4 }, \ + { 1, 0, 12000, 10, 24, 6 }, \ + { 1, 0, 18000, 14, 36, 6 }, \ + { 1, 0, 24000, 9, 48, 8 }, \ + { 1, 0, 36000, 13, 72, 8 }, \ + { 1, 0, 48000, 8, 96, 8 }, \ + { 1, 0, 54000, 12, 108, 8 } } \ } #define AR5K_RATES_TURBO { 8, { \ @@ -708,14 +710,14 @@ struct ath5k_rate_table { { 1, MODULATION_XR, 1000, 2, 139, 1 }, \ { 1, MODULATION_XR, 2000, 6, 150, 2 }, \ { 1, MODULATION_XR, 3000, 1, 150, 3 }, \ - { 1, IEEE80211_RATE_OFDM, 6000, 11, 140, 4 }, \ - { 1, IEEE80211_RATE_OFDM, 9000, 15, 18, 4 }, \ - { 1, IEEE80211_RATE_OFDM, 12000, 10, 152, 6 }, \ - { 1, IEEE80211_RATE_OFDM, 18000, 14, 36, 6 }, \ - { 1, IEEE80211_RATE_OFDM, 24000, 9, 176, 8 }, \ - { 1, IEEE80211_RATE_OFDM, 36000, 13, 72, 8 }, \ - { 1, IEEE80211_RATE_OFDM, 48000, 8, 96, 8 }, \ - { 1, IEEE80211_RATE_OFDM, 54000, 12, 108, 8 } } \ + { 1, 0, 6000, 11, 140, 4 }, \ + { 1, 0, 9000, 15, 18, 4 }, \ + { 1, 0, 12000, 10, 152, 6 }, \ + { 1, 0, 18000, 14, 36, 6 }, \ + { 1, 0, 24000, 9, 176, 8 }, \ + { 1, 0, 36000, 13, 72, 8 }, \ + { 1, 0, 48000, 8, 96, 8 }, \ + { 1, 0, 54000, 12, 108, 8 } } \ } /* @@ -895,7 +897,7 @@ struct ath5k_capabilities { * Supported PHY modes * (ie. CHANNEL_A, CHANNEL_B, ...) */ - DECLARE_BITMAP(cap_mode, NUM_DRIVER_MODES); + DECLARE_BITMAP(cap_mode, AR5K_MODE_MAX); /* * Frequency range (without regulation restrictions) @@ -907,14 +909,6 @@ struct ath5k_capabilities { u16 range_5ghz_max; } cap_range; - /* - * Active regulation domain settings - */ - struct { - enum ath5k_regdom reg_current; - enum ath5k_regdom reg_hw; - } cap_regdomain; - /* * Values stored in the EEPROM (some of them...) */ @@ -1129,8 +1123,6 @@ extern int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio); extern u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio); extern int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val); extern void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, u32 interrupt_level); -/* Regulatory Domain/Channels Setup */ -extern u16 ath5k_get_regdomain(struct ath5k_hw *ah); /* Misc functions */ extern int ath5k_hw_get_capability(struct ath5k_hw *ah, enum ath5k_capability_type cap_type, u32 capability, u32 *result); diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index bef967ce34a6..52e55f67b735 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -240,6 +240,8 @@ static int ath5k_chan_set(struct ath5k_softc *sc, static void ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode); static void ath5k_mode_setup(struct ath5k_softc *sc); +static void ath5k_set_total_hw_rates(struct ath5k_softc *sc); + /* Descriptor setup */ static int ath5k_desc_alloc(struct ath5k_softc *sc, struct pci_dev *pdev); @@ -515,12 +517,12 @@ ath5k_pci_probe(struct pci_dev *pdev, /* Single chip radio (!RF5111) */ if(sc->ah->ah_radio_5ghz_revision && !sc->ah->ah_radio_2ghz_revision) { /* No 5GHz support -> report 2GHz radio */ - if(!test_bit(MODE_IEEE80211A, sc->ah->ah_capabilities.cap_mode)){ + if(!test_bit(AR5K_MODE_11A, sc->ah->ah_capabilities.cap_mode)){ ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n", ath5k_chip_name(AR5K_VERSION_RAD,sc->ah->ah_radio_5ghz_revision), sc->ah->ah_radio_5ghz_revision); /* No 2GHz support (5110 and some 5Ghz only cards) -> report 5Ghz radio */ - } else if(!test_bit(MODE_IEEE80211B, sc->ah->ah_capabilities.cap_mode)){ + } else if(!test_bit(AR5K_MODE_11B, sc->ah->ah_capabilities.cap_mode)){ ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n", ath5k_chip_name(AR5K_VERSION_RAD,sc->ah->ah_radio_5ghz_revision), sc->ah->ah_radio_5ghz_revision); @@ -693,11 +695,14 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) goto err; } + /* Set *_rates so we can map hw rate index */ + ath5k_set_total_hw_rates(sc); + /* NB: setup here so ath5k_rate_update is happy */ - if (test_bit(MODE_IEEE80211A, ah->ah_modes)) - ath5k_setcurmode(sc, MODE_IEEE80211A); + if (test_bit(AR5K_MODE_11A, ah->ah_modes)) + ath5k_setcurmode(sc, AR5K_MODE_11A); else - ath5k_setcurmode(sc, MODE_IEEE80211B); + ath5k_setcurmode(sc, AR5K_MODE_11B); /* * Allocate tx+rx descriptors and populate the lists. @@ -837,12 +842,9 @@ ath5k_copy_rates(struct ieee80211_rate *rates, return 0; for (i = 0, count = 0; i < rt->rate_count && max > 0; i++) { - if (!rt->rates[i].valid) - continue; - rates->rate = rt->rates[i].rate_kbps / 100; - rates->val = rt->rates[i].rate_code; - rates->flags = rt->rates[i].modulation; - rates++; + rates[count].bitrate = rt->rates[i].rate_kbps / 100; + rates[count].hw_value = rt->rates[i].rate_code; + rates[count].flags = rt->rates[i].modulation; count++; max--; } @@ -856,43 +858,22 @@ ath5k_copy_channels(struct ath5k_hw *ah, unsigned int mode, unsigned int max) { - static const struct { unsigned int mode, mask, chan; } map[] = { - [MODE_IEEE80211A] = { CHANNEL_OFDM, CHANNEL_OFDM | CHANNEL_TURBO, CHANNEL_A }, - [MODE_ATHEROS_TURBO] = { CHANNEL_OFDM|CHANNEL_TURBO, CHANNEL_OFDM | CHANNEL_TURBO, CHANNEL_T }, - [MODE_IEEE80211B] = { CHANNEL_CCK, CHANNEL_CCK, CHANNEL_B }, - [MODE_IEEE80211G] = { CHANNEL_OFDM, CHANNEL_OFDM, CHANNEL_G }, - [MODE_ATHEROS_TURBOG] = { CHANNEL_OFDM | CHANNEL_TURBO, CHANNEL_OFDM | CHANNEL_TURBO, CHANNEL_TG }, - }; - static const struct ath5k_regchannel chans_2ghz[] = - IEEE80211_CHANNELS_2GHZ; - static const struct ath5k_regchannel chans_5ghz[] = - IEEE80211_CHANNELS_5GHZ; - const struct ath5k_regchannel *chans; - enum ath5k_regdom dmn; - unsigned int i, count, size, chfreq, all, f, ch; + unsigned int i, count, size, chfreq, freq, ch; if (!test_bit(mode, ah->ah_modes)) return 0; - all = ah->ah_regdomain == DMN_DEFAULT || CHAN_DEBUG == 1; - switch (mode) { - case MODE_IEEE80211A: - case MODE_ATHEROS_TURBO: + case AR5K_MODE_11A: + case AR5K_MODE_11A_TURBO: /* 1..220, but 2GHz frequencies are filtered by check_channel */ - size = all ? 220 : ARRAY_SIZE(chans_5ghz); - chans = chans_5ghz; - dmn = ath5k_regdom2flag(ah->ah_regdomain, - IEEE80211_CHANNELS_5GHZ_MIN); + size = 220 ; chfreq = CHANNEL_5GHZ; break; - case MODE_IEEE80211B: - case MODE_IEEE80211G: - case MODE_ATHEROS_TURBOG: - size = all ? 26 : ARRAY_SIZE(chans_2ghz); - chans = chans_2ghz; - dmn = ath5k_regdom2flag(ah->ah_regdomain, - IEEE80211_CHANNELS_2GHZ_MIN); + case AR5K_MODE_11B: + case AR5K_MODE_11G: + case AR5K_MODE_11G_TURBO: + size = 26; chfreq = CHANNEL_2GHZ; break; default: @@ -901,25 +882,26 @@ ath5k_copy_channels(struct ath5k_hw *ah, } for (i = 0, count = 0; i < size && max > 0; i++) { - ch = all ? i + 1 : chans[i].chan; - f = ath5k_ieee2mhz(ch); - /* Check if channel is supported by the chipset */ - if (!ath5k_channel_ok(ah, f, chfreq)) - continue; + ch = i + 1 ; + freq = ath5k_ieee2mhz(ch); - /* Match regulation domain */ - if (!all && !(IEEE80211_DMN(chans[i].domain) & - IEEE80211_DMN(dmn))) + /* Check if channel is supported by the chipset */ + if (!ath5k_channel_ok(ah, freq, chfreq)) continue; - if (!all && (chans[i].mode & map[mode].mask) != map[mode].mode) - continue; + /* Write channel info and increment counter */ + channels[count].center_freq = freq; + + if((mode == AR5K_MODE_11A) || + (mode == AR5K_MODE_11G)){ + channels[count].hw_value = chfreq|CHANNEL_OFDM; + } else if((mode == AR5K_MODE_11A_TURBO) || + (mode == AR5K_MODE_11G_TURBO)){ + channels[count].hw_value = chfreq|CHANNEL_OFDM|CHANNEL_TURBO; + }if(mode == AR5K_MODE_11B) { + channels[count].hw_value = CHANNEL_B; + } - /* Write channel and increment counter */ - channels->chan = ch; - channels->freq = f; - channels->val = map[mode].chan; - channels++; count++; max--; } @@ -927,95 +909,76 @@ ath5k_copy_channels(struct ath5k_hw *ah, return count; } -/* Only tries to register modes our EEPROM says it can support */ -#define REGISTER_MODE(m) do { \ - ret = ath5k_register_mode(hw, m); \ - if (ret) \ - return ret; \ -} while (0) \ - -static inline int -ath5k_register_mode(struct ieee80211_hw *hw, u8 m) +static int +ath5k_getchannels(struct ieee80211_hw *hw) { struct ath5k_softc *sc = hw->priv; - struct ieee80211_hw_mode *modes = sc->modes; - unsigned int i; - int ret; + struct ath5k_hw *ah = sc->ah; + struct ieee80211_supported_band *sbands = sc->sbands; + const struct ath5k_rate_table *hw_rates; + unsigned int max_r, max_c, count_r, count_c; + int mode2g = AR5K_MODE_11G; - if (!test_bit(m, sc->ah->ah_capabilities.cap_mode)) - return 0; + BUILD_BUG_ON(ARRAY_SIZE(sc->sbands) < IEEE80211_NUM_BANDS); - for (i = 0; i < NUM_DRIVER_MODES; i++) { - if (modes[i].mode != m || !modes[i].num_channels) - continue; - ret = ieee80211_register_hwmode(hw, &modes[i]); - if (ret) { - ATH5K_ERR(sc, "can't register hwmode %u\n", m); - return ret; + max_r = ARRAY_SIZE(sc->rates); + max_c = ARRAY_SIZE(sc->channels); + count_r = count_c = 0; + + /* 2GHz band */ + if(!test_bit(AR5K_MODE_11G, sc->ah->ah_capabilities.cap_mode)){ + mode2g = AR5K_MODE_11B; + if(!test_bit(AR5K_MODE_11B, sc->ah->ah_capabilities.cap_mode)){ + mode2g = -1; } - return 0; } - BUG(); -} -static int -ath5k_getchannels(struct ieee80211_hw *hw) -{ - struct ath5k_softc *sc = hw->priv; - struct ath5k_hw *ah = sc->ah; - struct ieee80211_hw_mode *modes = sc->modes; - unsigned int i, max_r, max_c; - int ret; + if(mode2g > 0){ + struct ieee80211_supported_band *sband = &sbands[IEEE80211_BAND_2GHZ]; - BUILD_BUG_ON(ARRAY_SIZE(sc->modes) < 3); + sband->bitrates = sc->rates; + sband->channels = sc->channels; - /* The order here does not matter */ - modes[0].mode = MODE_IEEE80211G; - modes[1].mode = MODE_IEEE80211B; - modes[2].mode = MODE_IEEE80211A; + sband->band = IEEE80211_BAND_2GHZ; + sband->n_channels = ath5k_copy_channels(ah, sband->channels, + mode2g, max_c); - max_r = ARRAY_SIZE(sc->rates); - max_c = ARRAY_SIZE(sc->channels); + hw_rates = ath5k_hw_get_rate_table(ah, mode2g); + sband->n_bitrates = ath5k_copy_rates(sband->bitrates, + hw_rates,max_r); - for (i = 0; i < NUM_DRIVER_MODES; i++) { - struct ieee80211_hw_mode *mode = &modes[i]; - const struct ath5k_rate_table *hw_rates; + count_c = sband->n_channels; + count_r = sband->n_bitrates; - if (i == 0) { - modes[0].rates = sc->rates; - modes->channels = sc->channels; - } else { - struct ieee80211_hw_mode *prev_mode = &modes[i-1]; - int prev_num_r = prev_mode->num_rates; - int prev_num_c = prev_mode->num_channels; - mode->rates = &prev_mode->rates[prev_num_r]; - mode->channels = &prev_mode->channels[prev_num_c]; - } + hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband; + + max_r -= count_r; + max_c -= count_c; - hw_rates = ath5k_hw_get_rate_table(ah, mode->mode); - mode->num_rates = ath5k_copy_rates(mode->rates, hw_rates, - max_r); - mode->num_channels = ath5k_copy_channels(ah, mode->channels, - mode->mode, max_c); - max_r -= mode->num_rates; - max_c -= mode->num_channels; } - /* We try to register all modes this driver supports. We don't bother - * with MODE_IEEE80211B for AR5212 as MODE_IEEE80211G already accounts - * for that as per mac80211. Then, REGISTER_MODE() will will actually - * check the eeprom reading for more reliable capability information. - * Order matters here as per mac80211's latest preference. This will - * all hopefullly soon go away. */ + /* 5GHz band */ - REGISTER_MODE(MODE_IEEE80211G); - if (ah->ah_version != AR5K_AR5212) - REGISTER_MODE(MODE_IEEE80211B); - REGISTER_MODE(MODE_IEEE80211A); + if(test_bit(AR5K_MODE_11A, sc->ah->ah_capabilities.cap_mode)){ + struct ieee80211_supported_band *sband = &sbands[IEEE80211_BAND_5GHZ]; - ath5k_debug_dump_modes(sc, modes); + sband->bitrates = &sc->rates[count_r]; + sband->channels = &sc->channels[count_c]; - return ret; + sband->band = IEEE80211_BAND_5GHZ; + sband->n_channels = ath5k_copy_channels(ah, sband->channels, + AR5K_MODE_11A, max_c); + + hw_rates = ath5k_hw_get_rate_table(ah, AR5K_MODE_11A); + sband->n_bitrates = ath5k_copy_rates(sband->bitrates, + hw_rates,max_r); + + hw->wiphy->bands[IEEE80211_BAND_5GHZ] = sband; + } + +/* FIXME: ath5k_debug_dump_modes(sc, modes); */ + + return 0; } /* @@ -1030,11 +993,15 @@ ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan) struct ath5k_hw *ah = sc->ah; int ret; - ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "%u (%u MHz) -> %u (%u MHz)\n", - sc->curchan->chan, sc->curchan->freq, - chan->chan, chan->freq); + ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "(%u MHz) -> (%u MHz)\n", + sc->curchan->center_freq, chan->center_freq); + + if (chan->center_freq != sc->curchan->center_freq || + chan->hw_value != sc->curchan->hw_value) { + + sc->curchan = chan; + sc->curband = &sc->sbands[chan->band]; - if (chan->freq != sc->curchan->freq || chan->val != sc->curchan->val) { /* * To switch channels clear any pending DMA operations; * wait long enough for the RX fifo to drain, reset the @@ -1044,13 +1011,13 @@ ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan) ath5k_hw_set_intr(ah, 0); /* disable interrupts */ ath5k_txq_cleanup(sc); /* clear pending tx frames */ ath5k_rx_stop(sc); /* turn off frame recv */ - ret = ath5k_hw_reset(ah, sc->opmode, chan, true); + ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, true); if (ret) { - ATH5K_ERR(sc, "%s: unable to reset channel %u " - "(%u Mhz)\n", __func__, chan->chan, chan->freq); + ATH5K_ERR(sc, "%s: unable to reset channel " + "(%u Mhz)\n", __func__, chan->center_freq); return ret; } - sc->curchan = chan; + ath5k_hw_set_txpower_limit(sc->ah, 0); /* @@ -1081,6 +1048,9 @@ ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan) return 0; } +/* + * TODO: CLEAN THIS !!! + */ static void ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode) { @@ -1121,10 +1091,6 @@ ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode) continue; } sc->hwmap[i].txflags = IEEE80211_RADIOTAP_F_DATAPAD; - if (SHPREAMBLE_FLAG(ix) || rt->rates[ix].modulation == - IEEE80211_RATE_OFDM) - sc->hwmap[i].txflags |= - IEEE80211_RADIOTAP_F_SHORTPRE; /* receive frames include FCS */ sc->hwmap[i].rxflags = sc->hwmap[i].txflags | IEEE80211_RADIOTAP_F_FCS; @@ -1142,6 +1108,12 @@ ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode) } sc->curmode = mode; + + if(mode == AR5K_MODE_11A){ + sc->curband = &sc->sbands[IEEE80211_BAND_5GHZ]; + } else { + sc->curband = &sc->sbands[IEEE80211_BAND_2GHZ]; + } } static void @@ -1164,6 +1136,72 @@ ath5k_mode_setup(struct ath5k_softc *sc) ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "RX filter 0x%x\n", rfilt); } +/* + * Match the hw provided rate index (through descriptors) + * to an index for sc->curband->bitrates, so it can be used + * by the stack. + * + * This one is a little bit tricky but i think i'm right + * about this... + * + * We have 4 rate tables in the following order: + * XR (4 rates) + * 802.11a (8 rates) + * 802.11b (4 rates) + * 802.11g (12 rates) + * that make the hw rate table. + * + * Lets take a 5211 for example that supports a and b modes only. + * First comes the 802.11a table and then 802.11b (total 12 rates). + * When hw returns eg. 11 it points to the last 802.11b rate (11Mbit), + * if it returns 2 it points to the second 802.11a rate etc. + * + * Same goes for 5212 who has xr/a/b/g support (total 28 rates). + * First comes the XR table, then 802.11a, 802.11b and 802.11g. + * When hw returns eg. 27 it points to the last 802.11g rate (54Mbits) etc + */ +static void +ath5k_set_total_hw_rates(struct ath5k_softc *sc){ + + struct ath5k_hw *ah = sc->ah; + + if(test_bit(AR5K_MODE_11A, ah->ah_modes)) + sc->a_rates = 8; + + if(test_bit(AR5K_MODE_11B, ah->ah_modes)) + sc->b_rates = 4; + + if(test_bit(AR5K_MODE_11G, ah->ah_modes)) + sc->g_rates = 12; + + /* XXX: Need to see what what happens when + xr disable bits in eeprom are set */ + if(ah->ah_version >= AR5K_AR5212) + sc->xr_rates = 4; + +} + +static inline int +ath5k_hw_to_driver_rix(struct ath5k_softc *sc, int hw_rix){ + + int mac80211_rix; + + if(sc->curband->band == IEEE80211_BAND_2GHZ){ + /* We setup a g ratetable for both b/g modes */ + mac80211_rix = hw_rix - sc->b_rates - sc->a_rates - sc->xr_rates; + } else { + mac80211_rix = hw_rix - sc->xr_rates; + } + + /* Something went wrong, fallback to basic rate for this band */ + if((mac80211_rix >= sc->curband->n_bitrates) || + (mac80211_rix <= 0 )){ + mac80211_rix = 1; + } + + return mac80211_rix; +} + @@ -1268,7 +1306,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, ret = ah->ah_setup_tx_desc(ah, ds, pktlen, ieee80211_get_hdrlen_from_skb(skb), AR5K_PKT_TYPE_NORMAL, - (ctl->power_level * 2), ctl->tx_rate, ctl->retry_limit, keyidx, 0, flags, 0, 0); + (sc->power_level * 2), ctl->tx_rate->hw_value, ctl->retry_limit, keyidx, 0, flags, 0, 0); if (ret) goto err_unmap; @@ -1791,9 +1829,8 @@ accept: rxs.mactime = ath5k_extend_tsf(sc->ah, ds->ds_rxstat.rs_tstamp); rxs.flag |= RX_FLAG_TSFT; - rxs.freq = sc->curchan->freq; - rxs.channel = sc->curchan->chan; - rxs.phymode = sc->curmode; + rxs.freq = sc->curchan->center_freq; + rxs.band = sc->curband->band; /* * signal quality: @@ -1811,7 +1848,7 @@ accept: rxs.signal = ds->ds_rxstat.rs_rssi * 100 / 64; rxs.antenna = ds->ds_rxstat.rs_antenna; - rxs.rate = ds->ds_rxstat.rs_rate; + rxs.rate_idx = ath5k_hw_to_driver_rix(sc,ds->ds_rxstat.rs_rate); rxs.flag |= ath5k_rx_decrypted(sc, ds, skb); ath5k_debug_dump_skb(sc, skb, "RX ", 0); @@ -1958,7 +1995,7 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, ds->ds_data = bf->skbaddr; ret = ah->ah_setup_tx_desc(ah, ds, skb->len, ieee80211_get_hdrlen_from_skb(skb), - AR5K_PKT_TYPE_BEACON, (ctl->power_level * 2), ctl->tx_rate, 1, + AR5K_PKT_TYPE_BEACON, (sc->power_level * 2), ctl->tx_rate->hw_value, 1, AR5K_TXKEYIX_INVALID, antenna, flags, 0, 0); if (ret) goto err_unmap; @@ -2211,7 +2248,8 @@ ath5k_init(struct ath5k_softc *sc) * be followed by initialization of the appropriate bits * and then setup of the interrupt mask. */ - sc->curchan = sc->hw->conf.chan; + sc->curchan = sc->hw->conf.channel; + sc->curband = &sc->sbands[sc->curchan->band]; ret = ath5k_hw_reset(sc->ah, sc->opmode, sc->curchan, false); if (ret) { ATH5K_ERR(sc, "unable to reset hardware: %d\n", ret); @@ -2448,7 +2486,7 @@ ath5k_calibrate(unsigned long data) struct ath5k_hw *ah = sc->ah; ATH5K_DBG(sc, ATH5K_DEBUG_CALIBRATE, "channel %u/%x\n", - sc->curchan->chan, sc->curchan->val); + ieee80211_frequency_to_channel(sc->curchan->center_freq), sc->curchan->hw_value); if (ath5k_hw_get_rf_gain(ah) == AR5K_RFGAIN_NEED_CHANGE) { /* @@ -2460,7 +2498,7 @@ ath5k_calibrate(unsigned long data) } if (ath5k_hw_phy_calibrate(ah, sc->curchan)) ATH5K_ERR(sc, "calibration of channel %u failed\n", - sc->curchan->chan); + ieee80211_frequency_to_channel(sc->curchan->center_freq)); mod_timer(&sc->calib_tim, round_jiffies(jiffies + msecs_to_jiffies(ath5k_calinterval * 1000))); @@ -2558,7 +2596,7 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb, memmove(skb->data, skb->data+pad, hdrlen); } - sc->led_txrate = ctl->tx_rate; + sc->led_txrate = ctl->tx_rate->hw_value; spin_lock_irqsave(&sc->txbuflock, flags); if (list_empty(&sc->txbuf)) { @@ -2597,11 +2635,6 @@ ath5k_reset(struct ieee80211_hw *hw) int ret; ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "resetting\n"); - /* - * Convert to a hw channel description with the flags - * constrained to reflect the current operating mode. - */ - sc->curchan = hw->conf.chan; ath5k_hw_set_intr(ah, 0); ath5k_txq_cleanup(sc); @@ -2692,6 +2725,9 @@ end: mutex_unlock(&sc->lock); } +/* + * TODO: Phy disable/diversity etc + */ static int ath5k_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) @@ -2699,9 +2735,9 @@ ath5k_config(struct ieee80211_hw *hw, struct ath5k_softc *sc = hw->priv; sc->bintval = conf->beacon_int; - ath5k_setcurmode(sc, conf->phymode); + sc->power_level = conf->power_level; - return ath5k_chan_set(sc, conf->chan); + return ath5k_chan_set(sc, conf->channel); } static int diff --git a/drivers/net/wireless/ath5k/base.h b/drivers/net/wireless/ath5k/base.h index 8287ae787f12..bbe7a5438154 100644 --- a/drivers/net/wireless/ath5k/base.h +++ b/drivers/net/wireless/ath5k/base.h @@ -83,7 +83,7 @@ struct ath5k_txq { #if CHAN_DEBUG #define ATH_CHAN_MAX (26+26+26+200+200) #else -#define ATH_CHAN_MAX (14+14+14+252+20) /* XXX what's the max? */ +#define ATH_CHAN_MAX (14+14+14+252+20) #endif /* Software Carrier, keeps track of the driver state @@ -95,12 +95,19 @@ struct ath5k_softc { struct ieee80211_tx_queue_stats tx_stats; struct ieee80211_low_level_stats ll_stats; struct ieee80211_hw *hw; /* IEEE 802.11 common */ - struct ieee80211_hw_mode modes[NUM_DRIVER_MODES]; + struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; struct ieee80211_channel channels[ATH_CHAN_MAX]; - struct ieee80211_rate rates[AR5K_MAX_RATES * NUM_DRIVER_MODES]; + struct ieee80211_rate rates[AR5K_MAX_RATES * IEEE80211_NUM_BANDS]; enum ieee80211_if_types opmode; struct ath5k_hw *ah; /* Atheros HW */ + struct ieee80211_supported_band *curband; + + u8 a_rates; + u8 b_rates; + u8 g_rates; + u8 xr_rates; + #if ATH5K_DEBUG struct ath5k_dbg_info debug; /* debug info */ #endif @@ -169,6 +176,7 @@ struct ath5k_softc { unsigned int nexttbtt; /* next beacon time in TU */ struct timer_list calib_tim; /* calibration timer */ + int power_level; /* Requested tx power in dbm */ }; #define ath5k_hw_hasbssidmask(_ah) \ diff --git a/drivers/net/wireless/ath5k/hw.c b/drivers/net/wireless/ath5k/hw.c index c2de2d958e8e..998da6be2be3 100644 --- a/drivers/net/wireless/ath5k/hw.c +++ b/drivers/net/wireless/ath5k/hw.c @@ -140,9 +140,6 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) * HW information */ - /* Get reg domain from eeprom */ - ath5k_get_regdomain(ah); - ah->ah_op_mode = IEEE80211_IF_TYPE_STA; ah->ah_radar.r_enabled = AR5K_TUNE_RADAR_ALERT; ah->ah_turbo = false; @@ -405,15 +402,15 @@ const struct ath5k_rate_table *ath5k_hw_get_rate_table(struct ath5k_hw *ah, /* Get rate tables */ switch (mode) { - case MODE_IEEE80211A: + case AR5K_MODE_11A: return &ath5k_rt_11a; - case MODE_ATHEROS_TURBO: + case AR5K_MODE_11A_TURBO: return &ath5k_rt_turbo; - case MODE_IEEE80211B: + case AR5K_MODE_11B: return &ath5k_rt_11b; - case MODE_IEEE80211G: + case AR5K_MODE_11G: return &ath5k_rt_11g; - case MODE_ATHEROS_TURBOG: + case AR5K_MODE_11G_TURBO: return &ath5k_rt_xr; } @@ -457,15 +454,15 @@ static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah, ds_coef_exp, ds_coef_man, clock; if (!(ah->ah_version == AR5K_AR5212) || - !(channel->val & CHANNEL_OFDM)) + !(channel->hw_value & CHANNEL_OFDM)) BUG(); /* Seems there are two PLLs, one for baseband sampling and one * for tuning. Tuning basebands are 40 MHz or 80MHz when in * turbo. */ - clock = channel->val & CHANNEL_TURBO ? 80 : 40; + clock = channel->hw_value & CHANNEL_TURBO ? 80 : 40; coef_scaled = ((5 * (clock << 24)) / 2) / - channel->freq; + channel->center_freq; for (coef_exp = 31; coef_exp > 0; coef_exp--) if ((coef_scaled >> coef_exp) & 0x1) @@ -492,8 +489,7 @@ static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah, * ath5k_hw_write_rate_duration - set rate duration during hw resets * * @ah: the &struct ath5k_hw - * @driver_mode: one of enum ieee80211_phymode or our one of our own - * vendor modes + * @mode: one of enum ath5k_driver_mode * * Write the rate duration table for the current mode upon hw reset. This * is a helper for ath5k_hw_reset(). It seems all this is doing is setting @@ -504,19 +500,20 @@ static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah, * */ static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah, - unsigned int driver_mode) + unsigned int mode) { struct ath5k_softc *sc = ah->ah_sc; const struct ath5k_rate_table *rt; + struct ieee80211_rate srate = {}; unsigned int i; /* Get rate table for the current operating mode */ - rt = ath5k_hw_get_rate_table(ah, - driver_mode); + rt = ath5k_hw_get_rate_table(ah, mode); /* Write rate duration table */ for (i = 0; i < rt->rate_count; i++) { const struct ath5k_rate *rate, *control_rate; + u32 reg; u16 tx_time; @@ -526,6 +523,8 @@ static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah, /* Set ACK timeout */ reg = AR5K_RATE_DUR(rate->rate_code); + srate.bitrate = control_rate->rate_kbps/100; + /* An ACK frame consists of 10 bytes. If you add the FCS, * which ieee80211_generic_frame_duration() adds, * its 14 bytes. Note we use the control rate and not the @@ -533,7 +532,7 @@ static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah, * ieee80211_duration() for a brief description of * what rate we should choose to TX ACKs. */ tx_time = ieee80211_generic_frame_duration(sc->hw, - sc->vif, 10, control_rate->rate_kbps/100); + sc->vif, 10, &srate); ath5k_hw_reg_write(ah, tx_time, reg); @@ -567,7 +566,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, { struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; u32 data, s_seq, s_ant, s_led[3]; - unsigned int i, mode, freq, ee_mode, ant[2], driver_mode = -1; + unsigned int i, mode, freq, ee_mode, ant[2]; int ret; ATH5K_TRACE(ah->ah_sc); @@ -602,7 +601,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, /*Wakeup the device*/ - ret = ath5k_hw_nic_wakeup(ah, channel->val, false); + ret = ath5k_hw_nic_wakeup(ah, channel->hw_value, false); if (ret) return ret; @@ -624,37 +623,32 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, return -EINVAL; } - switch (channel->val & CHANNEL_MODES) { + switch (channel->hw_value & CHANNEL_MODES) { case CHANNEL_A: - mode = AR5K_INI_VAL_11A; + mode = AR5K_MODE_11A; freq = AR5K_INI_RFGAIN_5GHZ; ee_mode = AR5K_EEPROM_MODE_11A; - driver_mode = MODE_IEEE80211A; break; case CHANNEL_G: - mode = AR5K_INI_VAL_11G; + mode = AR5K_MODE_11G; freq = AR5K_INI_RFGAIN_2GHZ; ee_mode = AR5K_EEPROM_MODE_11G; - driver_mode = MODE_IEEE80211G; break; case CHANNEL_B: - mode = AR5K_INI_VAL_11B; + mode = AR5K_MODE_11B; freq = AR5K_INI_RFGAIN_2GHZ; ee_mode = AR5K_EEPROM_MODE_11B; - driver_mode = MODE_IEEE80211B; break; case CHANNEL_T: - mode = AR5K_INI_VAL_11A_TURBO; + mode = AR5K_MODE_11A_TURBO; freq = AR5K_INI_RFGAIN_5GHZ; ee_mode = AR5K_EEPROM_MODE_11A; - driver_mode = MODE_ATHEROS_TURBO; break; /*Is this ok on 5211 too ?*/ case CHANNEL_TG: - mode = AR5K_INI_VAL_11G_TURBO; + mode = AR5K_MODE_11G_TURBO; freq = AR5K_INI_RFGAIN_2GHZ; ee_mode = AR5K_EEPROM_MODE_11G; - driver_mode = MODE_ATHEROS_TURBOG; break; case CHANNEL_XR: if (ah->ah_version == AR5K_AR5211) { @@ -662,14 +656,13 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, "XR mode not available on 5211"); return -EINVAL; } - mode = AR5K_INI_VAL_XR; + mode = AR5K_MODE_XR; freq = AR5K_INI_RFGAIN_5GHZ; ee_mode = AR5K_EEPROM_MODE_11A; - driver_mode = MODE_IEEE80211A; break; default: ATH5K_ERR(ah->ah_sc, - "invalid channel: %d\n", channel->freq); + "invalid channel: %d\n", channel->center_freq); return -EINVAL; } @@ -702,7 +695,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, if (ah->ah_version > AR5K_AR5211){ /* found on 5213+ */ ath5k_hw_reg_write(ah, 0x0002a002, AR5K_PHY(11)); - if (channel->val == CHANNEL_G) + if (channel->hw_value == CHANNEL_G) ath5k_hw_reg_write(ah, 0x00f80d80, AR5K_PHY(83)); /* 0x00fc0ec0 */ else ath5k_hw_reg_write(ah, 0x00000000, AR5K_PHY(83)); @@ -720,7 +713,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, AR5K_SREV_RAD_5112A) { ath5k_hw_reg_write(ah, AR5K_PHY_CCKTXCTL_WORLD, AR5K_PHY_CCKTXCTL); - if (channel->val & CHANNEL_5GHZ) + if (channel->hw_value & CHANNEL_5GHZ) data = 0xffb81020; else data = 0xffb80d20; @@ -740,7 +733,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, * mac80211 are integrated */ if (ah->ah_version == AR5K_AR5212 && ah->ah_sc->vif != NULL) - ath5k_hw_write_rate_duration(ah, driver_mode); + ath5k_hw_write_rate_duration(ah, mode); /* * Write RF registers @@ -756,7 +749,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, /* Write OFDM timings on 5212*/ if (ah->ah_version == AR5K_AR5212 && - channel->val & CHANNEL_OFDM) { + channel->hw_value & CHANNEL_OFDM) { ret = ath5k_hw_write_ofdm_timings(ah, channel); if (ret) return ret; @@ -765,7 +758,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, /*Enable/disable 802.11b mode on 5111 (enable 2111 frequency converter + CCK)*/ if (ah->ah_radio == AR5K_RF5111) { - if (driver_mode == MODE_IEEE80211B) + if (mode == AR5K_MODE_11B) AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG, AR5K_TXCFG_B_MODE); else @@ -903,7 +896,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, if (ah->ah_version != AR5K_AR5210) { data = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) & AR5K_PHY_RX_DELAY_M; - data = (channel->val & CHANNEL_CCK) ? + data = (channel->hw_value & CHANNEL_CCK) ? ((data << 2) / 22) : (data / 10); udelay(100 + data); @@ -920,11 +913,11 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, if (ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL, AR5K_PHY_AGCCTL_CAL, 0, false)) { ATH5K_ERR(ah->ah_sc, "calibration timeout (%uMHz)\n", - channel->freq); + channel->center_freq); return -EAGAIN; } - ret = ath5k_hw_noise_floor_calibration(ah, channel->freq); + ret = ath5k_hw_noise_floor_calibration(ah, channel->center_freq); if (ret) return ret; @@ -932,7 +925,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, /* A and G modes can use QAM modulation which requires enabling * I and Q calibration. Don't bother in B mode. */ - if (!(driver_mode == MODE_IEEE80211B)) { + if (!(mode == AR5K_MODE_11B)) { ah->ah_calibration = true; AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15); @@ -1590,9 +1583,10 @@ static int ath5k_hw_eeprom_read(struct ath5k_hw *ah, u32 offset, u16 *data) /* * Write to eeprom - currently disabled, use at your own risk */ +#if 0 static int ath5k_hw_eeprom_write(struct ath5k_hw *ah, u32 offset, u16 data) { -#if 0 + u32 status, timeout; ATH5K_TRACE(ah->ah_sc); @@ -1634,10 +1628,11 @@ static int ath5k_hw_eeprom_write(struct ath5k_hw *ah, u32 offset, u16 data) } udelay(15); } -#endif + ATH5K_ERR(ah->ah_sc, "EEPROM Write is disabled!"); return -EIO; } +#endif /* * Translate binary channel representation in EEPROM to frequency @@ -2042,50 +2037,6 @@ static int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac) return 0; } -/* - * Read/Write regulatory domain - */ -static bool ath5k_eeprom_regulation_domain(struct ath5k_hw *ah, bool write, - enum ath5k_regdom *regdomain) -{ - u16 ee_regdomain; - - /* Read current value */ - if (write != true) { - ee_regdomain = ah->ah_capabilities.cap_eeprom.ee_regdomain; - *regdomain = ath5k_regdom_to_ieee(ee_regdomain); - return true; - } - - ee_regdomain = ath5k_regdom_from_ieee(*regdomain); - - /* Try to write a new value */ - if (ah->ah_capabilities.cap_eeprom.ee_protect & - AR5K_EEPROM_PROTECT_WR_128_191) - return false; - if (ath5k_hw_eeprom_write(ah, AR5K_EEPROM_REG_DOMAIN, ee_regdomain)!=0) - return false; - - ah->ah_capabilities.cap_eeprom.ee_regdomain = ee_regdomain; - - return true; -} - -/* - * Use the above to write a new regulatory domain - */ -int ath5k_hw_set_regdomain(struct ath5k_hw *ah, u16 regdomain) -{ - enum ath5k_regdom ieee_regdomain; - - ieee_regdomain = ath5k_regdom_to_ieee(regdomain); - - if (ath5k_eeprom_regulation_domain(ah, true, &ieee_regdomain) == true) - return 0; - - return -EIO; -} - /* * Fill the capabilities struct */ @@ -2108,8 +2059,8 @@ static int ath5k_hw_get_capabilities(struct ath5k_hw *ah) ah->ah_capabilities.cap_range.range_2ghz_max = 0; /* Set supported modes */ - __set_bit(MODE_IEEE80211A, ah->ah_capabilities.cap_mode); - __set_bit(MODE_ATHEROS_TURBO, ah->ah_capabilities.cap_mode); + __set_bit(AR5K_MODE_11A, ah->ah_capabilities.cap_mode); + __set_bit(AR5K_MODE_11A_TURBO, ah->ah_capabilities.cap_mode); } else { /* * XXX The tranceiver supports frequencies from 4920 to 6100GHz @@ -2131,12 +2082,12 @@ static int ath5k_hw_get_capabilities(struct ath5k_hw *ah) ah->ah_capabilities.cap_range.range_5ghz_max = 6100; /* Set supported modes */ - __set_bit(MODE_IEEE80211A, + __set_bit(AR5K_MODE_11A, ah->ah_capabilities.cap_mode); - __set_bit(MODE_ATHEROS_TURBO, + __set_bit(AR5K_MODE_11A_TURBO, ah->ah_capabilities.cap_mode); if (ah->ah_version == AR5K_AR5212) - __set_bit(MODE_ATHEROS_TURBOG, + __set_bit(AR5K_MODE_11G_TURBO, ah->ah_capabilities.cap_mode); } @@ -2148,11 +2099,11 @@ static int ath5k_hw_get_capabilities(struct ath5k_hw *ah) ah->ah_capabilities.cap_range.range_2ghz_max = 2732; if (AR5K_EEPROM_HDR_11B(ee_header)) - __set_bit(MODE_IEEE80211B, + __set_bit(AR5K_MODE_11B, ah->ah_capabilities.cap_mode); if (AR5K_EEPROM_HDR_11G(ee_header)) - __set_bit(MODE_IEEE80211G, + __set_bit(AR5K_MODE_11G, ah->ah_capabilities.cap_mode); } } @@ -4248,35 +4199,6 @@ void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, } -/*********************************\ - Regulatory Domain/Channels Setup -\*********************************/ - -u16 ath5k_get_regdomain(struct ath5k_hw *ah) -{ - u16 regdomain; - enum ath5k_regdom ieee_regdomain; -#ifdef COUNTRYCODE - u16 code; -#endif - - ath5k_eeprom_regulation_domain(ah, false, &ieee_regdomain); - ah->ah_capabilities.cap_regdomain.reg_hw = ieee_regdomain; - -#ifdef COUNTRYCODE - /* - * Get the regulation domain by country code. This will ignore - * the settings found in the EEPROM. - */ - code = ieee80211_name2countrycode(COUNTRYCODE); - ieee_regdomain = ieee80211_countrycode2regdomain(code); -#endif - - regdomain = ath5k_regdom_from_ieee(ieee_regdomain); - ah->ah_capabilities.cap_regdomain.reg_current = regdomain; - - return regdomain; -} /****************\ diff --git a/drivers/net/wireless/ath5k/initvals.c b/drivers/net/wireless/ath5k/initvals.c index 2c22f1d4ee64..a255d8bfa949 100644 --- a/drivers/net/wireless/ath5k/initvals.c +++ b/drivers/net/wireless/ath5k/initvals.c @@ -1317,7 +1317,7 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel) /* For AR5211 */ } else if (ah->ah_version == AR5K_AR5211) { - if(mode > 2){ /* AR5K_INI_VAL_11B */ + if(mode > 2){ /* AR5K_MODE_11B */ ATH5K_ERR(ah->ah_sc,"unsupported channel mode: %d\n", mode); return -EINVAL; } diff --git a/drivers/net/wireless/ath5k/phy.c b/drivers/net/wireless/ath5k/phy.c index b95941797141..8b576b314cf5 100644 --- a/drivers/net/wireless/ath5k/phy.c +++ b/drivers/net/wireless/ath5k/phy.c @@ -1018,7 +1018,7 @@ static int ath5k_hw_rf5111_rfregs(struct ath5k_hw *ah, int obdb = -1, bank = -1; u32 ee_mode; - AR5K_ASSERT_ENTRY(mode, AR5K_INI_VAL_MAX); + AR5K_ASSERT_ENTRY(mode, AR5K_MODE_MAX); rf = ah->ah_rf_banks; @@ -1038,8 +1038,8 @@ static int ath5k_hw_rf5111_rfregs(struct ath5k_hw *ah, } /* Modify bank 0 */ - if (channel->val & CHANNEL_2GHZ) { - if (channel->val & CHANNEL_CCK) + if (channel->hw_value & CHANNEL_2GHZ) { + if (channel->hw_value & CHANNEL_CCK) ee_mode = AR5K_EEPROM_MODE_11B; else ee_mode = AR5K_EEPROM_MODE_11G; @@ -1058,10 +1058,10 @@ static int ath5k_hw_rf5111_rfregs(struct ath5k_hw *ah, } else { /* For 11a, Turbo and XR */ ee_mode = AR5K_EEPROM_MODE_11A; - obdb = channel->freq >= 5725 ? 3 : - (channel->freq >= 5500 ? 2 : - (channel->freq >= 5260 ? 1 : - (channel->freq > 4000 ? 0 : -1))); + obdb = channel->center_freq >= 5725 ? 3 : + (channel->center_freq >= 5500 ? 2 : + (channel->center_freq >= 5260 ? 1 : + (channel->center_freq > 4000 ? 0 : -1))); if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6], ee->ee_pwd_84, 1, 51, 3, true)) @@ -1119,12 +1119,12 @@ static int ath5k_hw_rf5112_rfregs(struct ath5k_hw *ah, int obdb = -1, bank = -1; u32 ee_mode; - AR5K_ASSERT_ENTRY(mode, AR5K_INI_VAL_MAX); + AR5K_ASSERT_ENTRY(mode, AR5K_MODE_MAX); rf = ah->ah_rf_banks; if (ah->ah_radio_5ghz_revision >= AR5K_SREV_RAD_2112A - && !test_bit(MODE_IEEE80211A, ah->ah_capabilities.cap_mode)){ + && !test_bit(AR5K_MODE_11A, ah->ah_capabilities.cap_mode)){ rf_ini = rfregs_2112a; rf_size = ARRAY_SIZE(rfregs_5112a); if (mode < 2) { @@ -1156,8 +1156,8 @@ static int ath5k_hw_rf5112_rfregs(struct ath5k_hw *ah, } /* Modify bank 6 */ - if (channel->val & CHANNEL_2GHZ) { - if (channel->val & CHANNEL_OFDM) + if (channel->hw_value & CHANNEL_2GHZ) { + if (channel->hw_value & CHANNEL_OFDM) ee_mode = AR5K_EEPROM_MODE_11G; else ee_mode = AR5K_EEPROM_MODE_11B; @@ -1173,10 +1173,10 @@ static int ath5k_hw_rf5112_rfregs(struct ath5k_hw *ah, } else { /* For 11a, Turbo and XR */ ee_mode = AR5K_EEPROM_MODE_11A; - obdb = channel->freq >= 5725 ? 3 : - (channel->freq >= 5500 ? 2 : - (channel->freq >= 5260 ? 1 : - (channel->freq > 4000 ? 0 : -1))); + obdb = channel->center_freq >= 5725 ? 3 : + (channel->center_freq >= 5500 ? 2 : + (channel->center_freq >= 5260 ? 1 : + (channel->center_freq > 4000 ? 0 : -1))); if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6], ee->ee_ob[ee_mode][obdb], 3, 279, 0, true)) @@ -1219,7 +1219,7 @@ static int ath5k_hw_rf5413_rfregs(struct ath5k_hw *ah, unsigned int rf_size, i; int bank = -1; - AR5K_ASSERT_ENTRY(mode, AR5K_INI_VAL_MAX); + AR5K_ASSERT_ENTRY(mode, AR5K_MODE_MAX); rf = ah->ah_rf_banks; @@ -1445,7 +1445,7 @@ static u32 ath5k_hw_rf5110_chan2athchan(struct ieee80211_channel *channel) * newer chipsets like the AR5212A who have a completely * different RF/PHY part. */ - athchan = (ath5k_hw_bitswap((channel->chan - 24) / 2, 5) << 1) | + athchan = (ath5k_hw_bitswap((ieee80211_frequency_to_channel(channel->center_freq) - 24) / 2, 5) << 1) | (1 << 6) | 0x1; return athchan; @@ -1506,7 +1506,7 @@ static int ath5k_hw_rf5111_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) { struct ath5k_athchan_2ghz ath5k_channel_2ghz; - unsigned int ath5k_channel = channel->chan; + unsigned int ath5k_channel = ieee80211_frequency_to_channel(channel->center_freq); u32 data0, data1, clock; int ret; @@ -1515,9 +1515,9 @@ static int ath5k_hw_rf5111_channel(struct ath5k_hw *ah, */ data0 = data1 = 0; - if (channel->val & CHANNEL_2GHZ) { + if (channel->hw_value & CHANNEL_2GHZ) { /* Map 2GHz channel to 5GHz Atheros channel ID */ - ret = ath5k_hw_rf5111_chan2athchan(channel->chan, + ret = ath5k_hw_rf5111_chan2athchan(ieee80211_frequency_to_channel(channel->center_freq), &ath5k_channel_2ghz); if (ret) return ret; @@ -1555,7 +1555,7 @@ static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah, u16 c; data = data0 = data1 = data2 = 0; - c = channel->freq; + c = channel->center_freq; /* * Set the channel on the RF5112 or newer @@ -1604,13 +1604,13 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) * Check bounds supported by the PHY * (don't care about regulation restrictions at this point) */ - if ((channel->freq < ah->ah_capabilities.cap_range.range_2ghz_min || - channel->freq > ah->ah_capabilities.cap_range.range_2ghz_max) && - (channel->freq < ah->ah_capabilities.cap_range.range_5ghz_min || - channel->freq > ah->ah_capabilities.cap_range.range_5ghz_max)) { + if ((channel->center_freq < ah->ah_capabilities.cap_range.range_2ghz_min || + channel->center_freq > ah->ah_capabilities.cap_range.range_2ghz_max) && + (channel->center_freq < ah->ah_capabilities.cap_range.range_5ghz_min || + channel->center_freq > ah->ah_capabilities.cap_range.range_5ghz_max)) { ATH5K_ERR(ah->ah_sc, "channel out of supported range (%u MHz)\n", - channel->freq); + channel->center_freq); return -EINVAL; } @@ -1632,9 +1632,9 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) if (ret) return ret; - ah->ah_current_channel.freq = channel->freq; - ah->ah_current_channel.val = channel->val; - ah->ah_turbo = channel->val == CHANNEL_T ? true : false; + ah->ah_current_channel.center_freq = channel->center_freq; + ah->ah_current_channel.hw_value = channel->hw_value; + ah->ah_turbo = channel->hw_value == CHANNEL_T ? true : false; return 0; } @@ -1797,11 +1797,11 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah, if (ret) { ATH5K_ERR(ah->ah_sc, "calibration timeout (%uMHz)\n", - channel->freq); + channel->center_freq); return ret; } - ret = ath5k_hw_noise_floor_calibration(ah, channel->freq); + ret = ath5k_hw_noise_floor_calibration(ah, channel->center_freq); if (ret) return ret; @@ -1848,10 +1848,10 @@ static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah, ((u32)q_coff) | ((u32)i_coff << AR5K_PHY_IQ_CORR_Q_I_COFF_S)); done: - ath5k_hw_noise_floor_calibration(ah, channel->freq); + ath5k_hw_noise_floor_calibration(ah, channel->center_freq); /* Request RF gain */ - if (channel->val & CHANNEL_5GHZ) { + if (channel->hw_value & CHANNEL_5GHZ) { ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txpower.txp_max, AR5K_PHY_PAPD_PROBE_TXPOWER) | AR5K_PHY_PAPD_PROBE_TX_NEXT, AR5K_PHY_PAPD_PROBE); -- cgit v1.2.1 From 400ec45a02b2a9ef75c26c490ba80801d19b7e7b Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Sun, 3 Feb 2008 21:51:49 -0500 Subject: ath5k: Cleanup after API changes Cleanup after API changes patch (checkpatch.pl stuff) and on ath5k_hw_channel() make use of the existing ath5k_channel_ok() instead of re-implementing the checks again. This was necessary to make the code cleaner and fit the 80-chars wide limit so sending it within the same patch. Finally make a note that we *may* eventually move cap_range stuff to struct wiphy (band frequency range capabilities). This information can later be exported to userspace, for example, and giving it access to mac80211 and drivers in general can come in handy. Changes to initvals.c, phy.c Changes-licensed-under: ISC Changes to ath5k.h, base.c Changes-licensed-under: 3-Clause-BSD Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/ath5k.h | 8 ++- drivers/net/wireless/ath5k/base.c | 127 ++++++++++++++++++++-------------- drivers/net/wireless/ath5k/initvals.c | 6 +- drivers/net/wireless/ath5k/phy.c | 35 +++++----- 4 files changed, 102 insertions(+), 74 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath5k/ath5k.h b/drivers/net/wireless/ath5k/ath5k.h index 9ea8c549b781..18223d9833f1 100644 --- a/drivers/net/wireless/ath5k/ath5k.h +++ b/drivers/net/wireless/ath5k/ath5k.h @@ -263,8 +263,10 @@ enum ath5k_driver_mode { /* adding this flag to rate_code enables short preamble, see ar5212_reg.h */ #define AR5K_SET_SHORT_PREAMBLE 0x04 -#define HAS_SHPREAMBLE(_ix) (rt->rates[_ix].modulation == IEEE80211_RATE_SHORT_PREAMBLE) -#define SHPREAMBLE_FLAG(_ix) (HAS_SHPREAMBLE(_ix) ? AR5K_SET_SHORT_PREAMBLE : 0) +#define HAS_SHPREAMBLE(_ix) \ + (rt->rates[_ix].modulation == IEEE80211_RATE_SHORT_PREAMBLE) +#define SHPREAMBLE_FLAG(_ix) \ + (HAS_SHPREAMBLE(_ix) ? AR5K_SET_SHORT_PREAMBLE : 0) /****************\ TX DEFINITIONS @@ -892,6 +894,8 @@ enum ath5k_capability_type { AR5K_CAP_RFSILENT = 20, /* Supports RFsilent */ }; + +/* XXX: we *may* move cap_range stuff to struct wiphy */ struct ath5k_capabilities { /* * Supported PHY modes diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index 52e55f67b735..e3efd869922f 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -80,7 +80,7 @@ MODULE_AUTHOR("Nick Kossifidis"); MODULE_DESCRIPTION("Support for 5xxx series of Atheros 802.11 wireless LAN cards."); MODULE_SUPPORTED_DEVICE("Atheros 5xxx WLAN cards"); MODULE_LICENSE("Dual BSD/GPL"); -MODULE_VERSION("0.1.1 (EXPERIMENTAL)"); +MODULE_VERSION("0.5.0 (EXPERIMENTAL)"); /* Known PCI ids */ @@ -513,35 +513,46 @@ ath5k_pci_probe(struct pci_dev *pdev, sc->ah->ah_mac_srev, sc->ah->ah_phy_revision); - if(!sc->ah->ah_single_chip){ + if (!sc->ah->ah_single_chip) { /* Single chip radio (!RF5111) */ - if(sc->ah->ah_radio_5ghz_revision && !sc->ah->ah_radio_2ghz_revision) { + if (sc->ah->ah_radio_5ghz_revision && + !sc->ah->ah_radio_2ghz_revision) { /* No 5GHz support -> report 2GHz radio */ - if(!test_bit(AR5K_MODE_11A, sc->ah->ah_capabilities.cap_mode)){ + if (!test_bit(AR5K_MODE_11A, + sc->ah->ah_capabilities.cap_mode)) { ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n", - ath5k_chip_name(AR5K_VERSION_RAD,sc->ah->ah_radio_5ghz_revision), - sc->ah->ah_radio_5ghz_revision); - /* No 2GHz support (5110 and some 5Ghz only cards) -> report 5Ghz radio */ - } else if(!test_bit(AR5K_MODE_11B, sc->ah->ah_capabilities.cap_mode)){ + ath5k_chip_name(AR5K_VERSION_RAD, + sc->ah->ah_radio_5ghz_revision), + sc->ah->ah_radio_5ghz_revision); + /* No 2GHz support (5110 and some + * 5Ghz only cards) -> report 5Ghz radio */ + } else if (!test_bit(AR5K_MODE_11B, + sc->ah->ah_capabilities.cap_mode)) { ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n", - ath5k_chip_name(AR5K_VERSION_RAD,sc->ah->ah_radio_5ghz_revision), - sc->ah->ah_radio_5ghz_revision); + ath5k_chip_name(AR5K_VERSION_RAD, + sc->ah->ah_radio_5ghz_revision), + sc->ah->ah_radio_5ghz_revision); /* Multiband radio */ } else { ATH5K_INFO(sc, "RF%s multiband radio found" " (0x%x)\n", - ath5k_chip_name(AR5K_VERSION_RAD,sc->ah->ah_radio_5ghz_revision), - sc->ah->ah_radio_5ghz_revision); + ath5k_chip_name(AR5K_VERSION_RAD, + sc->ah->ah_radio_5ghz_revision), + sc->ah->ah_radio_5ghz_revision); } } - /* Multi chip radio (RF5111 - RF2111) -> report both 2GHz/5GHz radios */ - else if(sc->ah->ah_radio_5ghz_revision && sc->ah->ah_radio_2ghz_revision){ + /* Multi chip radio (RF5111 - RF2111) -> + * report both 2GHz/5GHz radios */ + else if (sc->ah->ah_radio_5ghz_revision && + sc->ah->ah_radio_2ghz_revision){ ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n", - ath5k_chip_name(AR5K_VERSION_RAD,sc->ah->ah_radio_5ghz_revision), - sc->ah->ah_radio_5ghz_revision); + ath5k_chip_name(AR5K_VERSION_RAD, + sc->ah->ah_radio_5ghz_revision), + sc->ah->ah_radio_5ghz_revision); ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n", - ath5k_chip_name(AR5K_VERSION_RAD,sc->ah->ah_radio_2ghz_revision), - sc->ah->ah_radio_2ghz_revision); + ath5k_chip_name(AR5K_VERSION_RAD, + sc->ah->ah_radio_2ghz_revision), + sc->ah->ah_radio_2ghz_revision); } } @@ -891,14 +902,17 @@ ath5k_copy_channels(struct ath5k_hw *ah, /* Write channel info and increment counter */ channels[count].center_freq = freq; - - if((mode == AR5K_MODE_11A) || - (mode == AR5K_MODE_11G)){ - channels[count].hw_value = chfreq|CHANNEL_OFDM; - } else if((mode == AR5K_MODE_11A_TURBO) || - (mode == AR5K_MODE_11G_TURBO)){ - channels[count].hw_value = chfreq|CHANNEL_OFDM|CHANNEL_TURBO; - }if(mode == AR5K_MODE_11B) { + switch (mode) { + case AR5K_MODE_11A: + case AR5K_MODE_11G: + channels[count].hw_value = chfreq | CHANNEL_OFDM; + break; + case AR5K_MODE_11A_TURBO: + case AR5K_MODE_11G_TURBO: + channels[count].hw_value = chfreq | + CHANNEL_OFDM | CHANNEL_TURBO; + break; + case AR5K_MODE_11B: channels[count].hw_value = CHANNEL_B; } @@ -926,15 +940,16 @@ ath5k_getchannels(struct ieee80211_hw *hw) count_r = count_c = 0; /* 2GHz band */ - if(!test_bit(AR5K_MODE_11G, sc->ah->ah_capabilities.cap_mode)){ + if (!test_bit(AR5K_MODE_11G, sc->ah->ah_capabilities.cap_mode)) { mode2g = AR5K_MODE_11B; - if(!test_bit(AR5K_MODE_11B, sc->ah->ah_capabilities.cap_mode)){ + if (!test_bit(AR5K_MODE_11B, + sc->ah->ah_capabilities.cap_mode)) mode2g = -1; - } } - if(mode2g > 0){ - struct ieee80211_supported_band *sband = &sbands[IEEE80211_BAND_2GHZ]; + if (mode2g > 0) { + struct ieee80211_supported_band *sband = + &sbands[IEEE80211_BAND_2GHZ]; sband->bitrates = sc->rates; sband->channels = sc->channels; @@ -945,7 +960,7 @@ ath5k_getchannels(struct ieee80211_hw *hw) hw_rates = ath5k_hw_get_rate_table(ah, mode2g); sband->n_bitrates = ath5k_copy_rates(sband->bitrates, - hw_rates,max_r); + hw_rates, max_r); count_c = sband->n_channels; count_r = sband->n_bitrates; @@ -959,8 +974,9 @@ ath5k_getchannels(struct ieee80211_hw *hw) /* 5GHz band */ - if(test_bit(AR5K_MODE_11A, sc->ah->ah_capabilities.cap_mode)){ - struct ieee80211_supported_band *sband = &sbands[IEEE80211_BAND_5GHZ]; + if (test_bit(AR5K_MODE_11A, sc->ah->ah_capabilities.cap_mode)) { + struct ieee80211_supported_band *sband = + &sbands[IEEE80211_BAND_5GHZ]; sband->bitrates = &sc->rates[count_r]; sband->channels = &sc->channels[count_c]; @@ -971,7 +987,7 @@ ath5k_getchannels(struct ieee80211_hw *hw) hw_rates = ath5k_hw_get_rate_table(ah, AR5K_MODE_11A); sband->n_bitrates = ath5k_copy_rates(sband->bitrates, - hw_rates,max_r); + hw_rates, max_r); hw->wiphy->bands[IEEE80211_BAND_5GHZ] = sband; } @@ -1109,7 +1125,7 @@ ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode) sc->curmode = mode; - if(mode == AR5K_MODE_11A){ + if (mode == AR5K_MODE_11A) { sc->curband = &sc->sbands[IEEE80211_BAND_5GHZ]; } else { sc->curband = &sc->sbands[IEEE80211_BAND_2GHZ]; @@ -1161,43 +1177,43 @@ ath5k_mode_setup(struct ath5k_softc *sc) * When hw returns eg. 27 it points to the last 802.11g rate (54Mbits) etc */ static void -ath5k_set_total_hw_rates(struct ath5k_softc *sc){ +ath5k_set_total_hw_rates(struct ath5k_softc *sc) { struct ath5k_hw *ah = sc->ah; - if(test_bit(AR5K_MODE_11A, ah->ah_modes)) + if (test_bit(AR5K_MODE_11A, ah->ah_modes)) sc->a_rates = 8; - if(test_bit(AR5K_MODE_11B, ah->ah_modes)) + if (test_bit(AR5K_MODE_11B, ah->ah_modes)) sc->b_rates = 4; - if(test_bit(AR5K_MODE_11G, ah->ah_modes)) + if (test_bit(AR5K_MODE_11G, ah->ah_modes)) sc->g_rates = 12; /* XXX: Need to see what what happens when xr disable bits in eeprom are set */ - if(ah->ah_version >= AR5K_AR5212) + if (ah->ah_version >= AR5K_AR5212) sc->xr_rates = 4; } static inline int -ath5k_hw_to_driver_rix(struct ath5k_softc *sc, int hw_rix){ +ath5k_hw_to_driver_rix(struct ath5k_softc *sc, int hw_rix) { int mac80211_rix; - if(sc->curband->band == IEEE80211_BAND_2GHZ){ + if(sc->curband->band == IEEE80211_BAND_2GHZ) { /* We setup a g ratetable for both b/g modes */ - mac80211_rix = hw_rix - sc->b_rates - sc->a_rates - sc->xr_rates; + mac80211_rix = + hw_rix - sc->b_rates - sc->a_rates - sc->xr_rates; } else { mac80211_rix = hw_rix - sc->xr_rates; } /* Something went wrong, fallback to basic rate for this band */ - if((mac80211_rix >= sc->curband->n_bitrates) || - (mac80211_rix <= 0 )){ + if ((mac80211_rix >= sc->curband->n_bitrates) || + (mac80211_rix <= 0 )) mac80211_rix = 1; - } return mac80211_rix; } @@ -1306,7 +1322,8 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, ret = ah->ah_setup_tx_desc(ah, ds, pktlen, ieee80211_get_hdrlen_from_skb(skb), AR5K_PKT_TYPE_NORMAL, - (sc->power_level * 2), ctl->tx_rate->hw_value, ctl->retry_limit, keyidx, 0, flags, 0, 0); + (sc->power_level * 2), ctl->tx_rate->hw_value, + ctl->retry_limit, keyidx, 0, flags, 0, 0); if (ret) goto err_unmap; @@ -1848,7 +1865,8 @@ accept: rxs.signal = ds->ds_rxstat.rs_rssi * 100 / 64; rxs.antenna = ds->ds_rxstat.rs_antenna; - rxs.rate_idx = ath5k_hw_to_driver_rix(sc,ds->ds_rxstat.rs_rate); + rxs.rate_idx = ath5k_hw_to_driver_rix(sc, + ds->ds_rxstat.rs_rate); rxs.flag |= ath5k_rx_decrypted(sc, ds, skb); ath5k_debug_dump_skb(sc, skb, "RX ", 0); @@ -1995,8 +2013,9 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, ds->ds_data = bf->skbaddr; ret = ah->ah_setup_tx_desc(ah, ds, skb->len, ieee80211_get_hdrlen_from_skb(skb), - AR5K_PKT_TYPE_BEACON, (sc->power_level * 2), ctl->tx_rate->hw_value, 1, - AR5K_TXKEYIX_INVALID, antenna, flags, 0, 0); + AR5K_PKT_TYPE_BEACON, (sc->power_level * 2), + ctl->tx_rate->hw_value, 1, AR5K_TXKEYIX_INVALID, + antenna, flags, 0, 0); if (ret) goto err_unmap; @@ -2486,7 +2505,8 @@ ath5k_calibrate(unsigned long data) struct ath5k_hw *ah = sc->ah; ATH5K_DBG(sc, ATH5K_DEBUG_CALIBRATE, "channel %u/%x\n", - ieee80211_frequency_to_channel(sc->curchan->center_freq), sc->curchan->hw_value); + ieee80211_frequency_to_channel(sc->curchan->center_freq), + sc->curchan->hw_value); if (ath5k_hw_get_rf_gain(ah) == AR5K_RFGAIN_NEED_CHANGE) { /* @@ -2498,7 +2518,8 @@ ath5k_calibrate(unsigned long data) } if (ath5k_hw_phy_calibrate(ah, sc->curchan)) ATH5K_ERR(sc, "calibration of channel %u failed\n", - ieee80211_frequency_to_channel(sc->curchan->center_freq)); + ieee80211_frequency_to_channel( + sc->curchan->center_freq)); mod_timer(&sc->calib_tim, round_jiffies(jiffies + msecs_to_jiffies(ath5k_calinterval * 1000))); diff --git a/drivers/net/wireless/ath5k/initvals.c b/drivers/net/wireless/ath5k/initvals.c index a255d8bfa949..cfcb1fe7bd34 100644 --- a/drivers/net/wireless/ath5k/initvals.c +++ b/drivers/net/wireless/ath5k/initvals.c @@ -1317,8 +1317,10 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel) /* For AR5211 */ } else if (ah->ah_version == AR5K_AR5211) { - if(mode > 2){ /* AR5K_MODE_11B */ - ATH5K_ERR(ah->ah_sc,"unsupported channel mode: %d\n", mode); + /* AR5K_MODE_11B */ + if (mode > 2) { + ATH5K_ERR(ah->ah_sc, + "unsupported channel mode: %d\n", mode); return -EINVAL; } diff --git a/drivers/net/wireless/ath5k/phy.c b/drivers/net/wireless/ath5k/phy.c index 8b576b314cf5..248c0f545f24 100644 --- a/drivers/net/wireless/ath5k/phy.c +++ b/drivers/net/wireless/ath5k/phy.c @@ -1124,7 +1124,7 @@ static int ath5k_hw_rf5112_rfregs(struct ath5k_hw *ah, rf = ah->ah_rf_banks; if (ah->ah_radio_5ghz_revision >= AR5K_SREV_RAD_2112A - && !test_bit(AR5K_MODE_11A, ah->ah_capabilities.cap_mode)){ + && !test_bit(AR5K_MODE_11A, ah->ah_capabilities.cap_mode)) { rf_ini = rfregs_2112a; rf_size = ARRAY_SIZE(rfregs_5112a); if (mode < 2) { @@ -1445,9 +1445,10 @@ static u32 ath5k_hw_rf5110_chan2athchan(struct ieee80211_channel *channel) * newer chipsets like the AR5212A who have a completely * different RF/PHY part. */ - athchan = (ath5k_hw_bitswap((ieee80211_frequency_to_channel(channel->center_freq) - 24) / 2, 5) << 1) | - (1 << 6) | 0x1; - + athchan = (ath5k_hw_bitswap( + (ieee80211_frequency_to_channel( + channel->center_freq) - 24) / 2, 5) + << 1) | (1 << 6) | 0x1; return athchan; } @@ -1506,7 +1507,8 @@ static int ath5k_hw_rf5111_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) { struct ath5k_athchan_2ghz ath5k_channel_2ghz; - unsigned int ath5k_channel = ieee80211_frequency_to_channel(channel->center_freq); + unsigned int ath5k_channel = + ieee80211_frequency_to_channel(channel->center_freq); u32 data0, data1, clock; int ret; @@ -1517,8 +1519,9 @@ static int ath5k_hw_rf5111_channel(struct ath5k_hw *ah, if (channel->hw_value & CHANNEL_2GHZ) { /* Map 2GHz channel to 5GHz Atheros channel ID */ - ret = ath5k_hw_rf5111_chan2athchan(ieee80211_frequency_to_channel(channel->center_freq), - &ath5k_channel_2ghz); + ret = ath5k_hw_rf5111_chan2athchan( + ieee80211_frequency_to_channel(channel->center_freq), + &ath5k_channel_2ghz); if (ret) return ret; @@ -1599,19 +1602,17 @@ static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah, int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) { int ret; - /* - * Check bounds supported by the PHY - * (don't care about regulation restrictions at this point) - */ - if ((channel->center_freq < ah->ah_capabilities.cap_range.range_2ghz_min || - channel->center_freq > ah->ah_capabilities.cap_range.range_2ghz_max) && - (channel->center_freq < ah->ah_capabilities.cap_range.range_5ghz_min || - channel->center_freq > ah->ah_capabilities.cap_range.range_5ghz_max)) { + * Check bounds supported by the PHY (we don't care about regultory + * restrictions at this point). Note: hw_value already has the band + * (CHANNEL_2GHZ, or CHANNEL_5GHZ) so we inform ath5k_channel_ok() + * of the band by that */ + if (!ath5k_channel_ok(ah, channel->center_freq, channel->hw_value)) { ATH5K_ERR(ah->ah_sc, - "channel out of supported range (%u MHz)\n", + "channel frequency (%u MHz) out of supported " + "band range\n", channel->center_freq); - return -EINVAL; + return -EINVAL; } /* -- cgit v1.2.1 From a3f4b914a03a11f3ccc98243b20a647bb8f31691 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Sun, 3 Feb 2008 21:52:10 -0500 Subject: ath5k: ath5k_copy_channels() was not setting the channel band ath5k_copy_channels() wasn't setting the channel's band so all driver channels had a 2GHz band set. Lets set this. Changes-licensed-under: 3-Clause-BSD Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/base.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index e3efd869922f..44c0133e844f 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -902,6 +902,8 @@ ath5k_copy_channels(struct ath5k_hw *ah, /* Write channel info and increment counter */ channels[count].center_freq = freq; + channels[count].band = (chfreq == CHANNEL_2GHZ) ? + IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; switch (mode) { case AR5K_MODE_11A: case AR5K_MODE_11G: -- cgit v1.2.1 From e9ddc0f25ce524d257e6cf779e495f567ed7678f Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 4 Feb 2008 09:56:32 -0500 Subject: ath5k: Use our own Kconfig file, we'll be expanding this shortly Apologoes, this is a re-post of patch-04, forgot to git-add our Kconfig... New series (only 2 patches needed fixing, which I am reposting) can be found here: http://kernel.org/pub/linux/kernel/people/mcgrof/patches/ath5k/2008-02-04.v2/ Use our own Kconfig file, we'll be expanding this shortly. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/Kconfig | 18 +----------------- drivers/net/wireless/ath5k/Kconfig | 16 ++++++++++++++++ drivers/net/wireless/ath5k/Makefile | 8 ++++++-- 3 files changed, 23 insertions(+), 19 deletions(-) create mode 100644 drivers/net/wireless/ath5k/Kconfig (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 714a6ca30ad2..cfedbda81e3f 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -732,23 +732,7 @@ config P54_PCI If you choose to build a module, it'll be called p54pci. -config ATH5K - tristate "Atheros 5xxx wireless cards support" - depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL - ---help--- - This module adds support for wireless adapters based on - Atheros 5xxx chipset. - - Currently the following chip versions are supported: - - MAC: AR5211 AR5212 - PHY: RF5111/2111 RF5112/2112 RF5413/2413 - - This driver uses the kernel's mac80211 subsystem. - - If you choose to build a module, it'll be called ath5k. Say M if - unsure. - +source "drivers/net/wireless/ath5k/Kconfig" source "drivers/net/wireless/iwlwifi/Kconfig" source "drivers/net/wireless/hostap/Kconfig" source "drivers/net/wireless/bcm43xx/Kconfig" diff --git a/drivers/net/wireless/ath5k/Kconfig b/drivers/net/wireless/ath5k/Kconfig new file mode 100644 index 000000000000..af1b6b8c991a --- /dev/null +++ b/drivers/net/wireless/ath5k/Kconfig @@ -0,0 +1,16 @@ +config ATH5K + tristate "Atheros 5xxx wireless cards support" + depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL + ---help--- + This module adds support for wireless adapters based on + Atheros 5xxx chipset. + + Currently the following chip versions are supported: + + MAC: AR5211 AR5212 + PHY: RF5111/2111 RF5112/2112 RF5413/2413 + + This driver uses the kernel's mac80211 subsystem. + + If you choose to build a module, it'll be called ath5k. Say M if + unsure. diff --git a/drivers/net/wireless/ath5k/Makefile b/drivers/net/wireless/ath5k/Makefile index ada1095d4ef1..0f14b00f648e 100644 --- a/drivers/net/wireless/ath5k/Makefile +++ b/drivers/net/wireless/ath5k/Makefile @@ -1,2 +1,6 @@ -ath5k-objs = base.o hw.o initvals.o phy.o debug.o -obj-$(CONFIG_ATH5K) += ath5k.o +ath5k-y += base.o +ath5k-y += hw.o +ath5k-y += initvals.o +ath5k-y += phy.o +ath5k-y += debug.o +obj-$(CONFIG_ATH5K) += ath5k.o -- cgit v1.2.1 From b446197cc14ef060baeed5acbcddf148c04d03f8 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Mon, 4 Feb 2008 10:03:54 -0500 Subject: ath5k: Port debug.c over to the new band API and enable as build option This patch finishes the port and enables debug as an build option. This was tested on: Atheros AR5213A chip found (MAC: 0x59, PHY: 0x43) RF5112A multiband radio found (0x36) Note: For 2 GHz band on the above card I noticed we get negative channel numbers. Will look into this unless someone beats me to it. Example out put when loading using: sudo modprobe ath5k debug=0x00000400 Band 2 GHz: channels 26, rates 12 channels: 1 2412 00c0 0000 2 2417 00c0 0000 3 2422 00c0 0000 4 2427 00c0 0000 5 2432 00c0 0000 6 2437 00c0 0000 7 2442 00c0 0000 8 2447 00c0 0000 9 2452 00c0 0000 10 2457 00c0 0000 11 2462 00c0 0000 12 2467 00c0 0000 13 2472 00c0 0000 14 2484 00c0 0000 -498 2512 00c0 0000 -494 2532 00c0 0000 -490 2552 00c0 0000 -486 2572 00c0 0000 -482 2592 00c0 0000 -478 2612 00c0 0000 -474 2632 00c0 0000 -470 2652 00c0 0000 -466 2672 00c0 0000 -462 2692 00c0 0000 -458 2712 00c0 0000 -454 2732 00c0 0000 Band 5 GHz: channels 194, rates 8 channels: 27 5135 0140 0000 28 5140 0140 0000 [... etc ] 219 6095 0140 0000 220 6100 0140 0000 rates: 60 000b 0000 0000 90 000f 0000 0000 120 000a 0000 0000 180 000e 0000 0000 240 0009 0000 0000 360 000d 0000 0000 480 0008 0000 0000 540 000c 0000 0000 Changes to base.c, base.h Changes-licensed-under: 3-Clause-BSD Changes to debug.c, debug.h Changes-licensed-under: GPL Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/Kconfig | 21 ++++++++++++++ drivers/net/wireless/ath5k/Makefile | 2 +- drivers/net/wireless/ath5k/base.c | 2 +- drivers/net/wireless/ath5k/base.h | 4 +-- drivers/net/wireless/ath5k/debug.c | 55 ++++++++++++++++++++++++------------- drivers/net/wireless/ath5k/debug.h | 19 ++++--------- 6 files changed, 67 insertions(+), 36 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath5k/Kconfig b/drivers/net/wireless/ath5k/Kconfig index af1b6b8c991a..f1f2aea2eab4 100644 --- a/drivers/net/wireless/ath5k/Kconfig +++ b/drivers/net/wireless/ath5k/Kconfig @@ -14,3 +14,24 @@ config ATH5K If you choose to build a module, it'll be called ath5k. Say M if unsure. + +config ATH5K_DEBUG + bool "Atheros 5xxx debugging" + depends on ATH5K + ---help--- + Atheros 5xxx debugging messages. + + Say Y, if and you will get debug options for ath5k. + To use this, you need to mount debugfs: + + mkdir /debug/ + mount -t debugfs debug /debug/ + + You will get access to files under: + /debug/ath5k/phy0/ + + To enable debug, pass the debug level to the debug module + parameter. For example: + + modprobe ath5k debug=0x00000400 + diff --git a/drivers/net/wireless/ath5k/Makefile b/drivers/net/wireless/ath5k/Makefile index 0f14b00f648e..564ecd0c5d4b 100644 --- a/drivers/net/wireless/ath5k/Makefile +++ b/drivers/net/wireless/ath5k/Makefile @@ -2,5 +2,5 @@ ath5k-y += base.o ath5k-y += hw.o ath5k-y += initvals.o ath5k-y += phy.o -ath5k-y += debug.o +ath5k-$(CONFIG_ATH5K_DEBUG) += debug.o obj-$(CONFIG_ATH5K) += ath5k.o diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index 44c0133e844f..5ca441d7a6c1 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -994,7 +994,7 @@ ath5k_getchannels(struct ieee80211_hw *hw) hw->wiphy->bands[IEEE80211_BAND_5GHZ] = sband; } -/* FIXME: ath5k_debug_dump_modes(sc, modes); */ + ath5k_debug_dump_bands(sc); return 0; } diff --git a/drivers/net/wireless/ath5k/base.h b/drivers/net/wireless/ath5k/base.h index bbe7a5438154..3a9755893018 100644 --- a/drivers/net/wireless/ath5k/base.h +++ b/drivers/net/wireless/ath5k/base.h @@ -108,9 +108,9 @@ struct ath5k_softc { u8 g_rates; u8 xr_rates; -#if ATH5K_DEBUG +#ifdef CONFIG_ATH5K_DEBUG struct ath5k_dbg_info debug; /* debug info */ -#endif +#endif /* CONFIG_ATH5K_DEBUG */ struct ath5k_buf *bufptr; /* allocated buffer ptr */ struct ath5k_desc *desc; /* TX/RX descriptors */ diff --git a/drivers/net/wireless/ath5k/debug.c b/drivers/net/wireless/ath5k/debug.c index bb581ef6d1ef..05bf4fb8f907 100644 --- a/drivers/net/wireless/ath5k/debug.c +++ b/drivers/net/wireless/ath5k/debug.c @@ -65,7 +65,7 @@ static unsigned int ath5k_debug; module_param_named(debug, ath5k_debug, uint, 0); -#if ATH5K_DEBUG +#ifdef CONFIG_ATH5K_DEBUG #include #include "reg.h" @@ -340,7 +340,7 @@ static struct { { ATH5K_DEBUG_LED, "led", "LED mamagement" }, { ATH5K_DEBUG_DUMP_RX, "dumprx", "print received skb content" }, { ATH5K_DEBUG_DUMP_TX, "dumptx", "print transmit skb content" }, - { ATH5K_DEBUG_DUMPMODES, "dumpmodes", "dump modes" }, + { ATH5K_DEBUG_DUMPBANDS, "dumpbands", "dump bands" }, { ATH5K_DEBUG_TRACE, "trace", "trace function calls" }, { ATH5K_DEBUG_ANY, "all", "show all debug levels" }, }; @@ -452,30 +452,47 @@ ath5k_debug_finish_device(struct ath5k_softc *sc) /* functions used in other places */ void -ath5k_debug_dump_modes(struct ath5k_softc *sc, struct ieee80211_hw_mode *modes) +ath5k_debug_dump_bands(struct ath5k_softc *sc) { - unsigned int m, i; + unsigned int b, i; - if (likely(!(sc->debug.level & ATH5K_DEBUG_DUMPMODES))) + if (likely(!(sc->debug.level & ATH5K_DEBUG_DUMPBANDS))) return; - for (m = 0; m < NUM_DRIVER_MODES; m++) { - printk(KERN_DEBUG "Mode %u: channels %d, rates %d\n", m, - modes[m].num_channels, modes[m].num_rates); + BUG_ON(!sc->sbands); + + for (b = 0; b < IEEE80211_NUM_BANDS; b++) { + struct ieee80211_supported_band *band = &sc->sbands[b]; + char bname[5]; + switch (band->band) { + case IEEE80211_BAND_2GHZ: + strcpy(bname, "2 GHz"); + break; + case IEEE80211_BAND_5GHZ: + strcpy(bname, "5 GHz"); + break; + default: + printk(KERN_DEBUG "Band not supported: %d\n", + band->band); + return; + } + printk(KERN_DEBUG "Band %s: channels %d, rates %d\n", bname, + band->n_channels, band->n_bitrates); printk(KERN_DEBUG " channels:\n"); - for (i = 0; i < modes[m].num_channels; i++) + for (i = 0; i < band->n_channels; i++) printk(KERN_DEBUG " %3d %d %.4x %.4x\n", - modes[m].channels[i].chan, - modes[m].channels[i].freq, - modes[m].channels[i].val, - modes[m].channels[i].flag); + ieee80211_frequency_to_channel( + band->channels[i].center_freq), + band->channels[i].center_freq, + band->channels[i].hw_value, + band->channels[i].flags); printk(KERN_DEBUG " rates:\n"); - for (i = 0; i < modes[m].num_rates; i++) + for (i = 0; i < band->n_bitrates; i++) printk(KERN_DEBUG " %4d %.4x %.4x %.4x\n", - modes[m].rates[i].rate, - modes[m].rates[i].val, - modes[m].rates[i].flags, - modes[m].rates[i].val2); + band->bitrates[i].bitrate, + band->bitrates[i].hw_value, + band->bitrates[i].flags, + band->bitrates[i].hw_value_short); } } @@ -548,4 +565,4 @@ ath5k_debug_printtxbuf(struct ath5k_softc *sc, !done ? ' ' : (ds->ds_txstat.ts_status == 0) ? '*' : '!'); } -#endif /* if ATH5K_DEBUG */ +#endif /* ifdef CONFIG_ATH5K_DEBUG */ diff --git a/drivers/net/wireless/ath5k/debug.h b/drivers/net/wireless/ath5k/debug.h index c4fd8c43df0c..16fbb6fbab35 100644 --- a/drivers/net/wireless/ath5k/debug.h +++ b/drivers/net/wireless/ath5k/debug.h @@ -61,11 +61,6 @@ #ifndef _ATH5K_DEBUG_H #define _ATH5K_DEBUG_H -/* set this to 1 for debugging output */ -#ifndef ATH5K_DEBUG -#define ATH5K_DEBUG 0 -#endif - struct ath5k_softc; struct ath5k_hw; struct ieee80211_hw_mode; @@ -96,7 +91,7 @@ struct ath5k_dbg_info { * @ATH5K_DEBUG_LED: led management * @ATH5K_DEBUG_DUMP_RX: print received skb content * @ATH5K_DEBUG_DUMP_TX: print transmit skb content - * @ATH5K_DEBUG_DUMPMODES: dump modes + * @ATH5K_DEBUG_DUMPBANDS: dump bands * @ATH5K_DEBUG_TRACE: trace function calls * @ATH5K_DEBUG_ANY: show at any debug level * @@ -118,12 +113,12 @@ enum ath5k_debug_level { ATH5K_DEBUG_LED = 0x00000080, ATH5K_DEBUG_DUMP_RX = 0x00000100, ATH5K_DEBUG_DUMP_TX = 0x00000200, - ATH5K_DEBUG_DUMPMODES = 0x00000400, + ATH5K_DEBUG_DUMPBANDS = 0x00000400, ATH5K_DEBUG_TRACE = 0x00001000, ATH5K_DEBUG_ANY = 0xffffffff }; -#if ATH5K_DEBUG +#ifdef CONFIG_ATH5K_DEBUG #define ATH5K_TRACE(_sc) do { \ if (unlikely((_sc)->debug.level & ATH5K_DEBUG_TRACE)) \ @@ -158,8 +153,7 @@ void ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah); void -ath5k_debug_dump_modes(struct ath5k_softc *sc, - struct ieee80211_hw_mode *modes); +ath5k_debug_dump_bands(struct ath5k_softc *sc); void ath5k_debug_dump_skb(struct ath5k_softc *sc, @@ -196,8 +190,7 @@ static inline void ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) {} static inline void -ath5k_debug_dump_modes(struct ath5k_softc *sc, - struct ieee80211_hw_mode *modes) {} +ath5k_debug_dump_bands(struct ath5k_softc *sc) {} static inline void ath5k_debug_dump_skb(struct ath5k_softc *sc, @@ -207,6 +200,6 @@ static inline void ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf, int done) {} -#endif /* if ATH5K_DEBUG */ +#endif /* ifdef CONFIG_ATH5K_DEBUG */ #endif /* ifndef _ATH5K_DEBUG_H */ -- cgit v1.2.1 From 6844e63a9458d15b4437aa467c99128d994b0f6c Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Sun, 3 Feb 2008 21:53:20 -0500 Subject: ath5k: Use software encryption for now Hardware encryption doesn't work yet so lets use software encryption for now. Changes-licensed-under: 3-Clause-BSD Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/base.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index 5ca441d7a6c1..0b743f7b3a14 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -2928,7 +2928,9 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, switch(key->alg) { case ALG_WEP: - break; + /* XXX: fix hardware encryption, its not working. For now + * allow software encryption */ + /* break; */ case ALG_TKIP: case ALG_CCMP: return -EOPNOTSUPP; -- cgit v1.2.1 From e71c9fac316221a4594f3bd58c2d30ada0cabaf6 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Sun, 3 Feb 2008 21:53:51 -0500 Subject: ath5k/phy.c: fix negative array index Author: Adrian Bunk This patch fixes a negative array index spotted by the Coverity checker. Changes-licensed-under: ISC Acked-by: Nick Kossifidis Signed-off-by: Adrian Bunk Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/phy.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath5k/phy.c b/drivers/net/wireless/ath5k/phy.c index 248c0f545f24..405195ffb24d 100644 --- a/drivers/net/wireless/ath5k/phy.c +++ b/drivers/net/wireless/ath5k/phy.c @@ -1178,6 +1178,9 @@ static int ath5k_hw_rf5112_rfregs(struct ath5k_hw *ah, (channel->center_freq >= 5260 ? 1 : (channel->center_freq > 4000 ? 0 : -1))); + if (obdb == -1) + return -EINVAL; + if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6], ee->ee_ob[ee_mode][obdb], 3, 279, 0, true)) return -EINVAL; -- cgit v1.2.1 From 70e2fed4ec14df84ed72554d573794714b15a078 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 3 Feb 2008 15:50:40 +0100 Subject: rt2x00: Rate structure overhaul Recent changes to the rate structure registration broke rt2x00, the hw_value was reduced from 32bits to 16bits while rt2x00 used the full 32bits. However the way rt2x00 used the value was inflexible and needed to be changed anyway. This patch creates a array containing information for each rate, the hw_value passed to mac80211 is the index value for that array including a field to indicate if short preamble should be enabled. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00config.c | 4 +- drivers/net/wireless/rt2x00/rt2x00dev.c | 173 ++++++++++++++++++----------- drivers/net/wireless/rt2x00/rt2x00lib.h | 45 ++++++++ drivers/net/wireless/rt2x00/rt2x00reg.h | 71 ------------ 4 files changed, 153 insertions(+), 140 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index 9fba485a40ac..a4d7917f2df5 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -246,9 +246,7 @@ config: band = &rt2x00dev->bands[conf->channel->band]; rate = &band->bitrates[band->n_bitrates - 1]; - - libconf.basic_rates = - DEVICE_GET_RATE_FIELD(rate->hw_value, RATEMASK) & DEV_BASIC_RATEMASK; + libconf.basic_rates = rt2x00_get_rate(rate->hw_value)->ratemask; } if (flags & CONFIG_UPDATE_CHANNEL) { diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 83a72ae36638..f0ba481c51e6 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -551,10 +551,10 @@ void rt2x00lib_rxdone(struct queue_entry *entry, struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status; struct ieee80211_supported_band *sband; - struct ieee80211_rate *rate; struct ieee80211_hdr *hdr; + const struct rt2x00_rate *rate; unsigned int i; - int val = 0, idx = -1; + int idx = -1; u16 fc; /* @@ -562,19 +562,15 @@ void rt2x00lib_rxdone(struct queue_entry *entry, */ sband = &rt2x00dev->bands[rt2x00dev->curr_band]; for (i = 0; i < sband->n_bitrates; i++) { - rate = &sband->bitrates[i]; + rate = rt2x00_get_rate(sband->bitrates[i].hw_value); /* * When frame was received with an OFDM bitrate, * the signal is the PLCP value. If it was received with - * a CCK bitrate the signal is the rate in 0.5kbit/s. + * a CCK bitrate the signal is the rate in 100kbit/s. */ - if (!rxdesc->ofdm) - val = DEVICE_GET_RATE_FIELD(rate->hw_value, RATE); - else - val = DEVICE_GET_RATE_FIELD(rate->hw_value, PLCP); - - if (val == rxdesc->signal) { + if ((rxdesc->ofdm && rate->plcp == rxdesc->signal) || + (!rxdesc->ofdm && rate->bitrate == rxdesc->signal)) { idx = i; break; } @@ -583,7 +579,7 @@ void rt2x00lib_rxdone(struct queue_entry *entry, /* * Only update link status if this is a beacon frame carrying our bssid. */ - hdr = (struct ieee80211_hdr*)entry->skb->data; + hdr = (struct ieee80211_hdr *)entry->skb->data; fc = le16_to_cpu(hdr->frame_control); if (is_beacon(fc) && rxdesc->my_bss) rt2x00lib_update_link_stats(&rt2x00dev->link, rxdesc->rssi); @@ -617,9 +613,9 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev, { struct txentry_desc txdesc; struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); - struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + const struct rt2x00_rate *rate; int tx_rate; - int bitrate; int length; int duration; int residual; @@ -636,8 +632,8 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev, /* * Read required fields from ieee80211 header. */ - frame_control = le16_to_cpu(ieee80211hdr->frame_control); - seq_ctrl = le16_to_cpu(ieee80211hdr->seq_ctrl); + frame_control = le16_to_cpu(hdr->frame_control); + seq_ctrl = le16_to_cpu(hdr->seq_ctrl); tx_rate = control->tx_rate->hw_value; @@ -661,16 +657,12 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev, tx_rate = control->rts_cts_rate->hw_value; } - /* - * Check for OFDM - */ - if (DEVICE_GET_RATE_FIELD(tx_rate, RATEMASK) & DEV_OFDM_RATEMASK) - __set_bit(ENTRY_TXD_OFDM_RATE, &txdesc.flags); + rate = rt2x00_get_rate(tx_rate); /* * Check if more fragments are pending */ - if (ieee80211_get_morefrag(ieee80211hdr)) { + if (ieee80211_get_morefrag(hdr)) { __set_bit(ENTRY_TXD_BURST, &txdesc.flags); __set_bit(ENTRY_TXD_MORE_FRAG, &txdesc.flags); } @@ -698,21 +690,21 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev, * PLCP setup * Length calculation depends on OFDM/CCK rate. */ - txdesc.signal = DEVICE_GET_RATE_FIELD(tx_rate, PLCP); + txdesc.signal = rate->plcp; txdesc.service = 0x04; length = skb->len + FCS_LEN; - if (test_bit(ENTRY_TXD_OFDM_RATE, &txdesc.flags)) { + if (rate->flags & DEV_RATE_OFDM) { + __set_bit(ENTRY_TXD_OFDM_RATE, &txdesc.flags); + txdesc.length_high = (length >> 6) & 0x3f; txdesc.length_low = length & 0x3f; } else { - bitrate = DEVICE_GET_RATE_FIELD(tx_rate, RATE); - /* * Convert length to microseconds. */ - residual = get_duration_res(length, bitrate); - duration = get_duration(length, bitrate); + residual = get_duration_res(length, rate->bitrate); + duration = get_duration(length, rate->bitrate); if (residual != 0) { duration++; @@ -720,7 +712,7 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev, /* * Check if we need to set the Length Extension */ - if (bitrate == 110 && residual <= 30) + if (rate->bitrate == 110 && residual <= 30) txdesc.service |= 0x80; } @@ -731,7 +723,7 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev, * When preamble is enabled we should set the * preamble bit for the signal. */ - if (DEVICE_GET_RATE_FIELD(tx_rate, PREAMBLE)) + if (rt2x00_get_rate_preamble(tx_rate)) txdesc.signal |= 0x08; } @@ -756,6 +748,81 @@ EXPORT_SYMBOL_GPL(rt2x00lib_write_tx_desc); /* * Driver initialization handlers. */ +const struct rt2x00_rate rt2x00_supported_rates[12] = { + { + .flags = 0, + .bitrate = 10, + .ratemask = DEV_RATEMASK_1MB, + .plcp = 0x00, + }, + { + .flags = DEV_RATE_SHORT_PREAMBLE, + .bitrate = 20, + .ratemask = DEV_RATEMASK_2MB, + .plcp = 0x01, + }, + { + .flags = DEV_RATE_SHORT_PREAMBLE, + .bitrate = 55, + .ratemask = DEV_RATEMASK_5_5MB, + .plcp = 0x02, + }, + { + .flags = DEV_RATE_SHORT_PREAMBLE, + .bitrate = 110, + .ratemask = DEV_RATEMASK_11MB, + .plcp = 0x03, + }, + { + .flags = DEV_RATE_OFDM, + .bitrate = 60, + .ratemask = DEV_RATEMASK_6MB, + .plcp = 0x0b, + }, + { + .flags = DEV_RATE_OFDM, + .bitrate = 90, + .ratemask = DEV_RATEMASK_9MB, + .plcp = 0x0f, + }, + { + .flags = DEV_RATE_OFDM, + .bitrate = 120, + .ratemask = DEV_RATEMASK_12MB, + .plcp = 0x0a, + }, + { + .flags = DEV_RATE_OFDM, + .bitrate = 180, + .ratemask = DEV_RATEMASK_18MB, + .plcp = 0x0e, + }, + { + .flags = DEV_RATE_OFDM, + .bitrate = 240, + .ratemask = DEV_RATEMASK_24MB, + .plcp = 0x09, + }, + { + .flags = DEV_RATE_OFDM, + .bitrate = 360, + .ratemask = DEV_RATEMASK_36MB, + .plcp = 0x0d, + }, + { + .flags = DEV_RATE_OFDM, + .bitrate = 480, + .ratemask = DEV_RATEMASK_48MB, + .plcp = 0x08, + }, + { + .flags = DEV_RATE_OFDM, + .bitrate = 540, + .ratemask = DEV_RATEMASK_54MB, + .plcp = 0x0c, + }, +}; + static void rt2x00lib_channel(struct ieee80211_channel *entry, const int channel, const int tx_power, const int value) @@ -770,18 +837,17 @@ static void rt2x00lib_channel(struct ieee80211_channel *entry, } static void rt2x00lib_rate(struct ieee80211_rate *entry, - const int rate, const int mask, - const int plcp, const int flags) + const u16 index, const struct rt2x00_rate *rate) { - entry->bitrate = rate; - entry->hw_value = - DEVICE_SET_RATE_FIELD(rate, RATE) | - DEVICE_SET_RATE_FIELD(mask, RATEMASK) | - DEVICE_SET_RATE_FIELD(plcp, PLCP); - entry->flags = flags; + entry->flags = 0; + entry->bitrate = rate->bitrate; + entry->hw_value = rt2x00_create_rate_hw_value(index, 0); entry->hw_value_short = entry->hw_value; - if (entry->flags & IEEE80211_RATE_SHORT_PREAMBLE) - entry->hw_value_short |= DEVICE_SET_RATE_FIELD(1, PREAMBLE); + + if (rate->flags & DEV_RATE_SHORT_PREAMBLE) { + entry->flags |= IEEE80211_RATE_SHORT_PREAMBLE; + entry->hw_value_short |= rt2x00_create_rate_hw_value(index, 1); + } } static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev, @@ -807,33 +873,8 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev, /* * Initialize Rate list. */ - rt2x00lib_rate(&rates[0], 10, DEV_RATEMASK_1MB, - 0x00, 0); - rt2x00lib_rate(&rates[1], 20, DEV_RATEMASK_2MB, - 0x01, IEEE80211_RATE_SHORT_PREAMBLE); - rt2x00lib_rate(&rates[2], 55, DEV_RATEMASK_5_5MB, - 0x02, IEEE80211_RATE_SHORT_PREAMBLE); - rt2x00lib_rate(&rates[3], 110, DEV_RATEMASK_11MB, - 0x03, IEEE80211_RATE_SHORT_PREAMBLE); - - if (spec->num_rates > 4) { - rt2x00lib_rate(&rates[4], 60, DEV_RATEMASK_6MB, - 0x0b, 0); - rt2x00lib_rate(&rates[5], 90, DEV_RATEMASK_9MB, - 0x0f, 0); - rt2x00lib_rate(&rates[6], 120, DEV_RATEMASK_12MB, - 0x0a, 0); - rt2x00lib_rate(&rates[7], 180, DEV_RATEMASK_18MB, - 0x0e, 0); - rt2x00lib_rate(&rates[8], 240, DEV_RATEMASK_24MB, - 0x09, 0); - rt2x00lib_rate(&rates[9], 360, DEV_RATEMASK_36MB, - 0x0d, 0); - rt2x00lib_rate(&rates[10], 480, DEV_RATEMASK_48MB, - 0x08, 0); - rt2x00lib_rate(&rates[11], 540, DEV_RATEMASK_54MB, - 0x0c, 0); - } + for (i = 0; i < spec->num_rates; i++) + rt2x00lib_rate(&rates[0], i, rt2x00_get_rate(i)); /* * Initialize Channel list. diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index f6789fdaaf6e..ca9630c75520 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -33,6 +33,51 @@ #define LINK_TUNE_INTERVAL ( round_jiffies_relative(HZ) ) #define RFKILL_POLL_INTERVAL ( 1000 ) +/* + * rt2x00_rate: Per rate device information + */ +struct rt2x00_rate { + unsigned short flags; +#define DEV_RATE_OFDM 0x0001 +#define DEV_RATE_SHORT_PREAMBLE 0x0002 + + unsigned short bitrate; /* In 100kbit/s */ + + unsigned short ratemask; +#define DEV_RATEMASK_1MB ( (1 << 1) - 1 ) +#define DEV_RATEMASK_2MB ( (1 << 2) - 1 ) +#define DEV_RATEMASK_5_5MB ( (1 << 3) - 1 ) +#define DEV_RATEMASK_11MB ( (1 << 4) - 1 ) +#define DEV_RATEMASK_6MB ( (1 << 5) - 1 ) +#define DEV_RATEMASK_9MB ( (1 << 6) - 1 ) +#define DEV_RATEMASK_12MB ( (1 << 7) - 1 ) +#define DEV_RATEMASK_18MB ( (1 << 8) - 1 ) +#define DEV_RATEMASK_24MB ( (1 << 9) - 1 ) +#define DEV_RATEMASK_36MB ( (1 << 10) - 1 ) +#define DEV_RATEMASK_48MB ( (1 << 11) - 1 ) +#define DEV_RATEMASK_54MB ( (1 << 12) - 1 ) + + unsigned short plcp; +}; + +extern const struct rt2x00_rate rt2x00_supported_rates[12]; + +static inline u16 rt2x00_create_rate_hw_value(const u16 index, + const u16 short_preamble) +{ + return (short_preamble << 8) | (index & 0xff); +} + +static inline const struct rt2x00_rate *rt2x00_get_rate(const u16 hw_value) +{ + return &rt2x00_supported_rates[hw_value & 0xff]; +} + +static inline int rt2x00_get_rate_preamble(const u16 hw_value) +{ + return (hw_value & 0xff00); +} + /* * Radio control handlers. */ diff --git a/drivers/net/wireless/rt2x00/rt2x00reg.h b/drivers/net/wireless/rt2x00/rt2x00reg.h index e0ebe51c082f..0325bed2fbf5 100644 --- a/drivers/net/wireless/rt2x00/rt2x00reg.h +++ b/drivers/net/wireless/rt2x00/rt2x00reg.h @@ -220,75 +220,4 @@ static inline u8 rt2x00_get_field8(const u8 reg, return (reg & field.bit_mask) >> field.bit_offset; } -/* - * Device specific rate value. - * We will have to create the device specific rate value - * passed to the ieee80211 kernel. We need to make it a consist of - * multiple fields because we want to store more then 1 device specific - * values inside the value. - * 1 - rate, stored as 100 kbit/s. - * 2 - preamble, short_preamble enabled flag. - * 3 - MASK_RATE, which rates are enabled in this mode, this mask - * corresponds with the TX register format for the current device. - * 4 - plcp, 802.11b rates are device specific, - * 802.11g rates are set according to the ieee802.11a-1999 p.14. - * The bit to enable preamble is set in a seperate define. - */ -#define DEV_RATE FIELD32(0x000007ff) -#define DEV_PREAMBLE FIELD32(0x00000800) -#define DEV_RATEMASK FIELD32(0x00fff000) -#define DEV_PLCP FIELD32(0xff000000) - -/* - * Bitfields - */ -#define DEV_RATEBIT_1MB ( 1 << 0 ) -#define DEV_RATEBIT_2MB ( 1 << 1 ) -#define DEV_RATEBIT_5_5MB ( 1 << 2 ) -#define DEV_RATEBIT_11MB ( 1 << 3 ) -#define DEV_RATEBIT_6MB ( 1 << 4 ) -#define DEV_RATEBIT_9MB ( 1 << 5 ) -#define DEV_RATEBIT_12MB ( 1 << 6 ) -#define DEV_RATEBIT_18MB ( 1 << 7 ) -#define DEV_RATEBIT_24MB ( 1 << 8 ) -#define DEV_RATEBIT_36MB ( 1 << 9 ) -#define DEV_RATEBIT_48MB ( 1 << 10 ) -#define DEV_RATEBIT_54MB ( 1 << 11 ) - -/* - * Bitmasks for DEV_RATEMASK - */ -#define DEV_RATEMASK_1MB ( (DEV_RATEBIT_1MB << 1) -1 ) -#define DEV_RATEMASK_2MB ( (DEV_RATEBIT_2MB << 1) -1 ) -#define DEV_RATEMASK_5_5MB ( (DEV_RATEBIT_5_5MB << 1) -1 ) -#define DEV_RATEMASK_11MB ( (DEV_RATEBIT_11MB << 1) -1 ) -#define DEV_RATEMASK_6MB ( (DEV_RATEBIT_6MB << 1) -1 ) -#define DEV_RATEMASK_9MB ( (DEV_RATEBIT_9MB << 1) -1 ) -#define DEV_RATEMASK_12MB ( (DEV_RATEBIT_12MB << 1) -1 ) -#define DEV_RATEMASK_18MB ( (DEV_RATEBIT_18MB << 1) -1 ) -#define DEV_RATEMASK_24MB ( (DEV_RATEBIT_24MB << 1) -1 ) -#define DEV_RATEMASK_36MB ( (DEV_RATEBIT_36MB << 1) -1 ) -#define DEV_RATEMASK_48MB ( (DEV_RATEBIT_48MB << 1) -1 ) -#define DEV_RATEMASK_54MB ( (DEV_RATEBIT_54MB << 1) -1 ) - -/* - * Bitmask groups of bitrates - */ -#define DEV_BASIC_RATEMASK \ - ( DEV_RATEMASK_11MB | \ - DEV_RATEBIT_6MB | DEV_RATEBIT_12MB | DEV_RATEBIT_24MB ) - -#define DEV_CCK_RATEMASK ( DEV_RATEMASK_11MB ) -#define DEV_OFDM_RATEMASK ( DEV_RATEMASK_54MB & ~DEV_CCK_RATEMASK ) - -/* - * Macro's to set and get specific fields from the device specific val and val2 - * fields inside the ieee80211_rate entry. - */ -#define DEVICE_SET_RATE_FIELD(__value, __mask) \ - (int)( ((__value) << DEV_##__mask.bit_offset) & DEV_##__mask.bit_mask ) - -#define DEVICE_GET_RATE_FIELD(__value, __mask) \ - (int)( ((__value) & DEV_##__mask.bit_mask) >> DEV_##__mask.bit_offset ) - #endif /* RT2X00REG_H */ -- cgit v1.2.1 From f5507ce90be4e00a84b5bb4c7b4324455aa6ee21 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 3 Feb 2008 15:51:13 +0100 Subject: rt2x00: Remove HWMODE_{A,B,G} rt2500usb initialized the SIFS and EIFS without using the values coming from rt2x000lib. After this is fixed HWMODE_{A,B,G} is now unused and can be removed in favour of the ieee80211_band enumeration which could still be usefull later. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2500usb.c | 14 +++----------- drivers/net/wireless/rt2x00/rt2500usb.h | 2 +- drivers/net/wireless/rt2x00/rt2x00.h | 6 +----- drivers/net/wireless/rt2x00/rt2x00config.c | 17 ++--------------- drivers/net/wireless/rt2x00/rt2x00dev.c | 6 +++--- 5 files changed, 10 insertions(+), 35 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 38c968ee50f1..df176cd2ef42 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -358,18 +358,9 @@ static int rt2500usb_config_preamble(struct rt2x00_dev *rt2x00dev, } static void rt2500usb_config_phymode(struct rt2x00_dev *rt2x00dev, - const int phymode, const int basic_rate_mask) { rt2500usb_register_write(rt2x00dev, TXRX_CSR11, basic_rate_mask); - - if (phymode == HWMODE_B) { - rt2500usb_register_write(rt2x00dev, MAC_CSR11, 0x000b); - rt2500usb_register_write(rt2x00dev, MAC_CSR12, 0x0040); - } else { - rt2500usb_register_write(rt2x00dev, MAC_CSR11, 0x0005); - rt2500usb_register_write(rt2x00dev, MAC_CSR12, 0x016c); - } } static void rt2500usb_config_channel(struct rt2x00_dev *rt2x00dev, @@ -507,6 +498,8 @@ static void rt2500usb_config_duration(struct rt2x00_dev *rt2x00dev, u16 reg; rt2500usb_register_write(rt2x00dev, MAC_CSR10, libconf->slot_time); + rt2500usb_register_write(rt2x00dev, MAC_CSR11, libconf->sifs); + rt2500usb_register_write(rt2x00dev, MAC_CSR12, libconf->eifs); rt2500usb_register_read(rt2x00dev, TXRX_CSR18, ®); rt2x00_set_field16(®, TXRX_CSR18_INTERVAL, @@ -519,8 +512,7 @@ static void rt2500usb_config(struct rt2x00_dev *rt2x00dev, const unsigned int flags) { if (flags & CONFIG_UPDATE_PHYMODE) - rt2500usb_config_phymode(rt2x00dev, libconf->phymode, - libconf->basic_rates); + rt2500usb_config_phymode(rt2x00dev, libconf->basic_rates); if (flags & CONFIG_UPDATE_CHANNEL) rt2500usb_config_channel(rt2x00dev, &libconf->rf, libconf->conf->power_level); diff --git a/drivers/net/wireless/rt2x00/rt2500usb.h b/drivers/net/wireless/rt2x00/rt2500usb.h index 23ba0c15741f..647cd2d56ab9 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.h +++ b/drivers/net/wireless/rt2x00/rt2500usb.h @@ -135,7 +135,7 @@ * Misc MAC_CSR registers. * MAC_CSR9: Timer control. * MAC_CSR10: Slot time. - * MAC_CSR11: IFS. + * MAC_CSR11: SIFS. * MAC_CSR12: EIFS. * MAC_CSR13: Power mode0. * MAC_CSR14: Power mode1. diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 4fa762bdb734..93dbe2b286d5 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -390,10 +390,6 @@ static inline struct rt2x00_intf* vif_to_intf(struct ieee80211_vif *vif) return (struct rt2x00_intf *)vif->drv_priv; } -#define HWMODE_B 0 -#define HWMODE_G 1 -#define HWMODE_A 2 - /* * Details about the supported modes, rates and channels * of a particular chipset. This is used by rt2x00lib @@ -433,7 +429,7 @@ struct rt2x00lib_conf { struct antenna_setup ant; - int phymode; + enum ieee80211_band band; int basic_rates; int slot_time; diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index a4d7917f2df5..69959124d25d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -229,23 +229,10 @@ config: memset(&libconf, 0, sizeof(libconf)); if (flags & CONFIG_UPDATE_PHYMODE) { - switch (conf->channel->band) { - case IEEE80211_BAND_5GHZ: - libconf.phymode = HWMODE_A; - break; - case IEEE80211_BAND_2GHZ: - /* Uh oh. what about B? */ - libconf.phymode = HWMODE_G; - break; - default: - ERROR(rt2x00dev, - "Attempt to configure unsupported mode (%d)" - "Defaulting to 802.11b", conf->channel->band); - libconf.phymode = HWMODE_B; - } - band = &rt2x00dev->bands[conf->channel->band]; rate = &band->bitrates[band->n_bitrates - 1]; + + libconf.band = conf->channel->band; libconf.basic_rates = rt2x00_get_rate(rate->hw_value)->ratemask; } diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index f0ba481c51e6..72c4f13a5336 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -896,7 +896,7 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev, * Rates: CCK. * Channels: 2.4 GHz */ - if (spec->num_modes > HWMODE_B) { + if (spec->num_modes > 0) { sbands[IEEE80211_BAND_2GHZ].n_channels = 14; sbands[IEEE80211_BAND_2GHZ].n_bitrates = 4; sbands[IEEE80211_BAND_2GHZ].channels = channels; @@ -909,7 +909,7 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev, * Rates: CCK, OFDM. * Channels: 2.4 GHz */ - if (spec->num_modes > HWMODE_G) { + if (spec->num_modes > 1) { sbands[IEEE80211_BAND_2GHZ].n_channels = 14; sbands[IEEE80211_BAND_2GHZ].n_bitrates = spec->num_rates; sbands[IEEE80211_BAND_2GHZ].channels = channels; @@ -922,7 +922,7 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev, * Rates: OFDM. * Channels: OFDM, UNII, HiperLAN2. */ - if (spec->num_modes > HWMODE_A) { + if (spec->num_modes > 2) { sbands[IEEE80211_BAND_5GHZ].n_channels = spec->num_channels - 14; sbands[IEEE80211_BAND_5GHZ].n_bitrates = spec->num_rates - 4; sbands[IEEE80211_BAND_5GHZ].channels = &channels[14]; -- cgit v1.2.1 From f2a3c7f5c8e3c1356dbbce1e9ac2e7f4d5365ba9 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 3 Feb 2008 15:52:45 +0100 Subject: rt2x00: Use ieee80211_channel_to_frequency() No need to perform the calculation ourselves when wireless provides a helper function for it. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00dev.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 72c4f13a5336..2b99f22ef036 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -827,10 +827,7 @@ static void rt2x00lib_channel(struct ieee80211_channel *entry, const int channel, const int tx_power, const int value) { - if (channel <= 14) - entry->center_freq = 2407 + (5 * channel); - else - entry->center_freq = 5000 + (5 * channel); + entry->center_freq = ieee80211_channel_to_frequency(channel); entry->hw_value = value; entry->max_power = tx_power; entry->max_antenna_gain = 0xff; -- cgit v1.2.1 From a9450b70a755abf093600035ef5361c53343fe9a Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 3 Feb 2008 15:53:40 +0100 Subject: rt2x00: Make use of MAC80211_LED_TRIGGERS Make use of the led triggers provided by mac80211 to control the led status. This can be enabled through a per-driver configuration option which will automatically enable the generic handler in rt2x00lib. This has been enabled for rt2500usb and rt73usb for the moment since the led class will call set_brightness in irq context which will not work correctly with the usb drivers who need to sleep. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/Kconfig | 28 +++++ drivers/net/wireless/rt2x00/Makefile | 4 + drivers/net/wireless/rt2x00/rt2400pci.c | 88 +++++++++------- drivers/net/wireless/rt2x00/rt2500pci.c | 88 +++++++++------- drivers/net/wireless/rt2x00/rt2500usb.c | 91 ++++++++-------- drivers/net/wireless/rt2x00/rt2x00.h | 27 +++-- drivers/net/wireless/rt2x00/rt2x00dev.c | 19 +++- drivers/net/wireless/rt2x00/rt2x00lib.h | 33 ++++++ drivers/net/wireless/rt2x00/rt61pci.c | 180 +++++++++++++++----------------- drivers/net/wireless/rt2x00/rt73usb.c | 165 ++++++++++++++--------------- 10 files changed, 403 insertions(+), 320 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index 28f3e5e94ab6..88a6ef693862 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig @@ -38,6 +38,13 @@ config RT2X00_LIB_RFKILL select RFKILL select INPUT_POLLDEV +config RT2X00_LIB_LEDS + boolean + depends on RT2X00_LIB + select LEDS_CLASS + select LEDS_TRIGGERS + select MAC80211_LEDS + config RT2400PCI tristate "Ralink rt2400 pci/pcmcia support" depends on RT2X00 && PCI @@ -57,6 +64,13 @@ config RT2400PCI_RFKILL hardware button to control the radio state. This feature depends on the RF switch subsystem rfkill. +config RT2400PCI_LEDS + bool "RT2400 leds support" + depends on RT2400PCI + select RT2X00_LIB_LEDS + ---help--- + This adds support for led triggers provided my mac80211. + config RT2500PCI tristate "Ralink rt2500 pci/pcmcia support" depends on RT2X00 && PCI @@ -76,6 +90,13 @@ config RT2500PCI_RFKILL hardware button to control the radio state. This feature depends on the RF switch subsystem rfkill. +config RT2500PCI_LEDS + bool "RT2500 leds support" + depends on RT2500PCI + select RT2X00_LIB_LEDS + ---help--- + This adds support for led triggers provided my mac80211. + config RT61PCI tristate "Ralink rt61 pci/pcmcia support" depends on RT2X00 && PCI @@ -96,6 +117,13 @@ config RT61PCI_RFKILL hardware button to control the radio state. This feature depends on the RF switch subsystem rfkill. +config RT61PCI_LEDS + bool "RT61 leds support" + depends on RT61PCI + select RT2X00_LIB_LEDS + ---help--- + This adds support for led triggers provided my mac80211. + config RT2500USB tristate "Ralink rt2500 usb support" depends on RT2X00 && USB diff --git a/drivers/net/wireless/rt2x00/Makefile b/drivers/net/wireless/rt2x00/Makefile index ab40e1f6b303..757bbc077d93 100644 --- a/drivers/net/wireless/rt2x00/Makefile +++ b/drivers/net/wireless/rt2x00/Makefile @@ -12,6 +12,10 @@ ifeq ($(CONFIG_RT2X00_LIB_FIRMWARE),y) rt2x00lib-objs += rt2x00firmware.o endif +ifeq ($(CONFIG_RT2X00_LIB_LEDS),y) + rt2x00lib-objs += rt2x00leds.o +endif + obj-$(CONFIG_RT2X00_LIB) += rt2x00lib.o obj-$(CONFIG_RT2X00_LIB_PCI) += rt2x00pci.o obj-$(CONFIG_RT2X00_LIB_USB) += rt2x00usb.o diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index feb8c09a33ad..69b4852d4c7f 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -243,6 +243,30 @@ static int rt2400pci_rfkill_poll(struct rt2x00_dev *rt2x00dev) #define rt2400pci_rfkill_poll NULL #endif /* CONFIG_RT2400PCI_RFKILL */ +#ifdef CONFIG_RT2400PCI_LEDS +static void rt2400pci_led_brightness(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + struct rt2x00_led *led = + container_of(led_cdev, struct rt2x00_led, led_dev); + unsigned int enabled = brightness != LED_OFF; + unsigned int activity = + led->rt2x00dev->led_flags & LED_SUPPORT_ACTIVITY; + u32 reg; + + rt2x00pci_register_read(led->rt2x00dev, LEDCSR, ®); + + if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC) { + rt2x00_set_field32(®, LEDCSR_LINK, enabled); + rt2x00_set_field32(®, LEDCSR_ACTIVITY, enabled && activity); + } + + rt2x00pci_register_write(led->rt2x00dev, LEDCSR, reg); +} +#else +#define rt2400pci_led_brightness NULL +#endif /* CONFIG_RT2400PCI_LEDS */ + /* * Configuration handlers. */ @@ -510,34 +534,6 @@ static void rt2400pci_config_cw(struct rt2x00_dev *rt2x00dev, rt2x00pci_register_write(rt2x00dev, CSR11, reg); } -/* - * LED functions. - */ -static void rt2400pci_enable_led(struct rt2x00_dev *rt2x00dev) -{ - u32 reg; - - rt2x00pci_register_read(rt2x00dev, LEDCSR, ®); - - rt2x00_set_field32(®, LEDCSR_ON_PERIOD, 70); - rt2x00_set_field32(®, LEDCSR_OFF_PERIOD, 30); - rt2x00_set_field32(®, LEDCSR_LINK, - (rt2x00dev->led_mode != LED_MODE_ASUS)); - rt2x00_set_field32(®, LEDCSR_ACTIVITY, - (rt2x00dev->led_mode != LED_MODE_TXRX_ACTIVITY)); - rt2x00pci_register_write(rt2x00dev, LEDCSR, reg); -} - -static void rt2400pci_disable_led(struct rt2x00_dev *rt2x00dev) -{ - u32 reg; - - rt2x00pci_register_read(rt2x00dev, LEDCSR, ®); - rt2x00_set_field32(®, LEDCSR_LINK, 0); - rt2x00_set_field32(®, LEDCSR_ACTIVITY, 0); - rt2x00pci_register_write(rt2x00dev, LEDCSR, reg); -} - /* * Link tuning */ @@ -703,6 +699,11 @@ static int rt2400pci_init_registers(struct rt2x00_dev *rt2x00dev) (rt2x00dev->rx->data_size / 128)); rt2x00pci_register_write(rt2x00dev, CSR9, reg); + rt2x00pci_register_read(rt2x00dev, LEDCSR, ®); + rt2x00_set_field32(®, LEDCSR_ON_PERIOD, 70); + rt2x00_set_field32(®, LEDCSR_OFF_PERIOD, 30); + rt2x00pci_register_write(rt2x00dev, LEDCSR, reg); + rt2x00pci_register_write(rt2x00dev, CNT3, 0x3f080000); rt2x00pci_register_read(rt2x00dev, ARCSR0, ®); @@ -872,11 +873,6 @@ static int rt2400pci_enable_radio(struct rt2x00_dev *rt2x00dev) */ rt2400pci_toggle_irq(rt2x00dev, STATE_RADIO_IRQ_ON); - /* - * Enable LED - */ - rt2400pci_enable_led(rt2x00dev); - return 0; } @@ -884,11 +880,6 @@ static void rt2400pci_disable_radio(struct rt2x00_dev *rt2x00dev) { u32 reg; - /* - * Disable LED - */ - rt2400pci_disable_led(rt2x00dev); - rt2x00pci_register_write(rt2x00dev, PWRCSR0, 0); /* @@ -1273,8 +1264,24 @@ static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev) /* * Store led mode, for correct led behaviour. */ - rt2x00dev->led_mode = - rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE); +#ifdef CONFIG_RT2400PCI_LEDS + value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE); + + switch (value) { + case LED_MODE_ASUS: + case LED_MODE_ALPHA: + case LED_MODE_DEFAULT: + rt2x00dev->led_flags = LED_SUPPORT_RADIO; + break; + case LED_MODE_TXRX_ACTIVITY: + rt2x00dev->led_flags = + LED_SUPPORT_RADIO | LED_SUPPORT_ACTIVITY; + break; + case LED_MODE_SIGNAL_STRENGTH: + rt2x00dev->led_flags = LED_SUPPORT_RADIO; + break; + } +#endif /* CONFIG_RT2400PCI_LEDS */ /* * Detect if this device has an hardware controlled radio. @@ -1594,6 +1601,7 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { .link_stats = rt2400pci_link_stats, .reset_tuner = rt2400pci_reset_tuner, .link_tuner = rt2400pci_link_tuner, + .led_brightness = rt2400pci_led_brightness, .write_tx_desc = rt2400pci_write_tx_desc, .write_tx_data = rt2x00pci_write_tx_data, .kick_tx_queue = rt2400pci_kick_tx_queue, diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 36c64f751b1d..bb359a14b4ae 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -243,6 +243,30 @@ static int rt2500pci_rfkill_poll(struct rt2x00_dev *rt2x00dev) #define rt2500pci_rfkill_poll NULL #endif /* CONFIG_RT2500PCI_RFKILL */ +#ifdef CONFIG_RT2500PCI_LEDS +static void rt2500pci_led_brightness(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + struct rt2x00_led *led = + container_of(led_cdev, struct rt2x00_led, led_dev); + unsigned int enabled = brightness != LED_OFF; + unsigned int activity = + led->rt2x00dev->led_flags & LED_SUPPORT_ACTIVITY; + u32 reg; + + rt2x00pci_register_read(led->rt2x00dev, LEDCSR, ®); + + if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC) { + rt2x00_set_field32(®, LEDCSR_LINK, enabled); + rt2x00_set_field32(®, LEDCSR_ACTIVITY, enabled && activity); + } + + rt2x00pci_register_write(led->rt2x00dev, LEDCSR, reg); +} +#else +#define rt2500pci_led_brightness NULL +#endif /* CONFIG_RT2500PCI_LEDS */ + /* * Configuration handlers. */ @@ -548,34 +572,6 @@ static void rt2500pci_config(struct rt2x00_dev *rt2x00dev, rt2500pci_config_duration(rt2x00dev, libconf); } -/* - * LED functions. - */ -static void rt2500pci_enable_led(struct rt2x00_dev *rt2x00dev) -{ - u32 reg; - - rt2x00pci_register_read(rt2x00dev, LEDCSR, ®); - - rt2x00_set_field32(®, LEDCSR_ON_PERIOD, 70); - rt2x00_set_field32(®, LEDCSR_OFF_PERIOD, 30); - rt2x00_set_field32(®, LEDCSR_LINK, - (rt2x00dev->led_mode != LED_MODE_ASUS)); - rt2x00_set_field32(®, LEDCSR_ACTIVITY, - (rt2x00dev->led_mode != LED_MODE_TXRX_ACTIVITY)); - rt2x00pci_register_write(rt2x00dev, LEDCSR, reg); -} - -static void rt2500pci_disable_led(struct rt2x00_dev *rt2x00dev) -{ - u32 reg; - - rt2x00pci_register_read(rt2x00dev, LEDCSR, ®); - rt2x00_set_field32(®, LEDCSR_LINK, 0); - rt2x00_set_field32(®, LEDCSR_ACTIVITY, 0); - rt2x00pci_register_write(rt2x00dev, LEDCSR, reg); -} - /* * Link tuning */ @@ -795,6 +791,11 @@ static int rt2500pci_init_registers(struct rt2x00_dev *rt2x00dev) rt2x00_set_field32(®, CSR11_CW_SELECT, 0); rt2x00pci_register_write(rt2x00dev, CSR11, reg); + rt2x00pci_register_read(rt2x00dev, LEDCSR, ®); + rt2x00_set_field32(®, LEDCSR_ON_PERIOD, 70); + rt2x00_set_field32(®, LEDCSR_OFF_PERIOD, 30); + rt2x00pci_register_write(rt2x00dev, LEDCSR, reg); + rt2x00pci_register_write(rt2x00dev, CNT3, 0); rt2x00pci_register_read(rt2x00dev, TXCSR8, ®); @@ -1026,11 +1027,6 @@ static int rt2500pci_enable_radio(struct rt2x00_dev *rt2x00dev) */ rt2500pci_toggle_irq(rt2x00dev, STATE_RADIO_IRQ_ON); - /* - * Enable LED - */ - rt2500pci_enable_led(rt2x00dev); - return 0; } @@ -1038,11 +1034,6 @@ static void rt2500pci_disable_radio(struct rt2x00_dev *rt2x00dev) { u32 reg; - /* - * Disable LED - */ - rt2500pci_disable_led(rt2x00dev); - rt2x00pci_register_write(rt2x00dev, PWRCSR0, 0); /* @@ -1445,8 +1436,24 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev) /* * Store led mode, for correct led behaviour. */ - rt2x00dev->led_mode = - rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE); +#ifdef CONFIG_RT2500PCI_LEDS + value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE); + + switch (value) { + case LED_MODE_ASUS: + case LED_MODE_ALPHA: + case LED_MODE_DEFAULT: + rt2x00dev->led_flags = LED_SUPPORT_RADIO; + break; + case LED_MODE_TXRX_ACTIVITY: + rt2x00dev->led_flags = + LED_SUPPORT_RADIO | LED_SUPPORT_ACTIVITY; + break; + case LED_MODE_SIGNAL_STRENGTH: + rt2x00dev->led_flags = LED_SUPPORT_RADIO; + break; + } +#endif /* CONFIG_RT2500PCI_LEDS */ /* * Detect if this device has an hardware controlled radio. @@ -1906,6 +1913,7 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = { .link_stats = rt2500pci_link_stats, .reset_tuner = rt2500pci_reset_tuner, .link_tuner = rt2500pci_link_tuner, + .led_brightness = rt2500pci_led_brightness, .write_tx_desc = rt2500pci_write_tx_desc, .write_tx_data = rt2x00pci_write_tx_data, .kick_tx_queue = rt2500pci_kick_tx_queue, diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index df176cd2ef42..6352ebe8cb43 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -282,6 +282,31 @@ static const struct rt2x00debug rt2500usb_rt2x00debug = { }; #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ +#ifdef CONFIG_RT2500USB_LEDS +static void rt2500usb_led_brightness(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + struct rt2x00_led *led = + container_of(led_cdev, struct rt2x00_led, led_dev); + unsigned int enabled = brightness != LED_OFF; + unsigned int activity = + led->rt2x00dev->led_flags & LED_SUPPORT_ACTIVITY; + u16 reg; + + rt2500usb_register_read(led->rt2x00dev, MAC_CSR20, ®); + + if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC) { + rt2x00_set_field16(®, MAC_CSR20_LINK, enabled); + rt2x00_set_field16(®, MAC_CSR20_ACTIVITY, + enabled && activity); + } + + rt2500usb_register_write(led->rt2x00dev, MAC_CSR20, reg); +} +#else +#define rt2500usb_led_brightness NULL +#endif /* CONFIG_RT2500USB_LEDS */ + /* * Configuration handlers. */ @@ -525,36 +550,6 @@ static void rt2500usb_config(struct rt2x00_dev *rt2x00dev, rt2500usb_config_duration(rt2x00dev, libconf); } -/* - * LED functions. - */ -static void rt2500usb_enable_led(struct rt2x00_dev *rt2x00dev) -{ - u16 reg; - - rt2500usb_register_read(rt2x00dev, MAC_CSR21, ®); - rt2x00_set_field16(®, MAC_CSR21_ON_PERIOD, 70); - rt2x00_set_field16(®, MAC_CSR21_OFF_PERIOD, 30); - rt2500usb_register_write(rt2x00dev, MAC_CSR21, reg); - - rt2500usb_register_read(rt2x00dev, MAC_CSR20, ®); - rt2x00_set_field16(®, MAC_CSR20_LINK, - (rt2x00dev->led_mode != LED_MODE_ASUS)); - rt2x00_set_field16(®, MAC_CSR20_ACTIVITY, - (rt2x00dev->led_mode != LED_MODE_TXRX_ACTIVITY)); - rt2500usb_register_write(rt2x00dev, MAC_CSR20, reg); -} - -static void rt2500usb_disable_led(struct rt2x00_dev *rt2x00dev) -{ - u16 reg; - - rt2500usb_register_read(rt2x00dev, MAC_CSR20, ®); - rt2x00_set_field16(®, MAC_CSR20_LINK, 0); - rt2x00_set_field16(®, MAC_CSR20_ACTIVITY, 0); - rt2500usb_register_write(rt2x00dev, MAC_CSR20, reg); -} - /* * Link tuning */ @@ -751,6 +746,11 @@ static int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev) rt2x00_set_field16(®, MAC_CSR1_HOST_READY, 0); rt2500usb_register_write(rt2x00dev, MAC_CSR1, reg); + rt2500usb_register_read(rt2x00dev, MAC_CSR21, ®); + rt2x00_set_field16(®, MAC_CSR21_ON_PERIOD, 70); + rt2x00_set_field16(®, MAC_CSR21_OFF_PERIOD, 30); + rt2500usb_register_write(rt2x00dev, MAC_CSR21, reg); + rt2500usb_register_read(rt2x00dev, TXRX_CSR5, ®); rt2x00_set_field16(®, TXRX_CSR5_BBP_ID0, 13); rt2x00_set_field16(®, TXRX_CSR5_BBP_ID0_VALID, 1); @@ -924,21 +924,11 @@ static int rt2500usb_enable_radio(struct rt2x00_dev *rt2x00dev) return -EIO; } - /* - * Enable LED - */ - rt2500usb_enable_led(rt2x00dev); - return 0; } static void rt2500usb_disable_radio(struct rt2x00_dev *rt2x00dev) { - /* - * Disable LED - */ - rt2500usb_disable_led(rt2x00dev); - rt2500usb_register_write(rt2x00dev, MAC_CSR13, 0x2121); rt2500usb_register_write(rt2x00dev, MAC_CSR14, 0x2121); @@ -1370,8 +1360,24 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev) /* * Store led mode, for correct led behaviour. */ - rt2x00dev->led_mode = - rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE); +#ifdef CONFIG_RT2500USB_LEDS + value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE); + + switch (value) { + case LED_MODE_ASUS: + case LED_MODE_ALPHA: + case LED_MODE_DEFAULT: + rt2x00dev->led_flags = LED_SUPPORT_RADIO; + break; + case LED_MODE_TXRX_ACTIVITY: + rt2x00dev->led_flags = + LED_SUPPORT_RADIO | LED_SUPPORT_ACTIVITY; + break; + case LED_MODE_SIGNAL_STRENGTH: + rt2x00dev->led_flags = LED_SUPPORT_RADIO; + break; + } +#endif /* CONFIG_RT2500USB_LEDS */ /* * Check if the BBP tuning should be disabled. @@ -1817,6 +1823,7 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { .link_stats = rt2500usb_link_stats, .reset_tuner = rt2500usb_reset_tuner, .link_tuner = rt2500usb_link_tuner, + .led_brightness = rt2500usb_led_brightness, .write_tx_desc = rt2500usb_write_tx_desc, .write_tx_data = rt2x00usb_write_tx_data, .get_tx_data_len = rt2500usb_get_tx_data_len, diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 93dbe2b286d5..76270e9c31ff 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -30,12 +30,14 @@ #include #include #include +#include #include #include #include #include "rt2x00debug.h" +#include "rt2x00leds.h" #include "rt2x00reg.h" #include "rt2x00queue.h" @@ -512,6 +514,8 @@ struct rt2x00lib_ops { struct link_qual *qual); void (*reset_tuner) (struct rt2x00_dev *rt2x00dev); void (*link_tuner) (struct rt2x00_dev *rt2x00dev); + void (*led_brightness) (struct led_classdev *led_cdev, + enum led_brightness brightness); /* * TX control handlers @@ -664,6 +668,19 @@ struct rt2x00_dev { struct rt2x00debug_intf *debugfs_intf; #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ + /* + * LED structure for changing the LED status + * by mac8011 or the kernel. + */ +#ifdef CONFIG_RT2X00_LIB_LEDS + unsigned int led_flags; + struct rt2x00_trigger trigger_qual; + struct rt2x00_led led_radio; + struct rt2x00_led led_assoc; + struct rt2x00_led led_qual; + u16 led_mcu_reg; +#endif /* CONFIG_RT2X00_LIB_LEDS */ + /* * Device flags. * In these flags the current status and some @@ -755,16 +772,6 @@ struct rt2x00_dev { */ u16 tx_power; - /* - * LED register (for rt61pci & rt73usb). - */ - u16 led_reg; - - /* - * Led mode (LED_MODE_*) - */ - u8 led_mode; - /* * Rssi <-> Dbm offset */ diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 2b99f22ef036..23dc566b26fd 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -378,6 +378,11 @@ static void rt2x00lib_link_tuner(struct work_struct *work) */ rt2x00lib_precalculate_link_signal(&rt2x00dev->link.qual); + /* + * Send a signal to the led to update the led signal strength. + */ + rt2x00leds_led_quality(rt2x00dev, rt2x00dev->link.qual.avg_rssi); + /* * Evaluate antenna setup, make this the last step since this could * possibly reset some statistics. @@ -1139,6 +1144,11 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) goto exit; } + /* + * Register LED. + */ + rt2x00leds_register(rt2x00dev); + /* * Allocatie rfkill. */ @@ -1186,6 +1196,11 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev) */ rt2x00rfkill_free(rt2x00dev); + /* + * Free LED. + */ + rt2x00leds_unregister(rt2x00dev); + /* * Free ieee80211_hw memory. */ @@ -1227,6 +1242,7 @@ int rt2x00lib_suspend(struct rt2x00_dev *rt2x00dev, pm_message_t state) */ rt2x00lib_stop(rt2x00dev); rt2x00lib_uninitialize(rt2x00dev); + rt2x00leds_suspend(rt2x00dev); rt2x00debug_deregister(rt2x00dev); exit: @@ -1270,9 +1286,10 @@ int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev) NOTICE(rt2x00dev, "Waking up.\n"); /* - * Open the debugfs entry. + * Open the debugfs entry and restore led handling. */ rt2x00debug_register(rt2x00dev); + rt2x00leds_resume(rt2x00dev); /* * Only continue if mac80211 had open interfaces. diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index ca9630c75520..2a611e4366b5 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -183,4 +183,37 @@ static inline void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev) } #endif /* CONFIG_RT2X00_LIB_RFKILL */ +/* + * LED handlers + */ +#ifdef CONFIG_RT2X00_LIB_LEDS +void rt2x00leds_led_quality(struct rt2x00_dev *rt2x00dev, int rssi); +int rt2x00leds_register(struct rt2x00_dev *rt2x00dev); +void rt2x00leds_unregister(struct rt2x00_dev *rt2x00dev); +void rt2x00leds_suspend(struct rt2x00_dev *rt2x00dev); +void rt2x00leds_resume(struct rt2x00_dev *rt2x00dev); +#else +static inline void rt2x00leds_led_quality(struct rt2x00_dev *rt2x00dev, + int rssi) +{ +} + +static inline int rt2x00leds_register(struct rt2x00_dev *rt2x00dev) +{ + return 0; +} + +static inline void rt2x00leds_unregister(struct rt2x00_dev *rt2x00dev) +{ +} + +static inline void rt2x00leds_suspend(struct rt2x00_dev *rt2x00dev) +{ +} + +static inline void rt2x00leds_resume(struct rt2x00_dev *rt2x00dev) +{ +} +#endif /* CONFIG_RT2X00_LIB_LEDS */ + #endif /* RT2X00LIB_H */ diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 1dd30510ed1e..a049ff62e791 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -155,6 +155,12 @@ rf_write: rt2x00_rf_write(rt2x00dev, word, value); } +#ifdef CONFIG_RT61PCI_LEDS +/* + * This function is only called from rt61pci_led_brightness() + * make gcc happy by placing this function inside the + * same ifdef statement as the caller. + */ static void rt61pci_mcu_request(struct rt2x00_dev *rt2x00dev, const u8 command, const u8 token, const u8 arg0, const u8 arg1) @@ -181,6 +187,7 @@ static void rt61pci_mcu_request(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(®, HOST_CMD_CSR_INTERRUPT_MCU, 1); rt2x00pci_register_write(rt2x00dev, HOST_CMD_CSR, reg); } +#endif /* CONFIG_RT61PCI_LEDS */ static void rt61pci_eepromregister_read(struct eeprom_93cx6 *eeprom) { @@ -268,6 +275,48 @@ static int rt61pci_rfkill_poll(struct rt2x00_dev *rt2x00dev) #define rt61pci_rfkill_poll NULL #endif /* CONFIG_RT61PCI_RFKILL */ +#ifdef CONFIG_RT61PCI_LEDS +static void rt61pci_led_brightness(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + struct rt2x00_led *led = + container_of(led_cdev, struct rt2x00_led, led_dev); + unsigned int enabled = brightness != LED_OFF; + unsigned int a_mode = + (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_5GHZ); + unsigned int bg_mode = + (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_2GHZ); + + if (led->type == LED_TYPE_RADIO) { + rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg, + MCU_LEDCS_RADIO_STATUS, enabled); + + rt61pci_mcu_request(led->rt2x00dev, MCU_LED, 0xff, + (led->rt2x00dev->led_mcu_reg & 0xff), + ((led->rt2x00dev->led_mcu_reg >> 8))); + } else if (led->type == LED_TYPE_ASSOC) { + rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg, + MCU_LEDCS_LINK_BG_STATUS, bg_mode); + rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg, + MCU_LEDCS_LINK_A_STATUS, a_mode); + + rt61pci_mcu_request(led->rt2x00dev, MCU_LED, 0xff, + (led->rt2x00dev->led_mcu_reg & 0xff), + ((led->rt2x00dev->led_mcu_reg >> 8))); + } else if (led->type == LED_TYPE_QUALITY) { + /* + * The brightness is divided into 6 levels (0 - 5), + * this means we need to convert the brightness + * argument into the matching level within that range. + */ + rt61pci_mcu_request(led->rt2x00dev, MCU_LED_STRENGTH, 0xff, + brightness / (LED_FULL / 6), 0); + } +} +#else +#define rt61pci_led_brightness NULL +#endif /* CONFIG_RT61PCI_LEDS */ + /* * Configuration handlers. */ @@ -681,78 +730,6 @@ static void rt61pci_config(struct rt2x00_dev *rt2x00dev, rt61pci_config_duration(rt2x00dev, libconf); } -/* - * LED functions. - */ -static void rt61pci_enable_led(struct rt2x00_dev *rt2x00dev) -{ - u32 reg; - u8 arg0; - u8 arg1; - - rt2x00pci_register_read(rt2x00dev, MAC_CSR14, ®); - rt2x00_set_field32(®, MAC_CSR14_ON_PERIOD, 70); - rt2x00_set_field32(®, MAC_CSR14_OFF_PERIOD, 30); - rt2x00pci_register_write(rt2x00dev, MAC_CSR14, reg); - - rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_RADIO_STATUS, 1); - rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_A_STATUS, - rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ); - rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_BG_STATUS, - rt2x00dev->rx_status.band != IEEE80211_BAND_5GHZ); - - arg0 = rt2x00dev->led_reg & 0xff; - arg1 = (rt2x00dev->led_reg >> 8) & 0xff; - - rt61pci_mcu_request(rt2x00dev, MCU_LED, 0xff, arg0, arg1); -} - -static void rt61pci_disable_led(struct rt2x00_dev *rt2x00dev) -{ - u16 led_reg; - u8 arg0; - u8 arg1; - - led_reg = rt2x00dev->led_reg; - rt2x00_set_field16(&led_reg, MCU_LEDCS_RADIO_STATUS, 0); - rt2x00_set_field16(&led_reg, MCU_LEDCS_LINK_BG_STATUS, 0); - rt2x00_set_field16(&led_reg, MCU_LEDCS_LINK_A_STATUS, 0); - - arg0 = led_reg & 0xff; - arg1 = (led_reg >> 8) & 0xff; - - rt61pci_mcu_request(rt2x00dev, MCU_LED, 0xff, arg0, arg1); -} - -static void rt61pci_activity_led(struct rt2x00_dev *rt2x00dev, int rssi) -{ - u8 led; - - if (rt2x00dev->led_mode != LED_MODE_SIGNAL_STRENGTH) - return; - - /* - * Led handling requires a positive value for the rssi, - * to do that correctly we need to add the correction. - */ - rssi += rt2x00dev->rssi_offset; - - if (rssi <= 30) - led = 0; - else if (rssi <= 39) - led = 1; - else if (rssi <= 49) - led = 2; - else if (rssi <= 53) - led = 3; - else if (rssi <= 63) - led = 4; - else - led = 5; - - rt61pci_mcu_request(rt2x00dev, MCU_LED_STRENGTH, 0xff, led, 0); -} - /* * Link tuning */ @@ -787,11 +764,6 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev) u8 up_bound; u8 low_bound; - /* - * Update Led strength - */ - rt61pci_activity_led(rt2x00dev, rssi); - rt61pci_bbp_read(rt2x00dev, 17, &r17); /* @@ -1192,6 +1164,11 @@ static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev) rt2x00pci_register_write(rt2x00dev, MAC_CSR13, 0x0000e000); + rt2x00pci_register_read(rt2x00dev, MAC_CSR14, ®); + rt2x00_set_field32(®, MAC_CSR14_ON_PERIOD, 70); + rt2x00_set_field32(®, MAC_CSR14_OFF_PERIOD, 30); + rt2x00pci_register_write(rt2x00dev, MAC_CSR14, reg); + /* * Invalidate all Shared Keys (SEC_CSR0), * and clear the Shared key Cipher algorithms (SEC_CSR1 & SEC_CSR5) @@ -1403,11 +1380,6 @@ static int rt61pci_enable_radio(struct rt2x00_dev *rt2x00dev) rt2x00_set_field32(®, RX_CNTL_CSR_ENABLE_RX_DMA, 1); rt2x00pci_register_write(rt2x00dev, RX_CNTL_CSR, reg); - /* - * Enable LED - */ - rt61pci_enable_led(rt2x00dev); - return 0; } @@ -1415,11 +1387,6 @@ static void rt61pci_disable_radio(struct rt2x00_dev *rt2x00dev) { u32 reg; - /* - * Disable LED - */ - rt61pci_disable_led(rt2x00dev); - rt2x00pci_register_write(rt2x00dev, MAC_CSR10, 0x00001818); /* @@ -2048,35 +2015,51 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev) * If the eeprom value is invalid, * switch to default led mode. */ +#ifdef CONFIG_RT61PCI_LEDS rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &eeprom); - rt2x00dev->led_mode = rt2x00_get_field16(eeprom, EEPROM_LED_LED_MODE); + value = rt2x00_get_field16(eeprom, EEPROM_LED_LED_MODE); + + switch (value) { + case LED_MODE_TXRX_ACTIVITY: + case LED_MODE_ASUS: + case LED_MODE_ALPHA: + case LED_MODE_DEFAULT: + rt2x00dev->led_flags = + LED_SUPPORT_RADIO | LED_SUPPORT_ASSOC; + break; + case LED_MODE_SIGNAL_STRENGTH: + rt2x00dev->led_flags = + LED_SUPPORT_RADIO | LED_SUPPORT_ASSOC | + LED_SUPPORT_QUALITY; + break; + } - rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LED_MODE, - rt2x00dev->led_mode); - rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_0, + rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_LED_MODE, value); + rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_0, rt2x00_get_field16(eeprom, EEPROM_LED_POLARITY_GPIO_0)); - rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_1, + rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_1, rt2x00_get_field16(eeprom, EEPROM_LED_POLARITY_GPIO_1)); - rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_2, + rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_2, rt2x00_get_field16(eeprom, EEPROM_LED_POLARITY_GPIO_2)); - rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_3, + rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_3, rt2x00_get_field16(eeprom, EEPROM_LED_POLARITY_GPIO_3)); - rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_4, + rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_4, rt2x00_get_field16(eeprom, EEPROM_LED_POLARITY_GPIO_4)); - rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_ACT, + rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_ACT, rt2x00_get_field16(eeprom, EEPROM_LED_POLARITY_ACT)); - rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_READY_BG, + rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_READY_BG, rt2x00_get_field16(eeprom, EEPROM_LED_POLARITY_RDY_G)); - rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_READY_A, + rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_READY_A, rt2x00_get_field16(eeprom, EEPROM_LED_POLARITY_RDY_A)); +#endif /* CONFIG_RT61PCI_LEDS */ return 0; } @@ -2484,6 +2467,7 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { .link_stats = rt61pci_link_stats, .reset_tuner = rt61pci_reset_tuner, .link_tuner = rt61pci_link_tuner, + .led_brightness = rt61pci_led_brightness, .write_tx_desc = rt61pci_write_tx_desc, .write_tx_data = rt2x00pci_write_tx_data, .kick_tx_queue = rt61pci_kick_tx_queue, diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 9cbc879da037..ca5a9855adbd 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -278,6 +278,50 @@ static const struct rt2x00debug rt73usb_rt2x00debug = { }; #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ +#ifdef CONFIG_RT73USB_LEDS +static void rt73usb_led_brightness(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + struct rt2x00_led *led = + container_of(led_cdev, struct rt2x00_led, led_dev); + unsigned int enabled = brightness != LED_OFF; + unsigned int a_mode = + (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_5GHZ); + unsigned int bg_mode = + (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_2GHZ); + + if (led->type == LED_TYPE_RADIO) { + rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg, + MCU_LEDCS_RADIO_STATUS, enabled); + + rt2x00usb_vendor_request_sw(led->rt2x00dev, USB_LED_CONTROL, 0, + led->rt2x00dev->led_mcu_reg, + REGISTER_TIMEOUT); + } else if (led->type == LED_TYPE_ASSOC) { + rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg, + MCU_LEDCS_LINK_BG_STATUS, bg_mode); + rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg, + MCU_LEDCS_LINK_A_STATUS, a_mode); + + rt2x00usb_vendor_request_sw(led->rt2x00dev, USB_LED_CONTROL, 0, + led->rt2x00dev->led_mcu_reg, + REGISTER_TIMEOUT); + } else if (led->type == LED_TYPE_QUALITY) { + /* + * The brightness is divided into 6 levels (0 - 5), + * this means we need to convert the brightness + * argument into the matching level within that range. + */ + rt2x00usb_vendor_request_sw(led->rt2x00dev, USB_LED_CONTROL, + brightness / (LED_FULL / 6), + led->rt2x00dev->led_mcu_reg, + REGISTER_TIMEOUT); + } +} +#else +#define rt73usb_led_brightness NULL +#endif /* CONFIG_RT73USB_LEDS */ + /* * Configuration handlers. */ @@ -629,68 +673,6 @@ static void rt73usb_config(struct rt2x00_dev *rt2x00dev, rt73usb_config_duration(rt2x00dev, libconf); } -/* - * LED functions. - */ -static void rt73usb_enable_led(struct rt2x00_dev *rt2x00dev) -{ - u32 reg; - - rt73usb_register_read(rt2x00dev, MAC_CSR14, ®); - rt2x00_set_field32(®, MAC_CSR14_ON_PERIOD, 70); - rt2x00_set_field32(®, MAC_CSR14_OFF_PERIOD, 30); - rt73usb_register_write(rt2x00dev, MAC_CSR14, reg); - - rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_RADIO_STATUS, 1); - rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_A_STATUS, - (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ)); - rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_BG_STATUS, - (rt2x00dev->rx_status.band != IEEE80211_BAND_5GHZ)); - - rt2x00usb_vendor_request_sw(rt2x00dev, USB_LED_CONTROL, 0x0000, - rt2x00dev->led_reg, REGISTER_TIMEOUT); -} - -static void rt73usb_disable_led(struct rt2x00_dev *rt2x00dev) -{ - rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_RADIO_STATUS, 0); - rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_BG_STATUS, 0); - rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_A_STATUS, 0); - - rt2x00usb_vendor_request_sw(rt2x00dev, USB_LED_CONTROL, 0x0000, - rt2x00dev->led_reg, REGISTER_TIMEOUT); -} - -static void rt73usb_activity_led(struct rt2x00_dev *rt2x00dev, int rssi) -{ - u32 led; - - if (rt2x00dev->led_mode != LED_MODE_SIGNAL_STRENGTH) - return; - - /* - * Led handling requires a positive value for the rssi, - * to do that correctly we need to add the correction. - */ - rssi += rt2x00dev->rssi_offset; - - if (rssi <= 30) - led = 0; - else if (rssi <= 39) - led = 1; - else if (rssi <= 49) - led = 2; - else if (rssi <= 53) - led = 3; - else if (rssi <= 63) - led = 4; - else - led = 5; - - rt2x00usb_vendor_request_sw(rt2x00dev, USB_LED_CONTROL, led, - rt2x00dev->led_reg, REGISTER_TIMEOUT); -} - /* * Link tuning */ @@ -725,11 +707,6 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev) u8 up_bound; u8 low_bound; - /* - * Update Led strength - */ - rt73usb_activity_led(rt2x00dev, rssi); - rt73usb_bbp_read(rt2x00dev, 17, &r17); /* @@ -914,8 +891,6 @@ static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev, void *data, return status; } - rt73usb_disable_led(rt2x00dev); - return 0; } @@ -993,6 +968,11 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev) rt73usb_register_write(rt2x00dev, MAC_CSR13, 0x00007f00); + rt73usb_register_read(rt2x00dev, MAC_CSR14, ®); + rt2x00_set_field32(®, MAC_CSR14_ON_PERIOD, 70); + rt2x00_set_field32(®, MAC_CSR14_OFF_PERIOD, 30); + rt73usb_register_write(rt2x00dev, MAC_CSR14, reg); + /* * Invalidate all Shared Keys (SEC_CSR0), * and clear the Shared key Cipher algorithms (SEC_CSR1 & SEC_CSR5) @@ -1152,21 +1132,11 @@ static int rt73usb_enable_radio(struct rt2x00_dev *rt2x00dev) return -EIO; } - /* - * Enable LED - */ - rt73usb_enable_led(rt2x00dev); - return 0; } static void rt73usb_disable_radio(struct rt2x00_dev *rt2x00dev) { - /* - * Disable LED - */ - rt73usb_disable_led(rt2x00dev); - rt73usb_register_write(rt2x00dev, MAC_CSR10, 0x00001818); /* @@ -1615,33 +1585,49 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev) /* * Store led settings, for correct led behaviour. */ +#ifdef CONFIG_RT73USB_LEDS rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &eeprom); - rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LED_MODE, - rt2x00dev->led_mode); - rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_0, + switch (value) { + case LED_MODE_TXRX_ACTIVITY: + case LED_MODE_ASUS: + case LED_MODE_ALPHA: + case LED_MODE_DEFAULT: + rt2x00dev->led_flags = + LED_SUPPORT_RADIO | LED_SUPPORT_ASSOC; + break; + case LED_MODE_SIGNAL_STRENGTH: + rt2x00dev->led_flags = + LED_SUPPORT_RADIO | LED_SUPPORT_ASSOC | + LED_SUPPORT_QUALITY; + break; + } + + rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_LED_MODE, value); + rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_0, rt2x00_get_field16(eeprom, EEPROM_LED_POLARITY_GPIO_0)); - rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_1, + rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_1, rt2x00_get_field16(eeprom, EEPROM_LED_POLARITY_GPIO_1)); - rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_2, + rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_2, rt2x00_get_field16(eeprom, EEPROM_LED_POLARITY_GPIO_2)); - rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_3, + rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_3, rt2x00_get_field16(eeprom, EEPROM_LED_POLARITY_GPIO_3)); - rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_GPIO_4, + rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_4, rt2x00_get_field16(eeprom, EEPROM_LED_POLARITY_GPIO_4)); - rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_ACT, + rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_ACT, rt2x00_get_field16(eeprom, EEPROM_LED_POLARITY_ACT)); - rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_READY_BG, + rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_READY_BG, rt2x00_get_field16(eeprom, EEPROM_LED_POLARITY_RDY_G)); - rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_POLARITY_READY_A, + rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_READY_A, rt2x00_get_field16(eeprom, EEPROM_LED_POLARITY_RDY_A)); +#endif /* CONFIG_RT73USB_LEDS */ return 0; } @@ -2084,6 +2070,7 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { .link_stats = rt73usb_link_stats, .reset_tuner = rt73usb_reset_tuner, .link_tuner = rt73usb_link_tuner, + .led_brightness = rt73usb_led_brightness, .write_tx_desc = rt73usb_write_tx_desc, .write_tx_data = rt2x00usb_write_tx_data, .get_tx_data_len = rt73usb_get_tx_data_len, -- cgit v1.2.1 From 3b640f21af4b6b36b546fecbd3fe5109981360da Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 3 Feb 2008 15:54:11 +0100 Subject: rt2x00: Enable LED class support for rt2500usb/rt73usb Add kerneldoc for vendor request functions in rt2x00usb. Add asynchroneous vendor request function in rt2x00usb. With the availability of the asynchroneuous vendor request we can now enable LED class support for rt2500usb and rt73usb. Since LED handling is not important, it doesn't really matter if a register call fails (This solution is better then no LED class support at all). Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/Kconfig | 14 ++ drivers/net/wireless/rt2x00/rt2500usb.c | 20 ++- drivers/net/wireless/rt2x00/rt2x00leds.c | 217 +++++++++++++++++++++++++++++++ drivers/net/wireless/rt2x00/rt2x00leds.h | 63 +++++++++ drivers/net/wireless/rt2x00/rt2x00usb.c | 52 ++++++++ drivers/net/wireless/rt2x00/rt2x00usb.h | 129 +++++++++++++----- drivers/net/wireless/rt2x00/rt73usb.c | 21 ++- 7 files changed, 463 insertions(+), 53 deletions(-) create mode 100644 drivers/net/wireless/rt2x00/rt2x00leds.c create mode 100644 drivers/net/wireless/rt2x00/rt2x00leds.h (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index 88a6ef693862..51adb2f37c55 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig @@ -133,6 +133,13 @@ config RT2500USB When compiled as a module, this driver will be called "rt2500usb.ko". +config RT2500USB_LEDS + bool "RT2500 leds support" + depends on RT2500USB + select RT2X00_LIB_LEDS + ---help--- + This adds support for led triggers provided my mac80211. + config RT73USB tristate "Ralink rt73 usb support" depends on RT2X00 && USB @@ -143,6 +150,13 @@ config RT73USB When compiled as a module, this driver will be called "rt73usb.ko". +config RT73USB_LEDS + bool "RT73 leds support" + depends on RT73USB + select RT2X00_LIB_LEDS + ---help--- + This adds support for led triggers provided my mac80211. + config RT2X00_LIB_DEBUGFS bool "Ralink debugfs support" depends on RT2X00_LIB && MAC80211_DEBUGFS diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 6352ebe8cb43..a64b62b20051 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -291,17 +291,16 @@ static void rt2500usb_led_brightness(struct led_classdev *led_cdev, unsigned int enabled = brightness != LED_OFF; unsigned int activity = led->rt2x00dev->led_flags & LED_SUPPORT_ACTIVITY; - u16 reg; - - rt2500usb_register_read(led->rt2x00dev, MAC_CSR20, ®); if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC) { - rt2x00_set_field16(®, MAC_CSR20_LINK, enabled); - rt2x00_set_field16(®, MAC_CSR20_ACTIVITY, - enabled && activity); + rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg, + MAC_CSR20_LINK, enabled); + rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg, + MAC_CSR20_ACTIVITY, enabled && activity); } - rt2500usb_register_write(led->rt2x00dev, MAC_CSR20, reg); + rt2x00usb_vendor_request_async(led->rt2x00dev, USB_SINGLE_WRITE, + MAC_CSR20, led->rt2x00dev->led_mcu_reg); } #else #define rt2500usb_led_brightness NULL @@ -1377,6 +1376,13 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev) rt2x00dev->led_flags = LED_SUPPORT_RADIO; break; } + + /* + * Store the current led register value, we need it later + * in set_brightness but that is called in irq context which + * means we can't use rt2500usb_register_read() at that time. + */ + rt2500usb_register_read(rt2x00dev, MAC_CSR20, &rt2x00dev->led_mcu_reg); #endif /* CONFIG_RT2500USB_LEDS */ /* diff --git a/drivers/net/wireless/rt2x00/rt2x00leds.c b/drivers/net/wireless/rt2x00/rt2x00leds.c new file mode 100644 index 000000000000..9c29d17e0cc2 --- /dev/null +++ b/drivers/net/wireless/rt2x00/rt2x00leds.c @@ -0,0 +1,217 @@ +/* + Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the + Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + Module: rt2x00lib + Abstract: rt2x00 led specific routines. + */ + +#include +#include + +#include "rt2x00.h" +#include "rt2x00lib.h" + +void rt2x00leds_led_quality(struct rt2x00_dev *rt2x00dev, int rssi) +{ + if (!rt2x00dev->trigger_qual.registered) + return; + + /* + * Led handling requires a positive value for the rssi, + * to do that correctly we need to add the correction. + */ + rssi += rt2x00dev->rssi_offset; + + /* + * Get the rssi level, this is used to convert the rssi + * to a LED value inside the range LED_OFF - LED_FULL. + */ + if (rssi <= 30) + rssi = 0; + else if (rssi <= 39) + rssi = 1; + else if (rssi <= 49) + rssi = 2; + else if (rssi <= 53) + rssi = 3; + else if (rssi <= 63) + rssi = 4; + else + rssi = 5; + + /* + * Note that we must _not_ send LED_OFF since the driver + * is going to calculate the value and might use it in a + * division. + */ + led_trigger_event(&rt2x00dev->trigger_qual.trigger, + ((LED_FULL / 6) * rssi) + 1); +} + +static int rt2x00leds_register_trigger(struct rt2x00_dev *rt2x00dev, + struct rt2x00_trigger *trigger, + const char *name) +{ + int retval; + + trigger->trigger.name = name; + retval = led_trigger_register(&trigger->trigger); + if (retval) { + ERROR(rt2x00dev, "Failed to register led trigger.\n"); + return retval; + } + + trigger->registered = 1; + + return 0; +} + +static int rt2x00leds_register_led(struct rt2x00_dev *rt2x00dev, + struct rt2x00_led *led, + enum led_type type, + const char *name, char *trigger) +{ + struct device *device = wiphy_dev(rt2x00dev->hw->wiphy); + int retval; + + led->led_dev.name = name; + led->led_dev.brightness_set = rt2x00dev->ops->lib->led_brightness; + led->led_dev.default_trigger = trigger; + + retval = led_classdev_register(device, &led->led_dev); + if (retval) { + ERROR(rt2x00dev, "Failed to register led handler.\n"); + return retval; + } + + led->rt2x00dev = rt2x00dev; + led->type = type; + led->registered = 1; + + return 0; +} + +int rt2x00leds_register(struct rt2x00_dev *rt2x00dev) +{ + char *trigger; + char dev_name[16]; + char name[32]; + int retval; + + if (!rt2x00dev->ops->lib->led_brightness) + return 0; + + snprintf(dev_name, sizeof(dev_name), "%s-%s", + rt2x00dev->ops->name, wiphy_name(rt2x00dev->hw->wiphy)); + + if (rt2x00dev->led_flags & LED_SUPPORT_RADIO) { + trigger = ieee80211_get_radio_led_name(rt2x00dev->hw); + snprintf(name, sizeof(name), "%s:radio", dev_name); + + retval = rt2x00leds_register_led(rt2x00dev, + &rt2x00dev->led_radio, + LED_TYPE_RADIO, + name, trigger); + if (retval) + goto exit_fail; + } + + if (rt2x00dev->led_flags & LED_SUPPORT_ASSOC) { + trigger = ieee80211_get_assoc_led_name(rt2x00dev->hw); + snprintf(name, sizeof(name), "%s:assoc", dev_name); + + retval = rt2x00leds_register_led(rt2x00dev, + &rt2x00dev->led_assoc, + LED_TYPE_ASSOC, + name, trigger); + if (retval) + goto exit_fail; + } + + if (rt2x00dev->led_flags & LED_SUPPORT_QUALITY) { + snprintf(name, sizeof(name), "%s:quality", dev_name); + + retval = rt2x00leds_register_trigger(rt2x00dev, + &rt2x00dev->trigger_qual, + name); + + retval = rt2x00leds_register_led(rt2x00dev, + &rt2x00dev->led_qual, + LED_TYPE_QUALITY, + name, name); + if (retval) + goto exit_fail; + } + + return 0; + +exit_fail: + rt2x00leds_unregister(rt2x00dev); + return retval; +} + +static void rt2x00leds_unregister_trigger(struct rt2x00_trigger *trigger) +{ + if (!trigger->registered) + return; + + led_trigger_unregister(&trigger->trigger); + trigger->registered = 0; +} + +static void rt2x00leds_unregister_led(struct rt2x00_led *led) +{ + if (!led->registered) + return; + + led_classdev_unregister(&led->led_dev); + + led->led_dev.brightness_set(&led->led_dev, LED_OFF); + led->registered = 0; +} + +void rt2x00leds_unregister(struct rt2x00_dev *rt2x00dev) +{ + rt2x00leds_unregister_trigger(&rt2x00dev->trigger_qual); + rt2x00leds_unregister_led(&rt2x00dev->led_qual); + rt2x00leds_unregister_led(&rt2x00dev->led_assoc); + rt2x00leds_unregister_led(&rt2x00dev->led_radio); +} + +void rt2x00leds_suspend(struct rt2x00_dev *rt2x00dev) +{ + if (rt2x00dev->led_qual.registered) + led_classdev_suspend(&rt2x00dev->led_qual.led_dev); + if (rt2x00dev->led_assoc.registered) + led_classdev_suspend(&rt2x00dev->led_assoc.led_dev); + if (rt2x00dev->led_radio.registered) + led_classdev_suspend(&rt2x00dev->led_radio.led_dev); +} + +void rt2x00leds_resume(struct rt2x00_dev *rt2x00dev) +{ + if (rt2x00dev->led_radio.registered) + led_classdev_resume(&rt2x00dev->led_radio.led_dev); + if (rt2x00dev->led_assoc.registered) + led_classdev_resume(&rt2x00dev->led_assoc.led_dev); + if (rt2x00dev->led_qual.registered) + led_classdev_resume(&rt2x00dev->led_qual.led_dev); +} diff --git a/drivers/net/wireless/rt2x00/rt2x00leds.h b/drivers/net/wireless/rt2x00/rt2x00leds.h new file mode 100644 index 000000000000..11e71e9ce853 --- /dev/null +++ b/drivers/net/wireless/rt2x00/rt2x00leds.h @@ -0,0 +1,63 @@ +/* + Copyright (C) 2004 - 2008 rt2x00 SourceForge Project + + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the + Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + Module: rt2x00lib + Abstract: rt2x00 led datastructures and routines + */ + +#ifndef RT2X00LEDS_H +#define RT2X00LEDS_H + +/* +* Flags used by driver to indicate which + * which led types are supported. + */ +#define LED_SUPPORT_RADIO 0x000001 +#define LED_SUPPORT_ASSOC 0x000002 +#define LED_SUPPORT_ACTIVITY 0x000004 +#define LED_SUPPORT_QUALITY 0x000008 + +enum led_type { + LED_TYPE_RADIO, + LED_TYPE_ASSOC, + LED_TYPE_QUALITY, +}; + +#ifdef CONFIG_RT2X00_LIB_LEDS + +struct rt2x00_led { + struct rt2x00_dev *rt2x00dev; + struct led_classdev led_dev; + + enum led_type type; + unsigned int registered; +}; + +struct rt2x00_trigger { + struct led_trigger trigger; + + enum led_type type; + unsigned int registered; +}; + +#endif /* CONFIG_RT2X00_LIB_LEDS */ + +#endif /* RT2X00LEDS_H */ diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index fc606448908e..44ab2167c6ee 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -122,6 +122,58 @@ int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev, } EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request_buff); +static void rt2x00usb_vendor_request_async_complete(struct urb *urb) +{ + /* + * We're done with it, descrease usage count and let the + * usb layer delete it as soon as it is done with it. + */ + usb_put_urb(urb); +} + +int rt2x00usb_vendor_request_async(struct rt2x00_dev *rt2x00dev, + const u8 request, const u16 offset, + const u16 value) +{ + struct usb_device *usb_dev = rt2x00dev_usb_dev(rt2x00dev); + struct usb_ctrlrequest *ctrl; + struct urb *urb; + int status; + + urb = usb_alloc_urb(0, GFP_NOIO); + if (!urb) + return -ENOMEM; + + ctrl = kmalloc(sizeof(struct usb_ctrlrequest), GFP_NOIO); + if (!ctrl) { + status = -ENOMEM; + goto exit; + } + + ctrl->bRequestType= USB_VENDOR_REQUEST_OUT; + ctrl->bRequest = request; + ctrl->wValue = cpu_to_le16p(&value); + ctrl->wIndex = cpu_to_le16p(&offset); + ctrl->wLength = 0; + + usb_fill_control_urb(urb, usb_dev, usb_sndctrlpipe(usb_dev, 0), + (unsigned char *)ctrl, NULL, 0, + rt2x00usb_vendor_request_async_complete, NULL); + + status = usb_submit_urb(urb, GFP_ATOMIC); + if (!status) + goto exit; + + return 0; + +exit: + usb_put_urb(urb); + kfree(ctrl); + + return status; +} +EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request_async); + /* * TX data handlers. */ diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h index af606638e227..275b089a2a4d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.h +++ b/drivers/net/wireless/rt2x00/rt2x00usb.h @@ -60,34 +60,47 @@ #define USB_VENDOR_REQUEST_IN ( USB_DIR_IN | USB_VENDOR_REQUEST ) #define USB_VENDOR_REQUEST_OUT ( USB_DIR_OUT | USB_VENDOR_REQUEST ) -/* - * USB vendor commands. - */ -#define USB_DEVICE_MODE 0x01 -#define USB_SINGLE_WRITE 0x02 -#define USB_SINGLE_READ 0x03 -#define USB_MULTI_WRITE 0x06 -#define USB_MULTI_READ 0x07 -#define USB_EEPROM_WRITE 0x08 -#define USB_EEPROM_READ 0x09 -#define USB_LED_CONTROL 0x0a /* RT73USB */ -#define USB_RX_CONTROL 0x0c +/** + * enum rt2x00usb_vendor_request: USB vendor commands. + */ +enum rt2x00usb_vendor_request { + USB_DEVICE_MODE = 1, + USB_SINGLE_WRITE = 2, + USB_SINGLE_READ = 3, + USB_MULTI_WRITE = 6, + USB_MULTI_READ = 7, + USB_EEPROM_WRITE = 8, + USB_EEPROM_READ = 9, + USB_LED_CONTROL = 10, /* RT73USB */ + USB_RX_CONTROL = 12, +}; -/* - * Device modes offset +/** + * enum rt2x00usb_mode_offset: Device modes offset. */ -#define USB_MODE_RESET 0x01 -#define USB_MODE_UNPLUG 0x02 -#define USB_MODE_FUNCTION 0x03 -#define USB_MODE_TEST 0x04 -#define USB_MODE_SLEEP 0x07 /* RT73USB */ -#define USB_MODE_FIRMWARE 0x08 /* RT73USB */ -#define USB_MODE_WAKEUP 0x09 /* RT73USB */ +enum rt2x00usb_mode_offset { + USB_MODE_RESET = 1, + USB_MODE_UNPLUG = 2, + USB_MODE_FUNCTION = 3, + USB_MODE_TEST = 4, + USB_MODE_SLEEP = 7, /* RT73USB */ + USB_MODE_FIRMWARE = 8, /* RT73USB */ + USB_MODE_WAKEUP = 9, /* RT73USB */ +}; -/* - * Used to read/write from/to the device. +/** + * rt2x00usb_vendor_request - Send register command to device + * @rt2x00dev: Pointer to &struct rt2x00_dev + * @request: USB vendor command (See &enum rt2x00usb_vendor_request) + * @requesttype: Request type &USB_VENDOR_REQUEST_* + * @offset: Register offset to perform action on + * @value: Value to write to device + * @buffer: Buffer where information will be read/written to by device + * @buffer_length: Size of &buffer + * @timeout: Operation timeout + * * This is the main function to communicate with the device, - * the buffer argument _must_ either be NULL or point to + * the &buffer argument _must_ either be NULL or point to * a buffer allocated by kmalloc. Failure to do so can lead * to unexpected behavior depending on the architecture. */ @@ -97,13 +110,21 @@ int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev, void *buffer, const u16 buffer_length, const int timeout); -/* - * Used to read/write from/to the device. +/** + * rt2x00usb_vendor_request_buff - Send register command to device (buffered) + * @rt2x00dev: Pointer to &struct rt2x00_dev + * @request: USB vendor command (See &enum rt2x00usb_vendor_request) + * @requesttype: Request type &USB_VENDOR_REQUEST_* + * @offset: Register offset to perform action on + * @buffer: Buffer where information will be read/written to by device + * @buffer_length: Size of &buffer + * @timeout: Operation timeout + * * This function will use a previously with kmalloc allocated cache * to communicate with the device. The contents of the buffer pointer * will be copied to this cache when writing, or read from the cache * when reading. - * Buffers send to rt2x00usb_vendor_request _must_ be allocated with + * Buffers send to &rt2x00usb_vendor_request _must_ be allocated with * kmalloc. Hence the reason for using a previously allocated cache * which has been allocated properly. */ @@ -112,15 +133,32 @@ int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev, const u16 offset, void *buffer, const u16 buffer_length, const int timeout); -/* - * A version of rt2x00usb_vendor_request_buff which must be called - * if the usb_cache_mutex is already held. */ +/** + * rt2x00usb_vendor_request_buff - Send register command to device (buffered) + * @rt2x00dev: Pointer to &struct rt2x00_dev + * @request: USB vendor command (See &enum rt2x00usb_vendor_request) + * @requesttype: Request type &USB_VENDOR_REQUEST_* + * @offset: Register offset to perform action on + * @buffer: Buffer where information will be read/written to by device + * @buffer_length: Size of &buffer + * @timeout: Operation timeout + * + * A version of &rt2x00usb_vendor_request_buff which must be called + * if the usb_cache_mutex is already held. + */ int rt2x00usb_vendor_req_buff_lock(struct rt2x00_dev *rt2x00dev, const u8 request, const u8 requesttype, const u16 offset, void *buffer, const u16 buffer_length, const int timeout); -/* +/** + * rt2x00usb_vendor_request_sw - Send single register command to device + * @rt2x00dev: Pointer to &struct rt2x00_dev + * @request: USB vendor command (See &enum rt2x00usb_vendor_request) + * @offset: Register offset to perform action on + * @value: Value to write to device + * @timeout: Operation timeout + * * Simple wrapper around rt2x00usb_vendor_request to write a single * command to the device. Since we don't use the buffer argument we * don't have to worry about kmalloc here. @@ -136,7 +174,12 @@ static inline int rt2x00usb_vendor_request_sw(struct rt2x00_dev *rt2x00dev, value, NULL, 0, timeout); } -/* +/** + * rt2x00usb_eeprom_read - Read eeprom from device + * @rt2x00dev: Pointer to &struct rt2x00_dev + * @eeprom: Pointer to eeprom array to store the information in + * @length: Number of bytes to read from the eeprom + * * Simple wrapper around rt2x00usb_vendor_request to read the eeprom * from the device. Note that the eeprom argument _must_ be allocated using * kmalloc for correct handling inside the kernel USB layer. @@ -147,10 +190,28 @@ static inline int rt2x00usb_eeprom_read(struct rt2x00_dev *rt2x00dev, int timeout = REGISTER_TIMEOUT * (lenght / sizeof(u16)); return rt2x00usb_vendor_request(rt2x00dev, USB_EEPROM_READ, - USB_VENDOR_REQUEST_IN, 0x0000, - 0x0000, eeprom, lenght, timeout); + USB_VENDOR_REQUEST_IN, 0, 0, + eeprom, lenght, timeout); } +/** + * rt2x00usb_vendor_request_async - Send register command to device (async) + * @rt2x00dev: Pointer to &struct rt2x00_dev + * @request: USB vendor command (See &enum rt2x00usb_vendor_request) + * @offset: Register offset to perform action on + * @value: Value to write to device + * + * Asynchroneous version of &rt2x00usb_vendor_request this is required + * for some routines where the driver cannot sleep because it is in + * irq context. Note that with this function the driver will not be + * notified on failure or timeout of the command. It will only be notified + * if the start of the command succeeded or not. This means it should not be + * used when the command must succeed. + */ +int rt2x00usb_vendor_request_async(struct rt2x00_dev *rt2x00dev, + const u8 request, const u16 offset, + const u16 value); + /* * Radio handlers */ diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index ca5a9855adbd..92c8f601296f 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -294,28 +294,25 @@ static void rt73usb_led_brightness(struct led_classdev *led_cdev, rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg, MCU_LEDCS_RADIO_STATUS, enabled); - rt2x00usb_vendor_request_sw(led->rt2x00dev, USB_LED_CONTROL, 0, - led->rt2x00dev->led_mcu_reg, - REGISTER_TIMEOUT); + rt2x00usb_vendor_request_async(led->rt2x00dev, USB_LED_CONTROL, + 0, led->rt2x00dev->led_mcu_reg); } else if (led->type == LED_TYPE_ASSOC) { rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg, MCU_LEDCS_LINK_BG_STATUS, bg_mode); rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg, MCU_LEDCS_LINK_A_STATUS, a_mode); - rt2x00usb_vendor_request_sw(led->rt2x00dev, USB_LED_CONTROL, 0, - led->rt2x00dev->led_mcu_reg, - REGISTER_TIMEOUT); + rt2x00usb_vendor_request_async(led->rt2x00dev, USB_LED_CONTROL, + 0, led->rt2x00dev->led_mcu_reg); } else if (led->type == LED_TYPE_QUALITY) { /* * The brightness is divided into 6 levels (0 - 5), * this means we need to convert the brightness * argument into the matching level within that range. */ - rt2x00usb_vendor_request_sw(led->rt2x00dev, USB_LED_CONTROL, - brightness / (LED_FULL / 6), - led->rt2x00dev->led_mcu_reg, - REGISTER_TIMEOUT); + rt2x00usb_vendor_request_async(led->rt2x00dev, USB_LED_CONTROL, + brightness / (LED_FULL / 6), + led->rt2x00dev->led_mcu_reg); } } #else @@ -871,7 +868,7 @@ static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev, void *data, rt2x00usb_vendor_request(rt2x00dev, USB_MULTI_WRITE, USB_VENDOR_REQUEST_OUT, - FIRMWARE_IMAGE_BASE + i, 0x0000, + FIRMWARE_IMAGE_BASE + i, 0, cache, buflen, timeout); ptr += buflen; @@ -884,7 +881,7 @@ static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev, void *data, * we need to specify a long timeout time. */ status = rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, - 0x0000, USB_MODE_FIRMWARE, + 0, USB_MODE_FIRMWARE, REGISTER_TIMEOUT_FIRMWARE); if (status < 0) { ERROR(rt2x00dev, "Failed to write Firmware to device.\n"); -- cgit v1.2.1 From 8f5fa7f04484e933b3ac8dfe77995d3f1cedde5f Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 3 Feb 2008 15:54:34 +0100 Subject: rt2x00: Fix rate initialization Fix typo in rate initialization. This fixes the WARN_ON() in net/wireless/util.cpp:83 Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 23dc566b26fd..d69f7407b972 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -876,7 +876,7 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev, * Initialize Rate list. */ for (i = 0; i < spec->num_rates; i++) - rt2x00lib_rate(&rates[0], i, rt2x00_get_rate(i)); + rt2x00lib_rate(&rates[i], i, rt2x00_get_rate(i)); /* * Initialize Channel list. -- cgit v1.2.1 From b86af631b8482b908979b61d06ae7d14e5966885 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 3 Feb 2008 15:56:02 +0100 Subject: rt2x00: Release rt2x00 2.1.0 Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 76270e9c31ff..f6ec9fe23096 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -44,7 +44,7 @@ /* * Module information. */ -#define DRV_VERSION "2.0.14" +#define DRV_VERSION "2.1.0" #define DRV_PROJECT "http://rt2x00.serialmonkey.com" /* -- cgit v1.2.1 From 78330fddec4e326af5e6aede0fc97824c690ba1d Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 6 Feb 2008 02:37:18 +0200 Subject: iwlwifi: Fix HT compilation breakage caused by cfg80211 API for channels/bitrates patch This patch fixes compilation breakage caused by 'cfg80211 API for channels/bitrates' patch. however it doesn't fix the driver's functional problems caused by that patch. Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 2 +- drivers/net/wireless/iwlwifi/iwl-4965.c | 11 ++-- drivers/net/wireless/iwlwifi/iwl-4965.h | 18 ++++--- drivers/net/wireless/iwlwifi/iwl4965-base.c | 83 +++++++++++------------------ 4 files changed, 50 insertions(+), 64 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index f018ce464d97..a8223c4cc97c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -464,7 +464,7 @@ static void rs_tx_status(void *priv_rate, IWL_DEBUG_RATE("enter\n"); retries = tx_resp->retry_count; - + /* FIXME : this is wrong */ first_index = &sband->bitrates[0] - tx_resp->control.tx_rate; if ((first_index < 0) || (first_index >= IWL_RATE_COUNT)) { IWL_DEBUG_RATE("leave: Rate out of bounds: %d\n", first_index); diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 886a4b86605c..cc141f8ba616 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -3459,14 +3459,15 @@ static int parse_elems(u8 *start, size_t len, struct ieee802_11_elems *elems) return 0; } -void iwl4965_init_ht_hw_capab(struct ieee80211_ht_info *ht_info, int mode) +void iwl4965_init_ht_hw_capab(struct ieee80211_ht_info *ht_info, + enum ieee80211_band band) { ht_info->cap = 0; memset(ht_info->supp_mcs_set, 0, 16); ht_info->ht_supported = 1; - if (mode == MODE_IEEE80211A) { + if (band == IEEE80211_BAND_5GHZ) { ht_info->cap |= (u16)IEEE80211_HT_CAP_SUP_WIDTH; ht_info->cap |= (u16)IEEE80211_HT_CAP_SGI_40; ht_info->supp_mcs_set[4] = 0x01; @@ -3896,7 +3897,9 @@ static int iwl4965_tx_status_reply_compressed_ba(struct iwl4965_priv *priv, tx_status->flags |= IEEE80211_TX_STATUS_AMPDU; tx_status->ampdu_ack_map = successes; tx_status->ampdu_ack_len = agg->frame_count; + /* FIXME Wrong rate tx_status->control.tx_rate = agg->rate_n_flags; + */ IWL_DEBUG_TX_REPLY("Bitmap %llx\n", bitmap); @@ -4218,7 +4221,7 @@ void iwl4965_add_station(struct iwl4965_priv *priv, const u8 *addr, int is_ap) static u8 iwl4965_is_channel_extension(struct iwl4965_priv *priv, enum ieee80211_band band, - u16 channel, u8 extension_chan_offset) + u16 channel, u8 extension_chan_offset) { const struct iwl4965_channel_info *ch_info; @@ -4252,7 +4255,7 @@ static u8 iwl4965_is_fat_tx_allowed(struct iwl4965_priv *priv, return 0; } - return (iwl4965_is_channel_extension(priv, priv->phymode, + return (iwl4965_is_channel_extension(priv, priv->band, iwl_ht_conf->control_channel, iwl_ht_conf->extension_chan_offset)); } diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index cb8f7f2a8d48..45cf4830568e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -772,17 +772,21 @@ extern int iwl4965_set_fat_chan_info(struct iwl4965_priv *priv, extern void iwl4965_rf_kill_ct_config(struct iwl4965_priv *priv); #ifdef CONFIG_IWL4965_HT -extern void iwl4965_init_ht_hw_capab(struct ieee80211_ht_info *ht_info, - int mode); -extern void iwl4965_set_rxon_ht(struct iwl4965_priv *priv, - struct iwl_ht_info *ht_info); -extern void iwl4965_set_ht_add_station(struct iwl4965_priv *priv, u8 index, +void iwl4965_init_ht_hw_capab(struct ieee80211_ht_info *ht_info, + enum ieee80211_band band); +void iwl4965_set_rxon_ht(struct iwl4965_priv *priv, + struct iwl_ht_info *ht_info); +void iwl4965_set_ht_add_station(struct iwl4965_priv *priv, u8 index, struct ieee80211_ht_info *sta_ht_inf); -extern int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw, +int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw, enum ieee80211_ampdu_mlme_action action, const u8 *addr, u16 tid, u16 *ssn); -extern int iwl4965_check_empty_hw_queue(struct iwl4965_priv *priv, int sta_id, +int iwl4965_check_empty_hw_queue(struct iwl4965_priv *priv, int sta_id, u8 tid, int txq_id); +#else +static inline void iwl4965_init_ht_hw_capab(struct ieee80211_ht_info *ht_info, + enum ieee80211_band band) {} + #endif /*CONFIG_IWL4965_HT */ /* Structures, enum, and defines specific to the 4965 */ diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 933e0d44f69f..d0e385aa59e8 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -1893,24 +1893,20 @@ static u16 iwl4965_supported_rate_to_ie(u8 *ie, u16 supported_rate, return ret_rates; } -#ifdef CONFIG_IWL4965_HT -void static iwl4965_set_ht_capab(struct ieee80211_hw *hw, - struct ieee80211_ht_cap *ht_cap, - u8 use_current_config); -#endif - /** * iwl4965_fill_probe_req - fill in all required fields and IE for probe request */ static u16 iwl4965_fill_probe_req(struct iwl4965_priv *priv, - struct ieee80211_mgmt *frame, - int left, int is_direct) + enum ieee80211_band band, + struct ieee80211_mgmt *frame, + int left, int is_direct) { int len = 0; u8 *pos = NULL; u16 active_rates, ret_rates, cck_rates, active_rate_basic; #ifdef CONFIG_IWL4965_HT - struct ieee80211_hw_mode *mode; + const struct ieee80211_supported_band *sband = + iwl4965_get_hw_mode(priv, band); #endif /* CONFIG_IWL4965_HT */ /* Make sure there is enough space for the probe request, @@ -1995,13 +1991,18 @@ static u16 iwl4965_fill_probe_req(struct iwl4965_priv *priv, len += 2 + *pos; #ifdef CONFIG_IWL4965_HT - mode = priv->hw->conf.mode; - if (mode->ht_info.ht_supported) { + if (sband && sband->ht_info.ht_supported) { + struct ieee80211_ht_cap *ht_cap; pos += (*pos) + 1; *pos++ = WLAN_EID_HT_CAPABILITY; *pos++ = sizeof(struct ieee80211_ht_cap); - iwl4965_set_ht_capab(priv->hw, - (struct ieee80211_ht_cap *)pos, 0); + ht_cap = (struct ieee80211_ht_cap *)pos; + ht_cap->cap_info = cpu_to_le16(sband->ht_info.cap); + memcpy(ht_cap->supp_mcs_set, sband->ht_info.supp_mcs_set, 16); + ht_cap->ampdu_params_info =(sband->ht_info.ampdu_factor & + IEEE80211_HT_CAP_AMPDU_FACTOR) | + ((sband->ht_info.ampdu_density << 2) & + IEEE80211_HT_CAP_AMPDU_DENSITY); len += 2 + sizeof(struct ieee80211_ht_cap); } #endif /*CONFIG_IWL4965_HT */ @@ -3592,8 +3593,9 @@ static int iwl4965_tx_status_reply_tx(struct iwl4965_priv *priv, tx_status->control.flags &= ~IEEE80211_TXCTL_AMPDU; tx_status->flags = iwl4965_is_tx_success(status)? IEEE80211_TX_STATUS_ACK : 0; + /* FIXME Wrong Rate tx_status->control.tx_rate = - iwl4965_hw_get_rate_n_flags(tx_resp->rate_n_flags); + iwl4965_hw_get_rate_n_flags(tx_resp->rate_n_flags); */ /* FIXME: code repetition end */ IWL_DEBUG_TX_REPLY("1 Frame 0x%x failure :%d\n", @@ -5775,22 +5777,20 @@ static int iwl4965_init_geos(struct iwl4965_priv *priv) } /* 5.2GHz channels start after the 2.4GHz channels */ -#ifdef CONFIG_IWL4965_HT - iwl4965_init_ht_hw_capab(&modes[A].ht_info, MODE_IEEE80211A); -#endif -#ifdef CONFIG_IWL4965_HT - iwl4965_init_ht_hw_capab(&modes[G].ht_info, MODE_IEEE80211G); -#endif band = &priv->bands[IEEE80211_BAND_5GHZ]; band->channels = &channels[ARRAY_SIZE(iwl4965_eeprom_band_1)]; band->bitrates = &rates[4]; band->n_bitrates = 8; /* just OFDM */ + iwl4965_init_ht_hw_capab(&band->ht_info, IEEE80211_BAND_5GHZ); + band = &priv->bands[IEEE80211_BAND_2GHZ]; band->channels = channels; band->bitrates = rates; band->n_bitrates = 12; /* OFDM & CCK */ + iwl4965_init_ht_hw_capab(&band->ht_info, IEEE80211_BAND_2GHZ); + priv->ieee_channels = channels; priv->ieee_rates = rates; @@ -6860,8 +6860,9 @@ static void iwl4965_bg_request_scan(struct work_struct *data) int rc = 0; struct iwl4965_scan_cmd *scan; struct ieee80211_conf *conf = NULL; - u8 direct_mask; + u16 cmd_len; enum ieee80211_band band; + u8 direct_mask; conf = ieee80211_get_hw_conf(priv->hw); @@ -6970,18 +6971,10 @@ static void iwl4965_bg_request_scan(struct work_struct *data) } else direct_mask = 0; - /* We don't build a direct scan probe request; the uCode will do - * that based on the direct_mask added to each channel entry */ - scan->tx_cmd.len = cpu_to_le16( - iwl4965_fill_probe_req(priv, (struct ieee80211_mgmt *)scan->data, - IWL_MAX_SCAN_SIZE - sizeof(*scan), 0)); scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; scan->tx_cmd.sta_id = priv->hw_setting.bcast_sta_id; scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; - /* flags + rate selection */ - - scan->tx_cmd.tx_flags |= cpu_to_le32(0x200); switch (priv->scan_bands) { case 2: @@ -7007,6 +7000,13 @@ static void iwl4965_bg_request_scan(struct work_struct *data) goto done; } + /* We don't build a direct scan probe request; the uCode will do + * that based on the direct_mask added to each channel entry */ + cmd_len = iwl4965_fill_probe_req(priv, band, + (struct ieee80211_mgmt *)scan->data, + IWL_MAX_SCAN_SIZE - sizeof(*scan), 0); + + scan->tx_cmd.len = cpu_to_le16(cmd_len); /* select Rx chains */ /* Force use of chains B and C (0x6) for scan Rx. @@ -7468,10 +7468,10 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co } #ifdef CONFIG_IWL4965_HT - /* if we are switching fron ht to 2.4 clear flags + /* if we are switching from ht to 2.4 clear flags * from any ht related info since 2.4 does not * support ht */ - if ((le16_to_cpu(priv->staging_rxon.channel) != conf->channel) + if ((le16_to_cpu(priv->staging_rxon.channel) != conf->channel->hw_value) #ifdef IEEE80211_CONF_CHANNEL_SWITCH && !(conf->flags & IEEE80211_CONF_CHANNEL_SWITCH) #endif @@ -8188,27 +8188,6 @@ static int iwl4965_mac_conf_ht(struct ieee80211_hw *hw, return 0; } -static void iwl4965_set_ht_capab(struct ieee80211_hw *hw, - struct ieee80211_ht_cap *ht_cap, - u8 use_current_config) -{ - struct ieee80211_conf *conf = &hw->conf; - - if (use_current_config) { - ht_cap->cap_info = cpu_to_le16(conf->ht_conf.cap); - memcpy(ht_cap->supp_mcs_set, - conf->ht_conf.supp_mcs_set, 16); - } else { - ht_cap->cap_info = cpu_to_le16(mode->ht_info.cap); - memcpy(ht_cap->supp_mcs_set, - mode->ht_info.supp_mcs_set, 16); - } - ht_cap->ampdu_params_info = - (mode->ht_info.ampdu_factor & IEEE80211_HT_CAP_AMPDU_FACTOR) | - ((mode->ht_info.ampdu_density << 2) & - IEEE80211_HT_CAP_AMPDU_DENSITY); -} - #endif /*CONFIG_IWL4965_HT*/ /***************************************************************************** -- cgit v1.2.1 From 292ae1745b8fe25b8182655d4bd5628e7947ea6b Mon Sep 17 00:00:00 2001 From: Ron Rindjunsky Date: Wed, 6 Feb 2008 11:20:39 -0800 Subject: iwlwifi: remove IWL{4965,3945}_QOS This patch removes the IWL4965_QOS and IWL3945_QOS defines from Kconfig file along with all uses of it. These defines were relevant for the period QoS code was tested to be stable in driver's flows. Signed-off-by: Ron Rindjunsky Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/Kconfig | 16 +--------------- drivers/net/wireless/iwlwifi/iwl-3945.h | 5 ----- drivers/net/wireless/iwlwifi/iwl-4965.h | 5 ----- drivers/net/wireless/iwlwifi/iwl3945-base.c | 17 ++--------------- drivers/net/wireless/iwlwifi/iwl4965-base.c | 18 +----------------- 5 files changed, 4 insertions(+), 57 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index 9c3fe1835a12..24c3e3ddafc6 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig @@ -24,17 +24,10 @@ config IWL4965 say M here and read . The module will be called iwl4965.ko. -config IWL4965_QOS - bool "Enable Wireless QoS in iwl4965 driver" - depends on IWL4965 - ---help--- - This option will enable wireless quality of service (QoS) for the - iwl4965 driver. - config IWL4965_HT bool "Enable 802.11n HT features in iwl4965 driver" depends on EXPERIMENTAL - depends on IWL4965 && IWL4965_QOS + depends on IWL4965 ---help--- This option enables IEEE 802.11n High Throughput features for the iwl4965 driver. @@ -104,13 +97,6 @@ config IWL3945 say M here and read . The module will be called iwl3945.ko. -config IWL3945_QOS - bool "Enable Wireless QoS in iwl3945 driver" - depends on IWL3945 - ---help--- - This option will enable wireless quality of service (QoS) for the - iwl3945 driver. - 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 1beb5b676797..393cff6f2270 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -431,8 +431,6 @@ union iwl3945_ht_rate_supp { }; }; -#ifdef CONFIG_IWL3945_QOS - union iwl3945_qos_capabity { struct { u8 edca_count:4; /* bit 0-3 */ @@ -460,7 +458,6 @@ struct iwl3945_qos_info { union iwl3945_qos_capabity qos_cap; struct iwl3945_qosparam_cmd def_qos_parm; }; -#endif /*CONFIG_IWL3945_QOS */ #define STA_PS_STATUS_WAKE 0 #define STA_PS_STATUS_SLEEP 1 @@ -869,9 +866,7 @@ struct iwl3945_priv { u16 assoc_capability; u8 ps_mode; -#ifdef CONFIG_IWL3945_QOS struct iwl3945_qos_info qos_data; -#endif /*CONFIG_IWL3945_QOS */ struct workqueue_struct *workqueue; diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index 45cf4830568e..67189ab93dbe 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -510,8 +510,6 @@ struct iwl_ht_info { }; #endif /*CONFIG_IWL4965_HT */ -#ifdef CONFIG_IWL4965_QOS - union iwl4965_qos_capabity { struct { u8 edca_count:4; /* bit 0-3 */ @@ -539,7 +537,6 @@ struct iwl4965_qos_info { union iwl4965_qos_capabity qos_cap; struct iwl4965_qosparam_cmd def_qos_parm; }; -#endif /*CONFIG_IWL4965_QOS */ #define STA_PS_STATUS_WAKE 0 #define STA_PS_STATUS_SLEEP 1 @@ -1173,9 +1170,7 @@ struct iwl4965_priv { u16 assoc_capability; u8 ps_mode; -#ifdef CONFIG_IWL4965_QOS struct iwl4965_qos_info qos_data; -#endif /*CONFIG_IWL4965_QOS */ struct workqueue_struct *workqueue; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 41b45a2778bd..60e4b00d40fc 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -1910,7 +1910,6 @@ static u16 iwl3945_fill_probe_req(struct iwl3945_priv *priv, /* * QoS support */ -#ifdef CONFIG_IWL3945_QOS static int iwl3945_send_qos_params_command(struct iwl3945_priv *priv, struct iwl3945_qosparam_cmd *qos) { @@ -2039,7 +2038,6 @@ static void iwl3945_activate_qos(struct iwl3945_priv *priv, u8 force) } } -#endif /* CONFIG_IWL3945_QOS */ /* * Power management (not Tx power!) functions */ @@ -6770,9 +6768,8 @@ static void iwl3945_bg_post_associate(struct work_struct *data) iwl3945_sequence_reset(priv); -#ifdef CONFIG_IWL3945_QOS iwl3945_activate_qos(priv, 0); -#endif /* CONFIG_IWL3945_QOS */ + /* we have just associated, don't start scan too early */ priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN; mutex_unlock(&priv->mutex); @@ -7417,10 +7414,8 @@ static int iwl3945_mac_conf_tx(struct ieee80211_hw *hw, int queue, const struct ieee80211_tx_queue_params *params) { struct iwl3945_priv *priv = hw->priv; -#ifdef CONFIG_IWL3945_QOS unsigned long flags; int q; -#endif /* CONFIG_IWL3945_QOS */ IWL_DEBUG_MAC80211("enter\n"); @@ -7434,7 +7429,6 @@ static int iwl3945_mac_conf_tx(struct ieee80211_hw *hw, int queue, return 0; } -#ifdef CONFIG_IWL3945_QOS if (!priv->qos_data.qos_enable) { priv->qos_data.qos_active = 0; IWL_DEBUG_MAC80211("leave - qos not enabled\n"); @@ -7463,8 +7457,6 @@ static int iwl3945_mac_conf_tx(struct ieee80211_hw *hw, int queue, mutex_unlock(&priv->mutex); -#endif /*CONFIG_IWL3945_QOS */ - IWL_DEBUG_MAC80211("leave\n"); return 0; } @@ -7529,9 +7521,8 @@ static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw) mutex_lock(&priv->mutex); IWL_DEBUG_MAC80211("enter\n"); -#ifdef CONFIG_IWL3945_QOS iwl3945_reset_qos(priv); -#endif + cancel_delayed_work(&priv->post_associate); spin_lock_irqsave(&priv->lock, flags); @@ -7619,9 +7610,7 @@ static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk IWL_DEBUG_MAC80211("leave\n"); spin_unlock_irqrestore(&priv->lock, flags); -#ifdef CONFIG_IWL3945_QOS iwl3945_reset_qos(priv); -#endif queue_work(priv->workqueue, &priv->post_associate.work); @@ -8409,7 +8398,6 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e goto out_iounmap; } -#ifdef CONFIG_IWL3945_QOS if (iwl3945_param_qos_enable) priv->qos_data.qos_enable = 1; @@ -8417,7 +8405,6 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e priv->qos_data.qos_active = 0; priv->qos_data.qos_cap.val = 0; -#endif /* CONFIG_IWL3945_QOS */ iwl3945_set_rxon_channel(priv, IEEE80211_BAND_2GHZ, 6); iwl3945_setup_deferred_work(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index d0e385aa59e8..8284c94a1f01 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -2014,7 +2014,6 @@ static u16 iwl4965_fill_probe_req(struct iwl4965_priv *priv, /* * QoS support */ -#ifdef CONFIG_IWL4965_QOS static int iwl4965_send_qos_params_command(struct iwl4965_priv *priv, struct iwl4965_qosparam_cmd *qos) { @@ -2148,7 +2147,6 @@ static void iwl4965_activate_qos(struct iwl4965_priv *priv, u8 force) } } -#endif /* CONFIG_IWL4965_QOS */ /* * Power management (not Tx power!) functions */ @@ -7200,9 +7198,8 @@ static void iwl4965_bg_post_associate(struct work_struct *data) if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS) priv->assoc_station_added = 1; -#ifdef CONFIG_IWL4965_QOS iwl4965_activate_qos(priv, 0); -#endif /* CONFIG_IWL4965_QOS */ + /* we have just associated, don't start scan too early */ priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN; mutex_unlock(&priv->mutex); @@ -7577,9 +7574,7 @@ static void iwl4965_config_ap(struct iwl4965_priv *priv) /* restore RXON assoc */ priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; iwl4965_commit_rxon(priv); -#ifdef CONFIG_IWL4965_QOS iwl4965_activate_qos(priv, 1); -#endif iwl4965_rxon_add_station(priv, iwl4965_broadcast_addr, 0); } iwl4965_send_beacon_cmd(priv); @@ -7893,10 +7888,8 @@ static int iwl4965_mac_conf_tx(struct ieee80211_hw *hw, int queue, const struct ieee80211_tx_queue_params *params) { struct iwl4965_priv *priv = hw->priv; -#ifdef CONFIG_IWL4965_QOS unsigned long flags; int q; -#endif /* CONFIG_IWL4965_QOS */ IWL_DEBUG_MAC80211("enter\n"); @@ -7910,7 +7903,6 @@ static int iwl4965_mac_conf_tx(struct ieee80211_hw *hw, int queue, return 0; } -#ifdef CONFIG_IWL4965_QOS if (!priv->qos_data.qos_enable) { priv->qos_data.qos_active = 0; IWL_DEBUG_MAC80211("leave - qos not enabled\n"); @@ -7939,8 +7931,6 @@ static int iwl4965_mac_conf_tx(struct ieee80211_hw *hw, int queue, mutex_unlock(&priv->mutex); -#endif /*CONFIG_IWL4965_QOS */ - IWL_DEBUG_MAC80211("leave\n"); return 0; } @@ -8012,9 +8002,7 @@ static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw) spin_unlock_irqrestore(&priv->lock, flags); #endif /* CONFIG_IWL4965_HT */ -#ifdef CONFIG_IWL4965_QOS iwl4965_reset_qos(priv); -#endif cancel_delayed_work(&priv->post_associate); @@ -8103,9 +8091,7 @@ static int iwl4965_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk IWL_DEBUG_MAC80211("leave\n"); spin_unlock_irqrestore(&priv->lock, flags); -#ifdef CONFIG_IWL4965_QOS iwl4965_reset_qos(priv); -#endif queue_work(priv->workqueue, &priv->post_associate.work); @@ -8934,7 +8920,6 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e goto out_iounmap; } -#ifdef CONFIG_IWL4965_QOS if (iwl4965_param_qos_enable) priv->qos_data.qos_enable = 1; @@ -8942,7 +8927,6 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e priv->qos_data.qos_active = 0; priv->qos_data.qos_cap.val = 0; -#endif /* CONFIG_IWL4965_QOS */ iwl4965_set_rxon_channel(priv, IEEE80211_BAND_2GHZ, 6); iwl4965_setup_deferred_work(priv); -- cgit v1.2.1 From eed0fd2102206bf6108460274c40ee6b8e863369 Mon Sep 17 00:00:00 2001 From: Stefano Brivio Date: Fri, 8 Feb 2008 06:31:10 +0100 Subject: b43legacy: add definitions for MAC control register This adds some definitions for the MAC control register and uses them. This is basically no functional change. The patch by Michael Buesch has been ported to b43legacy. Signed-off-by: Stefano Brivio Signed-off-by: John W. Linville --- drivers/net/wireless/b43legacy/b43legacy.h | 9 ++++++++- drivers/net/wireless/b43legacy/main.c | 29 ++++++++++++++--------------- 2 files changed, 22 insertions(+), 16 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/b43legacy/b43legacy.h b/drivers/net/wireless/b43legacy/b43legacy.h index 5f217d6d2e6a..ba08574a2470 100644 --- a/drivers/net/wireless/b43legacy/b43legacy.h +++ b/drivers/net/wireless/b43legacy/b43legacy.h @@ -199,6 +199,13 @@ #define B43legacy_MACCTL_TBTTHOLD 0x10000000 /* TBTT Hold */ #define B43legacy_MACCTL_GMODE 0x80000000 /* G Mode */ +/* MAC Command bitfield */ +#define B43legacy_MACCMD_BEACON0_VALID 0x00000001 /* Beacon 0 in template RAM is busy/valid */ +#define B43legacy_MACCMD_BEACON1_VALID 0x00000002 /* Beacon 1 in template RAM is busy/valid */ +#define B43legacy_MACCMD_DFQ_VALID 0x00000004 /* Directed frame queue valid (IBSS PS mode, ATIM) */ +#define B43legacy_MACCMD_CCA 0x00000008 /* Clear channel assessment */ +#define B43legacy_MACCMD_BGNOISE 0x00000010 /* Background noise */ + /* 802.11 core specific TM State Low flags */ #define B43legacy_TMSLOW_GMODE 0x20000000 /* G Mode Enable */ #define B43legacy_TMSLOW_PLLREFSEL 0x00200000 /* PLL Freq Ref Select */ @@ -645,7 +652,7 @@ struct b43legacy_wldev { bool __using_pio; /* Using pio rather than dma. */ bool bad_frames_preempt;/* Use "Bad Frames Preemption". */ - bool reg124_set_0x4; /* Variable to keep track of IRQ. */ + bool dfq_valid; /* Directed frame queue valid (IBSS PS mode, ATIM). */ bool short_preamble; /* TRUE if using short preamble. */ bool short_slot; /* TRUE if using short slot timing. */ bool radio_hw_enable; /* State of radio hardware enable bit. */ diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index d2a72a2cd178..9db949ed6519 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -805,9 +805,8 @@ static void b43legacy_generate_noise_sample(struct b43legacy_wldev *dev) { b43legacy_jssi_write(dev, 0x7F7F7F7F); b43legacy_write32(dev, B43legacy_MMIO_MACCMD, - b43legacy_read32(dev, - B43legacy_MMIO_MACCMD) - | (1 << 4)); + b43legacy_read32(dev, B43legacy_MMIO_MACCMD) + | B43legacy_MACCMD_BGNOISE); B43legacy_WARN_ON(dev->noisecalc.channel_at_start != dev->phy.channel); } @@ -896,18 +895,18 @@ static void handle_irq_tbtt_indication(struct b43legacy_wldev *dev) if (1/*FIXME: the last PSpoll frame was sent successfully */) b43legacy_power_saving_ctl_bits(dev, -1, -1); } - dev->reg124_set_0x4 = 0; if (b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS)) - dev->reg124_set_0x4 = 1; + dev->dfq_valid = 1; } static void handle_irq_atim_end(struct b43legacy_wldev *dev) { - if (!dev->reg124_set_0x4) /*FIXME rename this variable*/ - return; - b43legacy_write32(dev, B43legacy_MMIO_MACCMD, - b43legacy_read32(dev, B43legacy_MMIO_MACCMD) - | 0x4); + if (dev->dfq_valid) { + b43legacy_write32(dev, B43legacy_MMIO_MACCMD, + b43legacy_read32(dev, B43legacy_MMIO_MACCMD) + | B43legacy_MACCMD_DFQ_VALID); + dev->dfq_valid = 0; + } } static void handle_irq_pmq(struct b43legacy_wldev *dev) @@ -1107,7 +1106,7 @@ static int b43legacy_refresh_cached_beacon(struct b43legacy_wldev *dev, static void b43legacy_update_templates(struct b43legacy_wldev *dev) { - u32 status; + u32 cmd; B43legacy_WARN_ON(!dev->cached_beacon); @@ -1118,9 +1117,9 @@ static void b43legacy_update_templates(struct b43legacy_wldev *dev) b43legacy_write_probe_resp_template(dev, 0x268, 0x4A, &b43legacy_b_ratetable[0]); - status = b43legacy_read32(dev, B43legacy_MMIO_MACCMD); - status |= 0x03; - b43legacy_write32(dev, B43legacy_MMIO_MACCMD, status); + cmd = b43legacy_read32(dev, B43legacy_MMIO_MACCMD); + cmd |= B43legacy_MACCMD_BEACON0_VALID | B43legacy_MACCMD_BEACON1_VALID; + b43legacy_write32(dev, B43legacy_MMIO_MACCMD, cmd); } static void b43legacy_refresh_templates(struct b43legacy_wldev *dev, @@ -2928,7 +2927,7 @@ static void setup_struct_phy_for_init(struct b43legacy_wldev *dev, static void setup_struct_wldev_for_init(struct b43legacy_wldev *dev) { /* Flags */ - dev->reg124_set_0x4 = 0; + dev->dfq_valid = 0; /* Stats */ memset(&dev->stats, 0, sizeof(dev->stats)); -- cgit v1.2.1 From a297170dae2595f31b02e4553a3b217e115a15cf Mon Sep 17 00:00:00 2001 From: Stefano Brivio Date: Fri, 8 Feb 2008 06:31:25 +0100 Subject: b43legacy: fix upload of beacon packets to the hardware This fixes uploading of the beacon data and writing of the TIM and DTIM offsets. The patch by Michael Buesch has been ported to b43legacy. Signed-off-by: Stefano Brivio Signed-off-by: John W. Linville --- drivers/net/wireless/b43legacy/b43legacy.h | 19 ++- drivers/net/wireless/b43legacy/main.c | 257 ++++++++++++++++++----------- 2 files changed, 174 insertions(+), 102 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/b43legacy/b43legacy.h b/drivers/net/wireless/b43legacy/b43legacy.h index ba08574a2470..17abf3cb2b1f 100644 --- a/drivers/net/wireless/b43legacy/b43legacy.h +++ b/drivers/net/wireless/b43legacy/b43legacy.h @@ -130,13 +130,19 @@ #define B43legacy_SHM_SH_HOSTFHI 0x0060 /* Hostflags ucode opts (high) */ /* SHM_SHARED crypto engine */ #define B43legacy_SHM_SH_KEYIDXBLOCK 0x05D4 /* Key index/algorithm block */ -/* SHM_SHARED beacon variables */ +/* SHM_SHARED beacon/AP variables */ +#define B43legacy_SHM_SH_DTIMP 0x0012 /* DTIM period */ +#define B43legacy_SHM_SH_BTL0 0x0018 /* Beacon template length 0 */ +#define B43legacy_SHM_SH_BTL1 0x001A /* Beacon template length 1 */ +#define B43legacy_SHM_SH_BTSFOFF 0x001C /* Beacon TSF offset */ +#define B43legacy_SHM_SH_TIMPOS 0x001E /* TIM position in beacon */ #define B43legacy_SHM_SH_BEACPHYCTL 0x0054 /* Beacon PHY TX control word */ /* SHM_SHARED ACK/CTS control */ #define B43legacy_SHM_SH_ACKCTSPHYCTL 0x0022 /* ACK/CTS PHY control word */ /* SHM_SHARED probe response variables */ -#define B43legacy_SHM_SH_PRPHYCTL 0x0188 /* Probe Resp PHY TX control */ +#define B43legacy_SHM_SH_PRTLEN 0x004A /* Probe Response template length */ #define B43legacy_SHM_SH_PRMAXTIME 0x0074 /* Probe Response max time */ +#define B43legacy_SHM_SH_PRPHYCTL 0x0188 /* Probe Resp PHY TX control */ /* SHM_SHARED rate tables */ /* SHM_SHARED microcode soft registers */ #define B43legacy_SHM_SH_UCODEREV 0x0000 /* Microcode revision */ @@ -601,6 +607,12 @@ struct b43legacy_wl { u8 nr_devs; bool radiotap_enabled; + + /* The beacon we are currently using (AP or IBSS mode). + * This beacon stuff is protected by the irq_lock. */ + struct sk_buff *current_beacon; + bool beacon0_uploaded; + bool beacon1_uploaded; }; /* Pointers to the firmware data and meta information about it. */ @@ -699,9 +711,6 @@ struct b43legacy_wldev { u8 max_nr_keys; struct b43legacy_key key[58]; - /* Cached beacon template while uploading the template. */ - struct sk_buff *cached_beacon; - /* Firmware data */ struct b43legacy_firmware fw; diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 9db949ed6519..62e679a1c05f 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -962,16 +962,61 @@ static void b43legacy_write_beacon_template(struct b43legacy_wldev *dev, u16 ram_offset, u16 shm_size_offset, u8 rate) { - int len; - const u8 *data; - B43legacy_WARN_ON(!dev->cached_beacon); - len = min((size_t)dev->cached_beacon->len, + unsigned int i, len, variable_len; + const struct ieee80211_mgmt *bcn; + const u8 *ie; + bool tim_found = 0; + + bcn = (const struct ieee80211_mgmt *)(dev->wl->current_beacon->data); + len = min((size_t)dev->wl->current_beacon->len, 0x200 - sizeof(struct b43legacy_plcp_hdr6)); - data = (const u8 *)(dev->cached_beacon->data); - b43legacy_write_template_common(dev, data, - len, ram_offset, + + b43legacy_write_template_common(dev, (const u8 *)bcn, len, ram_offset, shm_size_offset, rate); + + /* Find the position of the TIM and the DTIM_period value + * and write them to SHM. */ + ie = bcn->u.beacon.variable; + variable_len = len - offsetof(struct ieee80211_mgmt, u.beacon.variable); + for (i = 0; i < variable_len - 2; ) { + uint8_t ie_id, ie_len; + + ie_id = ie[i]; + ie_len = ie[i + 1]; + if (ie_id == 5) { + u16 tim_position; + u16 dtim_period; + /* This is the TIM Information Element */ + + /* Check whether the ie_len is in the beacon data range. */ + if (variable_len < ie_len + 2 + i) + break; + /* A valid TIM is at least 4 bytes long. */ + if (ie_len < 4) + break; + tim_found = 1; + + tim_position = sizeof(struct b43legacy_plcp_hdr6); + tim_position += offsetof(struct ieee80211_mgmt, + u.beacon.variable); + tim_position += i; + + dtim_period = ie[i + 3]; + + b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, + B43legacy_SHM_SH_TIMPOS, tim_position); + b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, + B43legacy_SHM_SH_DTIMP, dtim_period); + break; + } + i += ie_len + 2; + } + if (!tim_found) { + b43legacywarn(dev->wl, "Did not find a valid TIM IE in the " + "beacon template packet. AP or IBSS operation " + "may be broken.\n"); + } } static void b43legacy_write_probe_resp_plcp(struct b43legacy_wldev *dev, @@ -1004,26 +1049,27 @@ static void b43legacy_write_probe_resp_plcp(struct b43legacy_wldev *dev, * 2) Patching duration field * 3) Stripping TIM */ -static u8 *b43legacy_generate_probe_resp(struct b43legacy_wldev *dev, - u16 *dest_size, - struct ieee80211_rate *rate) +static const u8 *b43legacy_generate_probe_resp(struct b43legacy_wldev *dev, + u16 *dest_size, + struct ieee80211_rate *rate) { const u8 *src_data; u8 *dest_data; - u16 src_size; - u16 elem_size; - u16 src_pos; - u16 dest_pos; + u16 src_size, elem_size, src_pos, dest_pos; __le16 dur; struct ieee80211_hdr *hdr; + size_t ie_start; + + src_size = dev->wl->current_beacon->len; + src_data = (const u8 *)dev->wl->current_beacon->data; - B43legacy_WARN_ON(!dev->cached_beacon); - src_size = dev->cached_beacon->len; - src_data = (const u8 *)dev->cached_beacon->data; + /* Get the start offset of the variable IEs in the packet. */ + ie_start = offsetof(struct ieee80211_mgmt, u.probe_resp.variable); + B43legacy_WARN_ON(ie_start != offsetof(struct ieee80211_mgmt, + u.beacon.variable)); - if (unlikely(src_size < 0x24)) { - b43legacydbg(dev->wl, "b43legacy_generate_probe_resp: " - "invalid beacon\n"); + if (src_size < ie_start) { + B43legacy_WARN_ON(1); return NULL; } @@ -1031,19 +1077,18 @@ static u8 *b43legacy_generate_probe_resp(struct b43legacy_wldev *dev, if (unlikely(!dest_data)) return NULL; - /* 0x24 is offset of first variable-len Information-Element - * in beacon frame. - */ - memcpy(dest_data, src_data, 0x24); - src_pos = 0x24; - dest_pos = 0x24; - for (; src_pos < src_size - 2; src_pos += elem_size) { + /* Copy the static data and all Information Elements, except the TIM. */ + memcpy(dest_data, src_data, ie_start); + src_pos = ie_start; + dest_pos = ie_start; + for ( ; src_pos < src_size - 2; src_pos += elem_size) { elem_size = src_data[src_pos + 1] + 2; - if (src_data[src_pos] != 0x05) { /* TIM */ - memcpy(dest_data + dest_pos, src_data + src_pos, - elem_size); - dest_pos += elem_size; + if (src_data[src_pos] == 5) { + /* This is the TIM. */ + continue; } + memcpy(dest_data + dest_pos, src_data + src_pos, elem_size); + dest_pos += elem_size; } *dest_size = dest_pos; hdr = (struct ieee80211_hdr *)dest_data; @@ -1065,11 +1110,10 @@ static void b43legacy_write_probe_resp_template(struct b43legacy_wldev *dev, u16 shm_size_offset, struct ieee80211_rate *rate) { - u8 *probe_resp_data; + const u8 *probe_resp_data; u16 size; - B43legacy_WARN_ON(!dev->cached_beacon); - size = dev->cached_beacon->len; + size = dev->wl->current_beacon->len; probe_resp_data = b43legacy_generate_probe_resp(dev, &size, rate); if (unlikely(!probe_resp_data)) return; @@ -1094,43 +1138,21 @@ static void b43legacy_write_probe_resp_template(struct b43legacy_wldev *dev, kfree(probe_resp_data); } -static int b43legacy_refresh_cached_beacon(struct b43legacy_wldev *dev, - struct sk_buff *beacon) +/* Asynchronously update the packet templates in template RAM. + * Locking: Requires wl->irq_lock to be locked. */ +static void b43legacy_update_templates(struct b43legacy_wl *wl, + struct sk_buff *beacon) { - if (dev->cached_beacon) - kfree_skb(dev->cached_beacon); - dev->cached_beacon = beacon; + /* This is the top half of the ansynchronous beacon update. The bottom + * half is the beacon IRQ. Beacon update must be asynchronous to avoid + * sending an invalid beacon. This can happen for example, if the + * firmware transmits a beacon while we are updating it. */ - return 0; -} - -static void b43legacy_update_templates(struct b43legacy_wldev *dev) -{ - u32 cmd; - - B43legacy_WARN_ON(!dev->cached_beacon); - - b43legacy_write_beacon_template(dev, 0x68, 0x18, - B43legacy_CCK_RATE_1MB); - b43legacy_write_beacon_template(dev, 0x468, 0x1A, - B43legacy_CCK_RATE_1MB); - b43legacy_write_probe_resp_template(dev, 0x268, 0x4A, - &b43legacy_b_ratetable[0]); - - cmd = b43legacy_read32(dev, B43legacy_MMIO_MACCMD); - cmd |= B43legacy_MACCMD_BEACON0_VALID | B43legacy_MACCMD_BEACON1_VALID; - b43legacy_write32(dev, B43legacy_MMIO_MACCMD, cmd); -} - -static void b43legacy_refresh_templates(struct b43legacy_wldev *dev, - struct sk_buff *beacon) -{ - int err; - - err = b43legacy_refresh_cached_beacon(dev, beacon); - if (unlikely(err)) - return; - b43legacy_update_templates(dev); + if (wl->current_beacon) + dev_kfree_skb_any(wl->current_beacon); + wl->current_beacon = beacon; + wl->beacon0_uploaded = 0; + wl->beacon1_uploaded = 0; } static void b43legacy_set_ssid(struct b43legacy_wldev *dev, @@ -1171,38 +1193,37 @@ static void b43legacy_set_beacon_int(struct b43legacy_wldev *dev, static void handle_irq_beacon(struct b43legacy_wldev *dev) { - u32 status; + struct b43legacy_wl *wl = dev->wl; + u32 cmd; - if (!b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_AP)) + if (!b43legacy_is_mode(wl, IEEE80211_IF_TYPE_AP)) return; - dev->irq_savedstate &= ~B43legacy_IRQ_BEACON; - status = b43legacy_read32(dev, B43legacy_MMIO_MACCMD); + /* This is the bottom half of the asynchronous beacon update. */ - if (!dev->cached_beacon || ((status & 0x1) && (status & 0x2))) { - /* ACK beacon IRQ. */ - b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_REASON, - B43legacy_IRQ_BEACON); - dev->irq_savedstate |= B43legacy_IRQ_BEACON; - if (dev->cached_beacon) - kfree_skb(dev->cached_beacon); - dev->cached_beacon = NULL; - return; - } - if (!(status & 0x1)) { - b43legacy_write_beacon_template(dev, 0x68, 0x18, - B43legacy_CCK_RATE_1MB); - status |= 0x1; - b43legacy_write32(dev, B43legacy_MMIO_MACCMD, - status); - } - if (!(status & 0x2)) { - b43legacy_write_beacon_template(dev, 0x468, 0x1A, - B43legacy_CCK_RATE_1MB); - status |= 0x2; - b43legacy_write32(dev, B43legacy_MMIO_MACCMD, - status); + cmd = b43legacy_read32(dev, B43legacy_MMIO_MACCMD); + if (!(cmd & B43legacy_MACCMD_BEACON0_VALID)) { + if (!wl->beacon0_uploaded) { + b43legacy_write_beacon_template(dev, 0x68, + B43legacy_SHM_SH_BTL0, + B43legacy_CCK_RATE_1MB); + b43legacy_write_probe_resp_template(dev, 0x268, + B43legacy_SHM_SH_PRTLEN, + &__b43legacy_ratetable[3]); + wl->beacon0_uploaded = 1; + } + cmd |= B43legacy_MACCMD_BEACON0_VALID; + } + if (!(cmd & B43legacy_MACCMD_BEACON1_VALID)) { + if (!wl->beacon1_uploaded) { + b43legacy_write_beacon_template(dev, 0x468, + B43legacy_SHM_SH_BTL1, + B43legacy_CCK_RATE_1MB); + wl->beacon1_uploaded = 1; + } + cmd |= B43legacy_MACCMD_BEACON1_VALID; } + b43legacy_write32(dev, B43legacy_MMIO_MACCMD, cmd); } static void handle_irq_ucode_debug(struct b43legacy_wldev *dev) @@ -2709,7 +2730,7 @@ static int b43legacy_op_config_interface(struct ieee80211_hw *hw, B43legacy_WARN_ON(conf->type != IEEE80211_IF_TYPE_AP); b43legacy_set_ssid(dev, conf->ssid, conf->ssid_len); if (conf->beacon) - b43legacy_refresh_templates(dev, conf->beacon); + b43legacy_update_templates(wl, conf->beacon); } b43legacy_write_mac_bssid_templates(dev); } @@ -3022,6 +3043,11 @@ static void b43legacy_wireless_core_exit(struct b43legacy_wldev *dev) kfree(phy->tssi2dbm); kfree(phy->lo_control); phy->lo_control = NULL; + if (dev->wl->current_beacon) { + dev_kfree_skb_any(dev->wl->current_beacon); + dev->wl->current_beacon = NULL; + } + ssb_device_disable(dev->dev, 0); ssb_bus_may_powerdown(dev->dev->bus); } @@ -3346,6 +3372,41 @@ out_unlock: return err; } +static int b43legacy_op_beacon_set_tim(struct ieee80211_hw *hw, + int aid, int set) +{ + struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); + struct sk_buff *beacon; + unsigned long flags; + + /* We could modify the existing beacon and set the aid bit in the TIM + * field, but that would probably require resizing and moving of data + * within the beacon template. Simply request a new beacon and let + * mac80211 do the hard work. */ + beacon = ieee80211_beacon_get(hw, wl->vif, NULL); + if (unlikely(!beacon)) + return -ENOMEM; + spin_lock_irqsave(&wl->irq_lock, flags); + b43legacy_update_templates(wl, beacon); + spin_unlock_irqrestore(&wl->irq_lock, flags); + + return 0; +} + +static int b43legacy_op_ibss_beacon_update(struct ieee80211_hw *hw, + struct sk_buff *beacon, + struct ieee80211_tx_control *ctl) +{ + struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); + unsigned long flags; + + spin_lock_irqsave(&wl->irq_lock, flags); + b43legacy_update_templates(wl, beacon); + spin_unlock_irqrestore(&wl->irq_lock, flags); + + return 0; +} + static const struct ieee80211_ops b43legacy_hw_ops = { .tx = b43legacy_op_tx, .conf_tx = b43legacy_op_conf_tx, @@ -3359,6 +3420,8 @@ static const struct ieee80211_ops b43legacy_hw_ops = { .start = b43legacy_op_start, .stop = b43legacy_op_stop, .set_retry_limit = b43legacy_op_set_retry_limit, + .set_tim = b43legacy_op_beacon_set_tim, + .beacon_update = b43legacy_op_ibss_beacon_update, }; /* Hard-reset the chip. Do not call this directly. -- cgit v1.2.1 From 4688be308f35f1e0099140a179d95c5e63b2319d Mon Sep 17 00:00:00 2001 From: Stefano Brivio Date: Fri, 8 Feb 2008 06:31:39 +0100 Subject: b43legacy: fix B43legacy_WARN_ON macro Fix the B43legacy_WARN_ON macro so that it will evaluate expressions. Signed-off-by: Stefano Brivio Signed-off-by: John W. Linville --- drivers/net/wireless/b43legacy/b43legacy.h | 14 ++++---------- drivers/net/wireless/b43legacy/main.c | 4 +--- 2 files changed, 5 insertions(+), 13 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/b43legacy/b43legacy.h b/drivers/net/wireless/b43legacy/b43legacy.h index 17abf3cb2b1f..6a63a6e474f7 100644 --- a/drivers/net/wireless/b43legacy/b43legacy.h +++ b/drivers/net/wireless/b43legacy/b43legacy.h @@ -330,15 +330,7 @@ enum { # undef assert #endif #ifdef CONFIG_B43LEGACY_DEBUG -# define B43legacy_WARN_ON(expr) \ - do { \ - if (unlikely((expr))) { \ - printk(KERN_INFO PFX "Test (%s) failed at:" \ - " %s:%d:%s()\n", \ - #expr, __FILE__, \ - __LINE__, __FUNCTION__); \ - } \ - } while (0) +# define B43legacy_WARN_ON(x) WARN_ON(x) # define B43legacy_BUG_ON(expr) \ do { \ if (unlikely((expr))) { \ @@ -349,7 +341,9 @@ enum { } while (0) # define B43legacy_DEBUG 1 #else -# define B43legacy_WARN_ON(x) do { /* nothing */ } while (0) +/* This will evaluate the argument even if debugging is disabled. */ +static inline bool __b43legacy_warn_on_dummy(bool x) { return x; } +# define B43_WARN_ON(x) __b43legacy_warn_on_dummy(unlikely(!!(x))) # define B43legacy_BUG_ON(x) do { /* nothing */ } while (0) # define B43legacy_DEBUG 0 #endif diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 62e679a1c05f..82953dd0bae0 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -1068,10 +1068,8 @@ static const u8 *b43legacy_generate_probe_resp(struct b43legacy_wldev *dev, B43legacy_WARN_ON(ie_start != offsetof(struct ieee80211_mgmt, u.beacon.variable)); - if (src_size < ie_start) { - B43legacy_WARN_ON(1); + if (B43legacy_WARN_ON(src_size < ie_start)) return NULL; - } dest_data = kmalloc(src_size, GFP_ATOMIC); if (unlikely(!dest_data)) -- cgit v1.2.1 From b9e0b449aef50aabc295e4487a7a030a0d358367 Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Fri, 8 Feb 2008 16:39:11 -0800 Subject: iwlwifi: Update iwlwifi version stamp to 1.2.26 We update the version stamp at this time to distinguish the in-kernel driver from the out of tree driver. The out of tree driver currently has version number 1.2.25, but the latest driver code can only be found in this in-kernel driver. Having a later version number will reduce confusion between the two versions as we transition from out of tree to in-kernel. Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl3945-base.c | 2 +- drivers/net/wireless/iwlwifi/iwl4965-base.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 60e4b00d40fc..4ad26f7613c5 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -91,7 +91,7 @@ int iwl3945_param_queues_num = IWL_MAX_NUM_QUEUES; /* def: 8 Tx queues */ #define VS #endif -#define IWLWIFI_VERSION "1.2.23k" VD VS +#define IWLWIFI_VERSION "1.2.26k" VD VS #define DRV_COPYRIGHT "Copyright(c) 2003-2007 Intel Corporation" #define DRV_VERSION IWLWIFI_VERSION diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 8284c94a1f01..f8931993ab70 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -90,7 +90,7 @@ int iwl4965_param_amsdu_size_8K; /* def: enable 8K amsdu size */ #define VS #endif -#define IWLWIFI_VERSION "1.2.23k" VD VS +#define IWLWIFI_VERSION "1.2.26k" VD VS #define DRV_COPYRIGHT "Copyright(c) 2003-2007 Intel Corporation" #define DRV_VERSION IWLWIFI_VERSION -- cgit v1.2.1 From bb1eeff12d4cd6c706ef9fae340a9c93bb41ad05 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sat, 9 Feb 2008 12:08:58 +0100 Subject: b43: Fix bandswitch This fixes bandswitching for the new mac80211 band API. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/b43.h | 11 +- drivers/net/wireless/b43/main.c | 317 ++++++++++++++++++++++++---------------- 2 files changed, 199 insertions(+), 129 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index 3e40323cd43f..76ad811af399 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -458,14 +458,11 @@ struct b43_iv { } __attribute__((__packed__)); -#define B43_PHYMODE(phytype) (1 << (phytype)) -#define B43_PHYMODE_A B43_PHYMODE(B43_PHYTYPE_A) -#define B43_PHYMODE_B B43_PHYMODE(B43_PHYTYPE_B) -#define B43_PHYMODE_G B43_PHYMODE(B43_PHYTYPE_G) - struct b43_phy { - /* Possible PHYMODEs on this PHY */ - u8 possible_phymodes; + /* Band support flags. */ + bool supports_2ghz; + bool supports_5ghz; + /* GMODE bit enabled? */ bool gmode; diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 017a041d07d0..071f61437c67 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -128,58 +128,143 @@ static struct ieee80211_rate __b43_ratetable[] = { #define b43_g_ratetable (__b43_ratetable + 0) #define b43_g_ratetable_size 12 -#define CHANTAB_ENT(_chanid, _freq) \ - { \ - .center_freq = (_freq), \ - .hw_value = (_chanid), \ - } +#define CHAN4G(_channel, _freq, _flags) { \ + .band = IEEE80211_BAND_2GHZ, \ + .center_freq = (_freq), \ + .hw_value = (_channel), \ + .flags = (_flags), \ + .max_antenna_gain = 0, \ + .max_power = 30, \ +} static struct ieee80211_channel b43_2ghz_chantable[] = { - CHANTAB_ENT(1, 2412), - CHANTAB_ENT(2, 2417), - CHANTAB_ENT(3, 2422), - CHANTAB_ENT(4, 2427), - CHANTAB_ENT(5, 2432), - CHANTAB_ENT(6, 2437), - CHANTAB_ENT(7, 2442), - CHANTAB_ENT(8, 2447), - CHANTAB_ENT(9, 2452), - CHANTAB_ENT(10, 2457), - CHANTAB_ENT(11, 2462), - CHANTAB_ENT(12, 2467), - CHANTAB_ENT(13, 2472), - CHANTAB_ENT(14, 2484), + CHAN4G(1, 2412, 0), + CHAN4G(2, 2417, 0), + CHAN4G(3, 2422, 0), + CHAN4G(4, 2427, 0), + CHAN4G(5, 2432, 0), + CHAN4G(6, 2437, 0), + CHAN4G(7, 2442, 0), + CHAN4G(8, 2447, 0), + CHAN4G(9, 2452, 0), + CHAN4G(10, 2457, 0), + CHAN4G(11, 2462, 0), + CHAN4G(12, 2467, 0), + CHAN4G(13, 2472, 0), + CHAN4G(14, 2484, 0), +}; +#undef CHAN4G + +#define CHAN5G(_channel, _flags) { \ + .band = IEEE80211_BAND_5GHZ, \ + .center_freq = 5000 + (5 * (_channel)), \ + .hw_value = (_channel), \ + .flags = (_flags), \ + .max_antenna_gain = 0, \ + .max_power = 30, \ +} +static struct ieee80211_channel b43_5ghz_nphy_chantable[] = { + CHAN5G(32, 0), CHAN5G(34, 0), + CHAN5G(36, 0), CHAN5G(38, 0), + CHAN5G(40, 0), CHAN5G(42, 0), + CHAN5G(44, 0), CHAN5G(46, 0), + CHAN5G(48, 0), CHAN5G(50, 0), + CHAN5G(52, 0), CHAN5G(54, 0), + CHAN5G(56, 0), CHAN5G(58, 0), + CHAN5G(60, 0), CHAN5G(62, 0), + CHAN5G(64, 0), CHAN5G(66, 0), + CHAN5G(68, 0), CHAN5G(70, 0), + CHAN5G(72, 0), CHAN5G(74, 0), + CHAN5G(76, 0), CHAN5G(78, 0), + CHAN5G(80, 0), CHAN5G(82, 0), + CHAN5G(84, 0), CHAN5G(86, 0), + CHAN5G(88, 0), CHAN5G(90, 0), + CHAN5G(92, 0), CHAN5G(94, 0), + CHAN5G(96, 0), CHAN5G(98, 0), + CHAN5G(100, 0), CHAN5G(102, 0), + CHAN5G(104, 0), CHAN5G(106, 0), + CHAN5G(108, 0), CHAN5G(110, 0), + CHAN5G(112, 0), CHAN5G(114, 0), + CHAN5G(116, 0), CHAN5G(118, 0), + CHAN5G(120, 0), CHAN5G(122, 0), + CHAN5G(124, 0), CHAN5G(126, 0), + CHAN5G(128, 0), CHAN5G(130, 0), + CHAN5G(132, 0), CHAN5G(134, 0), + CHAN5G(136, 0), CHAN5G(138, 0), + CHAN5G(140, 0), CHAN5G(142, 0), + CHAN5G(144, 0), CHAN5G(145, 0), + CHAN5G(146, 0), CHAN5G(147, 0), + CHAN5G(148, 0), CHAN5G(149, 0), + CHAN5G(150, 0), CHAN5G(151, 0), + CHAN5G(152, 0), CHAN5G(153, 0), + CHAN5G(154, 0), CHAN5G(155, 0), + CHAN5G(156, 0), CHAN5G(157, 0), + CHAN5G(158, 0), CHAN5G(159, 0), + CHAN5G(160, 0), CHAN5G(161, 0), + CHAN5G(162, 0), CHAN5G(163, 0), + CHAN5G(164, 0), CHAN5G(165, 0), + CHAN5G(166, 0), CHAN5G(168, 0), + CHAN5G(170, 0), CHAN5G(172, 0), + CHAN5G(174, 0), CHAN5G(176, 0), + CHAN5G(178, 0), CHAN5G(180, 0), + CHAN5G(182, 0), CHAN5G(184, 0), + CHAN5G(186, 0), CHAN5G(188, 0), + CHAN5G(190, 0), CHAN5G(192, 0), + CHAN5G(194, 0), CHAN5G(196, 0), + CHAN5G(198, 0), CHAN5G(200, 0), + CHAN5G(202, 0), CHAN5G(204, 0), + CHAN5G(206, 0), CHAN5G(208, 0), + CHAN5G(210, 0), CHAN5G(212, 0), + CHAN5G(214, 0), CHAN5G(216, 0), + CHAN5G(218, 0), CHAN5G(220, 0), + CHAN5G(222, 0), CHAN5G(224, 0), + CHAN5G(226, 0), CHAN5G(228, 0), }; -#ifdef NOTYET -static struct ieee80211_channel b43_5ghz_chantable[] = { - CHANTAB_ENT(36, 5180), - CHANTAB_ENT(40, 5200), - CHANTAB_ENT(44, 5220), - CHANTAB_ENT(48, 5240), - CHANTAB_ENT(52, 5260), - CHANTAB_ENT(56, 5280), - CHANTAB_ENT(60, 5300), - CHANTAB_ENT(64, 5320), - CHANTAB_ENT(149, 5745), - CHANTAB_ENT(153, 5765), - CHANTAB_ENT(157, 5785), - CHANTAB_ENT(161, 5805), - CHANTAB_ENT(165, 5825), +static struct ieee80211_channel b43_5ghz_aphy_chantable[] = { + CHAN5G(34, 0), CHAN5G(36, 0), + CHAN5G(38, 0), CHAN5G(40, 0), + CHAN5G(42, 0), CHAN5G(44, 0), + CHAN5G(46, 0), CHAN5G(48, 0), + CHAN5G(52, 0), CHAN5G(56, 0), + CHAN5G(60, 0), CHAN5G(64, 0), + CHAN5G(100, 0), CHAN5G(104, 0), + CHAN5G(108, 0), CHAN5G(112, 0), + CHAN5G(116, 0), CHAN5G(120, 0), + CHAN5G(124, 0), CHAN5G(128, 0), + CHAN5G(132, 0), CHAN5G(136, 0), + CHAN5G(140, 0), CHAN5G(149, 0), + CHAN5G(153, 0), CHAN5G(157, 0), + CHAN5G(161, 0), CHAN5G(165, 0), + CHAN5G(184, 0), CHAN5G(188, 0), + CHAN5G(192, 0), CHAN5G(196, 0), + CHAN5G(200, 0), CHAN5G(204, 0), + CHAN5G(208, 0), CHAN5G(212, 0), + CHAN5G(216, 0), +}; +#undef CHAN5G + +static struct ieee80211_supported_band b43_band_5GHz_nphy = { + .band = IEEE80211_BAND_5GHZ, + .channels = b43_5ghz_nphy_chantable, + .n_channels = ARRAY_SIZE(b43_5ghz_nphy_chantable), + .bitrates = b43_a_ratetable, + .n_bitrates = b43_a_ratetable_size, }; -static struct ieee80211_supported_band b43_band_5GHz = { - .channels = b43_5ghz_chantable, - .n_channels = ARRAY_SIZE(b43_5ghz_chantable), - .bitrates = b43_a_ratetable, - .n_bitrates = b43_a_ratetable_size, +static struct ieee80211_supported_band b43_band_5GHz_aphy = { + .band = IEEE80211_BAND_5GHZ, + .channels = b43_5ghz_aphy_chantable, + .n_channels = ARRAY_SIZE(b43_5ghz_aphy_chantable), + .bitrates = b43_a_ratetable, + .n_bitrates = b43_a_ratetable_size, }; -#endif static struct ieee80211_supported_band b43_band_2GHz = { - .channels = b43_2ghz_chantable, - .n_channels = ARRAY_SIZE(b43_2ghz_chantable), - .bitrates = b43_g_ratetable, - .n_bitrates = b43_g_ratetable_size, + .band = IEEE80211_BAND_2GHZ, + .channels = b43_2ghz_chantable, + .n_channels = ARRAY_SIZE(b43_2ghz_chantable), + .bitrates = b43_g_ratetable, + .n_bitrates = b43_g_ratetable_size, }; static void b43_wireless_core_exit(struct b43_wldev *dev); @@ -2657,45 +2742,6 @@ static int b43_op_get_stats(struct ieee80211_hw *hw, return 0; } -static const char *phymode_to_string(unsigned int phymode) -{ - switch (phymode) { - case B43_PHYMODE_A: - return "A"; - case B43_PHYMODE_B: - return "B"; - case B43_PHYMODE_G: - return "G"; - default: - B43_WARN_ON(1); - } - return ""; -} - -static int find_wldev_for_phymode(struct b43_wl *wl, - unsigned int phymode, - struct b43_wldev **dev, bool * gmode) -{ - struct b43_wldev *d; - - list_for_each_entry(d, &wl->devlist, list) { - if (d->phy.possible_phymodes & phymode) { - /* Ok, this device supports the PHY-mode. - * Now figure out how the gmode bit has to be - * set to support it. */ - if (phymode == B43_PHYMODE_A) - *gmode = 0; - else - *gmode = 1; - *dev = d; - - return 0; - } - } - - return -ESRCH; -} - static void b43_put_phy_into_reset(struct b43_wldev *dev) { struct ssb_device *sdev = dev->dev; @@ -2715,28 +2761,64 @@ static void b43_put_phy_into_reset(struct b43_wldev *dev) msleep(1); } +static const char * band_to_string(enum ieee80211_band band) +{ + switch (band) { + case IEEE80211_BAND_5GHZ: + return "5"; + case IEEE80211_BAND_2GHZ: + return "2.4"; + default: + break; + } + B43_WARN_ON(1); + return ""; +} + /* Expects wl->mutex locked */ -static int b43_switch_phymode(struct b43_wl *wl, unsigned int new_mode) +static int b43_switch_band(struct b43_wl *wl, struct ieee80211_channel *chan) { - struct b43_wldev *up_dev; + struct b43_wldev *up_dev = NULL; struct b43_wldev *down_dev; + struct b43_wldev *d; int err; - bool gmode = 0; + bool gmode; int prev_status; - err = find_wldev_for_phymode(wl, new_mode, &up_dev, &gmode); - if (err) { - b43err(wl, "Could not find a device for %s-PHY mode\n", - phymode_to_string(new_mode)); - return err; + /* Find a device and PHY which supports the band. */ + list_for_each_entry(d, &wl->devlist, list) { + switch (chan->band) { + case IEEE80211_BAND_5GHZ: + if (d->phy.supports_5ghz) { + up_dev = d; + gmode = 0; + } + break; + case IEEE80211_BAND_2GHZ: + if (d->phy.supports_2ghz) { + up_dev = d; + gmode = 1; + } + break; + default: + B43_WARN_ON(1); + return -EINVAL; + } + if (up_dev) + break; + } + if (!up_dev) { + b43err(wl, "Could not find a device for %s-GHz band operation\n", + band_to_string(chan->band)); + return -ENODEV; } if ((up_dev == wl->current_dev) && (!!wl->current_dev->phy.gmode == !!gmode)) { /* This device is already running. */ return 0; } - b43dbg(wl, "Reconfiguring PHYmode to %s-PHY\n", - phymode_to_string(new_mode)); + b43dbg(wl, "Switching to %s-GHz band\n", + band_to_string(chan->band)); down_dev = wl->current_dev; prev_status = b43_status(down_dev); @@ -2758,8 +2840,8 @@ static int b43_switch_phymode(struct b43_wl *wl, unsigned int new_mode) err = b43_wireless_core_init(up_dev); if (err) { b43err(wl, "Fatal: Could not initialize device for " - "newly selected %s-PHY mode\n", - phymode_to_string(new_mode)); + "selected %s-GHz band\n", + band_to_string(chan->band)); goto init_failure; } } @@ -2767,8 +2849,8 @@ static int b43_switch_phymode(struct b43_wl *wl, unsigned int new_mode) err = b43_wireless_core_start(up_dev); if (err) { b43err(wl, "Fatal: Coult not start device for " - "newly selected %s-PHY mode\n", - phymode_to_string(new_mode)); + "selected %s-GHz band\n", + band_to_string(chan->band)); b43_wireless_core_exit(up_dev); goto init_failure; } @@ -2778,7 +2860,7 @@ static int b43_switch_phymode(struct b43_wl *wl, unsigned int new_mode) wl->current_dev = up_dev; return 0; - init_failure: +init_failure: /* Whoops, failed to init the new core. No core is operating now. */ wl->current_dev = NULL; return err; @@ -2836,25 +2918,14 @@ static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) struct b43_wldev *dev; struct b43_phy *phy; unsigned long flags; - unsigned int new_phymode = 0xFFFF; int antenna; int err = 0; u32 savedirqs; mutex_lock(&wl->mutex); - /* Switch the PHY mode (if necessary). */ - switch (conf->channel->band) { - case IEEE80211_BAND_5GHZ: - new_phymode = B43_PHYMODE_A; - break; - case IEEE80211_BAND_2GHZ: - new_phymode = B43_PHYMODE_G; - break; - default: - B43_WARN_ON(1); - } - err = b43_switch_phymode(wl, new_phymode); + /* Switch the band (if necessary). This might change the active core. */ + err = b43_switch_band(wl, conf->channel); if (err) goto out_unlock_mutex; dev = wl->current_dev; @@ -3817,21 +3888,23 @@ static void b43_chip_reset(struct work_struct *work) b43info(wl, "Controller restarted\n"); } -static int b43_setup_modes(struct b43_wldev *dev, +static int b43_setup_bands(struct b43_wldev *dev, bool have_2ghz_phy, bool have_5ghz_phy) { struct ieee80211_hw *hw = dev->wl->hw; - struct b43_phy *phy = &dev->phy; - /* XXX: This function will go away soon, when mac80211 - * band stuff is rewritten. So this is just a hack. - * For now we always claim GPHY mode, as there is no - * support for NPHY and APHY in the device, yet. - * This assumption is OK, as any B, N or A PHY will already - * have died a horrible sanity check death earlier. */ + if (have_2ghz_phy) + hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &b43_band_2GHz; + if (dev->phy.type == B43_PHYTYPE_N) { + if (have_5ghz_phy) + hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &b43_band_5GHz_nphy; + } else { + if (have_5ghz_phy) + hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &b43_band_5GHz_aphy; + } - hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &b43_band_2GHz; - phy->possible_phymodes |= B43_PHYMODE_G; + dev->phy.supports_2ghz = have_2ghz_phy; + dev->phy.supports_5ghz = have_5ghz_phy; return 0; } @@ -3913,7 +3986,7 @@ static int b43_wireless_core_attach(struct b43_wldev *dev) err = b43_validate_chipaccess(dev); if (err) goto err_powerdown; - err = b43_setup_modes(dev, have_2ghz_phy, have_5ghz_phy); + err = b43_setup_bands(dev, have_2ghz_phy, have_5ghz_phy); if (err) goto err_powerdown; -- cgit v1.2.1 From 3330d7be7008fa8e213648750fc13613eecc54bb Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sun, 10 Feb 2008 16:49:38 +0100 Subject: mac80211: give burst time in txop rather than 0.1msec units This changes mac80211 to pass the burst time to conf_tx in txop units rather than 0.1msec units. 0.1msec units are only required by atheros hardware (according to current driver support), all other drivers do other calculations or require the txop value. Therefore, it results in fewer calculations and more precision if we just pass the txop value through to the driver. Signed-off-by: Johannes Berg Acked-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl3945-base.c | 2 +- drivers/net/wireless/iwlwifi/iwl4965-base.c | 2 +- drivers/net/wireless/p54common.c | 21 +++++++++++++-------- 3 files changed, 15 insertions(+), 10 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 4ad26f7613c5..bb3a5f633227 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -7442,7 +7442,7 @@ static int iwl3945_mac_conf_tx(struct ieee80211_hw *hw, int queue, priv->qos_data.def_qos_parm.ac[q].cw_max = cpu_to_le16(params->cw_max); priv->qos_data.def_qos_parm.ac[q].aifsn = params->aifs; priv->qos_data.def_qos_parm.ac[q].edca_txop = - cpu_to_le16((params->burst_time * 100)); + cpu_to_le16((params->txop * 32)); priv->qos_data.def_qos_parm.ac[q].reserved1 = 0; priv->qos_data.qos_active = 1; diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index f8931993ab70..fb4c84e31932 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -7916,7 +7916,7 @@ static int iwl4965_mac_conf_tx(struct ieee80211_hw *hw, int queue, priv->qos_data.def_qos_parm.ac[q].cw_max = cpu_to_le16(params->cw_max); priv->qos_data.def_qos_parm.ac[q].aifsn = params->aifs; priv->qos_data.def_qos_parm.ac[q].edca_txop = - cpu_to_le16((params->burst_time * 100)); + cpu_to_le16((params->txop * 32)); priv->qos_data.def_qos_parm.ac[q].reserved1 = 0; priv->qos_data.qos_active = 1; diff --git a/drivers/net/wireless/p54common.c b/drivers/net/wireless/p54common.c index 218ff7770ef6..0e9f887178ce 100644 --- a/drivers/net/wireless/p54common.c +++ b/drivers/net/wireless/p54common.c @@ -759,13 +759,12 @@ static int p54_set_leds(struct ieee80211_hw *dev, int mode, int link, int act) return 0; } -#define P54_SET_QUEUE(queue, ai_fs, cw_min, cw_max, burst) \ +#define P54_SET_QUEUE(queue, ai_fs, cw_min, cw_max, _txop) \ do { \ queue.aifs = cpu_to_le16(ai_fs); \ queue.cwmin = cpu_to_le16(cw_min); \ queue.cwmax = cpu_to_le16(cw_max); \ - queue.txop = (burst == 0) ? \ - 0 : cpu_to_le16((burst * 100) / 32 + 1); \ + queue.txop = cpu_to_le16(_txop); \ } while(0) static void p54_init_vdcf(struct ieee80211_hw *dev) @@ -783,10 +782,16 @@ static void p54_init_vdcf(struct ieee80211_hw *dev) vdcf = (struct p54_tx_control_vdcf *) hdr->data; - P54_SET_QUEUE(vdcf->queue[0], 0x0002, 0x0003, 0x0007, 0x000f); - P54_SET_QUEUE(vdcf->queue[1], 0x0002, 0x0007, 0x000f, 0x001e); - P54_SET_QUEUE(vdcf->queue[2], 0x0002, 0x000f, 0x03ff, 0x0014); - P54_SET_QUEUE(vdcf->queue[3], 0x0007, 0x000f, 0x03ff, 0x0000); + /* + * FIXME: The default values in the spec (IEEE 802.11 + * 7.3.2.19 Table 37) are 47, 94, 0, 0, why use + * 47, 94, 63, 0 here? Also, the default AIFS + * values (second parameter) are 2, 2, 3, 7... + */ + P54_SET_QUEUE(vdcf->queue[0], 0x0002, 0x0003, 0x0007, 47); + P54_SET_QUEUE(vdcf->queue[1], 0x0002, 0x0007, 0x000f, 94); + P54_SET_QUEUE(vdcf->queue[2], 0x0002, 0x000f, 0x03ff, 63); + P54_SET_QUEUE(vdcf->queue[3], 0x0007, 0x000f, 0x03ff, 0); } static void p54_set_vdcf(struct ieee80211_hw *dev) @@ -939,7 +944,7 @@ static int p54_conf_tx(struct ieee80211_hw *dev, int queue, if ((params) && !((queue < 0) || (queue > 4))) { P54_SET_QUEUE(vdcf->queue[queue], params->aifs, - params->cw_min, params->cw_max, params->burst_time); + params->cw_min, params->cw_max, params->txop); } else return -EINVAL; -- cgit v1.2.1 From 35f0d354bf0b0c125ac814419202f8c551081fda Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Wed, 13 Feb 2008 14:31:08 +0100 Subject: b43: Add HostFlags HI support This adds support for the high 16 bits of the hostflags. No functional change. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/b43.h | 63 ++++++++++++++++++++++++----------------- drivers/net/wireless/b43/main.c | 20 ++++++++----- drivers/net/wireless/b43/main.h | 4 +-- 3 files changed, 52 insertions(+), 35 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index 76ad811af399..33459d61a717 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -144,7 +144,8 @@ enum { #define B43_SHM_SH_PHYTYPE 0x0052 /* PHY type */ #define B43_SHM_SH_ANTSWAP 0x005C /* Antenna swap threshold */ #define B43_SHM_SH_HOSTFLO 0x005E /* Hostflags for ucode options (low) */ -#define B43_SHM_SH_HOSTFHI 0x0060 /* Hostflags for ucode options (high) */ +#define B43_SHM_SH_HOSTFMI 0x0060 /* Hostflags for ucode options (middle) */ +#define B43_SHM_SH_HOSTFHI 0x0062 /* Hostflags for ucode options (high) */ #define B43_SHM_SH_RFATT 0x0064 /* Current radio attenuation value */ #define B43_SHM_SH_RADAR 0x0066 /* Radar register */ #define B43_SHM_SH_PHYTXNOI 0x006E /* PHY noise directly after TX (lower 8bit only) */ @@ -232,31 +233,41 @@ enum { #define B43_MMIO_RADIO_HWENABLED_LO_MASK (1 << 4) /* HostFlags. See b43_hf_read/write() */ -#define B43_HF_ANTDIVHELP 0x00000001 /* ucode antenna div helper */ -#define B43_HF_SYMW 0x00000002 /* G-PHY SYM workaround */ -#define B43_HF_RXPULLW 0x00000004 /* RX pullup workaround */ -#define B43_HF_CCKBOOST 0x00000008 /* 4dB CCK power boost (exclusive with OFDM boost) */ -#define B43_HF_BTCOEX 0x00000010 /* Bluetooth coexistance */ -#define B43_HF_GDCW 0x00000020 /* G-PHY DV canceller filter bw workaround */ -#define B43_HF_OFDMPABOOST 0x00000040 /* Enable PA gain boost for OFDM */ -#define B43_HF_ACPR 0x00000080 /* Disable for Japan, channel 14 */ -#define B43_HF_EDCF 0x00000100 /* on if WME and MAC suspended */ -#define B43_HF_TSSIRPSMW 0x00000200 /* TSSI reset PSM ucode workaround */ -#define B43_HF_DSCRQ 0x00000400 /* Disable slow clock request in ucode */ -#define B43_HF_ACIW 0x00000800 /* ACI workaround: shift bits by 2 on PHY CRS */ -#define B43_HF_2060W 0x00001000 /* 2060 radio workaround */ -#define B43_HF_RADARW 0x00002000 /* Radar workaround */ -#define B43_HF_USEDEFKEYS 0x00004000 /* Enable use of default keys */ -#define B43_HF_BT4PRIOCOEX 0x00010000 /* Bluetooth 2-priority coexistance */ -#define B43_HF_FWKUP 0x00020000 /* Fast wake-up ucode */ -#define B43_HF_VCORECALC 0x00040000 /* Force VCO recalculation when powering up synthpu */ -#define B43_HF_PCISCW 0x00080000 /* PCI slow clock workaround */ -#define B43_HF_4318TSSI 0x00200000 /* 4318 TSSI */ -#define B43_HF_FBCMCFIFO 0x00400000 /* Flush bcast/mcast FIFO immediately */ -#define B43_HF_HWPCTL 0x00800000 /* Enable hardwarre power control */ -#define B43_HF_BTCOEXALT 0x01000000 /* Bluetooth coexistance in alternate pins */ -#define B43_HF_TXBTCHECK 0x02000000 /* Bluetooth check during transmission */ -#define B43_HF_SKCFPUP 0x04000000 /* Skip CFP update */ +#define B43_HF_ANTDIVHELP 0x000000000001ULL /* ucode antenna div helper */ +#define B43_HF_SYMW 0x000000000002ULL /* G-PHY SYM workaround */ +#define B43_HF_RXPULLW 0x000000000004ULL /* RX pullup workaround */ +#define B43_HF_CCKBOOST 0x000000000008ULL /* 4dB CCK power boost (exclusive with OFDM boost) */ +#define B43_HF_BTCOEX 0x000000000010ULL /* Bluetooth coexistance */ +#define B43_HF_GDCW 0x000000000020ULL /* G-PHY DC canceller filter bw workaround */ +#define B43_HF_OFDMPABOOST 0x000000000040ULL /* Enable PA gain boost for OFDM */ +#define B43_HF_ACPR 0x000000000080ULL /* Disable for Japan, channel 14 */ +#define B43_HF_EDCF 0x000000000100ULL /* on if WME and MAC suspended */ +#define B43_HF_TSSIRPSMW 0x000000000200ULL /* TSSI reset PSM ucode workaround */ +#define B43_HF_20IN40IQW 0x000000000200ULL /* 20 in 40 MHz I/Q workaround (rev >= 13 only) */ +#define B43_HF_DSCRQ 0x000000000400ULL /* Disable slow clock request in ucode */ +#define B43_HF_ACIW 0x000000000800ULL /* ACI workaround: shift bits by 2 on PHY CRS */ +#define B43_HF_2060W 0x000000001000ULL /* 2060 radio workaround */ +#define B43_HF_RADARW 0x000000002000ULL /* Radar workaround */ +#define B43_HF_USEDEFKEYS 0x000000004000ULL /* Enable use of default keys */ +#define B43_HF_AFTERBURNER 0x000000008000ULL /* Afterburner enabled */ +#define B43_HF_BT4PRIOCOEX 0x000000010000ULL /* Bluetooth 4-priority coexistance */ +#define B43_HF_FWKUP 0x000000020000ULL /* Fast wake-up ucode */ +#define B43_HF_VCORECALC 0x000000040000ULL /* Force VCO recalculation when powering up synthpu */ +#define B43_HF_PCISCW 0x000000080000ULL /* PCI slow clock workaround */ +#define B43_HF_4318TSSI 0x000000200000ULL /* 4318 TSSI */ +#define B43_HF_FBCMCFIFO 0x000000400000ULL /* Flush bcast/mcast FIFO immediately */ +#define B43_HF_HWPCTL 0x000000800000ULL /* Enable hardwarre power control */ +#define B43_HF_BTCOEXALT 0x000001000000ULL /* Bluetooth coexistance in alternate pins */ +#define B43_HF_TXBTCHECK 0x000002000000ULL /* Bluetooth check during transmission */ +#define B43_HF_SKCFPUP 0x000004000000ULL /* Skip CFP update */ +#define B43_HF_N40W 0x000008000000ULL /* N PHY 40 MHz workaround (rev >= 13 only) */ +#define B43_HF_ANTSEL 0x000020000000ULL /* Antenna selection (for testing antenna div.) */ +#define B43_HF_BT3COEXT 0x000020000000ULL /* Bluetooth 3-wire coexistence (rev >= 13 only) */ +#define B43_HF_BTCANT 0x000040000000ULL /* Bluetooth coexistence (antenna mode) (rev >= 13 only) */ +#define B43_HF_ANTSELEN 0x000100000000ULL /* Antenna selection enabled (rev >= 13 only) */ +#define B43_HF_ANTSELMODE 0x000200000000ULL /* Antenna selection mode (rev >= 13 only) */ +#define B43_HF_MLADVW 0x001000000000ULL /* N PHY ML ADV workaround (rev >= 13 only) */ +#define B43_HF_PR45960W 0x080000000000ULL /* PR 45960 workaround (rev >= 13 only) */ /* MacFilter offsets. */ #define B43_MACFILTER_SELF 0x0000 diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 071f61437c67..f745308faaad 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -465,24 +465,30 @@ out: } /* Read HostFlags */ -u32 b43_hf_read(struct b43_wldev * dev) +u64 b43_hf_read(struct b43_wldev * dev) { - u32 ret; + u64 ret; ret = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFHI); ret <<= 16; + ret |= b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFMI); + ret <<= 16; ret |= b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFLO); return ret; } /* Write HostFlags */ -void b43_hf_write(struct b43_wldev *dev, u32 value) +void b43_hf_write(struct b43_wldev *dev, u64 value) { - b43_shm_write16(dev, B43_SHM_SHARED, - B43_SHM_SH_HOSTFLO, (value & 0x0000FFFF)); - b43_shm_write16(dev, B43_SHM_SHARED, - B43_SHM_SH_HOSTFHI, ((value & 0xFFFF0000) >> 16)); + u16 lo, mi, hi; + + lo = (value & 0x00000000FFFFULL); + mi = (value & 0x0000FFFF0000ULL) >> 16; + hi = (value & 0xFFFF00000000ULL) >> 32; + b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFLO, lo); + b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFMI, mi); + b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFHI, hi); } void b43_tsf_read(struct b43_wldev *dev, u64 * tsf) diff --git a/drivers/net/wireless/b43/main.h b/drivers/net/wireless/b43/main.h index 2d52d9de9305..24a79f5d6ff5 100644 --- a/drivers/net/wireless/b43/main.h +++ b/drivers/net/wireless/b43/main.h @@ -95,8 +95,8 @@ u16 b43_shm_read16(struct b43_wldev *dev, u16 routing, u16 offset); void b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value); void b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value); -u32 b43_hf_read(struct b43_wldev *dev); -void b43_hf_write(struct b43_wldev *dev, u32 value); +u64 b43_hf_read(struct b43_wldev *dev); +void b43_hf_write(struct b43_wldev *dev, u64 value); void b43_dummy_transmission(struct b43_wldev *dev); -- cgit v1.2.1 From eaaf7894959d413d1e01443a622c507e1b4f61db Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Wed, 13 Feb 2008 11:32:29 -0800 Subject: iwlwifi-2.6: Adds and fixes defines about security This patch adds some missing defines defines for HW security. It also fixes the add_station host cmd layout. Signed-off-by: Emmanuel Grumbach Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-commands.h | 19 +++++++++++++------ drivers/net/wireless/iwlwifi/iwl-4965-commands.h | 19 +++++++++++++------ 2 files changed, 26 insertions(+), 12 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-commands.h b/drivers/net/wireless/iwlwifi/iwl-3945-commands.h index 46bb2c7d11dd..20fbb32c33bd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-commands.h @@ -515,14 +515,20 @@ struct iwl3945_qosparam_cmd { #define STA_CONTROL_MODIFY_MSK 0x01 /* key flags __le16*/ -#define STA_KEY_FLG_ENCRYPT_MSK __constant_cpu_to_le16(0x7) -#define STA_KEY_FLG_NO_ENC __constant_cpu_to_le16(0x0) -#define STA_KEY_FLG_WEP __constant_cpu_to_le16(0x1) -#define STA_KEY_FLG_CCMP __constant_cpu_to_le16(0x2) -#define STA_KEY_FLG_TKIP __constant_cpu_to_le16(0x3) +#define STA_KEY_FLG_ENCRYPT_MSK __constant_cpu_to_le16(0x0007) +#define STA_KEY_FLG_NO_ENC __constant_cpu_to_le16(0x0000) +#define STA_KEY_FLG_WEP __constant_cpu_to_le16(0x0001) +#define STA_KEY_FLG_CCMP __constant_cpu_to_le16(0x0002) +#define STA_KEY_FLG_TKIP __constant_cpu_to_le16(0x0003) #define STA_KEY_FLG_KEYID_POS 8 #define STA_KEY_FLG_INVALID __constant_cpu_to_le16(0x0800) +/* wep key is either from global key (0) or from station info array (1) */ +#define STA_KEY_FLG_WEP_KEY_MAP_MSK __constant_cpu_to_le16(0x0008) + +/* wep key in STA: 5-bytes (0) or 13-bytes (1) */ +#define STA_KEY_FLG_KEY_SIZE_MSK __constant_cpu_to_le16(0x1000) +#define STA_KEY_MULTICAST_MSK __constant_cpu_to_le16(0x4000) /* Flags indicate whether to modify vs. don't change various station params */ #define STA_MODIFY_KEY_MASK 0x01 @@ -546,7 +552,8 @@ struct iwl3945_keyinfo { u8 tkip_rx_tsc_byte2; /* TSC[2] for key mix ph1 detection */ u8 reserved1; __le16 tkip_rx_ttak[5]; /* 10-byte unicast TKIP TTAK */ - __le16 reserved2; + u8 key_offset; + u8 reserved2; u8 key[16]; /* 16-byte unicast decryption key */ } __attribute__ ((packed)); diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h index 9edd8abcf570..b21ffea325cf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h @@ -727,14 +727,20 @@ struct iwl4965_qosparam_cmd { #define STA_CONTROL_MODIFY_MSK 0x01 /* key flags __le16*/ -#define STA_KEY_FLG_ENCRYPT_MSK __constant_cpu_to_le16(0x7) -#define STA_KEY_FLG_NO_ENC __constant_cpu_to_le16(0x0) -#define STA_KEY_FLG_WEP __constant_cpu_to_le16(0x1) -#define STA_KEY_FLG_CCMP __constant_cpu_to_le16(0x2) -#define STA_KEY_FLG_TKIP __constant_cpu_to_le16(0x3) +#define STA_KEY_FLG_ENCRYPT_MSK __constant_cpu_to_le16(0x0007) +#define STA_KEY_FLG_NO_ENC __constant_cpu_to_le16(0x0000) +#define STA_KEY_FLG_WEP __constant_cpu_to_le16(0x0001) +#define STA_KEY_FLG_CCMP __constant_cpu_to_le16(0x0002) +#define STA_KEY_FLG_TKIP __constant_cpu_to_le16(0x0003) #define STA_KEY_FLG_KEYID_POS 8 #define STA_KEY_FLG_INVALID __constant_cpu_to_le16(0x0800) +/* wep key is either from global key (0) or from station info array (1) */ +#define STA_KEY_FLG_MAP_KEY_MSK __constant_cpu_to_le16(0x0008) + +/* wep key in STA: 5-bytes (0) or 13-bytes (1) */ +#define STA_KEY_FLG_KEY_SIZE_MSK __constant_cpu_to_le16(0x1000) +#define STA_KEY_MULTICAST_MSK __constant_cpu_to_le16(0x4000) /* Flags indicate whether to modify vs. don't change various station params */ #define STA_MODIFY_KEY_MASK 0x01 @@ -752,7 +758,8 @@ struct iwl4965_keyinfo { u8 tkip_rx_tsc_byte2; /* TSC[2] for key mix ph1 detection */ u8 reserved1; __le16 tkip_rx_ttak[5]; /* 10-byte unicast TKIP TTAK */ - __le16 reserved2; + u8 key_offset; + u8 reserved2; u8 key[16]; /* 16-byte unicast decryption key */ } __attribute__ ((packed)); -- cgit v1.2.1 From 5c1b09581ba91d156ec907f5cbad07d33bf9e2ed Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 13 Feb 2008 11:32:30 -0800 Subject: iwlwifi: change iwl->priv iwl_priv * type in iwl-YYY-io.h This patch makes all variables of type struct iwl_priv to be named priv This is needed for smooth change of debug printing mechanism Signed-off-by: Tomas Winkler Signed-off-by: Ester Kummer Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-io.h | 39 +++++++++++++----------------- drivers/net/wireless/iwlwifi/iwl-4965-io.h | 39 +++++++++++++----------------- 2 files changed, 34 insertions(+), 44 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-io.h b/drivers/net/wireless/iwlwifi/iwl-3945-io.h index 75e20d0a20d1..4a1872982027 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-io.h @@ -59,28 +59,28 @@ * */ -#define _iwl3945_write32(iwl, ofs, val) writel((val), (iwl)->hw_base + (ofs)) +#define _iwl3945_write32(priv, ofs, val) writel((val), (priv)->hw_base + (ofs)) #ifdef CONFIG_IWL3945_DEBUG -static inline void __iwl3945_write32(const char *f, u32 l, struct iwl3945_priv *iwl, +static inline void __iwl3945_write32(const char *f, u32 l, struct iwl3945_priv *priv, u32 ofs, u32 val) { IWL_DEBUG_IO("write32(0x%08X, 0x%08X) - %s %d\n", ofs, val, f, l); - _iwl3945_write32(iwl, ofs, val); + _iwl3945_write32(priv, ofs, val); } -#define iwl3945_write32(iwl, ofs, val) \ - __iwl3945_write32(__FILE__, __LINE__, iwl, ofs, val) +#define iwl3945_write32(priv, ofs, val) \ + __iwl3945_write32(__FILE__, __LINE__, priv, ofs, val) #else -#define iwl3945_write32(iwl, ofs, val) _iwl3945_write32(iwl, ofs, val) +#define iwl3945_write32(priv, ofs, val) _iwl3945_write32(priv, ofs, val) #endif -#define _iwl3945_read32(iwl, ofs) readl((iwl)->hw_base + (ofs)) +#define _iwl3945_read32(priv, ofs) readl((priv)->hw_base + (ofs)) #ifdef CONFIG_IWL3945_DEBUG -static inline u32 __iwl3945_read32(char *f, u32 l, struct iwl3945_priv *iwl, u32 ofs) +static inline u32 __iwl3945_read32(char *f, u32 l, struct iwl3945_priv *priv, u32 ofs) { IWL_DEBUG_IO("read_direct32(0x%08X) - %s %d\n", ofs, f, l); - return _iwl3945_read32(iwl, ofs); + return _iwl3945_read32(priv, ofs); } -#define iwl3945_read32(iwl, ofs) __iwl3945_read32(__FILE__, __LINE__, iwl, ofs) +#define iwl3945_read32(priv, ofs) __iwl3945_read32(__FILE__, __LINE__, priv, ofs) #else #define iwl3945_read32(p, o) _iwl3945_read32(p, o) #endif @@ -105,18 +105,13 @@ static inline int __iwl3945_poll_bit(const char *f, u32 l, u32 bits, u32 mask, int timeout) { int ret = _iwl3945_poll_bit(priv, addr, bits, mask, timeout); - if (unlikely(ret == -ETIMEDOUT)) - IWL_DEBUG_IO - ("poll_bit(0x%08X, 0x%08X, 0x%08X) - timedout - %s %d\n", - addr, bits, mask, f, l); - else - IWL_DEBUG_IO - ("poll_bit(0x%08X, 0x%08X, 0x%08X) = 0x%08X - %s %d\n", - addr, bits, mask, ret, f, l); + IWL_DEBUG_IO("poll_bit(0x%08X, 0x%08X, 0x%08X) - %s- %s %d\n", + addr, bits, mask, + unlikely(ret == -ETIMEDOUT)?"timeout":"", f, l); return ret; } -#define iwl3945_poll_bit(iwl, addr, bits, mask, timeout) \ - __iwl3945_poll_bit(__FILE__, __LINE__, iwl, addr, bits, mask, timeout) +#define iwl3945_poll_bit(priv, addr, bits, mask, timeout) \ + __iwl3945_poll_bit(__FILE__, __LINE__, priv, addr, bits, mask, timeout) #else #define iwl3945_poll_bit(p, a, b, m, t) _iwl3945_poll_bit(p, a, b, m, t) #endif @@ -321,8 +316,8 @@ static inline int __iwl3945_poll_direct_bit(const char *f, u32 l, "- %s %d\n", addr, mask, ret, f, l); return ret; } -#define iwl3945_poll_direct_bit(iwl, addr, mask, timeout) \ - __iwl3945_poll_direct_bit(__FILE__, __LINE__, iwl, addr, mask, timeout) +#define iwl3945_poll_direct_bit(priv, addr, mask, timeout) \ + __iwl3945_poll_direct_bit(__FILE__, __LINE__, priv, addr, mask, timeout) #else #define iwl3945_poll_direct_bit _iwl3945_poll_direct_bit #endif diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-io.h b/drivers/net/wireless/iwlwifi/iwl-4965-io.h index 34a0b57eea0c..4af0c0175da2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-io.h @@ -59,28 +59,28 @@ * */ -#define _iwl4965_write32(iwl, ofs, val) writel((val), (iwl)->hw_base + (ofs)) +#define _iwl4965_write32(priv, ofs, val) writel((val), (priv)->hw_base + (ofs)) #ifdef CONFIG_IWL4965_DEBUG -static inline void __iwl4965_write32(const char *f, u32 l, struct iwl4965_priv *iwl, +static inline void __iwl4965_write32(const char *f, u32 l, struct iwl4965_priv *priv, u32 ofs, u32 val) { IWL_DEBUG_IO("write32(0x%08X, 0x%08X) - %s %d\n", ofs, val, f, l); - _iwl4965_write32(iwl, ofs, val); + _iwl4965_write32(priv, ofs, val); } -#define iwl4965_write32(iwl, ofs, val) \ - __iwl4965_write32(__FILE__, __LINE__, iwl, ofs, val) +#define iwl4965_write32(priv, ofs, val) \ + __iwl4965_write32(__FILE__, __LINE__, priv, ofs, val) #else -#define iwl4965_write32(iwl, ofs, val) _iwl4965_write32(iwl, ofs, val) +#define iwl4965_write32(priv, ofs, val) _iwl4965_write32(priv, ofs, val) #endif -#define _iwl4965_read32(iwl, ofs) readl((iwl)->hw_base + (ofs)) +#define _iwl4965_read32(priv, ofs) readl((priv)->hw_base + (ofs)) #ifdef CONFIG_IWL4965_DEBUG -static inline u32 __iwl4965_read32(char *f, u32 l, struct iwl4965_priv *iwl, u32 ofs) +static inline u32 __iwl4965_read32(char *f, u32 l, struct iwl4965_priv *priv, u32 ofs) { IWL_DEBUG_IO("read_direct32(0x%08X) - %s %d\n", ofs, f, l); - return _iwl4965_read32(iwl, ofs); + return _iwl4965_read32(priv, ofs); } -#define iwl4965_read32(iwl, ofs) __iwl4965_read32(__FILE__, __LINE__, iwl, ofs) +#define iwl4965_read32(priv, ofs) __iwl4965_read32(__FILE__, __LINE__, priv, ofs) #else #define iwl4965_read32(p, o) _iwl4965_read32(p, o) #endif @@ -105,18 +105,13 @@ static inline int __iwl4965_poll_bit(const char *f, u32 l, u32 bits, u32 mask, int timeout) { int ret = _iwl4965_poll_bit(priv, addr, bits, mask, timeout); - if (unlikely(ret == -ETIMEDOUT)) - IWL_DEBUG_IO - ("poll_bit(0x%08X, 0x%08X, 0x%08X) - timedout - %s %d\n", - addr, bits, mask, f, l); - else - IWL_DEBUG_IO - ("poll_bit(0x%08X, 0x%08X, 0x%08X) = 0x%08X - %s %d\n", - addr, bits, mask, ret, f, l); + IWL_DEBUG_IO("poll_bit(0x%08X, 0x%08X, 0x%08X) - %s- %s %d\n", + addr, bits, mask, + unlikely(ret == -ETIMEDOUT)?"timeout":"", f, l); return ret; } -#define iwl4965_poll_bit(iwl, addr, bits, mask, timeout) \ - __iwl4965_poll_bit(__FILE__, __LINE__, iwl, addr, bits, mask, timeout) +#define iwl4965_poll_bit(priv, addr, bits, mask, timeout) \ + __iwl4965_poll_bit(__FILE__, __LINE__, priv, addr, bits, mask, timeout) #else #define iwl4965_poll_bit(p, a, b, m, t) _iwl4965_poll_bit(p, a, b, m, t) #endif @@ -321,8 +316,8 @@ static inline int __iwl4965_poll_direct_bit(const char *f, u32 l, "- %s %d\n", addr, mask, ret, f, l); return ret; } -#define iwl4965_poll_direct_bit(iwl, addr, mask, timeout) \ - __iwl4965_poll_direct_bit(__FILE__, __LINE__, iwl, addr, mask, timeout) +#define iwl4965_poll_direct_bit(priv, addr, mask, timeout) \ + __iwl4965_poll_direct_bit(__FILE__, __LINE__, priv, addr, mask, timeout) #else #define iwl4965_poll_direct_bit _iwl4965_poll_direct_bit #endif -- cgit v1.2.1 From 3e82a822c7c8ea5477062ec8885d7b90696fe73f Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 13 Feb 2008 11:32:31 -0800 Subject: iwlwifi: Add tx_ant_num hw setting variable Added tx_ant_num variable into hw_setting This will be used for scanning TX antenna toggling On the way removed ac_queue_num unused Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 3 ++- drivers/net/wireless/iwlwifi/iwl-3945.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-4965.c | 4 +++- drivers/net/wireless/iwlwifi/iwl-4965.h | 4 ++-- 4 files changed, 9 insertions(+), 6 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 50d927bb2170..82d282730b75 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -2300,7 +2300,6 @@ int iwl3945_hw_set_hw_setting(struct iwl3945_priv *priv) return -ENOMEM; } - priv->hw_setting.ac_queue_count = AC_NUM; priv->hw_setting.rx_buf_size = IWL_RX_BUF_SIZE; priv->hw_setting.max_pkt_size = 2342; priv->hw_setting.tx_cmd_len = sizeof(struct iwl3945_tx_cmd); @@ -2308,6 +2307,8 @@ int iwl3945_hw_set_hw_setting(struct iwl3945_priv *priv) priv->hw_setting.max_rxq_log = RX_QUEUE_SIZE_LOG; priv->hw_setting.max_stations = IWL3945_STATION_COUNT; priv->hw_setting.bcast_sta_id = IWL3945_BROADCAST_ID; + + priv->hw_setting.tx_ant_num = 2; return 0; } diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 393cff6f2270..dde389d31637 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -508,8 +508,8 @@ struct iwl3945_ibss_seq { /** * struct iwl3945_driver_hw_info * @max_txq_num: Max # Tx queues supported - * @ac_queue_count: # Tx queues for EDCA Access Categories (AC) * @tx_cmd_len: Size of Tx command (but not including frame itself) + * @tx_ant_num: Number of TX antennas * @max_rxq_size: Max # Rx frames in Rx queue (must be power-of-2) * @rx_buf_size: * @max_pkt_size: @@ -521,8 +521,8 @@ struct iwl3945_ibss_seq { */ struct iwl3945_driver_hw_info { u16 max_txq_num; - u16 ac_queue_count; u16 tx_cmd_len; + u16 tx_ant_num; u16 max_rxq_size; u32 rx_buf_size; u32 max_pkt_size; diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index cc141f8ba616..237d3b24dd20 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -1794,7 +1794,6 @@ int iwl4965_hw_set_hw_setting(struct iwl4965_priv *priv) memset(priv->hw_setting.shared_virt, 0, sizeof(struct iwl4965_shared)); priv->hw_setting.max_txq_num = iwl4965_param_queues_num; - priv->hw_setting.ac_queue_count = AC_NUM; priv->hw_setting.tx_cmd_len = sizeof(struct iwl4965_tx_cmd); priv->hw_setting.max_rxq_size = RX_QUEUE_SIZE; priv->hw_setting.max_rxq_log = RX_QUEUE_SIZE_LOG; @@ -1805,6 +1804,9 @@ int iwl4965_hw_set_hw_setting(struct iwl4965_priv *priv) priv->hw_setting.max_pkt_size = priv->hw_setting.rx_buf_size - 256; priv->hw_setting.max_stations = IWL4965_STATION_COUNT; priv->hw_setting.bcast_sta_id = IWL4965_BROADCAST_ID; + + priv->hw_setting.tx_ant_num = 2; + return 0; } diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index 67189ab93dbe..ce17e4fec838 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -580,8 +580,8 @@ struct iwl4965_ibss_seq { /** * struct iwl4965_driver_hw_info * @max_txq_num: Max # Tx queues supported - * @ac_queue_count: # Tx queues for EDCA Access Categories (AC) * @tx_cmd_len: Size of Tx command (but not including frame itself) + * @tx_ant_num: Number of TX antennas * @max_rxq_size: Max # Rx frames in Rx queue (must be power-of-2) * @rx_buffer_size: * @max_rxq_log: Log-base-2 of max_rxq_size @@ -592,8 +592,8 @@ struct iwl4965_ibss_seq { */ struct iwl4965_driver_hw_info { u16 max_txq_num; - u16 ac_queue_count; u16 tx_cmd_len; + u16 tx_ant_num; u16 max_rxq_size; u32 rx_buf_size; u32 max_pkt_size; -- cgit v1.2.1 From 6e33e30d7ae11d527ad1d65ec09a65467d6db1b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=2E=C3=87a=C4=9Flar=20Onur?= Date: Thu, 14 Feb 2008 17:36:49 +0200 Subject: drivers/net/wireless/atmel.c: Use time_* macros MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The functions time_before, time_before_eq, time_after, and time_after_eq are more robust for comparing jiffies against other values. So following patch implements usage of the time_after() macro, defined at linux/jiffies.h, which deals with wrapping correctly Cc: linux-wireless@vger.kernel.org Signed-off-by: S.ÇaÄŸlar Onur Signed-off-by: John W. Linville --- drivers/net/wireless/atmel.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c index 63ec7a70ee76..ef2da4023d68 100644 --- a/drivers/net/wireless/atmel.c +++ b/drivers/net/wireless/atmel.c @@ -66,6 +66,7 @@ #include #include #include +#include #include #include "atmel.h" @@ -516,7 +517,7 @@ struct atmel_private { SITE_SURVEY_IN_PROGRESS, SITE_SURVEY_COMPLETED } site_survey_state; - time_t last_survey; + unsigned long last_survey; int station_was_associated, station_is_associated; int fast_scan; @@ -2283,7 +2284,7 @@ static int atmel_set_scan(struct net_device *dev, return -EAGAIN; /* Timeout old surveys. */ - if ((jiffies - priv->last_survey) > (20 * HZ)) + if (time_after(jiffies, priv->last_survey + 20 * HZ)) priv->site_survey_state = SITE_SURVEY_IDLE; priv->last_survey = jiffies; -- cgit v1.2.1 From 6cd74e3b99ec5aeed5346b1b3777903fa5e47db7 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Fri, 15 Feb 2008 21:58:53 +0100 Subject: WDEV: ath5k, typecheck on nonDEBUG At least type check the ATH5K_TRACE paramter on !ATH5K_DEBUG configs. Signed-off-by: Jiri Slaby Cc: Nick Kossifidis Acked-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/debug.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath5k/debug.h b/drivers/net/wireless/ath5k/debug.h index 16fbb6fbab35..8c0b5c57c76b 100644 --- a/drivers/net/wireless/ath5k/debug.h +++ b/drivers/net/wireless/ath5k/debug.h @@ -165,7 +165,9 @@ ath5k_debug_printtxbuf(struct ath5k_softc *sc, #else /* no debugging */ -#define ATH5K_TRACE(_sc) /* empty */ +#include + +#define ATH5K_TRACE(_sc) typecheck(struct ath5k_softc *, (_sc)) static inline void __attribute__ ((format (printf, 3, 4))) ATH5K_DBG(struct ath5k_softc *sc, unsigned int m, const char *fmt, ...) {} -- cgit v1.2.1 From 3230455d13860b26f638b9d58a8c5f20bf32fda2 Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Fri, 15 Feb 2008 14:34:37 -0800 Subject: iwlwifi: fix name of function in comment (_rx_card_state_notif) iwl_rx_card_state_notif is named iwl3945_rx_card_state_notif and iwl4965_rx_card_state_notif in the two iwlwifi drivers. Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl3945-base.c | 2 +- drivers/net/wireless/iwlwifi/iwl4965-base.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index bb3a5f633227..0fab832ce8c2 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -4777,7 +4777,7 @@ static void iwl3945_irq_tasklet(struct iwl3945_priv *priv) /* Queue restart only if RF_KILL switch was set to "kill" * when we loaded driver, and is now set to "enable". * After we're Alive, RF_KILL gets handled by - * iwl_rx_card_state_notif() */ + * iwl3945_rx_card_state_notif() */ if (!hw_rf_kill && !test_bit(STATUS_ALIVE, &priv->status)) { clear_bit(STATUS_RF_KILL_HW, &priv->status); queue_work(priv->workqueue, &priv->restart); diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index fb4c84e31932..20d012d4f37e 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -5149,7 +5149,7 @@ static void iwl4965_irq_tasklet(struct iwl4965_priv *priv) /* Queue restart only if RF_KILL switch was set to "kill" * when we loaded driver, and is now set to "enable". * After we're Alive, RF_KILL gets handled by - * iwl_rx_card_state_notif() */ + * iwl4965_rx_card_state_notif() */ if (!hw_rf_kill && !test_bit(STATUS_ALIVE, &priv->status)) { clear_bit(STATUS_RF_KILL_HW, &priv->status); queue_work(priv->workqueue, &priv->restart); -- cgit v1.2.1 From aa68cbfb20b417d68dc45c9ef5f3e51546b438b0 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 18 Feb 2008 14:20:30 +0100 Subject: rtl818x: fix RTS/CTS-less transmit This fixes packet transmission of packets without RTS/CTS. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/rtl8180_dev.c | 14 ++++++++++---- drivers/net/wireless/rtl8187_dev.c | 12 +++++++++--- 2 files changed, 19 insertions(+), 7 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rtl8180_dev.c b/drivers/net/wireless/rtl8180_dev.c index d0928c91c21c..b1b3a478335b 100644 --- a/drivers/net/wireless/rtl8180_dev.c +++ b/drivers/net/wireless/rtl8180_dev.c @@ -257,19 +257,25 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb, mapping = pci_map_single(priv->pdev, skb->data, skb->len, PCI_DMA_TODEVICE); + BUG_ON(!control->tx_rate); + tx_flags = RTL8180_TX_DESC_FLAG_OWN | RTL8180_TX_DESC_FLAG_FS | RTL8180_TX_DESC_FLAG_LS | - (control->tx_rate->hw_value << 24) | - (control->rts_cts_rate->hw_value << 19) | skb->len; + (control->tx_rate->hw_value << 24) | skb->len; if (priv->r8185) tx_flags |= RTL8180_TX_DESC_FLAG_DMA | RTL8180_TX_DESC_FLAG_NO_ENC; - if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS) + if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS) { + BUG_ON(!control->rts_cts_rate); tx_flags |= RTL8180_TX_DESC_FLAG_RTS; - else if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) + tx_flags |= control->rts_cts_rate->hw_value << 19; + } else if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) { + BUG_ON(!control->rts_cts_rate); tx_flags |= RTL8180_TX_DESC_FLAG_CTS; + tx_flags |= control->rts_cts_rate->hw_value << 19; + } *((struct ieee80211_tx_control **) skb->cb) = kmemdup(control, sizeof(*control), GFP_ATOMIC); diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c index 6ef67990692d..c03834d5cb0b 100644 --- a/drivers/net/wireless/rtl8187_dev.c +++ b/drivers/net/wireless/rtl8187_dev.c @@ -178,17 +178,23 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb, flags = skb->len; flags |= RTL8187_TX_FLAG_NO_ENCRYPT; - flags |= control->rts_cts_rate->hw_value << 19; + + BUG_ON(!control->tx_rate); + flags |= control->tx_rate->hw_value << 24; if (ieee80211_get_morefrag((struct ieee80211_hdr *)skb->data)) flags |= RTL8187_TX_FLAG_MORE_FRAG; if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS) { + BUG_ON(!control->rts_cts_rate); flags |= RTL8187_TX_FLAG_RTS; + flags |= control->rts_cts_rate->hw_value << 19; rts_dur = ieee80211_rts_duration(dev, priv->vif, skb->len, control); - } - if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) + } else if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) { + BUG_ON(!control->rts_cts_rate); flags |= RTL8187_TX_FLAG_CTS; + flags |= control->rts_cts_rate->hw_value << 19; + } hdr = (struct rtl8187_tx_hdr *)skb_push(skb, sizeof(*hdr)); hdr->flags = cpu_to_le32(flags); -- cgit v1.2.1 From d007b7f42e2a3a2b95ef43e8cc1a3dfe66b19736 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 18 Feb 2008 18:53:55 +0100 Subject: b43(legacy): include full timestamp in beacon frames Having the full RX timestamp in beacons is necessary for IBSS merge to work properly so extend the 16-bit timestamp to the full 64 bits for beacon frames (as well as when monitor mode is active.) Signed-off-by: Johannes Berg Signed-off-by: Michael Buesch Signed-off-by: Stefano Brivio Signed-off-by: John W. Linville --- drivers/net/wireless/b43/xmit.c | 14 +++++++++----- drivers/net/wireless/b43legacy/xmit.c | 14 +++++++++----- 2 files changed, 18 insertions(+), 10 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index 4014b6c8272b..187c11bee0f1 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c @@ -589,12 +589,16 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) status.antenna = !!(phystat0 & B43_RX_PHYST0_ANT); /* - * If monitors are present get full 64-bit timestamp. This - * code assumes we get to process the packet within 16 bits - * of timestamp, i.e. about 65 milliseconds after the PHY - * received the first symbol. + * All frames on monitor interfaces and beacons always need a full + * 64-bit timestamp. Monitor interfaces need it for diagnostic + * purposes and beacons for IBSS merging. + * This code assumes we get to process the packet within 16 bits + * of timestamp, i.e. about 65 milliseconds after the PHY received + * the first symbol. */ - if (dev->wl->radiotap_enabled) { + if (((fctl & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) + == (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON)) || + dev->wl->radiotap_enabled) { u16 low_mactime_now; b43_tsf_read(dev, &status.mactime); diff --git a/drivers/net/wireless/b43legacy/xmit.c b/drivers/net/wireless/b43legacy/xmit.c index 47e130e9fdf2..dcad2491a606 100644 --- a/drivers/net/wireless/b43legacy/xmit.c +++ b/drivers/net/wireless/b43legacy/xmit.c @@ -546,12 +546,16 @@ void b43legacy_rx(struct b43legacy_wldev *dev, status.antenna = !!(phystat0 & B43legacy_RX_PHYST0_ANT); /* - * If monitors are present get full 64-bit timestamp. This - * code assumes we get to process the packet within 16 bits - * of timestamp, i.e. about 65 milliseconds after the PHY - * received the first symbol. + * All frames on monitor interfaces and beacons always need a full + * 64-bit timestamp. Monitor interfaces need it for diagnostic + * purposes and beacons for IBSS merging. + * This code assumes we get to process the packet within 16 bits + * of timestamp, i.e. about 65 milliseconds after the PHY received + * the first symbol. */ - if (dev->wl->radiotap_enabled) { + if (((fctl & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) + == (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON)) || + dev->wl->radiotap_enabled) { u16 low_mactime_now; b43legacy_tsf_read(dev, &status.mactime); -- cgit v1.2.1 From 9f6adf23d87ad394ed03c038409550ca37029154 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Tue, 19 Feb 2008 14:05:33 -0800 Subject: iwlwifi: remove twice defined CSR register This patch removes twice defined CSR register. It was confusing Signed-off-by: Tomas Winkler Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-hw.h | 1 - drivers/net/wireless/iwlwifi/iwl-4965-hw.h | 1 - drivers/net/wireless/iwlwifi/iwl-4965.c | 7 ++++--- 3 files changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h index 571815d7e8bf..6693767adc9f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h @@ -324,7 +324,6 @@ struct iwl3945_eeprom { /*=== CSR (control and status registers) ===*/ #define CSR_BASE (0x000) -#define CSR_SW_VER (CSR_BASE+0x000) #define CSR_HW_IF_CONFIG_REG (CSR_BASE+0x000) /* hardware interface config */ #define CSR_INT_COALESCING (CSR_BASE+0x004) /* accum ints, 32-usec units */ #define CSR_INT (CSR_BASE+0x008) /* host interrupt status/ack */ diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h index ffe1e9dfdec7..cc726215ab93 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h @@ -413,7 +413,6 @@ struct iwl4965_eeprom { /*=== CSR (control and status registers) ===*/ #define CSR_BASE (0x000) -#define CSR_SW_VER (CSR_BASE+0x000) #define CSR_HW_IF_CONFIG_REG (CSR_BASE+0x000) /* hardware interface config */ #define CSR_INT_COALESCING (CSR_BASE+0x004) /* accum ints, 32-usec units */ #define CSR_INT (CSR_BASE+0x008) /* host interrupt status/ack */ diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 237d3b24dd20..a9c30bcb65b8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -545,9 +545,10 @@ int iwl4965_hw_nic_init(struct iwl4965_priv *priv) /* set CSR_HW_CONFIG_REG for uCode use */ - iwl4965_set_bit(priv, CSR_SW_VER, CSR_HW_IF_CONFIG_REG_BIT_KEDRON_R | - CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | - CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); + iwl4965_set_bit(priv, CSR_HW_IF_CONFIG_REG, + CSR_HW_IF_CONFIG_REG_BIT_KEDRON_R | + CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | + CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); rc = iwl4965_grab_nic_access(priv); if (rc < 0) { -- cgit v1.2.1 From e51c683717e3ac21713444e9a517aa8e0ad0ee48 Mon Sep 17 00:00:00 2001 From: Javier Cardona Date: Fri, 8 Feb 2008 18:41:17 -0800 Subject: zd1211rw: Fixed incorrect constant name. Trial and error reveals that CR_ZD1211B_TX_PWR_CTL* do not affect the transmission power. Instead these registers seem to control the contention windows limits for different QoS access categories. Signed-off-by: Javier Cardona Signed-off-by: Daniel Drake Signed-off-by: John W. Linville --- drivers/net/wireless/zd1211rw/zd_chip.c | 8 ++++---- drivers/net/wireless/zd1211rw/zd_chip.h | 9 ++++----- 2 files changed, 8 insertions(+), 9 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c index e3fba6f09455..db96adf90ae2 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.c +++ b/drivers/net/wireless/zd1211rw/zd_chip.c @@ -771,10 +771,10 @@ static int zd1211b_hw_init_hmac(struct zd_chip *chip) { static const struct zd_ioreq32 ioreqs[] = { { CR_ZD1211B_RETRY_MAX, 0x02020202 }, - { CR_ZD1211B_TX_PWR_CTL4, 0x007f003f }, - { CR_ZD1211B_TX_PWR_CTL3, 0x007f003f }, - { CR_ZD1211B_TX_PWR_CTL2, 0x003f001f }, - { CR_ZD1211B_TX_PWR_CTL1, 0x001f000f }, + { CR_ZD1211B_CWIN_MAX_MIN_AC0, 0x007f003f }, + { CR_ZD1211B_CWIN_MAX_MIN_AC1, 0x007f003f }, + { CR_ZD1211B_CWIN_MAX_MIN_AC2, 0x003f001f }, + { CR_ZD1211B_CWIN_MAX_MIN_AC3, 0x001f000f }, { CR_ZD1211B_AIFS_CTL1, 0x00280028 }, { CR_ZD1211B_AIFS_CTL2, 0x008C003C }, { CR_ZD1211B_TXOP, 0x01800824 }, diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h index 009c03777a35..5b6e3a3751ba 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.h +++ b/drivers/net/wireless/zd1211rw/zd_chip.h @@ -625,11 +625,10 @@ enum { #define CR_S_MD CTL_REG(0x0830) #define CR_USB_DEBUG_PORT CTL_REG(0x0888) - -#define CR_ZD1211B_TX_PWR_CTL1 CTL_REG(0x0b00) -#define CR_ZD1211B_TX_PWR_CTL2 CTL_REG(0x0b04) -#define CR_ZD1211B_TX_PWR_CTL3 CTL_REG(0x0b08) -#define CR_ZD1211B_TX_PWR_CTL4 CTL_REG(0x0b0c) +#define CR_ZD1211B_CWIN_MAX_MIN_AC0 CTL_REG(0x0b00) +#define CR_ZD1211B_CWIN_MAX_MIN_AC1 CTL_REG(0x0b04) +#define CR_ZD1211B_CWIN_MAX_MIN_AC2 CTL_REG(0x0b08) +#define CR_ZD1211B_CWIN_MAX_MIN_AC3 CTL_REG(0x0b0c) #define CR_ZD1211B_AIFS_CTL1 CTL_REG(0x0b10) #define CR_ZD1211B_AIFS_CTL2 CTL_REG(0x0b14) #define CR_ZD1211B_TXOP CTL_REG(0x0b20) -- cgit v1.2.1 From 2c1a1b124f793aaf9f6bcb8f6b5d05c29c2db690 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sun, 10 Feb 2008 16:03:55 +0100 Subject: zd1211rw: Fix beacon filter flags thinko We must not clear the FIF_BCN_PRBRESP_PROMISC bit in the new_flags. The zd-driver does support sending beacons and probe responses to the host. What the flag does is say "Send me all beacons and probe responses". And we actually do that. We always do that, so we ignore the case when the bit is disabled. But that is fine. But we must not clear the flag, as that tells mac80211 that we do not support passing beacons and probe responses to the stack. And that's not true. Signed-off-by: Michael Buesch Acked-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/zd1211rw/zd_mac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index 21b653458831..f90f03f676de 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -774,7 +774,7 @@ static void set_rx_filter_handler(struct work_struct *work) #define SUPPORTED_FIF_FLAGS \ (FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL | FIF_CONTROL | \ - FIF_OTHER_BSS) + FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC) static void zd_op_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, unsigned int *new_flags, -- cgit v1.2.1 From 5200e8cdf26e32d15f7a125fd75310150f9b2812 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Tue, 12 Feb 2008 14:02:06 +0100 Subject: p54: use IEEE 802.11e defaults for initialization This trival one-liner changes the QoS initialization values to match IEEE 802.11e defaults. Signed-off-by: Christian Lamparter Acked-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/p54common.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/p54common.c b/drivers/net/wireless/p54common.c index 0e9f887178ce..424de9f4d5e7 100644 --- a/drivers/net/wireless/p54common.c +++ b/drivers/net/wireless/p54common.c @@ -782,15 +782,9 @@ static void p54_init_vdcf(struct ieee80211_hw *dev) vdcf = (struct p54_tx_control_vdcf *) hdr->data; - /* - * FIXME: The default values in the spec (IEEE 802.11 - * 7.3.2.19 Table 37) are 47, 94, 0, 0, why use - * 47, 94, 63, 0 here? Also, the default AIFS - * values (second parameter) are 2, 2, 3, 7... - */ P54_SET_QUEUE(vdcf->queue[0], 0x0002, 0x0003, 0x0007, 47); P54_SET_QUEUE(vdcf->queue[1], 0x0002, 0x0007, 0x000f, 94); - P54_SET_QUEUE(vdcf->queue[2], 0x0002, 0x000f, 0x03ff, 63); + P54_SET_QUEUE(vdcf->queue[2], 0x0003, 0x000f, 0x03ff, 0); P54_SET_QUEUE(vdcf->queue[3], 0x0007, 0x000f, 0x03ff, 0); } -- cgit v1.2.1 From 19ae3a6a96859c0e64d9dd5d35515a6f23a9cad8 Mon Sep 17 00:00:00 2001 From: Daniel Drake Date: Tue, 12 Feb 2008 13:49:42 +0000 Subject: ipw2100/ipw2200: note firmware loading caveat in Kconfig help text Most wireless drivers load their firmware at interface open time, which generally occurs after the filesystem is available. However, the ipw drivers load their firmware at probe time because firmware is required to read the device MAC address. When built-in, probe happens before the filesystem is available, hence device init will only complete successfully if the user has made special arrangements (including firmware plus a loader in the initramfs). Note all this in the kconfig help text for both drivers. Signed-off-by: Daniel Drake Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/Kconfig | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index cfedbda81e3f..3c3ef966c95b 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -146,12 +146,15 @@ config IPW2100 configure your card: . + + It is recommended that you compile this driver as a module (M) + rather than built-in (Y). This driver requires firmware at device + initialization time, and when built-in this typically happens + before the filesystem is accessible (hence firmware will be + unavailable and initialization will fail). If you do choose to build + this driver into your kernel image, you can avoid this problem by + including the firmware and a firmware loader in an initramfs. - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . - The module will be called ipw2100.ko. - config IPW2100_MONITOR bool "Enable promiscuous mode" depends on IPW2100 @@ -201,11 +204,14 @@ config IPW2200 configure your card: . - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . - The module will be called ipw2200.ko. + + It is recommended that you compile this driver as a module (M) + rather than built-in (Y). This driver requires firmware at device + initialization time, and when built-in this typically happens + before the filesystem is accessible (hence firmware will be + unavailable and initialization will fail). If you do choose to build + this driver into your kernel image, you can avoid this problem by + including the firmware and a firmware loader in an initramfs. config IPW2200_MONITOR bool "Enable promiscuous mode" -- cgit v1.2.1 From 5c05863d0346c025a712b57622efe7828b29758e Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Wed, 13 Feb 2008 00:06:12 +0100 Subject: ipw2200: le*_add_cpu conversion replace all: little_endian_variable = cpu_to_leX(leX_to_cpu(little_endian_variable) + expression_in_cpu_byteorder); with: leX_add_cpu(&little_endian_variable, expression_in_cpu_byteorder); generated with semantic patch Signed-off-by: Marcin Slusarz Cc: Zhu Yi Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2200.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index a56d9fc6354f..3d4b590046a8 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -10349,9 +10349,7 @@ static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, remaining_bytes, PCI_DMA_TODEVICE)); - tfd->u.data.num_chunks = - cpu_to_le32(le32_to_cpu(tfd->u.data.num_chunks) + - 1); + le32_add_cpu(&tfd->u.data.num_chunks, 1); } } -- cgit v1.2.1 From 6f865c0ab9318cd4c357654e460cb4c9aaf23a92 Mon Sep 17 00:00:00 2001 From: Matthias Kaehlcke Date: Fri, 15 Feb 2008 20:56:48 +0100 Subject: prism54: Convert acl->sem in a mutex The semaphore acl->sem is used as mutex, convert it to the mutex API Signed-off-by: Matthias Kaehlcke Acked-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/prism54/isl_ioctl.c | 28 ++++++++++++++-------------- drivers/net/wireless/prism54/islpci_dev.h | 2 +- 2 files changed, 15 insertions(+), 15 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c index 1b595a6525f4..df1594ea942c 100644 --- a/drivers/net/wireless/prism54/isl_ioctl.c +++ b/drivers/net/wireless/prism54/isl_ioctl.c @@ -1780,7 +1780,7 @@ prism54_set_raw(struct net_device *ndev, struct iw_request_info *info, void prism54_acl_init(struct islpci_acl *acl) { - sema_init(&acl->sem, 1); + mutex_init(&acl->lock); INIT_LIST_HEAD(&acl->mac_list); acl->size = 0; acl->policy = MAC_POLICY_OPEN; @@ -1792,10 +1792,10 @@ prism54_clear_mac(struct islpci_acl *acl) struct list_head *ptr, *next; struct mac_entry *entry; - down(&acl->sem); + mutex_lock(&acl->lock); if (acl->size == 0) { - up(&acl->sem); + mutex_unlock(&acl->lock); return; } @@ -1806,7 +1806,7 @@ prism54_clear_mac(struct islpci_acl *acl) kfree(entry); } acl->size = 0; - up(&acl->sem); + mutex_unlock(&acl->lock); } void @@ -1833,13 +1833,13 @@ prism54_add_mac(struct net_device *ndev, struct iw_request_info *info, memcpy(entry->addr, addr->sa_data, ETH_ALEN); - if (down_interruptible(&acl->sem)) { + if (mutex_lock_interruptible(&acl->lock)) { kfree(entry); return -ERESTARTSYS; } list_add_tail(&entry->_list, &acl->mac_list); acl->size++; - up(&acl->sem); + mutex_unlock(&acl->lock); return 0; } @@ -1856,18 +1856,18 @@ prism54_del_mac(struct net_device *ndev, struct iw_request_info *info, if (addr->sa_family != ARPHRD_ETHER) return -EOPNOTSUPP; - if (down_interruptible(&acl->sem)) + if (mutex_lock_interruptible(&acl->lock)) return -ERESTARTSYS; list_for_each_entry(entry, &acl->mac_list, _list) { if (memcmp(entry->addr, addr->sa_data, ETH_ALEN) == 0) { list_del(&entry->_list); acl->size--; kfree(entry); - up(&acl->sem); + mutex_unlock(&acl->lock); return 0; } } - up(&acl->sem); + mutex_unlock(&acl->lock); return -EINVAL; } @@ -1882,7 +1882,7 @@ prism54_get_mac(struct net_device *ndev, struct iw_request_info *info, dwrq->length = 0; - if (down_interruptible(&acl->sem)) + if (mutex_lock_interruptible(&acl->lock)) return -ERESTARTSYS; list_for_each_entry(entry, &acl->mac_list, _list) { @@ -1891,7 +1891,7 @@ prism54_get_mac(struct net_device *ndev, struct iw_request_info *info, dwrq->length++; dst++; } - up(&acl->sem); + mutex_unlock(&acl->lock); return 0; } @@ -1955,11 +1955,11 @@ prism54_mac_accept(struct islpci_acl *acl, char *mac) struct mac_entry *entry; int res = 0; - if (down_interruptible(&acl->sem)) + if (mutex_lock_interruptible(&acl->lock)) return -ERESTARTSYS; if (acl->policy == MAC_POLICY_OPEN) { - up(&acl->sem); + mutex_unlock(&acl->lock); return 1; } @@ -1970,7 +1970,7 @@ prism54_mac_accept(struct islpci_acl *acl, char *mac) } } res = (acl->policy == MAC_POLICY_ACCEPT) ? !res : res; - up(&acl->sem); + mutex_unlock(&acl->lock); return res; } diff --git a/drivers/net/wireless/prism54/islpci_dev.h b/drivers/net/wireless/prism54/islpci_dev.h index 4e0182ce835b..b03a2ab0009b 100644 --- a/drivers/net/wireless/prism54/islpci_dev.h +++ b/drivers/net/wireless/prism54/islpci_dev.h @@ -55,7 +55,7 @@ struct islpci_acl { enum { MAC_POLICY_OPEN=0, MAC_POLICY_ACCEPT=1, MAC_POLICY_REJECT=2 } policy; struct list_head mac_list; /* a list of mac_entry */ int size; /* size of queue */ - struct semaphore sem; /* accessed in ioctls and trap_work */ + struct mutex lock; /* accessed in ioctls and trap_work */ }; struct islpci_membuf { -- cgit v1.2.1 From f8139218b32e9a68fc6779fa0ce45c5078c23c8a Mon Sep 17 00:00:00 2001 From: Matthias Kaehlcke Date: Fri, 15 Feb 2008 20:56:59 +0100 Subject: prism54: Convert stats_sem in a mutex The semaphore stats_sem is used as mutex, convert it to the mutex API Signed-off-by: Matthias Kaehlcke Acked-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/prism54/isl_ioctl.c | 8 ++++---- drivers/net/wireless/prism54/islpci_dev.c | 2 +- drivers/net/wireless/prism54/islpci_dev.h | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c index df1594ea942c..3fb6a7b54038 100644 --- a/drivers/net/wireless/prism54/isl_ioctl.c +++ b/drivers/net/wireless/prism54/isl_ioctl.c @@ -165,7 +165,7 @@ prism54_update_stats(struct work_struct *work) struct obj_bss bss, *bss2; union oid_res_t r; - down(&priv->stats_sem); + mutex_lock(&priv->stats_lock); /* Noise floor. * I'm not sure if the unit is dBm. @@ -207,7 +207,7 @@ prism54_update_stats(struct work_struct *work) mgt_get_request(priv, DOT11_OID_MPDUTXFAILED, 0, NULL, &r); priv->local_iwstatistics.discard.retries = r.u; - up(&priv->stats_sem); + mutex_unlock(&priv->stats_lock); return; } @@ -218,12 +218,12 @@ prism54_get_wireless_stats(struct net_device *ndev) islpci_private *priv = netdev_priv(ndev); /* If the stats are being updated return old data */ - if (down_trylock(&priv->stats_sem) == 0) { + if (mutex_trylock(&priv->stats_lock) == 0) { memcpy(&priv->iwstatistics, &priv->local_iwstatistics, sizeof (struct iw_statistics)); /* They won't be marked updated for the next time */ priv->local_iwstatistics.qual.updated = 0; - up(&priv->stats_sem); + mutex_unlock(&priv->stats_lock); } else priv->iwstatistics.qual.updated = 0; diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c index dbb538ccb4ec..eb7c1c6bcd8a 100644 --- a/drivers/net/wireless/prism54/islpci_dev.c +++ b/drivers/net/wireless/prism54/islpci_dev.c @@ -864,7 +864,7 @@ islpci_setup(struct pci_dev *pdev) mutex_init(&priv->mgmt_lock); priv->mgmt_received = NULL; init_waitqueue_head(&priv->mgmt_wqueue); - sema_init(&priv->stats_sem, 1); + mutex_init(&priv->stats_lock); spin_lock_init(&priv->slock); /* init state machine with off#1 state */ diff --git a/drivers/net/wireless/prism54/islpci_dev.h b/drivers/net/wireless/prism54/islpci_dev.h index b03a2ab0009b..85ddf89967af 100644 --- a/drivers/net/wireless/prism54/islpci_dev.h +++ b/drivers/net/wireless/prism54/islpci_dev.h @@ -88,7 +88,7 @@ typedef struct { /* Take care of the wireless stats */ struct work_struct stats_work; - struct semaphore stats_sem; + struct mutex stats_lock; /* remember when we last updated the stats */ unsigned long stats_timestamp; /* The first is accessed under semaphore locking. -- cgit v1.2.1 From f948db5de53ec49ede377df30eed0642cc213055 Mon Sep 17 00:00:00 2001 From: Matthias Kaehlcke Date: Fri, 15 Feb 2008 20:57:07 +0100 Subject: prism54: Convert wpa_sem in a mutex The semaphore wpa_sem is used as mutex, convert it to the mutex API Signed-off-by: Matthias Kaehlcke Acked-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/prism54/isl_ioctl.c | 10 +++++----- drivers/net/wireless/prism54/islpci_dev.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c index 3fb6a7b54038..2d91a56d6a39 100644 --- a/drivers/net/wireless/prism54/isl_ioctl.c +++ b/drivers/net/wireless/prism54/isl_ioctl.c @@ -2114,7 +2114,7 @@ prism54_wpa_bss_ie_add(islpci_private *priv, u8 *bssid, if (wpa_ie_len > MAX_WPA_IE_LEN) wpa_ie_len = MAX_WPA_IE_LEN; - down(&priv->wpa_sem); + mutex_lock(&priv->wpa_lock); /* try to use existing entry */ list_for_each(ptr, &priv->bss_wpa_list) { @@ -2165,7 +2165,7 @@ prism54_wpa_bss_ie_add(islpci_private *priv, u8 *bssid, kfree(bss); } - up(&priv->wpa_sem); + mutex_unlock(&priv->wpa_lock); } static size_t @@ -2175,7 +2175,7 @@ prism54_wpa_bss_ie_get(islpci_private *priv, u8 *bssid, u8 *wpa_ie) struct islpci_bss_wpa_ie *bss = NULL; size_t len = 0; - down(&priv->wpa_sem); + mutex_lock(&priv->wpa_lock); list_for_each(ptr, &priv->bss_wpa_list) { bss = list_entry(ptr, struct islpci_bss_wpa_ie, list); @@ -2187,7 +2187,7 @@ prism54_wpa_bss_ie_get(islpci_private *priv, u8 *bssid, u8 *wpa_ie) len = bss->wpa_ie_len; memcpy(wpa_ie, bss->wpa_ie, len); } - up(&priv->wpa_sem); + mutex_unlock(&priv->wpa_lock); return len; } @@ -2196,7 +2196,7 @@ void prism54_wpa_bss_ie_init(islpci_private *priv) { INIT_LIST_HEAD(&priv->bss_wpa_list); - sema_init(&priv->wpa_sem, 1); + mutex_init(&priv->wpa_lock); } void diff --git a/drivers/net/wireless/prism54/islpci_dev.h b/drivers/net/wireless/prism54/islpci_dev.h index 85ddf89967af..8e55a5fcffae 100644 --- a/drivers/net/wireless/prism54/islpci_dev.h +++ b/drivers/net/wireless/prism54/islpci_dev.h @@ -178,7 +178,7 @@ typedef struct { int wpa; /* WPA mode enabled */ struct list_head bss_wpa_list; int num_bss_wpa; - struct semaphore wpa_sem; + struct mutex wpa_lock; u8 wpa_ie[MAX_WPA_IE_LEN]; size_t wpa_ie_len; -- cgit v1.2.1 From 0d84d78db5bad848e385cbb1e4ae2ea1f5f27641 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sun, 10 Feb 2008 10:52:52 -0800 Subject: wireless: rt2x00: fix driver menu indenting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Michael Büker reports that the RT2x00 drivers are not indented as they should be, so use proper dependencies to make them be indented as expected. Signed-off-by: Randy Dunlap Ack-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/Kconfig | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index 51adb2f37c55..96d6fc68fe01 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig @@ -11,18 +11,17 @@ config RT2X00 will also be created. That library (when the driver is built as a module) will be called "rt2x00lib.ko". +if RT2X00 + config RT2X00_LIB tristate - depends on RT2X00 config RT2X00_LIB_PCI tristate - depends on RT2X00 select RT2X00_LIB config RT2X00_LIB_USB tristate - depends on RT2X00 select RT2X00_LIB config RT2X00_LIB_FIRMWARE @@ -47,7 +46,7 @@ config RT2X00_LIB_LEDS config RT2400PCI tristate "Ralink rt2400 pci/pcmcia support" - depends on RT2X00 && PCI + depends on PCI select RT2X00_LIB_PCI select EEPROM_93CX6 ---help--- @@ -73,7 +72,7 @@ config RT2400PCI_LEDS config RT2500PCI tristate "Ralink rt2500 pci/pcmcia support" - depends on RT2X00 && PCI + depends on PCI select RT2X00_LIB_PCI select EEPROM_93CX6 ---help--- @@ -99,7 +98,7 @@ config RT2500PCI_LEDS config RT61PCI tristate "Ralink rt61 pci/pcmcia support" - depends on RT2X00 && PCI + depends on PCI select RT2X00_LIB_PCI select RT2X00_LIB_FIRMWARE select EEPROM_93CX6 @@ -126,7 +125,7 @@ config RT61PCI_LEDS config RT2500USB tristate "Ralink rt2500 usb support" - depends on RT2X00 && USB + depends on USB select RT2X00_LIB_USB ---help--- This is an experimental driver for the Ralink rt2500 wireless chip. @@ -142,7 +141,7 @@ config RT2500USB_LEDS config RT73USB tristate "Ralink rt73 usb support" - depends on RT2X00 && USB + depends on USB select RT2X00_LIB_USB select RT2X00_LIB_FIRMWARE ---help--- @@ -171,3 +170,4 @@ config RT2X00_DEBUG ---help--- Enable debugging output for all rt2x00 modules +endif -- cgit v1.2.1 From 9c9dd2c9a42e8eb38b67f6c743c3d214664b8e2b Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 10 Feb 2008 22:46:52 +0100 Subject: rt2x00: Fix invalid DMA free Be more strict when using the queue_entry_priv_pci_rx and queue_entry_priv_pci_tx structures. Only use a particular type that matches the queue type. When freeing the DMA the priv_tx->data and priv_tx->dma was used. This is incorrect since the start of the DMA was in fact the priv_tx->desc pointer. Instead of recalculating the dma_addr_t for the DMA start this patch will swap the data and descriptor part of the allocated memory. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00pci.c | 85 +++++++++++++++++++++++---------- 1 file changed, 60 insertions(+), 25 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index 275c8a1e6638..238f1c1e4ad0 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c @@ -186,38 +186,44 @@ EXPORT_SYMBOL_GPL(rt2x00pci_txdone); /* * Device initialization handlers. */ -#define dma_size(__queue) \ -({ \ - (__queue)->limit * \ - ((__queue)->desc_size + (__queue)->data_size);\ +#define desc_size(__queue) \ +({ \ + ((__queue)->limit * (__queue)->desc_size);\ }) -#define priv_offset(__queue, __base, __i) \ -({ \ - (__base) + ((__i) * (__queue)->desc_size); \ +#define data_size(__queue) \ +({ \ + ((__queue)->limit * (__queue)->data_size);\ }) -#define data_addr_offset(__queue, __base, __i) \ -({ \ - (__base) + \ - ((__queue)->limit * (__queue)->desc_size) + \ - ((__i) * (__queue)->data_size); \ +#define dma_size(__queue) \ +({ \ + data_size(__queue) + desc_size(__queue);\ }) -#define data_dma_offset(__queue, __base, __i) \ -({ \ - (__base) + \ - ((__queue)->limit * (__queue)->desc_size) + \ - ((__i) * (__queue)->data_size); \ +#define desc_offset(__queue, __base, __i) \ +({ \ + (__base) + data_size(__queue) + \ + ((__i) * (__queue)->desc_size); \ +}) + +#define data_offset(__queue, __base, __i) \ +({ \ + (__base) + \ + ((__i) * (__queue)->data_size); \ }) static int rt2x00pci_alloc_queue_dma(struct rt2x00_dev *rt2x00dev, struct data_queue *queue) { struct pci_dev *pci_dev = rt2x00dev_pci(rt2x00dev); + struct queue_entry_priv_pci_rx *priv_rx; struct queue_entry_priv_pci_tx *priv_tx; + void *desc; void *data_addr; + void *data; dma_addr_t data_dma; + dma_addr_t dma; unsigned int i; /* @@ -227,14 +233,27 @@ static int rt2x00pci_alloc_queue_dma(struct rt2x00_dev *rt2x00dev, if (!data_addr) return -ENOMEM; + memset(data_addr, 0, dma_size(queue)); + /* * Initialize all queue entries to contain valid addresses. */ for (i = 0; i < queue->limit; i++) { - priv_tx = queue->entries[i].priv_data; - priv_tx->desc = priv_offset(queue, data_addr, i); - priv_tx->data = data_addr_offset(queue, data_addr, i); - priv_tx->dma = data_dma_offset(queue, data_dma, i); + desc = desc_offset(queue, data_addr, i); + data = data_offset(queue, data_addr, i); + dma = data_offset(queue, data_dma, i); + + if (queue->qid == QID_RX) { + priv_rx = queue->entries[i].priv_data; + priv_rx->desc = desc; + priv_rx->data = data; + priv_rx->dma = dma; + } else { + priv_tx = queue->entries[i].priv_data; + priv_tx->desc = desc; + priv_tx->data = data; + priv_tx->dma = dma; + } } return 0; @@ -244,12 +263,28 @@ static void rt2x00pci_free_queue_dma(struct rt2x00_dev *rt2x00dev, struct data_queue *queue) { struct pci_dev *pci_dev = rt2x00dev_pci(rt2x00dev); - struct queue_entry_priv_pci_tx *priv_tx = queue->entries[0].priv_data; + struct queue_entry_priv_pci_rx *priv_rx; + struct queue_entry_priv_pci_tx *priv_tx; + void *data_addr; + dma_addr_t data_dma; + + if (queue->qid == QID_RX) { + priv_rx = queue->entries[0].priv_data; + data_addr = priv_rx->data; + data_dma = priv_rx->dma; + + priv_rx->data = NULL; + } else { + priv_tx = queue->entries[0].priv_data; + data_addr = priv_tx->data; + data_dma = priv_tx->dma; + + priv_tx->data = NULL; + } - if (priv_tx->data) + if (data_addr) pci_free_consistent(pci_dev, dma_size(queue), - priv_tx->data, priv_tx->dma); - priv_tx->data = NULL; + data_addr, data_dma); } int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev) -- cgit v1.2.1 From 25fd893db26e90a1e9cf8ba151395766c70a69b3 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 10 Feb 2008 22:47:17 +0100 Subject: rt2x00: Make rt2x00 less verbose Remove the debug messages regarding initialization from EEPROM. The values are vendor specific, and are not really needed for debug purposes. If they ever become usefull we still have access to them through debugfs which also prints the exact same values... Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 4 ---- drivers/net/wireless/rt2x00/rt2500pci.c | 4 ---- drivers/net/wireless/rt2x00/rt2500usb.c | 4 ---- drivers/net/wireless/rt2x00/rt61pci.c | 4 ---- drivers/net/wireless/rt2x00/rt73usb.c | 4 ---- 5 files changed, 20 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 69b4852d4c7f..23bc51a96dbe 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -797,19 +797,15 @@ continue_csr_init: rt2400pci_bbp_write(rt2x00dev, 30, 0x21); rt2400pci_bbp_write(rt2x00dev, 31, 0x00); - DEBUG(rt2x00dev, "Start initialization from EEPROM...\n"); for (i = 0; i < EEPROM_BBP_SIZE; i++) { rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom); if (eeprom != 0xffff && eeprom != 0x0000) { reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID); value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE); - DEBUG(rt2x00dev, "BBP: 0x%02x, value: 0x%02x.\n", - reg_id, value); rt2400pci_bbp_write(rt2x00dev, reg_id, value); } } - DEBUG(rt2x00dev, "...End initialization from EEPROM.\n"); return 0; } diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index bb359a14b4ae..529b1841a085 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -951,19 +951,15 @@ continue_csr_init: rt2500pci_bbp_write(rt2x00dev, 61, 0x6d); rt2500pci_bbp_write(rt2x00dev, 62, 0x10); - DEBUG(rt2x00dev, "Start initialization from EEPROM...\n"); for (i = 0; i < EEPROM_BBP_SIZE; i++) { rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom); if (eeprom != 0xffff && eeprom != 0x0000) { reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID); value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE); - DEBUG(rt2x00dev, "BBP: 0x%02x, value: 0x%02x.\n", - reg_id, value); rt2500pci_bbp_write(rt2x00dev, reg_id, value); } } - DEBUG(rt2x00dev, "...End initialization from EEPROM.\n"); return 0; } diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index a64b62b20051..ab6e3f7f0f61 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -881,19 +881,15 @@ continue_csr_init: rt2500usb_bbp_write(rt2x00dev, 62, 0x10); rt2500usb_bbp_write(rt2x00dev, 75, 0xff); - DEBUG(rt2x00dev, "Start initialization from EEPROM...\n"); for (i = 0; i < EEPROM_BBP_SIZE; i++) { rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom); if (eeprom != 0xffff && eeprom != 0x0000) { reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID); value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE); - DEBUG(rt2x00dev, "BBP: 0x%02x, value: 0x%02x.\n", - reg_id, value); rt2500usb_bbp_write(rt2x00dev, reg_id, value); } } - DEBUG(rt2x00dev, "...End initialization from EEPROM.\n"); return 0; } diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index a049ff62e791..25b3c6e2a556 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -1282,19 +1282,15 @@ continue_csr_init: rt61pci_bbp_write(rt2x00dev, 102, 0x16); rt61pci_bbp_write(rt2x00dev, 107, 0x04); - DEBUG(rt2x00dev, "Start initialization from EEPROM...\n"); for (i = 0; i < EEPROM_BBP_SIZE; i++) { rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom); if (eeprom != 0xffff && eeprom != 0x0000) { reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID); value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE); - DEBUG(rt2x00dev, "BBP: 0x%02x, value: 0x%02x.\n", - reg_id, value); rt61pci_bbp_write(rt2x00dev, reg_id, value); } } - DEBUG(rt2x00dev, "...End initialization from EEPROM.\n"); return 0; } diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 92c8f601296f..f910d83e88f2 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -1087,19 +1087,15 @@ continue_csr_init: rt73usb_bbp_write(rt2x00dev, 102, 0x16); rt73usb_bbp_write(rt2x00dev, 107, 0x04); - DEBUG(rt2x00dev, "Start initialization from EEPROM...\n"); for (i = 0; i < EEPROM_BBP_SIZE; i++) { rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom); if (eeprom != 0xffff && eeprom != 0x0000) { reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID); value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE); - DEBUG(rt2x00dev, "BBP: 0x%02x, value: 0x%02x.\n", - reg_id, value); rt73usb_bbp_write(rt2x00dev, reg_id, value); } } - DEBUG(rt2x00dev, "...End initialization from EEPROM.\n"); return 0; } -- cgit v1.2.1 From 16938a24ae19562f078fd43a28500526ff78cd87 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 10 Feb 2008 22:47:46 +0100 Subject: rt2x00: Remove MGMT ring initialization Remove the last remnants of the MGMT ring initialization from rt61pci.ko Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt61pci.c | 2 -- drivers/net/wireless/rt2x00/rt61pci.h | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 25b3c6e2a556..a8ec910e5475 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -1070,7 +1070,6 @@ static int rt61pci_init_queues(struct rt2x00_dev *rt2x00dev) rt2x00_set_field32(®, TX_DMA_DST_CSR_DEST_AC1, 2); rt2x00_set_field32(®, TX_DMA_DST_CSR_DEST_AC2, 2); rt2x00_set_field32(®, TX_DMA_DST_CSR_DEST_AC3, 2); - rt2x00_set_field32(®, TX_DMA_DST_CSR_DEST_MGMT, 0); rt2x00pci_register_write(rt2x00dev, TX_DMA_DST_CSR, reg); rt2x00pci_register_read(rt2x00dev, LOAD_TX_RING_CSR, ®); @@ -1078,7 +1077,6 @@ static int rt61pci_init_queues(struct rt2x00_dev *rt2x00dev) rt2x00_set_field32(®, LOAD_TX_RING_CSR_LOAD_TXD_AC1, 1); rt2x00_set_field32(®, LOAD_TX_RING_CSR_LOAD_TXD_AC2, 1); rt2x00_set_field32(®, LOAD_TX_RING_CSR_LOAD_TXD_AC3, 1); - rt2x00_set_field32(®, LOAD_TX_RING_CSR_LOAD_TXD_MGMT, 0); rt2x00pci_register_write(rt2x00dev, LOAD_TX_RING_CSR, reg); rt2x00pci_register_read(rt2x00dev, RX_CNTL_CSR, ®); diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h index d291c0fe405c..2f9a8899a3e8 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.h +++ b/drivers/net/wireless/rt2x00/rt61pci.h @@ -880,7 +880,7 @@ struct hw_pairwise_ta_entry { #define TX_CNTL_CSR_ABORT_TX_MGMT FIELD32(0x00100000) /* - * LOAD_TX_RING_CSR: Load RX de + * LOAD_TX_RING_CSR: Load RX desriptor */ #define LOAD_TX_RING_CSR 0x3434 #define LOAD_TX_RING_CSR_LOAD_TXD_AC0 FIELD32(0x00000001) -- cgit v1.2.1 From 231be4e92cc0398781e6acda0e3f8ea54a7fa10f Mon Sep 17 00:00:00 2001 From: Adam Baker Date: Sun, 10 Feb 2008 22:48:19 +0100 Subject: rt2x00: correct address calc for queue private data When calculating the offset to add to the queue entry base to get the individual entry's private data area the base address must be treated as a char * not a struct queue_entry so we can do byte oriented pointer arithmetic with it. Signed-off-by: Adam Baker Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00queue.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index fde64ea3f4ef..943afc9067b1 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -160,7 +160,8 @@ static int rt2x00queue_alloc_entries(struct data_queue *queue, return -ENOMEM; #define QUEUE_ENTRY_PRIV_OFFSET(__base, __index, __limit, __esize, __psize) \ - ( (__base) + ((__limit) * (__esize)) + ((__index) * (__psize)) ) + ( ((char *)(__base)) + ((__limit) * (__esize)) + \ + ((__index) * (__psize)) ) for (i = 0; i < queue->limit; i++) { entries[i].flags = 0; -- cgit v1.2.1 From f590f48e87d1e61c03f01fa15be00e852c05426d Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 10 Feb 2008 22:48:47 +0100 Subject: rt2x00: Select CONFIG_NEW_LEDS Select CONFIG_NEW_LEDS before selecting the other LED config options. This fixes a link error when NEW_LEDS was disabled. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index 96d6fc68fe01..108b85e295ba 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig @@ -40,6 +40,7 @@ config RT2X00_LIB_RFKILL config RT2X00_LIB_LEDS boolean depends on RT2X00_LIB + select NEW_LEDS select LEDS_CLASS select LEDS_TRIGGERS select MAC80211_LEDS -- cgit v1.2.1 From 21795094e2b71b4b11bfb468321046c1336cef69 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 10 Feb 2008 22:49:13 +0100 Subject: rt2x00: make csr_cache and csr_addr an union The csr_cache and csr_addr pointers are both the same size and they are never used both by the same driver. This makes them a nice candidate for an union. We could merge into 1 pointer, but that would either upset sparse, or require a lot of __force casts. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00.h | 10 ++++++---- drivers/net/wireless/rt2x00/rt2x00pci.c | 10 +++++----- drivers/net/wireless/rt2x00/rt2x00pci.h | 8 ++++---- drivers/net/wireless/rt2x00/rt2x00usb.c | 16 ++++++++-------- 4 files changed, 23 insertions(+), 21 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index f6ec9fe23096..9098532e046a 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -707,11 +707,13 @@ struct rt2x00_dev { /* * Register pointers - * csr_addr: Base register address. (PCI) - * csr_cache: CSR cache for usb_control_msg. (USB) + * csr.base: CSR base register address. (PCI) + * csr.cache: CSR cache for usb_control_msg. (USB) */ - void __iomem *csr_addr; - void *csr_cache; + union csr { + void __iomem *base; + void *cache; + } csr; /* * Mutex to protect register accesses on USB devices. diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index 238f1c1e4ad0..b8c6a8c9d6d2 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c @@ -350,9 +350,9 @@ static void rt2x00pci_free_reg(struct rt2x00_dev *rt2x00dev) kfree(rt2x00dev->eeprom); rt2x00dev->eeprom = NULL; - if (rt2x00dev->csr_addr) { - iounmap(rt2x00dev->csr_addr); - rt2x00dev->csr_addr = NULL; + if (rt2x00dev->csr.base) { + iounmap(rt2x00dev->csr.base); + rt2x00dev->csr.base = NULL; } } @@ -360,9 +360,9 @@ static int rt2x00pci_alloc_reg(struct rt2x00_dev *rt2x00dev) { struct pci_dev *pci_dev = rt2x00dev_pci(rt2x00dev); - rt2x00dev->csr_addr = ioremap(pci_resource_start(pci_dev, 0), + rt2x00dev->csr.base = ioremap(pci_resource_start(pci_dev, 0), pci_resource_len(pci_dev, 0)); - if (!rt2x00dev->csr_addr) + if (!rt2x00dev->csr.base) goto exit; rt2x00dev->eeprom = kzalloc(rt2x00dev->ops->eeprom_size, GFP_KERNEL); diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.h b/drivers/net/wireless/rt2x00/rt2x00pci.h index 71335e16b058..8932b31d2624 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.h +++ b/drivers/net/wireless/rt2x00/rt2x00pci.h @@ -61,7 +61,7 @@ static inline void rt2x00pci_register_read(struct rt2x00_dev *rt2x00dev, const unsigned long offset, u32 *value) { - *value = readl(rt2x00dev->csr_addr + offset); + *value = readl(rt2x00dev->csr.base + offset); } static inline void @@ -69,14 +69,14 @@ rt2x00pci_register_multiread(struct rt2x00_dev *rt2x00dev, const unsigned long offset, void *value, const u16 length) { - memcpy_fromio(value, rt2x00dev->csr_addr + offset, length); + memcpy_fromio(value, rt2x00dev->csr.base + offset, length); } static inline void rt2x00pci_register_write(struct rt2x00_dev *rt2x00dev, const unsigned long offset, u32 value) { - writel(value, rt2x00dev->csr_addr + offset); + writel(value, rt2x00dev->csr.base + offset); } static inline void @@ -84,7 +84,7 @@ rt2x00pci_register_multiwrite(struct rt2x00_dev *rt2x00dev, const unsigned long offset, void *value, const u16 length) { - memcpy_toio(rt2x00dev->csr_addr + offset, value, length); + memcpy_toio(rt2x00dev->csr.base + offset, value, length); } /* diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 44ab2167c6ee..4219057d85cb 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -84,20 +84,20 @@ int rt2x00usb_vendor_req_buff_lock(struct rt2x00_dev *rt2x00dev, /* * Check for Cache availability. */ - if (unlikely(!rt2x00dev->csr_cache || buffer_length > CSR_CACHE_SIZE)) { + if (unlikely(!rt2x00dev->csr.cache || buffer_length > CSR_CACHE_SIZE)) { ERROR(rt2x00dev, "CSR cache not available.\n"); return -ENOMEM; } if (requesttype == USB_VENDOR_REQUEST_OUT) - memcpy(rt2x00dev->csr_cache, buffer, buffer_length); + memcpy(rt2x00dev->csr.cache, buffer, buffer_length); status = rt2x00usb_vendor_request(rt2x00dev, request, requesttype, - offset, 0, rt2x00dev->csr_cache, + offset, 0, rt2x00dev->csr.cache, buffer_length, timeout); if (!status && requesttype == USB_VENDOR_REQUEST_IN) - memcpy(buffer, rt2x00dev->csr_cache, buffer_length); + memcpy(buffer, rt2x00dev->csr.cache, buffer_length); return status; } @@ -562,14 +562,14 @@ static void rt2x00usb_free_reg(struct rt2x00_dev *rt2x00dev) kfree(rt2x00dev->eeprom); rt2x00dev->eeprom = NULL; - kfree(rt2x00dev->csr_cache); - rt2x00dev->csr_cache = NULL; + kfree(rt2x00dev->csr.cache); + rt2x00dev->csr.cache = NULL; } static int rt2x00usb_alloc_reg(struct rt2x00_dev *rt2x00dev) { - rt2x00dev->csr_cache = kzalloc(CSR_CACHE_SIZE, GFP_KERNEL); - if (!rt2x00dev->csr_cache) + rt2x00dev->csr.cache = kzalloc(CSR_CACHE_SIZE, GFP_KERNEL); + if (!rt2x00dev->csr.cache) goto exit; rt2x00dev->eeprom = kzalloc(rt2x00dev->ops->eeprom_size, GFP_KERNEL); -- cgit v1.2.1 From e44df9296a8ab9d9160e230d68a1b01015c94e93 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 10 Feb 2008 22:50:04 +0100 Subject: rt2x00: Fix scheduling while atomic errors in usb drivers Call rt2x00_config_intf() outside of the spinlock context since the call will sleep for USB drivers. By using the ieee80211_if_conf values as arguments we make keep access tp rt2x00_intf thread safe even without the lock. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00mac.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 8c24d3b36d28..91b62ddbf9f0 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -334,10 +334,17 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw, */ if (conf->type != IEEE80211_IF_TYPE_AP) memcpy(&intf->bssid, conf->bssid, ETH_ALEN); - rt2x00lib_config_intf(rt2x00dev, intf, conf->type, NULL, intf->bssid); spin_unlock(&intf->lock); + /* + * Call rt2x00_config_intf() outside of the spinlock context since + * the call will sleep for USB drivers. By using the ieee80211_if_conf + * values as arguments we make keep access to rt2x00_intf thread safe + * even without the lock. + */ + rt2x00lib_config_intf(rt2x00dev, intf, conf->type, NULL, conf->bssid); + /* * We only need to initialize the beacon when master mode is enabled. */ -- cgit v1.2.1 From 68598d294b6bc1ecc418359994234cb43f4635ad Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 10 Feb 2008 22:50:28 +0100 Subject: rt2x00: Add queue statistics to debugfs Rename "frame" folder to "queue" folder, add extra file to this folder which contains statistics about all hardware queues. This will help debugging and spotting problems in the queue indexing system. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00debug.c | 90 ++++++++++++++++++++++++++----- 1 file changed, 76 insertions(+), 14 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c index 4e048ac0a684..21af11a97334 100644 --- a/drivers/net/wireless/rt2x00/rt2x00debug.c +++ b/drivers/net/wireless/rt2x00/rt2x00debug.c @@ -33,7 +33,7 @@ #include "rt2x00lib.h" #include "rt2x00dump.h" -#define PRINT_LINE_LEN_MAX 32 +#define MAX_LINE_LENGTH 64 struct rt2x00debug_intf { /* @@ -60,8 +60,9 @@ struct rt2x00debug_intf { * - eeprom offset/value files * - bbp offset/value files * - rf offset/value files - * - frame dump folder + * - queue folder * - frame dump file + * - queue stats file */ struct dentry *driver_folder; struct dentry *driver_entry; @@ -76,8 +77,9 @@ struct rt2x00debug_intf { struct dentry *bbp_val_entry; struct dentry *rf_off_entry; struct dentry *rf_val_entry; - struct dentry *frame_folder; - struct dentry *frame_dump_entry; + struct dentry *queue_folder; + struct dentry *queue_frame_dump_entry; + struct dentry *queue_stats_entry; /* * The frame dump file only allows a single reader, @@ -269,6 +271,61 @@ static const struct file_operations rt2x00debug_fop_queue_dump = { .release = rt2x00debug_release_queue_dump, }; +static ssize_t rt2x00debug_read_queue_stats(struct file *file, + char __user *buf, + size_t length, + loff_t *offset) +{ + struct rt2x00debug_intf *intf = file->private_data; + struct data_queue *queue; + unsigned int lines = 1 + intf->rt2x00dev->data_queues; + size_t size; + char *data; + char *temp; + + if (*offset) + return 0; + + data = kzalloc(lines * MAX_LINE_LENGTH, GFP_KERNEL); + if (!data) + return -ENOMEM; + + temp = data + + sprintf(data, "qid\tcount\tlimit\tlength\tindex\tdone\tcrypto\n"); + + queue_for_each(intf->rt2x00dev, queue) { + spin_lock(&queue->lock); + + temp += sprintf(temp, "%d\t%d\t%d\t%d\t%d\t%d\t%d\n", queue->qid, + queue->count, queue->limit, queue->length, + queue->index[Q_INDEX], + queue->index[Q_INDEX_DONE], + queue->index[Q_INDEX_CRYPTO]); + + spin_unlock(&queue->lock); + } + + size = strlen(data); + size = min(size, length); + + if (copy_to_user(buf, data, size)) { + kfree(data); + return -EFAULT; + } + + kfree(data); + + *offset += size; + return size; +} + +static const struct file_operations rt2x00debug_fop_queue_stats = { + .owner = THIS_MODULE, + .read = rt2x00debug_read_queue_stats, + .open = rt2x00debug_file_open, + .release = rt2x00debug_file_release, +}; + #define RT2X00DEBUGFS_OPS_READ(__name, __format, __type) \ static ssize_t rt2x00debug_read_##__name(struct file *file, \ char __user *buf, \ @@ -386,7 +443,7 @@ static struct dentry *rt2x00debug_create_file_driver(const char *name, { char *data; - data = kzalloc(3 * PRINT_LINE_LEN_MAX, GFP_KERNEL); + data = kzalloc(3 * MAX_LINE_LENGTH, GFP_KERNEL); if (!data) return NULL; @@ -409,7 +466,7 @@ static struct dentry *rt2x00debug_create_file_chipset(const char *name, const struct rt2x00debug *debug = intf->debug; char *data; - data = kzalloc(8 * PRINT_LINE_LEN_MAX, GFP_KERNEL); + data = kzalloc(8 * MAX_LINE_LENGTH, GFP_KERNEL); if (!data) return NULL; @@ -496,20 +553,24 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev) #undef RT2X00DEBUGFS_CREATE_REGISTER_ENTRY - intf->frame_folder = - debugfs_create_dir("frame", intf->driver_folder); - if (IS_ERR(intf->frame_folder)) + intf->queue_folder = + debugfs_create_dir("queue", intf->driver_folder); + if (IS_ERR(intf->queue_folder)) goto exit; - intf->frame_dump_entry = - debugfs_create_file("dump", S_IRUGO, intf->frame_folder, + intf->queue_frame_dump_entry = + debugfs_create_file("dump", S_IRUGO, intf->queue_folder, intf, &rt2x00debug_fop_queue_dump); - if (IS_ERR(intf->frame_dump_entry)) + if (IS_ERR(intf->queue_frame_dump_entry)) goto exit; skb_queue_head_init(&intf->frame_dump_skbqueue); init_waitqueue_head(&intf->frame_dump_waitqueue); + intf->queue_stats_entry = + debugfs_create_file("queue", S_IRUGO, intf->queue_folder, + intf, &rt2x00debug_fop_queue_stats); + return; exit: @@ -528,8 +589,9 @@ void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev) skb_queue_purge(&intf->frame_dump_skbqueue); - debugfs_remove(intf->frame_dump_entry); - debugfs_remove(intf->frame_folder); + debugfs_remove(intf->queue_stats_entry); + debugfs_remove(intf->queue_frame_dump_entry); + debugfs_remove(intf->queue_folder); debugfs_remove(intf->rf_val_entry); debugfs_remove(intf->rf_off_entry); debugfs_remove(intf->bbp_val_entry); -- cgit v1.2.1 From 417f412f2dfae016e29bb128bece60bf75d94d48 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 10 Feb 2008 22:50:58 +0100 Subject: rt2x00: Fix typo in debug statement The second eeprom recovery message is about the RSSI offset for ieee802.11 A. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt61pci.c | 2 +- drivers/net/wireless/rt2x00/rt73usb.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index a8ec910e5475..6e7cbe8f4e32 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -1880,7 +1880,7 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev) rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_1, 0); rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_2, 0); rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_A, word); - EEPROM(rt2x00dev, "RSSI OFFSET BG: 0x%04x\n", word); + EEPROM(rt2x00dev, "RSSI OFFSET A: 0x%04x\n", word); } else { value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_A_1); if (value < -10 || value > 10) diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index f910d83e88f2..d2096d2dd993 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -1500,7 +1500,7 @@ static int rt73usb_validate_eeprom(struct rt2x00_dev *rt2x00dev) rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_1, 0); rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_2, 0); rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_A, word); - EEPROM(rt2x00dev, "RSSI OFFSET BG: 0x%04x\n", word); + EEPROM(rt2x00dev, "RSSI OFFSET A: 0x%04x\n", word); } else { value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_A_1); if (value < -10 || value > 10) -- cgit v1.2.1 From 647d0ca905f7d975e0bf41f571de6f443c814913 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 10 Feb 2008 22:51:21 +0100 Subject: rt2x00: Fix skbdesc->data_len initialization skbdesc->data_len was not initialized correctly in rt2x00pci, rt2x00usb, rt2500usb and rt73usb. The value was set to queue->data_size which means that the incorrect frame size was pased to the upper layers. Correctly base the value on either the skb->len, or the rx frame size passed to the driver by the device. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2500usb.c | 2 +- drivers/net/wireless/rt2x00/rt2x00pci.c | 4 ++-- drivers/net/wireless/rt2x00/rt2x00usb.c | 2 +- drivers/net/wireless/rt2x00/rt73usb.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index ab6e3f7f0f61..f9d6f539a80f 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1149,7 +1149,7 @@ static void rt2500usb_fill_rxdone(struct queue_entry *entry, * Set descriptor pointer. */ skbdesc->data = entry->skb->data; - skbdesc->data_len = entry->queue->data_size; + skbdesc->data_len = rxdesc->size; skbdesc->desc = entry->skb->data + rxdesc->size; skbdesc->desc_len = entry->queue->desc_size; diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index b8c6a8c9d6d2..8f88ca23c23a 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c @@ -63,7 +63,7 @@ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev, skbdesc = get_skb_frame_desc(skb); memset(skbdesc, 0, sizeof(*skbdesc)); skbdesc->data = skb->data; - skbdesc->data_len = queue->data_size; + skbdesc->data_len = skb->len; skbdesc->desc = priv_tx->desc; skbdesc->desc_len = queue->desc_size; skbdesc->entry = entry; @@ -131,7 +131,7 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) skbdesc = get_skb_frame_desc(entry->skb); memset(skbdesc, 0, sizeof(*skbdesc)); skbdesc->data = entry->skb->data; - skbdesc->data_len = queue->data_size; + skbdesc->data_len = entry->skb->len; skbdesc->desc = priv_rx->desc; skbdesc->desc_len = queue->desc_size; skbdesc->entry = entry; diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 4219057d85cb..450043b61773 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -254,7 +254,7 @@ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev, skbdesc = get_skb_frame_desc(skb); memset(skbdesc, 0, sizeof(*skbdesc)); skbdesc->data = skb->data + queue->desc_size; - skbdesc->data_len = queue->data_size; + skbdesc->data_len = skb->len - queue->desc_size; skbdesc->desc = skb->data; skbdesc->desc_len = queue->desc_size; skbdesc->entry = entry; diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index d2096d2dd993..5f3f74c23463 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -1399,7 +1399,7 @@ static void rt73usb_fill_rxdone(struct queue_entry *entry, * Set descriptor and data pointer. */ skbdesc->data = entry->skb->data + entry->queue->desc_size; - skbdesc->data_len = entry->queue->data_size; + skbdesc->data_len = rxdesc->size; skbdesc->desc = entry->skb->data; skbdesc->desc_len = entry->queue->desc_size; -- cgit v1.2.1 From 8f539276ee97bd174f644fb6c18bb9965b596032 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 10 Feb 2008 22:51:41 +0100 Subject: rt2x00: Fix queue->qid initialization As Adam Baker reported the queue->qid was not initialized correctly. The QID_AC_BE was assigned to the RX ring. This will move the queue initialization into a seperate function and makes sure that all queues are initialized directly with the correct qids. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00queue.c | 33 +++++++++++++++++-------------- 1 file changed, 18 insertions(+), 15 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 943afc9067b1..9188323f067b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -228,6 +228,18 @@ void rt2x00queue_uninitialize(struct rt2x00_dev *rt2x00dev) } } +static void rt2x00queue_init(struct rt2x00_dev *rt2x00dev, + struct data_queue *queue, enum data_queue_qid qid) +{ + spin_lock_init(&queue->lock); + + queue->rt2x00dev = rt2x00dev; + queue->qid = qid; + queue->aifs = 2; + queue->cw_min = 5; + queue->cw_max = 10; +} + int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev) { struct data_queue *queue; @@ -265,24 +277,15 @@ int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev) * TX: cw_max: 2^10 = 1024. * BCN & Atim: qid = QID_MGMT */ - qid = QID_AC_BE; - queue_for_each(rt2x00dev, queue) { - spin_lock_init(&queue->lock); + rt2x00queue_init(rt2x00dev, rt2x00dev->rx, QID_RX); - queue->rt2x00dev = rt2x00dev; - queue->qid = qid++; - queue->aifs = 2; - queue->cw_min = 5; - queue->cw_max = 10; - } + qid = QID_AC_BE; + tx_queue_for_each(rt2x00dev, queue) + rt2x00queue_init(rt2x00dev, queue, qid++); - /* - * Fix non-TX data qid's - */ - rt2x00dev->rx->qid = QID_RX; - rt2x00dev->bcn[0].qid = QID_MGMT; + rt2x00queue_init(rt2x00dev, &rt2x00dev->bcn[0], QID_MGMT); if (req_atim) - rt2x00dev->bcn[1].qid = QID_MGMT; + rt2x00queue_init(rt2x00dev, &rt2x00dev->bcn[1], QID_MGMT); return 0; } -- cgit v1.2.1 From c1aa3dc7acc6b97a6251f9d000494569d57fddca Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 10 Feb 2008 22:52:10 +0100 Subject: rt2x00: Cleanup Makefile Simplify the way rt2x00 assigns new objects to the rt2x00lib module. This saves a few if statements and overall does this looks much nicer. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/Makefile | 41 ++++++++++++++---------------------- 1 file changed, 16 insertions(+), 25 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/Makefile b/drivers/net/wireless/rt2x00/Makefile index 757bbc077d93..1087dbcf1a04 100644 --- a/drivers/net/wireless/rt2x00/Makefile +++ b/drivers/net/wireless/rt2x00/Makefile @@ -1,26 +1,17 @@ -rt2x00lib-objs := rt2x00dev.o rt2x00mac.o rt2x00config.o rt2x00queue.o +rt2x00lib-y += rt2x00dev.o +rt2x00lib-y += rt2x00mac.o +rt2x00lib-y += rt2x00config.o +rt2x00lib-y += rt2x00queue.o +rt2x00lib-$(CONFIG_RT2X00_LIB_DEBUGFS) += rt2x00debug.o +rt2x00lib-$(CONFIG_RT2X00_LIB_RFKILL) += rt2x00rfkill.o +rt2x00lib-$(CONFIG_RT2X00_LIB_FIRMWARE) += rt2x00firmware.o +rt2x00lib-$(CONFIG_RT2X00_LIB_LEDS) += rt2x00leds.o -ifeq ($(CONFIG_RT2X00_LIB_DEBUGFS),y) - rt2x00lib-objs += rt2x00debug.o -endif - -ifeq ($(CONFIG_RT2X00_LIB_RFKILL),y) - rt2x00lib-objs += rt2x00rfkill.o -endif - -ifeq ($(CONFIG_RT2X00_LIB_FIRMWARE),y) - rt2x00lib-objs += rt2x00firmware.o -endif - -ifeq ($(CONFIG_RT2X00_LIB_LEDS),y) - rt2x00lib-objs += rt2x00leds.o -endif - -obj-$(CONFIG_RT2X00_LIB) += rt2x00lib.o -obj-$(CONFIG_RT2X00_LIB_PCI) += rt2x00pci.o -obj-$(CONFIG_RT2X00_LIB_USB) += rt2x00usb.o -obj-$(CONFIG_RT2400PCI) += rt2400pci.o -obj-$(CONFIG_RT2500PCI) += rt2500pci.o -obj-$(CONFIG_RT61PCI) += rt61pci.o -obj-$(CONFIG_RT2500USB) += rt2500usb.o -obj-$(CONFIG_RT73USB) += rt73usb.o +obj-$(CONFIG_RT2X00_LIB) += rt2x00lib.o +obj-$(CONFIG_RT2X00_LIB_PCI) += rt2x00pci.o +obj-$(CONFIG_RT2X00_LIB_USB) += rt2x00usb.o +obj-$(CONFIG_RT2400PCI) += rt2400pci.o +obj-$(CONFIG_RT2500PCI) += rt2500pci.o +obj-$(CONFIG_RT61PCI) += rt61pci.o +obj-$(CONFIG_RT2500USB) += rt2500usb.o +obj-$(CONFIG_RT73USB) += rt73usb.o -- cgit v1.2.1 From 330e3f95b30d9616edd6df7646473179c159c00d Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 10 Feb 2008 22:52:36 +0100 Subject: rt2x00: Kill guardian urb during disable_radio When the radio is being disabled we should also kill the guardian urb which could still be pending in the device. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00usb.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 450043b61773..6cb4432e1ee0 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -378,6 +378,7 @@ void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev) { struct queue_entry_priv_usb_rx *priv_rx; struct queue_entry_priv_usb_tx *priv_tx; + struct queue_entry_priv_usb_bcn *priv_bcn; struct data_queue *queue; unsigned int i; @@ -392,12 +393,28 @@ void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev) usb_kill_urb(priv_rx->urb); } - txall_queue_for_each(rt2x00dev, queue) { + tx_queue_for_each(rt2x00dev, queue) { for (i = 0; i < queue->limit; i++) { priv_tx = queue->entries[i].priv_data; usb_kill_urb(priv_tx->urb); } } + + for (i = 0; i < rt2x00dev->bcn->limit; i++) { + priv_bcn = rt2x00dev->bcn->entries[i].priv_data; + usb_kill_urb(priv_bcn->urb); + + if (priv_bcn->guardian_urb) + usb_kill_urb(priv_bcn->guardian_urb); + } + + if (!test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags)) + return; + + for (i = 0; i < rt2x00dev->bcn[1].limit; i++) { + priv_tx = rt2x00dev->bcn[1].entries[i].priv_data; + usb_kill_urb(priv_tx->urb); + } } EXPORT_SYMBOL_GPL(rt2x00usb_disable_radio); -- cgit v1.2.1 From d3f5feaa5196049906f34c299fba8e3eda9c8646 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 10 Feb 2008 22:52:56 +0100 Subject: rt2x00: Release rt2x00 2.1.1 Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 9098532e046a..7a83e0a7dd05 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -44,7 +44,7 @@ /* * Module information. */ -#define DRV_VERSION "2.1.0" +#define DRV_VERSION "2.1.1" #define DRV_PROJECT "http://rt2x00.serialmonkey.com" /* -- cgit v1.2.1 From ac1aa7e4f3c73ecb09fddf59c1924530155d9359 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 17 Feb 2008 17:31:48 +0100 Subject: rt2x00: Send frames out with configured TX power mac80211 sends the txpower to use during config(), we already store it in the rt2x00_dev structure. When writing the descriptor correctly initialize the txpower field with this value to make sure all frames are send out with the correct tx power. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt61pci.c | 4 +--- drivers/net/wireless/rt2x00/rt73usb.c | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 6e7cbe8f4e32..d10273b744e4 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -1504,10 +1504,8 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_desc_write(txd, 2, word); rt2x00_desc_read(txd, 5, &word); -/* XXX: removed for now rt2x00_set_field32(&word, TXD_W5_TX_POWER, - TXPOWER_TO_DEV(control->power_level)); - */ + TXPOWER_TO_DEV(rt2x00dev->tx_power)); rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1); rt2x00_desc_write(txd, 5, word); diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 5f3f74c23463..badae9f18153 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -1240,10 +1240,8 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, rt2x00_desc_write(txd, 2, word); rt2x00_desc_read(txd, 5, &word); -/* XXX: removed for now rt2x00_set_field32(&word, TXD_W5_TX_POWER, - TXPOWER_TO_DEV(control->power_level)); - */ + TXPOWER_TO_DEV(rt2x00dev->tx_power)); rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1); rt2x00_desc_write(txd, 5, word); -- cgit v1.2.1 From baf26a7eae3b05d25dd967b92eb2e09406ed9cf4 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 17 Feb 2008 17:32:08 +0100 Subject: rt2x00: Don't report driver generated frames to tx_status() This adds a new flag for the skb_frame_desc structure which is used to tag rts/cts frames that are generated by the driver. Through the tag we can recognize frames we have generated ourselves, so we don't report their tx status to mac80211. This patch is based on the original patch by Mattias Nissler . Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 1 + drivers/net/wireless/rt2x00/rt2500pci.c | 1 + drivers/net/wireless/rt2x00/rt2500usb.c | 1 + drivers/net/wireless/rt2x00/rt2x00dev.c | 20 ++++++++++++++++---- drivers/net/wireless/rt2x00/rt2x00mac.c | 15 +++++++++++++++ drivers/net/wireless/rt2x00/rt2x00pci.c | 1 - drivers/net/wireless/rt2x00/rt2x00queue.h | 12 +++++++++++- drivers/net/wireless/rt2x00/rt2x00usb.c | 1 - drivers/net/wireless/rt2x00/rt61pci.c | 1 + drivers/net/wireless/rt2x00/rt73usb.c | 1 + 10 files changed, 47 insertions(+), 7 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 23bc51a96dbe..52ccb85fed65 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1531,6 +1531,7 @@ static int rt2400pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, */ skbdesc = get_skb_frame_desc(skb); memset(skbdesc, 0, sizeof(*skbdesc)); + skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED; skbdesc->data = skb->data; skbdesc->data_len = skb->len; skbdesc->desc = priv_tx->desc; diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 529b1841a085..3bf85604ca69 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1843,6 +1843,7 @@ static int rt2500pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, */ skbdesc = get_skb_frame_desc(skb); memset(skbdesc, 0, sizeof(*skbdesc)); + skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED; skbdesc->data = skb->data; skbdesc->data_len = skb->len; skbdesc->desc = priv_tx->desc; diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index f9d6f539a80f..f7dc06a74d1a 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1751,6 +1751,7 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw, */ skbdesc = get_skb_frame_desc(skb); memset(skbdesc, 0, sizeof(*skbdesc)); + skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED; skbdesc->data = skb->data + intf->beacon->queue->desc_size; skbdesc->data_len = skb->len - intf->beacon->queue->desc_size; skbdesc->desc = skb->data; diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index d69f7407b972..6ccbfc7cbf91 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -500,6 +500,7 @@ void rt2x00lib_txdone(struct queue_entry *entry, struct txdone_entry_desc *txdesc) { struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; + struct skb_frame_desc *skbdesc; struct ieee80211_tx_status tx_status; int success = !!(txdesc->status == TX_SUCCESS || txdesc->status == TX_SUCCESS_RETRY); @@ -540,12 +541,23 @@ void rt2x00lib_txdone(struct queue_entry *entry, } /* - * Send the tx_status to mac80211 & debugfs. - * mac80211 will clean up the skb structure. + * Send the tx_status to debugfs. Only send the status report + * to mac80211 when the frame originated from there. If this was + * a extra frame coming through a mac80211 library call (RTS/CTS) + * then we should not send the status report back. + * If send to mac80211, mac80211 will clean up the skb structure, + * otherwise we have to do it ourself. */ - get_skb_frame_desc(entry->skb)->frame_type = DUMP_FRAME_TXDONE; + skbdesc = get_skb_frame_desc(entry->skb); + skbdesc->frame_type = DUMP_FRAME_TXDONE; + rt2x00debug_dump_frame(rt2x00dev, entry->skb); - ieee80211_tx_status_irqsafe(rt2x00dev->hw, entry->skb, &tx_status); + + if (!(skbdesc->flags & FRAME_DESC_DRIVER_GENERATED)) + ieee80211_tx_status_irqsafe(rt2x00dev->hw, + entry->skb, &tx_status); + else + dev_kfree_skb(entry->skb); entry->skb = NULL; } EXPORT_SYMBOL_GPL(rt2x00lib_txdone); diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 91b62ddbf9f0..a54f6873e9ea 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -34,6 +34,7 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev, struct sk_buff *frag_skb, struct ieee80211_tx_control *control) { + struct skb_frame_desc *skbdesc; struct sk_buff *skb; int size; @@ -60,6 +61,13 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev, frag_skb->data, frag_skb->len, control, (struct ieee80211_rts *)(skb->data)); + /* + * Initialize skb descriptor + */ + skbdesc = get_skb_frame_desc(skb); + memset(skbdesc, 0, sizeof(*skbdesc)); + skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED; + if (rt2x00dev->ops->lib->write_tx_data(rt2x00dev, queue, skb, control)) { WARNING(rt2x00dev, "Failed to send RTS/CTS frame.\n"); return NETDEV_TX_BUSY; @@ -74,6 +82,7 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb, struct rt2x00_dev *rt2x00dev = hw->priv; struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data; struct data_queue *queue; + struct skb_frame_desc *skbdesc; u16 frame_control; /* @@ -121,6 +130,12 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb, } } + /* + * Initialize skb descriptor + */ + skbdesc = get_skb_frame_desc(skb); + memset(skbdesc, 0, sizeof(*skbdesc)); + if (rt2x00dev->ops->lib->write_tx_data(rt2x00dev, queue, skb, control)) { ieee80211_stop_queue(rt2x00dev->hw, control->queue); return NETDEV_TX_BUSY; diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index 8f88ca23c23a..7d2f406937cd 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c @@ -61,7 +61,6 @@ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev, * Fill in skb descriptor */ skbdesc = get_skb_frame_desc(skb); - memset(skbdesc, 0, sizeof(*skbdesc)); skbdesc->data = skb->data; skbdesc->data_len = skb->len; skbdesc->desc = priv_tx->desc; diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 956e0be8aadd..fbabf389b622 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -81,13 +81,23 @@ enum rt2x00_bcn_queue { RT2X00_BCN_QUEUE_ATIM = 101, }; +/** + * enum skb_frame_desc_flags: Flags for &struct skb_frame_desc + * + * @FRAME_DESC_DRIVER_GENERATED: Frame was generated inside driver + * and should not be reported back to mac80211 during txdone. + */ +enum skb_frame_desc_flags { + FRAME_DESC_DRIVER_GENERATED = 1 << 0, +}; + /** * struct skb_frame_desc: Descriptor information for the skb buffer * * This structure is placed over the skb->cb array, this means that * this structure should not exceed the size of that array (48 bytes). * - * @flags: Frame flags. + * @flags: Frame flags, see &enum skb_frame_desc_flags. * @frame_type: Frame type, see &enum rt2x00_dump_type. * @data: Pointer to data part of frame (Start of ieee80211 header). * @desc: Pointer to descriptor part of the frame. diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 6cb4432e1ee0..89471b24a443 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -252,7 +252,6 @@ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev, * Fill in skb descriptor */ skbdesc = get_skb_frame_desc(skb); - memset(skbdesc, 0, sizeof(*skbdesc)); skbdesc->data = skb->data + queue->desc_size; skbdesc->data_len = skb->len - queue->desc_size; skbdesc->desc = skb->data; diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index d10273b744e4..357f2c4183f6 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -2400,6 +2400,7 @@ static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, */ skbdesc = get_skb_frame_desc(skb); memset(skbdesc, 0, sizeof(*skbdesc)); + skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED; skbdesc->data = skb->data + intf->beacon->queue->desc_size; skbdesc->data_len = skb->len - intf->beacon->queue->desc_size; skbdesc->desc = skb->data; diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index badae9f18153..afd8533267a7 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -2002,6 +2002,7 @@ static int rt73usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, */ skbdesc = get_skb_frame_desc(skb); memset(skbdesc, 0, sizeof(*skbdesc)); + skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED; skbdesc->data = skb->data + intf->beacon->queue->desc_size; skbdesc->data_len = skb->len - intf->beacon->queue->desc_size; skbdesc->desc = skb->data; -- cgit v1.2.1 From e542239f639fa4e7b13a949d39d44ff1eccf7e3a Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 17 Feb 2008 17:33:13 +0100 Subject: rt2x00: Filter ACK_CTS based on FIF_CONTROL The ACK_CTS frame is a control frame, this means dropping the frame depends on the FIF_CONTROL flag for filtering. This also fixes an obvious typo in register definition. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt61pci.c | 5 +++-- drivers/net/wireless/rt2x00/rt61pci.h | 2 +- drivers/net/wireless/rt2x00/rt73usb.c | 3 ++- 3 files changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 357f2c4183f6..75f61f3c47b6 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -2325,8 +2325,9 @@ static void rt61pci_configure_filter(struct ieee80211_hw *hw, rt2x00_set_field32(®, TXRX_CSR0_DROP_VERSION_ERROR, 1); rt2x00_set_field32(®, TXRX_CSR0_DROP_MULTICAST, !(*total_flags & FIF_ALLMULTI)); - rt2x00_set_field32(®, TXRX_CSR0_DROP_BORADCAST, 0); - rt2x00_set_field32(®, TXRX_CSR0_DROP_ACK_CTS, 1); + rt2x00_set_field32(®, TXRX_CSR0_DROP_BROADCAST, 0); + rt2x00_set_field32(®, TXRX_CSR0_DROP_ACK_CTS, + !(*total_flags & FIF_CONTROL)); rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg); } diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h index 2f9a8899a3e8..d504e70125d5 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.h +++ b/drivers/net/wireless/rt2x00/rt61pci.h @@ -405,7 +405,7 @@ struct hw_pairwise_ta_entry { #define TXRX_CSR0_DROP_TO_DS FIELD32(0x00200000) #define TXRX_CSR0_DROP_VERSION_ERROR FIELD32(0x00400000) #define TXRX_CSR0_DROP_MULTICAST FIELD32(0x00800000) -#define TXRX_CSR0_DROP_BORADCAST FIELD32(0x01000000) +#define TXRX_CSR0_DROP_BROADCAST FIELD32(0x01000000) #define TXRX_CSR0_DROP_ACK_CTS FIELD32(0x02000000) #define TXRX_CSR0_TX_WITHOUT_WAITING FIELD32(0x04000000) diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index afd8533267a7..c3d4e9307785 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -1929,7 +1929,8 @@ static void rt73usb_configure_filter(struct ieee80211_hw *hw, rt2x00_set_field32(®, TXRX_CSR0_DROP_MULTICAST, !(*total_flags & FIF_ALLMULTI)); rt2x00_set_field32(®, TXRX_CSR0_DROP_BROADCAST, 0); - rt2x00_set_field32(®, TXRX_CSR0_DROP_ACK_CTS, 1); + rt2x00_set_field32(®, TXRX_CSR0_DROP_ACK_CTS, + !(*total_flags & FIF_CONTROL)); rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg); } -- cgit v1.2.1 From 30b3a23c2594e122e7086f97b5252a87eaf8a817 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 17 Feb 2008 17:33:24 +0100 Subject: rt2x00: Fix Descriptor DMA initialization As Adam Baker reported the DMA address for the descriptor base was incorrectly initialized in the PCI drivers. Instead of the DMA base for the descriptor, the DMA base for the data was passed resulting in a broken TX/RX state for PCI drivers. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 21 +++++++++++------- drivers/net/wireless/rt2x00/rt2500pci.c | 18 ++++++++++------ drivers/net/wireless/rt2x00/rt2x00pci.c | 38 ++++++++++++++++++--------------- drivers/net/wireless/rt2x00/rt2x00pci.h | 6 ++++-- drivers/net/wireless/rt2x00/rt61pci.c | 21 ++++++++++++------ 5 files changed, 63 insertions(+), 41 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 52ccb85fed65..28663c00b770 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -597,11 +597,12 @@ static void rt2400pci_init_rxentry(struct rt2x00_dev *rt2x00dev, u32 word; rt2x00_desc_read(priv_rx->desc, 2, &word); - rt2x00_set_field32(&word, RXD_W2_BUFFER_LENGTH, entry->queue->data_size); + rt2x00_set_field32(&word, RXD_W2_BUFFER_LENGTH, + entry->queue->data_size); rt2x00_desc_write(priv_rx->desc, 2, word); rt2x00_desc_read(priv_rx->desc, 1, &word); - rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, priv_rx->dma); + rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, priv_rx->data_dma); rt2x00_desc_write(priv_rx->desc, 1, word); rt2x00_desc_read(priv_rx->desc, 0, &word); @@ -616,7 +617,7 @@ static void rt2400pci_init_txentry(struct rt2x00_dev *rt2x00dev, u32 word; rt2x00_desc_read(priv_tx->desc, 1, &word); - rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, priv_tx->dma); + rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, priv_tx->data_dma); rt2x00_desc_write(priv_tx->desc, 1, word); rt2x00_desc_read(priv_tx->desc, 2, &word); @@ -648,22 +649,26 @@ static int rt2400pci_init_queues(struct rt2x00_dev *rt2x00dev) priv_tx = rt2x00dev->tx[1].entries[0].priv_data; rt2x00pci_register_read(rt2x00dev, TXCSR3, ®); - rt2x00_set_field32(®, TXCSR3_TX_RING_REGISTER, priv_tx->dma); + rt2x00_set_field32(®, TXCSR3_TX_RING_REGISTER, + priv_tx->desc_dma); rt2x00pci_register_write(rt2x00dev, TXCSR3, reg); priv_tx = rt2x00dev->tx[0].entries[0].priv_data; rt2x00pci_register_read(rt2x00dev, TXCSR5, ®); - rt2x00_set_field32(®, TXCSR5_PRIO_RING_REGISTER, priv_tx->dma); + rt2x00_set_field32(®, TXCSR5_PRIO_RING_REGISTER, + priv_tx->desc_dma); rt2x00pci_register_write(rt2x00dev, TXCSR5, reg); priv_tx = rt2x00dev->bcn[1].entries[0].priv_data; rt2x00pci_register_read(rt2x00dev, TXCSR4, ®); - rt2x00_set_field32(®, TXCSR4_ATIM_RING_REGISTER, priv_tx->dma); + rt2x00_set_field32(®, TXCSR4_ATIM_RING_REGISTER, + priv_tx->desc_dma); rt2x00pci_register_write(rt2x00dev, TXCSR4, reg); priv_tx = rt2x00dev->bcn[0].entries[0].priv_data; rt2x00pci_register_read(rt2x00dev, TXCSR6, ®); - rt2x00_set_field32(®, TXCSR6_BEACON_RING_REGISTER, priv_tx->dma); + rt2x00_set_field32(®, TXCSR6_BEACON_RING_REGISTER, + priv_tx->desc_dma); rt2x00pci_register_write(rt2x00dev, TXCSR6, reg); rt2x00pci_register_read(rt2x00dev, RXCSR1, ®); @@ -673,7 +678,7 @@ static int rt2400pci_init_queues(struct rt2x00_dev *rt2x00dev) priv_rx = rt2x00dev->rx->entries[0].priv_data; rt2x00pci_register_read(rt2x00dev, RXCSR2, ®); - rt2x00_set_field32(®, RXCSR2_RX_RING_REGISTER, priv_tx->dma); + rt2x00_set_field32(®, RXCSR2_RX_RING_REGISTER, priv_tx->desc_dma); rt2x00pci_register_write(rt2x00dev, RXCSR2, reg); return 0; diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 3bf85604ca69..ec7300e4fc56 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -691,7 +691,7 @@ static void rt2500pci_init_rxentry(struct rt2x00_dev *rt2x00dev, u32 word; rt2x00_desc_read(priv_rx->desc, 1, &word); - rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, priv_rx->dma); + rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, priv_rx->data_dma); rt2x00_desc_write(priv_rx->desc, 1, word); rt2x00_desc_read(priv_rx->desc, 0, &word); @@ -706,7 +706,7 @@ static void rt2500pci_init_txentry(struct rt2x00_dev *rt2x00dev, u32 word; rt2x00_desc_read(priv_tx->desc, 1, &word); - rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, priv_tx->dma); + rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, priv_tx->data_dma); rt2x00_desc_write(priv_tx->desc, 1, word); rt2x00_desc_read(priv_tx->desc, 0, &word); @@ -733,22 +733,26 @@ static int rt2500pci_init_queues(struct rt2x00_dev *rt2x00dev) priv_tx = rt2x00dev->tx[1].entries[0].priv_data; rt2x00pci_register_read(rt2x00dev, TXCSR3, ®); - rt2x00_set_field32(®, TXCSR3_TX_RING_REGISTER, priv_tx->dma); + rt2x00_set_field32(®, TXCSR3_TX_RING_REGISTER, + priv_tx->desc_dma); rt2x00pci_register_write(rt2x00dev, TXCSR3, reg); priv_tx = rt2x00dev->tx[0].entries[0].priv_data; rt2x00pci_register_read(rt2x00dev, TXCSR5, ®); - rt2x00_set_field32(®, TXCSR5_PRIO_RING_REGISTER, priv_tx->dma); + rt2x00_set_field32(®, TXCSR5_PRIO_RING_REGISTER, + priv_tx->desc_dma); rt2x00pci_register_write(rt2x00dev, TXCSR5, reg); priv_tx = rt2x00dev->bcn[1].entries[0].priv_data; rt2x00pci_register_read(rt2x00dev, TXCSR4, ®); - rt2x00_set_field32(®, TXCSR4_ATIM_RING_REGISTER, priv_tx->dma); + rt2x00_set_field32(®, TXCSR4_ATIM_RING_REGISTER, + priv_tx->desc_dma); rt2x00pci_register_write(rt2x00dev, TXCSR4, reg); priv_tx = rt2x00dev->bcn[0].entries[0].priv_data; rt2x00pci_register_read(rt2x00dev, TXCSR6, ®); - rt2x00_set_field32(®, TXCSR6_BEACON_RING_REGISTER, priv_tx->dma); + rt2x00_set_field32(®, TXCSR6_BEACON_RING_REGISTER, + priv_tx->desc_dma); rt2x00pci_register_write(rt2x00dev, TXCSR6, reg); rt2x00pci_register_read(rt2x00dev, RXCSR1, ®); @@ -758,7 +762,7 @@ static int rt2500pci_init_queues(struct rt2x00_dev *rt2x00dev) priv_rx = rt2x00dev->rx->entries[0].priv_data; rt2x00pci_register_read(rt2x00dev, RXCSR2, ®); - rt2x00_set_field32(®, RXCSR2_RX_RING_REGISTER, priv_tx->dma); + rt2x00_set_field32(®, RXCSR2_RX_RING_REGISTER, priv_tx->desc_dma); rt2x00pci_register_write(rt2x00dev, RXCSR2, reg); return 0; diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index 7d2f406937cd..1960d938d73b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c @@ -218,40 +218,44 @@ static int rt2x00pci_alloc_queue_dma(struct rt2x00_dev *rt2x00dev, struct pci_dev *pci_dev = rt2x00dev_pci(rt2x00dev); struct queue_entry_priv_pci_rx *priv_rx; struct queue_entry_priv_pci_tx *priv_tx; - void *desc; + void *addr; + dma_addr_t dma; + void *desc_addr; + dma_addr_t desc_dma; void *data_addr; - void *data; dma_addr_t data_dma; - dma_addr_t dma; unsigned int i; /* * Allocate DMA memory for descriptor and buffer. */ - data_addr = pci_alloc_consistent(pci_dev, dma_size(queue), &data_dma); - if (!data_addr) + addr = pci_alloc_consistent(pci_dev, dma_size(queue), &dma); + if (!addr) return -ENOMEM; - memset(data_addr, 0, dma_size(queue)); + memset(addr, 0, dma_size(queue)); /* * Initialize all queue entries to contain valid addresses. */ for (i = 0; i < queue->limit; i++) { - desc = desc_offset(queue, data_addr, i); - data = data_offset(queue, data_addr, i); - dma = data_offset(queue, data_dma, i); + desc_addr = desc_offset(queue, addr, i); + desc_dma = desc_offset(queue, dma, i); + data_addr = data_offset(queue, addr, i); + data_dma = data_offset(queue, dma, i); if (queue->qid == QID_RX) { priv_rx = queue->entries[i].priv_data; - priv_rx->desc = desc; - priv_rx->data = data; - priv_rx->dma = dma; + priv_rx->desc = desc_addr; + priv_rx->desc_dma = desc_dma; + priv_rx->data = data_addr; + priv_rx->data_dma = data_dma; } else { priv_tx = queue->entries[i].priv_data; - priv_tx->desc = desc; - priv_tx->data = data; - priv_tx->dma = dma; + priv_tx->desc = desc_addr; + priv_tx->desc_dma = desc_dma; + priv_tx->data = data_addr; + priv_tx->data_dma = data_dma; } } @@ -270,13 +274,13 @@ static void rt2x00pci_free_queue_dma(struct rt2x00_dev *rt2x00dev, if (queue->qid == QID_RX) { priv_rx = queue->entries[0].priv_data; data_addr = priv_rx->data; - data_dma = priv_rx->dma; + data_dma = priv_rx->data_dma; priv_rx->data = NULL; } else { priv_tx = queue->entries[0].priv_data; data_addr = priv_tx->data; - data_dma = priv_tx->dma; + data_dma = priv_tx->data_dma; priv_tx->data = NULL; } diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.h b/drivers/net/wireless/rt2x00/rt2x00pci.h index 8932b31d2624..9d1cdb99431c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.h +++ b/drivers/net/wireless/rt2x00/rt2x00pci.h @@ -103,9 +103,10 @@ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev, */ struct queue_entry_priv_pci_rx { __le32 *desc; + dma_addr_t desc_dma; void *data; - dma_addr_t dma; + dma_addr_t data_dma; }; /** @@ -118,9 +119,10 @@ struct queue_entry_priv_pci_rx { */ struct queue_entry_priv_pci_tx { __le32 *desc; + dma_addr_t desc_dma; void *data; - dma_addr_t dma; + dma_addr_t data_dma; struct ieee80211_tx_control control; }; diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 75f61f3c47b6..dcc694eb8b3b 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -975,7 +975,8 @@ static void rt61pci_init_rxentry(struct rt2x00_dev *rt2x00dev, u32 word; rt2x00_desc_read(priv_rx->desc, 5, &word); - rt2x00_set_field32(&word, RXD_W5_BUFFER_PHYSICAL_ADDRESS, priv_rx->dma); + rt2x00_set_field32(&word, RXD_W5_BUFFER_PHYSICAL_ADDRESS, + priv_rx->data_dma); rt2x00_desc_write(priv_rx->desc, 5, word); rt2x00_desc_read(priv_rx->desc, 0, &word); @@ -999,7 +1000,8 @@ static void rt61pci_init_txentry(struct rt2x00_dev *rt2x00dev, rt2x00_desc_write(priv_tx->desc, 5, word); rt2x00_desc_read(priv_tx->desc, 6, &word); - rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS, priv_tx->dma); + rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS, + priv_tx->data_dma); rt2x00_desc_write(priv_tx->desc, 6, word); rt2x00_desc_read(priv_tx->desc, 0, &word); @@ -1035,22 +1037,26 @@ static int rt61pci_init_queues(struct rt2x00_dev *rt2x00dev) priv_tx = rt2x00dev->tx[0].entries[0].priv_data; rt2x00pci_register_read(rt2x00dev, AC0_BASE_CSR, ®); - rt2x00_set_field32(®, AC0_BASE_CSR_RING_REGISTER, priv_tx->dma); + rt2x00_set_field32(®, AC0_BASE_CSR_RING_REGISTER, + priv_tx->desc_dma); rt2x00pci_register_write(rt2x00dev, AC0_BASE_CSR, reg); priv_tx = rt2x00dev->tx[1].entries[0].priv_data; rt2x00pci_register_read(rt2x00dev, AC1_BASE_CSR, ®); - rt2x00_set_field32(®, AC1_BASE_CSR_RING_REGISTER, priv_tx->dma); + rt2x00_set_field32(®, AC1_BASE_CSR_RING_REGISTER, + priv_tx->desc_dma); rt2x00pci_register_write(rt2x00dev, AC1_BASE_CSR, reg); priv_tx = rt2x00dev->tx[2].entries[0].priv_data; rt2x00pci_register_read(rt2x00dev, AC2_BASE_CSR, ®); - rt2x00_set_field32(®, AC2_BASE_CSR_RING_REGISTER, priv_tx->dma); + rt2x00_set_field32(®, AC2_BASE_CSR_RING_REGISTER, + priv_tx->desc_dma); rt2x00pci_register_write(rt2x00dev, AC2_BASE_CSR, reg); priv_tx = rt2x00dev->tx[3].entries[0].priv_data; rt2x00pci_register_read(rt2x00dev, AC3_BASE_CSR, ®); - rt2x00_set_field32(®, AC3_BASE_CSR_RING_REGISTER, priv_tx->dma); + rt2x00_set_field32(®, AC3_BASE_CSR_RING_REGISTER, + priv_tx->desc_dma); rt2x00pci_register_write(rt2x00dev, AC3_BASE_CSR, reg); rt2x00pci_register_read(rt2x00dev, RX_RING_CSR, ®); @@ -1062,7 +1068,8 @@ static int rt61pci_init_queues(struct rt2x00_dev *rt2x00dev) priv_rx = rt2x00dev->rx->entries[0].priv_data; rt2x00pci_register_read(rt2x00dev, RX_BASE_CSR, ®); - rt2x00_set_field32(®, RX_BASE_CSR_RING_REGISTER, priv_rx->dma); + rt2x00_set_field32(®, RX_BASE_CSR_RING_REGISTER, + priv_rx->desc_dma); rt2x00pci_register_write(rt2x00dev, RX_BASE_CSR, reg); rt2x00pci_register_read(rt2x00dev, TX_DMA_DST_CSR, ®); -- cgit v1.2.1 From ef8f66cd1d6f360340a73ee7ed0492ff0f5f42ea Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 17 Feb 2008 17:33:57 +0100 Subject: rt2x00: Remove reset_tsf() Specifications indicate the TSF registers are read-only, so there is no point in writing 0 to those registers. As far as I know there isn't another way to reset the TSF registers. So removing these callbacks will notify mac80211 about the lack of support. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 9 --------- drivers/net/wireless/rt2x00/rt2500pci.c | 9 --------- drivers/net/wireless/rt2x00/rt61pci.c | 9 --------- drivers/net/wireless/rt2x00/rt73usb.c | 9 --------- 4 files changed, 36 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 28663c00b770..6c025cf32423 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1510,14 +1510,6 @@ static u64 rt2400pci_get_tsf(struct ieee80211_hw *hw) return tsf; } -static void rt2400pci_reset_tsf(struct ieee80211_hw *hw) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - - rt2x00pci_register_write(rt2x00dev, CSR16, 0); - rt2x00pci_register_write(rt2x00dev, CSR17, 0); -} - static int rt2400pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, struct ieee80211_tx_control *control) { @@ -1586,7 +1578,6 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = { .conf_tx = rt2400pci_conf_tx, .get_tx_stats = rt2x00mac_get_tx_stats, .get_tsf = rt2400pci_get_tsf, - .reset_tsf = rt2400pci_reset_tsf, .beacon_update = rt2400pci_beacon_update, .tx_last_beacon = rt2400pci_tx_last_beacon, }; diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index ec7300e4fc56..93eaba852e5d 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1821,14 +1821,6 @@ static u64 rt2500pci_get_tsf(struct ieee80211_hw *hw) return tsf; } -static void rt2500pci_reset_tsf(struct ieee80211_hw *hw) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - - rt2x00pci_register_write(rt2x00dev, CSR16, 0); - rt2x00pci_register_write(rt2x00dev, CSR17, 0); -} - static int rt2500pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, struct ieee80211_tx_control *control) { @@ -1897,7 +1889,6 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = { .conf_tx = rt2x00mac_conf_tx, .get_tx_stats = rt2x00mac_get_tx_stats, .get_tsf = rt2500pci_get_tsf, - .reset_tsf = rt2500pci_reset_tsf, .beacon_update = rt2500pci_beacon_update, .tx_last_beacon = rt2500pci_tx_last_beacon, }; diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index dcc694eb8b3b..62d49376c9af 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -2366,14 +2366,6 @@ static u64 rt61pci_get_tsf(struct ieee80211_hw *hw) return tsf; } -static void rt61pci_reset_tsf(struct ieee80211_hw *hw) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - - rt2x00pci_register_write(rt2x00dev, TXRX_CSR12, 0); - rt2x00pci_register_write(rt2x00dev, TXRX_CSR13, 0); -} - static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, struct ieee80211_tx_control *control) { @@ -2450,7 +2442,6 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = { .conf_tx = rt2x00mac_conf_tx, .get_tx_stats = rt2x00mac_get_tx_stats, .get_tsf = rt61pci_get_tsf, - .reset_tsf = rt61pci_reset_tsf, .beacon_update = rt61pci_beacon_update, }; diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index c3d4e9307785..c56540602ad6 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -1972,14 +1972,6 @@ static u64 rt73usb_get_tsf(struct ieee80211_hw *hw) #define rt73usb_get_tsf NULL #endif -static void rt73usb_reset_tsf(struct ieee80211_hw *hw) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - - rt73usb_register_write(rt2x00dev, TXRX_CSR12, 0); - rt73usb_register_write(rt2x00dev, TXRX_CSR13, 0); -} - static int rt73usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, struct ieee80211_tx_control *control) { @@ -2047,7 +2039,6 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = { .conf_tx = rt2x00mac_conf_tx, .get_tx_stats = rt2x00mac_get_tx_stats, .get_tsf = rt73usb_get_tsf, - .reset_tsf = rt73usb_reset_tsf, .beacon_update = rt73usb_beacon_update, }; -- cgit v1.2.1 From de99ff82cdc2e5b596d01000eed9e0d05566f2d7 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 17 Feb 2008 17:34:26 +0100 Subject: rt2x00: Rename dscape -> mac80211 The dscape stack was renamed to mac80211 a long time ago, we are long overdue with fixing all comments to reflect this. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/Kconfig | 2 +- drivers/net/wireless/rt2x00/rt2400pci.h | 6 +++--- drivers/net/wireless/rt2x00/rt2500pci.h | 4 ++-- drivers/net/wireless/rt2x00/rt2500usb.h | 4 ++-- drivers/net/wireless/rt2x00/rt61pci.h | 4 ++-- drivers/net/wireless/rt2x00/rt73usb.h | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index 108b85e295ba..d5240aa06233 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig @@ -5,7 +5,7 @@ config RT2X00 This will enable the experimental support for the Ralink drivers, developed in the rt2x00 project . - These drivers will make use of the Devicescape ieee80211 stack. + These drivers will make use of the mac80211 stack. When building one of the individual drivers, the rt2x00 library will also be created. That library (when the driver is built as diff --git a/drivers/net/wireless/rt2x00/rt2400pci.h b/drivers/net/wireless/rt2x00/rt2400pci.h index 3d59d6621145..da178d44660e 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.h +++ b/drivers/net/wireless/rt2x00/rt2400pci.h @@ -923,13 +923,13 @@ #define RXD_W7_RESERVED FIELD32(0xffffffff) /* - * Macro's for converting txpower from EEPROM to dscape value - * and from dscape value to register value. + * Macro's for converting txpower from EEPROM to mac80211 value + * and from mac80211 value to register value. * NOTE: Logics in rt2400pci for txpower are reversed * compared to the other rt2x00 drivers. A higher txpower * value means that the txpower must be lowered. This is * important when converting the value coming from the - * dscape stack to the rt2400 acceptable value. + * mac80211 stack to the rt2400 acceptable value. */ #define MIN_TXPOWER 31 #define MAX_TXPOWER 62 diff --git a/drivers/net/wireless/rt2x00/rt2500pci.h b/drivers/net/wireless/rt2x00/rt2500pci.h index 0af130ca23c5..13899550465a 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.h +++ b/drivers/net/wireless/rt2x00/rt2500pci.h @@ -1213,8 +1213,8 @@ #define RXD_W10_DROP FIELD32(0x00000001) /* - * Macro's for converting txpower from EEPROM to dscape value - * and from dscape value to register value. + * Macro's for converting txpower from EEPROM to mac80211 value + * and from mac80211 value to register value. */ #define MIN_TXPOWER 0 #define MAX_TXPOWER 31 diff --git a/drivers/net/wireless/rt2x00/rt2500usb.h b/drivers/net/wireless/rt2x00/rt2500usb.h index 647cd2d56ab9..a37a068d0c71 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.h +++ b/drivers/net/wireless/rt2x00/rt2500usb.h @@ -787,8 +787,8 @@ #define RXD_W3_EIV FIELD32(0xffffffff) /* - * Macro's for converting txpower from EEPROM to dscape value - * and from dscape value to register value. + * Macro's for converting txpower from EEPROM to mac80211 value + * and from mac80211 value to register value. */ #define MIN_TXPOWER 0 #define MAX_TXPOWER 31 diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h index d504e70125d5..4ef7ef32d76d 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.h +++ b/drivers/net/wireless/rt2x00/rt61pci.h @@ -1455,8 +1455,8 @@ struct hw_pairwise_ta_entry { #define RXD_W15_RESERVED FIELD32(0xffffffff) /* - * Macro's for converting txpower from EEPROM to dscape value - * and from dscape value to register value. + * Macro's for converting txpower from EEPROM to mac80211 value + * and from mac80211 value to register value. */ #define MIN_TXPOWER 0 #define MAX_TXPOWER 31 diff --git a/drivers/net/wireless/rt2x00/rt73usb.h b/drivers/net/wireless/rt2x00/rt73usb.h index 3f9675655eb9..06d687425fef 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.h +++ b/drivers/net/wireless/rt2x00/rt73usb.h @@ -1023,8 +1023,8 @@ struct hw_pairwise_ta_entry { #define RXD_W5_RESERVED FIELD32(0xffffffff) /* - * Macro's for converting txpower from EEPROM to dscape value - * and from dscape value to register value. + * Macro's for converting txpower from EEPROM to mac80211 value + * and from mac80211 value to register value. */ #define MIN_TXPOWER 0 #define MAX_TXPOWER 31 -- cgit v1.2.1 From 31562e802a72caf0757f351fff563d558d48d087 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 17 Feb 2008 17:35:05 +0100 Subject: rt2x00: Cleanup mode registration Don't wildly pass any number for num_rates to rt2x00lib, instead pass which type of rates are supported (CCK, OFDM). Same for num_modes but then for the 2GHZ and 5GHZ band. This makes the interface look much nicer and makes extending it later easier. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 4 +- drivers/net/wireless/rt2x00/rt2500pci.c | 6 +-- drivers/net/wireless/rt2x00/rt2500usb.c | 6 +-- drivers/net/wireless/rt2x00/rt2x00.h | 38 +++++++++------- drivers/net/wireless/rt2x00/rt2x00dev.c | 80 ++++++++++++++++----------------- drivers/net/wireless/rt2x00/rt2x00lib.h | 5 ++- drivers/net/wireless/rt2x00/rt61pci.c | 6 +-- drivers/net/wireless/rt2x00/rt73usb.c | 8 ++-- 8 files changed, 81 insertions(+), 72 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 6c025cf32423..460ef2fb5104 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1352,8 +1352,8 @@ static void rt2400pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) /* * Initialize hw_mode information. */ - spec->num_modes = 1; - spec->num_rates = 4; + spec->supported_bands = SUPPORT_BAND_2GHZ; + spec->supported_rates = SUPPORT_RATE_CCK; spec->tx_power_a = NULL; spec->tx_power_bg = txpower; spec->tx_power_default = DEFAULT_TXPOWER; diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 93eaba852e5d..ffcd996df064 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1666,8 +1666,8 @@ static void rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) /* * Initialize hw_mode information. */ - spec->num_modes = 2; - spec->num_rates = 12; + spec->supported_bands = SUPPORT_BAND_2GHZ; + spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; spec->tx_power_a = NULL; spec->tx_power_bg = txpower; spec->tx_power_default = DEFAULT_TXPOWER; @@ -1688,9 +1688,9 @@ static void rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525e); spec->channels = rf_vals_bg_2525e; } else if (rt2x00_rf(&rt2x00dev->chip, RF5222)) { + spec->supported_bands |= SUPPORT_BAND_5GHZ; spec->num_channels = ARRAY_SIZE(rf_vals_5222); spec->channels = rf_vals_5222; - spec->num_modes = 3; } } diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index f7dc06a74d1a..826ed692878c 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1586,8 +1586,8 @@ static void rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) /* * Initialize hw_mode information. */ - spec->num_modes = 2; - spec->num_rates = 12; + spec->supported_bands = SUPPORT_BAND_2GHZ; + spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; spec->tx_power_a = NULL; spec->tx_power_bg = txpower; spec->tx_power_default = DEFAULT_TXPOWER; @@ -1608,9 +1608,9 @@ static void rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525e); spec->channels = rf_vals_bg_2525e; } else if (rt2x00_rf(&rt2x00dev->chip, RF5222)) { + spec->supported_bands |= SUPPORT_BAND_5GHZ; spec->num_channels = ARRAY_SIZE(rf_vals_5222); spec->channels = rf_vals_5222; - spec->num_modes = 3; } } diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 7a83e0a7dd05..e315d79b2aec 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -392,30 +392,38 @@ static inline struct rt2x00_intf* vif_to_intf(struct ieee80211_vif *vif) return (struct rt2x00_intf *)vif->drv_priv; } -/* +/** + * struct hw_mode_spec: Hardware specifications structure + * * Details about the supported modes, rates and channels * of a particular chipset. This is used by rt2x00lib * to build the ieee80211_hw_mode array for mac80211. + * + * @supported_bands: Bitmask contained the supported bands (2.4GHz, 5.2GHz). + * @supported_rates: Rate types which are supported (CCK, OFDM). + * @num_channels: Number of supported channels. This is used as array size + * for @tx_power_a, @tx_power_bg and @channels. + * channels: Device/chipset specific channel values (See &struct rf_channel). + * @tx_power_a: TX power values for all 5.2GHz channels (may be NULL). + * @tx_power_bg: TX power values for all 2.4GHz channels (may be NULL). + * @tx_power_default: Default TX power value to use when either + * @tx_power_a or @tx_power_bg is missing. */ struct hw_mode_spec { - /* - * Number of modes, rates and channels. - */ - int num_modes; - int num_rates; - int num_channels; + unsigned int supported_bands; +#define SUPPORT_BAND_2GHZ 0x00000001 +#define SUPPORT_BAND_5GHZ 0x00000002 + + unsigned int supported_rates; +#define SUPPORT_RATE_CCK 0x00000001 +#define SUPPORT_RATE_OFDM 0x00000002 + + unsigned int num_channels; + const struct rf_channel *channels; - /* - * txpower values. - */ const u8 *tx_power_a; const u8 *tx_power_bg; u8 tx_power_default; - - /* - * Device/chipset specific value. - */ - const struct rf_channel *channels; }; /* diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 6ccbfc7cbf91..a644b9a7ca8f 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -767,25 +767,25 @@ EXPORT_SYMBOL_GPL(rt2x00lib_write_tx_desc); */ const struct rt2x00_rate rt2x00_supported_rates[12] = { { - .flags = 0, + .flags = DEV_RATE_CCK, .bitrate = 10, .ratemask = DEV_RATEMASK_1MB, .plcp = 0x00, }, { - .flags = DEV_RATE_SHORT_PREAMBLE, + .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE, .bitrate = 20, .ratemask = DEV_RATEMASK_2MB, .plcp = 0x01, }, { - .flags = DEV_RATE_SHORT_PREAMBLE, + .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE, .bitrate = 55, .ratemask = DEV_RATEMASK_5_5MB, .plcp = 0x02, }, { - .flags = DEV_RATE_SHORT_PREAMBLE, + .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE, .bitrate = 110, .ratemask = DEV_RATEMASK_11MB, .plcp = 0x03, @@ -868,67 +868,64 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev, struct hw_mode_spec *spec) { struct ieee80211_hw *hw = rt2x00dev->hw; - struct ieee80211_supported_band *sbands; struct ieee80211_channel *channels; struct ieee80211_rate *rates; + unsigned int num_rates; unsigned int i; unsigned char tx_power; - sbands = &rt2x00dev->bands[0]; + num_rates = 0; + if (spec->supported_rates & SUPPORT_RATE_CCK) + num_rates += 4; + if (spec->supported_rates & SUPPORT_RATE_OFDM) + num_rates += 8; channels = kzalloc(sizeof(*channels) * spec->num_channels, GFP_KERNEL); if (!channels) return -ENOMEM; - rates = kzalloc(sizeof(*rates) * spec->num_rates, GFP_KERNEL); + rates = kzalloc(sizeof(*rates) * num_rates, GFP_KERNEL); if (!rates) goto exit_free_channels; /* * Initialize Rate list. */ - for (i = 0; i < spec->num_rates; i++) + for (i = 0; i < num_rates; i++) rt2x00lib_rate(&rates[i], i, rt2x00_get_rate(i)); /* * Initialize Channel list. */ for (i = 0; i < spec->num_channels; i++) { - if (spec->channels[i].channel <= 14) - tx_power = spec->tx_power_bg[i]; - else if (spec->tx_power_a) - tx_power = spec->tx_power_a[i]; - else - tx_power = spec->tx_power_default; + if (spec->channels[i].channel <= 14) { + if (spec->tx_power_bg) + tx_power = spec->tx_power_bg[i]; + else + tx_power = spec->tx_power_default; + } else { + if (spec->tx_power_a) + tx_power = spec->tx_power_a[i]; + else + tx_power = spec->tx_power_default; + } rt2x00lib_channel(&channels[i], spec->channels[i].channel, tx_power, i); } /* - * Intitialize 802.11b - * Rates: CCK. - * Channels: 2.4 GHz - */ - if (spec->num_modes > 0) { - sbands[IEEE80211_BAND_2GHZ].n_channels = 14; - sbands[IEEE80211_BAND_2GHZ].n_bitrates = 4; - sbands[IEEE80211_BAND_2GHZ].channels = channels; - sbands[IEEE80211_BAND_2GHZ].bitrates = rates; - hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &rt2x00dev->bands[IEEE80211_BAND_2GHZ]; - } - - /* - * Intitialize 802.11g + * Intitialize 802.11b, 802.11g * Rates: CCK, OFDM. * Channels: 2.4 GHz */ - if (spec->num_modes > 1) { - sbands[IEEE80211_BAND_2GHZ].n_channels = 14; - sbands[IEEE80211_BAND_2GHZ].n_bitrates = spec->num_rates; - sbands[IEEE80211_BAND_2GHZ].channels = channels; - sbands[IEEE80211_BAND_2GHZ].bitrates = rates; - hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &rt2x00dev->bands[IEEE80211_BAND_2GHZ]; + if (spec->supported_bands > SUPPORT_BAND_2GHZ) { + rt2x00dev->bands[IEEE80211_BAND_2GHZ].n_channels = 14; + rt2x00dev->bands[IEEE80211_BAND_2GHZ].n_bitrates = num_rates; + rt2x00dev->bands[IEEE80211_BAND_2GHZ].channels = channels; + rt2x00dev->bands[IEEE80211_BAND_2GHZ].bitrates = rates; + hw->wiphy->bands[IEEE80211_BAND_2GHZ] = + &rt2x00dev->bands[IEEE80211_BAND_2GHZ]; } /* @@ -936,12 +933,15 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev, * Rates: OFDM. * Channels: OFDM, UNII, HiperLAN2. */ - if (spec->num_modes > 2) { - sbands[IEEE80211_BAND_5GHZ].n_channels = spec->num_channels - 14; - sbands[IEEE80211_BAND_5GHZ].n_bitrates = spec->num_rates - 4; - sbands[IEEE80211_BAND_5GHZ].channels = &channels[14]; - sbands[IEEE80211_BAND_5GHZ].bitrates = &rates[4]; - hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &rt2x00dev->bands[IEEE80211_BAND_5GHZ]; + if (spec->supported_bands > SUPPORT_BAND_5GHZ) { + rt2x00dev->bands[IEEE80211_BAND_5GHZ].n_channels = + spec->num_channels - 14; + rt2x00dev->bands[IEEE80211_BAND_5GHZ].n_bitrates = + num_rates - 4; + rt2x00dev->bands[IEEE80211_BAND_5GHZ].channels = &channels[14]; + rt2x00dev->bands[IEEE80211_BAND_5GHZ].bitrates = &rates[4]; + hw->wiphy->bands[IEEE80211_BAND_5GHZ] = + &rt2x00dev->bands[IEEE80211_BAND_5GHZ]; } return 0; diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index 2a611e4366b5..34ccb3de687e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -38,8 +38,9 @@ */ struct rt2x00_rate { unsigned short flags; -#define DEV_RATE_OFDM 0x0001 -#define DEV_RATE_SHORT_PREAMBLE 0x0002 +#define DEV_RATE_CCK 0x0001 +#define DEV_RATE_OFDM 0x0002 +#define DEV_RATE_SHORT_PREAMBLE 0x0004 unsigned short bitrate; /* In 100kbit/s */ diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 62d49376c9af..d08349bed050 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -2209,8 +2209,8 @@ static void rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) /* * Initialize hw_mode information. */ - spec->num_modes = 2; - spec->num_rates = 12; + spec->supported_bands = SUPPORT_BAND_2GHZ; + spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; spec->tx_power_a = NULL; spec->tx_power_bg = txpower; spec->tx_power_default = DEFAULT_TXPOWER; @@ -2225,7 +2225,7 @@ static void rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) if (rt2x00_rf(&rt2x00dev->chip, RF5225) || rt2x00_rf(&rt2x00dev->chip, RF5325)) { - spec->num_modes = 3; + spec->supported_bands |= SUPPORT_BAND_5GHZ; spec->num_channels = ARRAY_SIZE(rf_vals_seq); txpower = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START); diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index c56540602ad6..bf2391b89571 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -1791,8 +1791,8 @@ static void rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) /* * Initialize hw_mode information. */ - spec->num_modes = 2; - spec->num_rates = 12; + spec->supported_bands = SUPPORT_BAND_2GHZ; + spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; spec->tx_power_a = NULL; spec->tx_power_bg = txpower; spec->tx_power_default = DEFAULT_TXPOWER; @@ -1801,20 +1801,20 @@ static void rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) spec->num_channels = ARRAY_SIZE(rf_vals_bg_2528); spec->channels = rf_vals_bg_2528; } else if (rt2x00_rf(&rt2x00dev->chip, RF5226)) { + spec->supported_bands |= SUPPORT_BAND_5GHZ; spec->num_channels = ARRAY_SIZE(rf_vals_5226); spec->channels = rf_vals_5226; } else if (rt2x00_rf(&rt2x00dev->chip, RF2527)) { spec->num_channels = 14; spec->channels = rf_vals_5225_2527; } else if (rt2x00_rf(&rt2x00dev->chip, RF5225)) { + spec->supported_bands |= SUPPORT_BAND_5GHZ; spec->num_channels = ARRAY_SIZE(rf_vals_5225_2527); spec->channels = rf_vals_5225_2527; } if (rt2x00_rf(&rt2x00dev->chip, RF5225) || rt2x00_rf(&rt2x00dev->chip, RF5226)) { - spec->num_modes = 3; - txpower = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START); for (i = 0; i < 14; i++) txpower[i] = TXPOWER_FROM_DEV(txpower[i]); -- cgit v1.2.1 From 47b10cd1375855dbc6675a176c71a512ac4b7317 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 17 Feb 2008 17:35:28 +0100 Subject: rt2x00: Remove async vendor request calls from rt2x00usb The async vendor requests are a ugly hack which is not working correctly. The proper fix for the scheduling while atomic issue is finding out why we can't use led classes for USB drivers and fix that. Just replace all async calls with the regular ones and print an error for the disallowed LED configuration attempts. That will help in determining which led class is causing the problem. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2500usb.c | 10 +++++-- drivers/net/wireless/rt2x00/rt2x00usb.c | 52 --------------------------------- drivers/net/wireless/rt2x00/rt2x00usb.h | 18 ------------ drivers/net/wireless/rt2x00/rt73usb.c | 23 ++++++++++----- 4 files changed, 24 insertions(+), 79 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 826ed692878c..9f59db91cfc2 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -292,6 +292,12 @@ static void rt2500usb_led_brightness(struct led_classdev *led_cdev, unsigned int activity = led->rt2x00dev->led_flags & LED_SUPPORT_ACTIVITY; + if (in_atomic()) { + NOTICE(led->rt2x00dev, + "Ignoring LED brightness command for led %d", led->type); + return; + } + if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC) { rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg, MAC_CSR20_LINK, enabled); @@ -299,8 +305,8 @@ static void rt2500usb_led_brightness(struct led_classdev *led_cdev, MAC_CSR20_ACTIVITY, enabled && activity); } - rt2x00usb_vendor_request_async(led->rt2x00dev, USB_SINGLE_WRITE, - MAC_CSR20, led->rt2x00dev->led_mcu_reg); + rt2500usb_register_write(led->rt2x00dev, MAC_CSR20, + led->rt2x00dev->led_mcu_reg); } #else #define rt2500usb_led_brightness NULL diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 89471b24a443..063b167da31e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -122,58 +122,6 @@ int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev, } EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request_buff); -static void rt2x00usb_vendor_request_async_complete(struct urb *urb) -{ - /* - * We're done with it, descrease usage count and let the - * usb layer delete it as soon as it is done with it. - */ - usb_put_urb(urb); -} - -int rt2x00usb_vendor_request_async(struct rt2x00_dev *rt2x00dev, - const u8 request, const u16 offset, - const u16 value) -{ - struct usb_device *usb_dev = rt2x00dev_usb_dev(rt2x00dev); - struct usb_ctrlrequest *ctrl; - struct urb *urb; - int status; - - urb = usb_alloc_urb(0, GFP_NOIO); - if (!urb) - return -ENOMEM; - - ctrl = kmalloc(sizeof(struct usb_ctrlrequest), GFP_NOIO); - if (!ctrl) { - status = -ENOMEM; - goto exit; - } - - ctrl->bRequestType= USB_VENDOR_REQUEST_OUT; - ctrl->bRequest = request; - ctrl->wValue = cpu_to_le16p(&value); - ctrl->wIndex = cpu_to_le16p(&offset); - ctrl->wLength = 0; - - usb_fill_control_urb(urb, usb_dev, usb_sndctrlpipe(usb_dev, 0), - (unsigned char *)ctrl, NULL, 0, - rt2x00usb_vendor_request_async_complete, NULL); - - status = usb_submit_urb(urb, GFP_ATOMIC); - if (!status) - goto exit; - - return 0; - -exit: - usb_put_urb(urb); - kfree(ctrl); - - return status; -} -EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request_async); - /* * TX data handlers. */ diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h index 275b089a2a4d..11e55180cbaf 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.h +++ b/drivers/net/wireless/rt2x00/rt2x00usb.h @@ -194,24 +194,6 @@ static inline int rt2x00usb_eeprom_read(struct rt2x00_dev *rt2x00dev, eeprom, lenght, timeout); } -/** - * rt2x00usb_vendor_request_async - Send register command to device (async) - * @rt2x00dev: Pointer to &struct rt2x00_dev - * @request: USB vendor command (See &enum rt2x00usb_vendor_request) - * @offset: Register offset to perform action on - * @value: Value to write to device - * - * Asynchroneous version of &rt2x00usb_vendor_request this is required - * for some routines where the driver cannot sleep because it is in - * irq context. Note that with this function the driver will not be - * notified on failure or timeout of the command. It will only be notified - * if the start of the command succeeded or not. This means it should not be - * used when the command must succeed. - */ -int rt2x00usb_vendor_request_async(struct rt2x00_dev *rt2x00dev, - const u8 request, const u16 offset, - const u16 value); - /* * Radio handlers */ diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index bf2391b89571..6546b0d607b9 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -290,29 +290,38 @@ static void rt73usb_led_brightness(struct led_classdev *led_cdev, unsigned int bg_mode = (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_2GHZ); + if (in_atomic()) { + NOTICE(led->rt2x00dev, + "Ignoring LED brightness command for led %d", led->type); + return; + } + if (led->type == LED_TYPE_RADIO) { rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg, MCU_LEDCS_RADIO_STATUS, enabled); - rt2x00usb_vendor_request_async(led->rt2x00dev, USB_LED_CONTROL, - 0, led->rt2x00dev->led_mcu_reg); + rt2x00usb_vendor_request_sw(led->rt2x00dev, USB_LED_CONTROL, + 0, led->rt2x00dev->led_mcu_reg, + REGISTER_TIMEOUT); } else if (led->type == LED_TYPE_ASSOC) { rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg, MCU_LEDCS_LINK_BG_STATUS, bg_mode); rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg, MCU_LEDCS_LINK_A_STATUS, a_mode); - rt2x00usb_vendor_request_async(led->rt2x00dev, USB_LED_CONTROL, - 0, led->rt2x00dev->led_mcu_reg); + rt2x00usb_vendor_request_sw(led->rt2x00dev, USB_LED_CONTROL, + 0, led->rt2x00dev->led_mcu_reg, + REGISTER_TIMEOUT); } else if (led->type == LED_TYPE_QUALITY) { /* * The brightness is divided into 6 levels (0 - 5), * this means we need to convert the brightness * argument into the matching level within that range. */ - rt2x00usb_vendor_request_async(led->rt2x00dev, USB_LED_CONTROL, - brightness / (LED_FULL / 6), - led->rt2x00dev->led_mcu_reg); + rt2x00usb_vendor_request_sw(led->rt2x00dev, USB_LED_CONTROL, + brightness / (LED_FULL / 6), + led->rt2x00dev->led_mcu_reg, + REGISTER_TIMEOUT); } } #else -- cgit v1.2.1 From 47ac26833663da51e7ac801db4badc2880c682c3 Mon Sep 17 00:00:00 2001 From: Gertjan van Wingerde Date: Sun, 17 Feb 2008 17:35:55 +0100 Subject: rt2x00: Fix hw mode registration with mac80211. The supported_bands field of struct hw_mode_spec now represents a bitfield, so bitfield operators need to be tested with when setting the band data. The current code generates the following warning: [176624.986244] WARNING: at /usr/local/src/incoming/compat-wireless-2.6/net/wireless/core.c:269 wiphy_register() [176624.986249] Pid: 12548, comm: modprobe Tainted: P 2.6.24.2#4 [176624.986251] [176624.986251] Call Trace: [176624.986277] [] :cfg80211:wiphy_register+0x17f/0x1a0 [176624.986282] [] :rt61pci:rt61pci_eepromregister_write+0x0/0x80 [176624.986302] [] :mac80211:ieee80211_register_hw+0x2c/0x2b0 [176624.986310] [] :rt2x00lib:rt2x00lib_probe_dev+0x350/0x3f0 [176624.986318] [] :rt2x00pci:rt2x00pci_probe+0x149/0x200 [176624.986325] [] pci_device_probe+0xf8/0x170 [176624.986331] [] driver_probe_device+0x9c/0x1c0 [176624.986335] [] __driver_attach+0x0/0xb0 [176624.986337] [] __driver_attach+0xa5/0xb0 [176624.986341] [] bus_for_each_dev+0x4d/0x80 [176624.986347] [] bus_add_driver+0xac/0x210 [176624.986351] [] __pci_register_driver+0x73/0xc0 [176624.986357] [] sys_init_module+0x18e/0x1a20 [176624.986374] [] system_call+0x7e/0x83 Signed-off-by: Gertjan van Wingerde Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00dev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index a644b9a7ca8f..b3a639aa0540 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -919,7 +919,7 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev, * Rates: CCK, OFDM. * Channels: 2.4 GHz */ - if (spec->supported_bands > SUPPORT_BAND_2GHZ) { + if (spec->supported_bands & SUPPORT_BAND_2GHZ) { rt2x00dev->bands[IEEE80211_BAND_2GHZ].n_channels = 14; rt2x00dev->bands[IEEE80211_BAND_2GHZ].n_bitrates = num_rates; rt2x00dev->bands[IEEE80211_BAND_2GHZ].channels = channels; @@ -933,7 +933,7 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev, * Rates: OFDM. * Channels: OFDM, UNII, HiperLAN2. */ - if (spec->supported_bands > SUPPORT_BAND_5GHZ) { + if (spec->supported_bands & SUPPORT_BAND_5GHZ) { rt2x00dev->bands[IEEE80211_BAND_5GHZ].n_channels = spec->num_channels - 14; rt2x00dev->bands[IEEE80211_BAND_5GHZ].n_bitrates = -- cgit v1.2.1 From ce359f90d3c65bf0a575683a28d25672facd3df0 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 17 Feb 2008 17:36:33 +0100 Subject: rt2x00: Fix MAC address defines in rt61pci The MAC address offset defines were incorrect because the byte offset was used instead of word index. This bug had no affect on normal operations since these defines weren't used. (EEPROM_MAC_ADDR_0 was used to read 6 bytes from). Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt61pci.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h index 4ef7ef32d76d..3511bba7ff65 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.h +++ b/drivers/net/wireless/rt2x00/rt61pci.h @@ -1130,10 +1130,10 @@ struct hw_pairwise_ta_entry { #define EEPROM_MAC_ADDR_0 0x0002 #define EEPROM_MAC_ADDR_BYTE0 FIELD16(0x00ff) #define EEPROM_MAC_ADDR_BYTE1 FIELD16(0xff00) -#define EEPROM_MAC_ADDR1 0x0004 +#define EEPROM_MAC_ADDR1 0x0003 #define EEPROM_MAC_ADDR_BYTE2 FIELD16(0x00ff) #define EEPROM_MAC_ADDR_BYTE3 FIELD16(0xff00) -#define EEPROM_MAC_ADDR_2 0x0006 +#define EEPROM_MAC_ADDR_2 0x0004 #define EEPROM_MAC_ADDR_BYTE4 FIELD16(0x00ff) #define EEPROM_MAC_ADDR_BYTE5 FIELD16(0xff00) -- cgit v1.2.1 From 2533d5f800d3693e9d000abfecd030ff02e305e4 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 17 Feb 2008 17:36:49 +0100 Subject: rt2x00: Release rt2x00 2.1.2 Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index e315d79b2aec..d0f027a14c95 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -44,7 +44,7 @@ /* * Module information. */ -#define DRV_VERSION "2.1.1" +#define DRV_VERSION "2.1.2" #define DRV_PROJECT "http://rt2x00.serialmonkey.com" /* -- cgit v1.2.1 From 013b73faff107e56cbe75fe4b881f5d80a8cf022 Mon Sep 17 00:00:00 2001 From: Roel Kluin <12o3l@tiscali.nl> Date: Tue, 19 Feb 2008 15:41:50 +0100 Subject: wireless: Convert to list_for_each_entry_rcu() Convert list_for_each_rcu() to list_for_each_entry_rcu() Signed-off-by: Roel Kluin <12o3l@tiscali.nl> Signed-off-by: John W. Linville --- drivers/net/wireless/strip.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c index 88efe1bae58f..bced3fe1cf8a 100644 --- a/drivers/net/wireless/strip.c +++ b/drivers/net/wireless/strip.c @@ -962,12 +962,12 @@ static char *time_delta(char buffer[], long time) /* get Nth element of the linked list */ static struct strip *strip_get_idx(loff_t pos) { - struct list_head *l; + struct strip *str; int i = 0; - list_for_each_rcu(l, &strip_list) { + list_for_each_entry_rcu(str, &strip_list, list) { if (pos == i) - return list_entry(l, struct strip, list); + return str; ++i; } return NULL; -- cgit v1.2.1 From e63e3fa7bd4d0dc8cbab5ab7aff84cd37d45295e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 20 Feb 2008 12:06:47 +0100 Subject: adm8211: fix sparse warnings Both of these seem to be actual errors, the first is just wrong and the second is my mistake introduced by the cfg80211 API update. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/adm8211.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c index 7d4218206c47..a1303ae03b0d 100644 --- a/drivers/net/wireless/adm8211.c +++ b/drivers/net/wireless/adm8211.c @@ -1109,7 +1109,7 @@ static void adm8211_hw_init(struct ieee80211_hw *dev) u32 reg; u8 cline; - reg = le32_to_cpu(ADM8211_CSR_READ(PAR)); + reg = ADM8211_CSR_READ(PAR); reg |= ADM8211_PAR_MRLE | ADM8211_PAR_MRME; reg &= ~(ADM8211_PAR_BAR | ADM8211_PAR_CAL); @@ -1702,13 +1702,9 @@ static int adm8211_tx(struct ieee80211_hw *dev, struct sk_buff *skb, int plcp, dur, len, plcp_signal, short_preamble; struct ieee80211_hdr *hdr; - if (control->tx_rate < 0) { - short_preamble = 1; - plcp_signal = -control->tx_rate->bitrate; - } else { - short_preamble = 0; - plcp_signal = control->tx_rate->bitrate; - } + short_preamble = !!(control->tx_rate->flags & + IEEE80211_TXCTL_SHORT_PREAMBLE); + plcp_signal = control->tx_rate->bitrate; hdr = (struct ieee80211_hdr *)skb->data; fc = le16_to_cpu(hdr->frame_control) & ~IEEE80211_FCTL_PROTECTED; -- cgit v1.2.1 From c2976ab005695c1b73f9dbdb4d0f85ed5e0319eb Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 20 Feb 2008 12:08:12 +0100 Subject: p54: fix sparse warnings This fixes a few sparse warnings in p54. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/p54common.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/p54common.c b/drivers/net/wireless/p54common.c index 424de9f4d5e7..9ae3be43156a 100644 --- a/drivers/net/wireless/p54common.c +++ b/drivers/net/wireless/p54common.c @@ -59,7 +59,7 @@ static struct ieee80211_channel p54_channels[] = { { .center_freq = 2484, .hw_value = 14, }, }; -struct ieee80211_supported_band band_2GHz = { +static struct ieee80211_supported_band band_2GHz = { .channels = p54_channels, .n_channels = ARRAY_SIZE(p54_channels), .bitrates = p54_rates, @@ -389,7 +389,7 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) while (entry != (struct sk_buff *)&priv->tx_queue) { range = (struct memrecord *)&entry->cb; if (range->start_addr == addr) { - struct ieee80211_tx_status status = {{0}}; + struct ieee80211_tx_status status; struct p54_control_hdr *entry_hdr; struct p54_tx_control_allocdata *entry_data; int pad = 0; @@ -405,6 +405,7 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) kfree_skb(entry); break; } + memset(&status, 0, sizeof(status)); memcpy(&status.control, range->control, sizeof(status.control)); kfree(range->control); -- cgit v1.2.1 From 8f300ae5b819f7655197925cdb1954edfd906a87 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sun, 24 Feb 2008 14:42:29 +0100 Subject: b43legacy: Fix nondebug build Fix a typo. Signed-off-by: Michael Buesch Acked-by: Stefano Brivio Signed-off-by: John W. Linville --- drivers/net/wireless/b43legacy/b43legacy.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/b43legacy/b43legacy.h b/drivers/net/wireless/b43legacy/b43legacy.h index 6a63a6e474f7..242b8ad4e33c 100644 --- a/drivers/net/wireless/b43legacy/b43legacy.h +++ b/drivers/net/wireless/b43legacy/b43legacy.h @@ -343,7 +343,7 @@ enum { #else /* This will evaluate the argument even if debugging is disabled. */ static inline bool __b43legacy_warn_on_dummy(bool x) { return x; } -# define B43_WARN_ON(x) __b43legacy_warn_on_dummy(unlikely(!!(x))) +# define B43legacy_WARN_ON(x) __b43legacy_warn_on_dummy(unlikely(!!(x))) # define B43legacy_BUG_ON(x) do { /* nothing */ } while (0) # define B43legacy_DEBUG 0 #endif -- cgit v1.2.1 From 9a89c839f79395426b84cf6da9d56773402b4c0e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 25 Feb 2008 11:12:18 +0100 Subject: adm8211: fix cfg80211 band API conversion Insert a missing band assignment. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/adm8211.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c index a1303ae03b0d..2e257ee2783b 100644 --- a/drivers/net/wireless/adm8211.c +++ b/drivers/net/wireless/adm8211.c @@ -1932,6 +1932,8 @@ static int __devinit adm8211_probe(struct pci_dev *pdev, priv->channel = 1; + dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; + err = ieee80211_register_hw(dev); if (err) { printk(KERN_ERR "%s (adm8211): Cannot register device\n", -- cgit v1.2.1 From 58e307398317ab55470547a7d72859c89edd187d Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 25 Feb 2008 17:51:53 +0100 Subject: p54: print unknown eeprom fields This patch allows p54common to print the uknown EEPROM fields, which can help when debugging/testing devices. Signed-off-by: Florian Fainelli Signed-off-by: John W. Linville --- drivers/net/wireless/p54common.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/p54common.c b/drivers/net/wireless/p54common.c index 9ae3be43156a..84cc000e71aa 100644 --- a/drivers/net/wireless/p54common.c +++ b/drivers/net/wireless/p54common.c @@ -291,6 +291,10 @@ int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) case PDR_END: i = len; break; + default: + printk(KERN_INFO "p54: unknown eeprom code : 0x%x\n", + le16_to_cpu(entry->code)); + break; } entry = (void *)entry + (entry_len + 1)*2; -- cgit v1.2.1 From 1497074ad79009f8fb465d795f9e0d2a428b7fa2 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 25 Feb 2008 23:20:33 +0100 Subject: rt2x00: Check for 5GHz band in link tuner Fix a typo in the link tuner where accidently the 2GHz band was checked instead of the 5GHz band. This forced the link tuner to work in an invalid range for the currently active band. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt61pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index d08349bed050..091fe398676d 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -769,7 +769,7 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev) /* * Determine r17 bounds. */ - if (rt2x00dev->rx_status.band == IEEE80211_BAND_2GHZ) { + if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) { low_bound = 0x28; up_bound = 0x48; if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) { -- cgit v1.2.1 From e6084239d39a10bac1186611fe7c523cea92c9ec Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 25 Feb 2008 23:22:13 +0100 Subject: rt2x00: Release rt2x00 2.1.3 Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index d0f027a14c95..fd65fccbdae7 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -44,7 +44,7 @@ /* * Module information. */ -#define DRV_VERSION "2.1.2" +#define DRV_VERSION "2.1.3" #define DRV_PROJECT "http://rt2x00.serialmonkey.com" /* -- cgit v1.2.1 From 38c07b430b50172b803fe4c7f76cba580ba9931f Mon Sep 17 00:00:00 2001 From: Pavel Roskin Date: Tue, 26 Feb 2008 17:59:14 -0500 Subject: ath5k: fix all endian issues reported by sparse Changes-licensed-under: ISC Signed-off-by: Pavel Roskin Acked-by: Luis R. Rodriguez Acked-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/base.c | 8 ++++---- drivers/net/wireless/ath5k/hw.c | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index 0b743f7b3a14..393b5f3c25a7 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -1717,11 +1717,11 @@ ath5k_check_ibss_hw_merge(struct ath5k_softc *sc, struct sk_buff *skb) u32 hw_tu; struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; - if ((mgmt->frame_control & IEEE80211_FCTL_FTYPE) == + if ((le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT && - (mgmt->frame_control & IEEE80211_FCTL_STYPE) == + (le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON && - mgmt->u.beacon.capab_info & WLAN_CAPABILITY_IBSS && + le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS && memcmp(mgmt->bssid, sc->ah->ah_bssid, ETH_ALEN) == 0) { /* * Received an IBSS beacon with the same BSSID. Hardware might @@ -1730,7 +1730,7 @@ ath5k_check_ibss_hw_merge(struct ath5k_softc *sc, struct sk_buff *skb) hw_tu = TSF_TO_TU(ath5k_hw_get_tsf64(sc->ah)); if (hw_tu >= sc->nexttbtt) { ath5k_beacon_update_timers(sc, - mgmt->u.beacon.timestamp); + le64_to_cpu(mgmt->u.beacon.timestamp)); ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "detected HW merge from received beacon\n"); } diff --git a/drivers/net/wireless/ath5k/hw.c b/drivers/net/wireless/ath5k/hw.c index 998da6be2be3..eec2b806a0de 100644 --- a/drivers/net/wireless/ath5k/hw.c +++ b/drivers/net/wireless/ath5k/hw.c @@ -531,8 +531,8 @@ static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah, * actual rate for this rate. See mac80211 tx.c * ieee80211_duration() for a brief description of * what rate we should choose to TX ACKs. */ - tx_time = ieee80211_generic_frame_duration(sc->hw, - sc->vif, 10, &srate); + tx_time = le16_to_cpu(ieee80211_generic_frame_duration(sc->hw, + sc->vif, 10, &srate)); ath5k_hw_reg_write(ah, tx_time, reg); -- cgit v1.2.1 From d0709a65181beb787ef3f58cfe45536a2bb254c8 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 25 Feb 2008 16:27:46 +0100 Subject: mac80211: RCU-ify STA info structure access This makes access to the STA hash table/list use RCU to protect against freeing of items. However, it's not a true RCU, the copy step is missing: whenever somebody changes a STA item it is simply updated. This is an existing race condition that is now somewhat understandable. This patch also fixes the race key freeing vs. STA destruction by making sure that sta_info_destroy() is always called under RTNL and frees the key. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 31 +++++++++++++++++------------- drivers/net/wireless/iwlwifi/iwl-4965-rs.c | 27 ++++++++++++++------------ 2 files changed, 33 insertions(+), 25 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index a8223c4cc97c..c4bfba6f3c2b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -471,10 +471,11 @@ static void rs_tx_status(void *priv_rate, return; } + rcu_read_lock(); + sta = sta_info_get(local, hdr->addr1); if (!sta || !sta->rate_ctrl_priv) { - if (sta) - sta_info_put(sta); + rcu_read_unlock(); IWL_DEBUG_RATE("leave: No STA priv data to update!\n"); return; } @@ -547,7 +548,7 @@ static void rs_tx_status(void *priv_rate, spin_unlock_irqrestore(&rs_sta->lock, flags); - sta_info_put(sta); + rcu_read_unlock(); IWL_DEBUG_RATE("leave\n"); @@ -658,6 +659,8 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, IWL_DEBUG_RATE("enter\n"); + rcu_read_lock(); + sta = sta_info_get(local, hdr->addr1); /* Send management frames and broadcast/multicast data using lowest @@ -668,8 +671,7 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, !sta || !sta->rate_ctrl_priv) { IWL_DEBUG_RATE("leave: No STA priv data to update!\n"); sel->rate = rate_lowest(local, band, sta); - if (sta) - sta_info_put(sta); + rcu_read_unlock(); return; } @@ -811,7 +813,7 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, else sta->txrate_idx = sta->last_txrate_idx; - sta_info_put(sta); + rcu_read_unlock(); IWL_DEBUG_RATE("leave: %d\n", index); @@ -843,13 +845,15 @@ int iwl3945_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id) unsigned long now = jiffies; u32 max_time = 0; + rcu_read_lock(); + sta = sta_info_get(local, priv->stations[sta_id].sta.sta.addr); if (!sta || !sta->rate_ctrl_priv) { - if (sta) { - sta_info_put(sta); + if (sta) IWL_DEBUG_RATE("leave - no private rate data!\n"); - } else + else IWL_DEBUG_RATE("leave - no station!\n"); + rcu_read_unlock(); return sprintf(buf, "station %d not found\n", sta_id); } @@ -890,7 +894,7 @@ int iwl3945_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id) i = j; } spin_unlock_irqrestore(&rs_sta->lock, flags); - sta_info_put(sta); + rcu_read_unlock(); /* Display the average rate of all samples taken. * @@ -927,11 +931,12 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) return; } + rcu_read_lock(); + sta = sta_info_get(local, priv->stations[sta_id].sta.sta.addr); if (!sta || !sta->rate_ctrl_priv) { - if (sta) - sta_info_put(sta); IWL_DEBUG_RATE("leave - no private rate data!\n"); + rcu_read_unlock(); return; } @@ -958,7 +963,7 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) break; } - sta_info_put(sta); + rcu_read_unlock(); spin_unlock_irqrestore(&rs_sta->lock, flags); rssi = priv->last_rx_rssi; diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c index 48a6a85355ec..46d85fd07faa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c @@ -847,12 +847,12 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, if (retries > 15) retries = 15; + rcu_read_lock(); sta = sta_info_get(local, hdr->addr1); if (!sta || !sta->rate_ctrl_priv) { - if (sta) - sta_info_put(sta); + rcu_read_unlock(); return; } @@ -891,7 +891,7 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, if ((rs_index < 0) || (rs_index >= IWL_RATE_COUNT)) { IWL_DEBUG_RATE("bad rate index at: %d rate 0x%X\n", rs_index, tx_mcs.rate_n_flags); - sta_info_put(sta); + rcu_read_unlock(); return; } @@ -909,7 +909,7 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, IWL_DEBUG_RATE("initial rate does not match 0x%x 0x%x\n", tx_mcs.rate_n_flags, le32_to_cpu(table->rs_table[0].rate_n_flags)); - sta_info_put(sta); + rcu_read_unlock(); return; } @@ -1025,7 +1025,7 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, /* See if there's a better rate or modulation mode to try. */ rs_rate_scale_perform(priv, dev, hdr, sta); - sta_info_put(sta); + rcu_read_unlock(); return; } @@ -2219,6 +2219,8 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, IWL_DEBUG_RATE_LIMIT("rate scale calculate new rate for skb\n"); + rcu_read_lock(); + sta = sta_info_get(local, hdr->addr1); /* Send management frames and broadcast/multicast data using lowest @@ -2227,8 +2229,7 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1) || !sta || !sta->rate_ctrl_priv) { sel->rate = rate_lowest(local, sband, sta); - if (sta) - sta_info_put(sta); + rcu_read_unlock(); return; } @@ -2261,7 +2262,7 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, sel->rate = rate_lowest(local, sband, sta); return; } - sta_info_put(sta); + rcu_read_unlock(); sel->rate = &priv->ieee_rates[i]; } @@ -2735,13 +2736,15 @@ int iwl4965_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id) u32 max_time = 0; u8 lq_type, antenna; + rcu_read_lock(); + sta = sta_info_get(local, priv->stations[sta_id].sta.sta.addr); if (!sta || !sta->rate_ctrl_priv) { - if (sta) { - sta_info_put(sta); + if (sta) IWL_DEBUG_RATE("leave - no private rate data!\n"); - } else + else IWL_DEBUG_RATE("leave - no station!\n"); + rcu_read_unlock(); return sprintf(buf, "station %d not found\n", sta_id); } @@ -2808,7 +2811,7 @@ int iwl4965_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id) "active_search %d rate index %d\n", lq_type, antenna, lq_sta->search_better_tbl, sta->last_txrate_idx); - sta_info_put(sta); + rcu_read_unlock(); return cnt; } -- cgit v1.2.1 From 38968d096b9f497e7ec4590b6b80eb8679e3646a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 25 Feb 2008 16:27:50 +0100 Subject: b43: verify sta_notify mac80211 callback This helps verify that nothing bad is going on in mac80211, it is unfortunately not possible to implement this generically in mac80211 easily because there we can't assume that we only have a single vif which b43 currently can assume. Signed-off-by: Johannes Berg Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index f745308faaad..c93b62fb5f65 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -3835,6 +3835,16 @@ static int b43_op_ibss_beacon_update(struct ieee80211_hw *hw, return 0; } +static void b43_op_sta_notify(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + enum sta_notify_cmd notify_cmd, + const u8 *addr) +{ + struct b43_wl *wl = hw_to_b43_wl(hw); + + B43_WARN_ON(!vif || wl->vif != vif); +} + static const struct ieee80211_ops b43_hw_ops = { .tx = b43_op_tx, .conf_tx = b43_op_conf_tx, @@ -3851,6 +3861,7 @@ static const struct ieee80211_ops b43_hw_ops = { .set_retry_limit = b43_op_set_retry_limit, .set_tim = b43_op_beacon_set_tim, .beacon_update = b43_op_ibss_beacon_update, + .sta_notify = b43_op_sta_notify, }; /* Hard-reset the chip. Do not call this directly. -- cgit v1.2.1 From 2acae16ee79386c73db10fa8e95c9cd42fbad272 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Sun, 2 Mar 2008 01:25:59 +0200 Subject: iwlwifi: removing unused priv->config This patch removes unused variable in iwlYYYY_priv Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.h | 1 - drivers/net/wireless/iwlwifi/iwl-4965.h | 1 - drivers/net/wireless/iwlwifi/iwl3945-base.c | 3 +-- drivers/net/wireless/iwlwifi/iwl4965-base.c | 3 +-- 4 files changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index dde389d31637..d36ae0045c57 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -800,7 +800,6 @@ struct iwl3945_priv { struct iwl3945_tx_queue txq[IWL_MAX_NUM_QUEUES]; unsigned long status; - u32 config; int last_rx_rssi; /* From Rx packet statisitics */ int last_rx_noise; /* From beacon statistics */ diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index ce17e4fec838..cc0745bfd1fb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -1104,7 +1104,6 @@ struct iwl4965_priv { u32 scd_base_addr; /* scheduler sram base address */ unsigned long status; - u32 config; int last_rx_rssi; /* From Rx packet statisitics */ int last_rx_noise; /* From beacon statistics */ diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 0fab832ce8c2..139a4a24bc00 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -4506,8 +4506,7 @@ static void iwl3945_dump_nic_error_log(struct iwl3945_priv *priv) if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) { IWL_ERROR("Start IWL Error Log Dump:\n"); - IWL_ERROR("Status: 0x%08lX, Config: %08X count: %d\n", - priv->status, priv->config, count); + IWL_ERROR("Status: 0x%08lX, count: %d\n", priv->status, count); } IWL_ERROR("Desc Time asrtPC blink2 " diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 20d012d4f37e..99a9f820bfd1 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -4886,8 +4886,7 @@ static void iwl4965_dump_nic_error_log(struct iwl4965_priv *priv) if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) { IWL_ERROR("Start IWL Error Log Dump:\n"); - IWL_ERROR("Status: 0x%08lX, Config: %08X count: %d\n", - priv->status, priv->config, count); + IWL_ERROR("Status: 0x%08lX, count: %d\n", priv->status, count); } desc = iwl4965_read_targ_mem(priv, base + 1 * sizeof(u32)); -- cgit v1.2.1 From 8211ef78d9023a8772e5acf6b7934598156b2fc8 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Sun, 2 Mar 2008 01:36:04 +0200 Subject: iwlwifi: refactor init geos function This patch refactors init geos function. It also fixes few minor bugs. IWL_MAX_RATE -> IWL_RATE_COUNT (IWL_MAX_RATE included also MCS setting) There are 9 and 13 rates for 4965 in 2.4 and 5.2 respectively (rate 60) Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-commands.h | 40 +++++++-------- drivers/net/wireless/iwlwifi/iwl-3945-rs.h | 4 +- drivers/net/wireless/iwlwifi/iwl-4965-commands.h | 40 +++++++-------- drivers/net/wireless/iwlwifi/iwl3945-base.c | 58 ++++++++++++--------- drivers/net/wireless/iwlwifi/iwl4965-base.c | 64 ++++++++++++++---------- 5 files changed, 115 insertions(+), 91 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-commands.h b/drivers/net/wireless/iwlwifi/iwl-3945-commands.h index 20fbb32c33bd..8b7ef9f1b57b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-commands.h @@ -666,26 +666,26 @@ struct iwl3945_rx_frame_hdr { u8 payload[0]; } __attribute__ ((packed)); -#define RX_RES_STATUS_NO_CRC32_ERROR __constant_cpu_to_le32(1 << 0) -#define RX_RES_STATUS_NO_RXE_OVERFLOW __constant_cpu_to_le32(1 << 1) - -#define RX_RES_PHY_FLAGS_BAND_24_MSK __constant_cpu_to_le16(1 << 0) -#define RX_RES_PHY_FLAGS_MOD_CCK_MSK __constant_cpu_to_le16(1 << 1) -#define RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK __constant_cpu_to_le16(1 << 2) -#define RX_RES_PHY_FLAGS_NARROW_BAND_MSK __constant_cpu_to_le16(1 << 3) -#define RX_RES_PHY_FLAGS_ANTENNA_MSK __constant_cpu_to_le16(0xf0) - -#define RX_RES_STATUS_SEC_TYPE_MSK (0x7 << 8) -#define RX_RES_STATUS_SEC_TYPE_NONE (0x0 << 8) -#define RX_RES_STATUS_SEC_TYPE_WEP (0x1 << 8) -#define RX_RES_STATUS_SEC_TYPE_CCMP (0x2 << 8) -#define RX_RES_STATUS_SEC_TYPE_TKIP (0x3 << 8) - -#define RX_RES_STATUS_DECRYPT_TYPE_MSK (0x3 << 11) -#define RX_RES_STATUS_NOT_DECRYPT (0x0 << 11) -#define RX_RES_STATUS_DECRYPT_OK (0x3 << 11) -#define RX_RES_STATUS_BAD_ICV_MIC (0x1 << 11) -#define RX_RES_STATUS_BAD_KEY_TTAK (0x2 << 11) +#define RX_RES_STATUS_NO_CRC32_ERROR __constant_cpu_to_le32(1 << 0) +#define RX_RES_STATUS_NO_RXE_OVERFLOW __constant_cpu_to_le32(1 << 1) + +#define RX_RES_PHY_FLAGS_BAND_24_MSK __constant_cpu_to_le16(1 << 0) +#define RX_RES_PHY_FLAGS_MOD_CCK_MSK __constant_cpu_to_le16(1 << 1) +#define RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK __constant_cpu_to_le16(1 << 2) +#define RX_RES_PHY_FLAGS_NARROW_BAND_MSK __constant_cpu_to_le16(1 << 3) +#define RX_RES_PHY_FLAGS_ANTENNA_MSK __constant_cpu_to_le16(0xf0) + +#define RX_RES_STATUS_SEC_TYPE_MSK (0x7 << 8) +#define RX_RES_STATUS_SEC_TYPE_NONE (0x0 << 8) +#define RX_RES_STATUS_SEC_TYPE_WEP (0x1 << 8) +#define RX_RES_STATUS_SEC_TYPE_CCMP (0x2 << 8) +#define RX_RES_STATUS_SEC_TYPE_TKIP (0x3 << 8) + +#define RX_RES_STATUS_DECRYPT_TYPE_MSK (0x3 << 11) +#define RX_RES_STATUS_NOT_DECRYPT (0x0 << 11) +#define RX_RES_STATUS_DECRYPT_OK (0x3 << 11) +#define RX_RES_STATUS_BAD_ICV_MIC (0x1 << 11) +#define RX_RES_STATUS_BAD_KEY_TTAK (0x2 << 11) struct iwl3945_rx_frame_end { __le32 status; diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.h b/drivers/net/wireless/iwlwifi/iwl-3945-rs.h index d5e9220f871d..3c61f08febe6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.h @@ -36,8 +36,8 @@ struct iwl3945_rate_info { u8 next_rs; /* next rate used in rs algo */ u8 prev_rs_tgg; /* previous rate used in TGG rs algo */ u8 next_rs_tgg; /* next rate used in TGG rs algo */ - u8 table_rs_index; /* index in rate scale table cmd */ - u8 prev_table_rs; /* prev in rate table cmd */ + u8 table_rs_index; /* index in rate scale table cmd */ + u8 prev_table_rs; /* prev in rate table cmd */ }; /* diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h index b21ffea325cf..327eabce182c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h @@ -875,26 +875,26 @@ struct iwl4965_rx_frame_hdr { u8 payload[0]; } __attribute__ ((packed)); -#define RX_RES_STATUS_NO_CRC32_ERROR __constant_cpu_to_le32(1 << 0) -#define RX_RES_STATUS_NO_RXE_OVERFLOW __constant_cpu_to_le32(1 << 1) - -#define RX_RES_PHY_FLAGS_BAND_24_MSK __constant_cpu_to_le16(1 << 0) -#define RX_RES_PHY_FLAGS_MOD_CCK_MSK __constant_cpu_to_le16(1 << 1) -#define RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK __constant_cpu_to_le16(1 << 2) -#define RX_RES_PHY_FLAGS_NARROW_BAND_MSK __constant_cpu_to_le16(1 << 3) -#define RX_RES_PHY_FLAGS_ANTENNA_MSK __constant_cpu_to_le16(0xf0) - -#define RX_RES_STATUS_SEC_TYPE_MSK (0x7 << 8) -#define RX_RES_STATUS_SEC_TYPE_NONE (0x0 << 8) -#define RX_RES_STATUS_SEC_TYPE_WEP (0x1 << 8) -#define RX_RES_STATUS_SEC_TYPE_CCMP (0x2 << 8) -#define RX_RES_STATUS_SEC_TYPE_TKIP (0x3 << 8) - -#define RX_RES_STATUS_DECRYPT_TYPE_MSK (0x3 << 11) -#define RX_RES_STATUS_NOT_DECRYPT (0x0 << 11) -#define RX_RES_STATUS_DECRYPT_OK (0x3 << 11) -#define RX_RES_STATUS_BAD_ICV_MIC (0x1 << 11) -#define RX_RES_STATUS_BAD_KEY_TTAK (0x2 << 11) +#define RX_RES_STATUS_NO_CRC32_ERROR __constant_cpu_to_le32(1 << 0) +#define RX_RES_STATUS_NO_RXE_OVERFLOW __constant_cpu_to_le32(1 << 1) + +#define RX_RES_PHY_FLAGS_BAND_24_MSK __constant_cpu_to_le16(1 << 0) +#define RX_RES_PHY_FLAGS_MOD_CCK_MSK __constant_cpu_to_le16(1 << 1) +#define RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK __constant_cpu_to_le16(1 << 2) +#define RX_RES_PHY_FLAGS_NARROW_BAND_MSK __constant_cpu_to_le16(1 << 3) +#define RX_RES_PHY_FLAGS_ANTENNA_MSK __constant_cpu_to_le16(0xf0) + +#define RX_RES_STATUS_SEC_TYPE_MSK (0x7 << 8) +#define RX_RES_STATUS_SEC_TYPE_NONE (0x0 << 8) +#define RX_RES_STATUS_SEC_TYPE_WEP (0x1 << 8) +#define RX_RES_STATUS_SEC_TYPE_CCMP (0x2 << 8) +#define RX_RES_STATUS_SEC_TYPE_TKIP (0x3 << 8) + +#define RX_RES_STATUS_DECRYPT_TYPE_MSK (0x3 << 11) +#define RX_RES_STATUS_NOT_DECRYPT (0x0 << 11) +#define RX_RES_STATUS_DECRYPT_OK (0x3 << 11) +#define RX_RES_STATUS_BAD_ICV_MIC (0x1 << 11) +#define RX_RES_STATUS_BAD_KEY_TTAK (0x2 << 11) struct iwl4965_rx_frame_end { __le32 status; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 139a4a24bc00..0cafbd42d84c 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -5118,11 +5118,12 @@ static int iwl3945_init_channel_map(struct iwl3945_priv *priv) ch_info->scan_power = eeprom_ch_info[ch].max_power_avg; ch_info->min_power = 0; - IWL_DEBUG_INFO("Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x" + IWL_DEBUG_INFO("Ch. %d [%sGHz] %s%s%s%s%s%s%s(0x%02x" " %ddBm): Ad-Hoc %ssupported\n", ch_info->channel, is_channel_a_band(ch_info) ? "5.2" : "2.4", + CHECK_AND_PRINT(VALID), CHECK_AND_PRINT(IBSS), CHECK_AND_PRINT(ACTIVE), CHECK_AND_PRINT(RADAR), @@ -5332,7 +5333,7 @@ static void iwl3945_init_hw_rates(struct iwl3945_priv *priv, static int iwl3945_init_geos(struct iwl3945_priv *priv) { struct iwl3945_channel_info *ch; - struct ieee80211_supported_band *band; + struct ieee80211_supported_band *sband; struct ieee80211_channel *channels; struct ieee80211_channel *geo_ch; struct ieee80211_rate *rates; @@ -5350,7 +5351,7 @@ static int iwl3945_init_geos(struct iwl3945_priv *priv) if (!channels) return -ENOMEM; - rates = kzalloc((sizeof(struct ieee80211_rate) * (IWL_MAX_RATES + 1)), + rates = kzalloc((sizeof(struct ieee80211_rate) * (IWL_RATE_COUNT + 1)), GFP_KERNEL); if (!rates) { kfree(channels); @@ -5358,38 +5359,38 @@ static int iwl3945_init_geos(struct iwl3945_priv *priv) } /* 5.2GHz channels start after the 2.4GHz channels */ - band = &priv->bands[IEEE80211_BAND_5GHZ]; - band->channels = &channels[ARRAY_SIZE(iwl3945_eeprom_band_1)]; - band->bitrates = &rates[4]; - band->n_bitrates = 8; /* just OFDM */ - - band = &priv->bands[IEEE80211_BAND_2GHZ]; - band->channels = channels; - band->bitrates = rates; - band->n_bitrates = 12; /* OFDM & CCK */ + sband = &priv->bands[IEEE80211_BAND_5GHZ]; + sband->channels = &channels[ARRAY_SIZE(iwl3945_eeprom_band_1)]; + /* just OFDM */ + sband->bitrates = &rates[IWL_FIRST_OFDM_RATE]; + sband->n_bitrates = IWL_RATE_COUNT - IWL_FIRST_OFDM_RATE; + + sband = &priv->bands[IEEE80211_BAND_2GHZ]; + sband->channels = channels; + /* OFDM & CCK */ + sband->bitrates = rates; + sband->n_bitrates = IWL_RATE_COUNT; priv->ieee_channels = channels; priv->ieee_rates = rates; iwl3945_init_hw_rates(priv, rates); - for (i = 0, geo_ch = channels; i < priv->channel_count; i++) { + for (i = 0; i < priv->channel_count; i++) { ch = &priv->channel_info[i]; - if (!is_channel_valid(ch)) { - IWL_DEBUG_INFO("Channel %d [%sGHz] is restricted -- " - "skipping.\n", - ch->channel, is_channel_a_band(ch) ? - "5.2" : "2.4"); + /* FIXME: might be removed if scan is OK*/ + if (!is_channel_valid(ch)) continue; - } if (is_channel_a_band(ch)) - geo_ch = &priv->bands[IEEE80211_BAND_5GHZ].channels[priv->bands[IEEE80211_BAND_5GHZ].n_channels++]; + sband = &priv->bands[IEEE80211_BAND_5GHZ]; else - geo_ch = &priv->bands[IEEE80211_BAND_2GHZ].channels[priv->bands[IEEE80211_BAND_2GHZ].n_channels++]; + sband = &priv->bands[IEEE80211_BAND_2GHZ]; - geo_ch->center_freq = ieee80211chan2mhz(ch->channel); + geo_ch = &sband->channels[sband->n_channels++]; + + geo_ch->center_freq = ieee80211_channel_to_frequency(ch->channel); geo_ch->max_power = ch->max_power_avg; geo_ch->max_antenna_gain = 0xff; geo_ch->hw_value = ch->channel; @@ -5407,8 +5408,19 @@ static int iwl3945_init_geos(struct iwl3945_priv *priv) if (ch->max_power_avg > priv->max_channel_txpower_limit) priv->max_channel_txpower_limit = ch->max_power_avg; - } else + } else { geo_ch->flags |= IEEE80211_CHAN_DISABLED; + } + + /* Save flags for reg domain usage */ + geo_ch->orig_flags = geo_ch->flags; + + IWL_DEBUG_INFO("Channel %d Freq=%d[%sGHz] %s flag=0%X\n", + ch->channel, geo_ch->center_freq, + is_channel_a_band(ch) ? "5.2" : "2.4", + geo_ch->flags & IEEE80211_CHAN_DISABLED ? + "restricted" : "valid", + geo_ch->flags); } if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) && priv->is_abg) { diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 99a9f820bfd1..46a43ff51526 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -5501,11 +5501,12 @@ static int iwl4965_init_channel_map(struct iwl4965_priv *priv) ch_info->scan_power = eeprom_ch_info[ch].max_power_avg; ch_info->min_power = 0; - IWL_DEBUG_INFO("Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x" + IWL_DEBUG_INFO("Ch. %d [%sGHz] %s%s%s%s%s%s%s(0x%02x" " %ddBm): Ad-Hoc %ssupported\n", ch_info->channel, is_channel_a_band(ch_info) ? "5.2" : "2.4", + CHECK_AND_PRINT(VALID), CHECK_AND_PRINT(IBSS), CHECK_AND_PRINT(ACTIVE), CHECK_AND_PRINT(RADAR), @@ -5748,7 +5749,7 @@ static void iwl4965_init_hw_rates(struct iwl4965_priv *priv, static int iwl4965_init_geos(struct iwl4965_priv *priv) { struct iwl4965_channel_info *ch; - struct ieee80211_supported_band *band; + struct ieee80211_supported_band *sband; struct ieee80211_channel *channels; struct ieee80211_channel *geo_ch; struct ieee80211_rate *rates; @@ -5766,7 +5767,7 @@ static int iwl4965_init_geos(struct iwl4965_priv *priv) if (!channels) return -ENOMEM; - rates = kzalloc((sizeof(struct ieee80211_rate) * (IWL_MAX_RATES + 1)), + rates = kzalloc((sizeof(struct ieee80211_rate) * (IWL_RATE_COUNT + 1)), GFP_KERNEL); if (!rates) { kfree(channels); @@ -5774,42 +5775,42 @@ static int iwl4965_init_geos(struct iwl4965_priv *priv) } /* 5.2GHz channels start after the 2.4GHz channels */ - band = &priv->bands[IEEE80211_BAND_5GHZ]; - band->channels = &channels[ARRAY_SIZE(iwl4965_eeprom_band_1)]; - band->bitrates = &rates[4]; - band->n_bitrates = 8; /* just OFDM */ + sband = &priv->bands[IEEE80211_BAND_5GHZ]; + sband->channels = &channels[ARRAY_SIZE(iwl4965_eeprom_band_1)]; + /* just OFDM */ + sband->bitrates = &rates[IWL_FIRST_OFDM_RATE]; + sband->n_bitrates = IWL_RATE_COUNT - IWL_FIRST_OFDM_RATE; - iwl4965_init_ht_hw_capab(&band->ht_info, IEEE80211_BAND_5GHZ); + iwl4965_init_ht_hw_capab(&sband->ht_info, IEEE80211_BAND_5GHZ); - band = &priv->bands[IEEE80211_BAND_2GHZ]; - band->channels = channels; - band->bitrates = rates; - band->n_bitrates = 12; /* OFDM & CCK */ + sband = &priv->bands[IEEE80211_BAND_2GHZ]; + sband->channels = channels; + /* OFDM & CCK */ + sband->bitrates = rates; + sband->n_bitrates = IWL_RATE_COUNT; - iwl4965_init_ht_hw_capab(&band->ht_info, IEEE80211_BAND_2GHZ); + iwl4965_init_ht_hw_capab(&sband->ht_info, IEEE80211_BAND_2GHZ); priv->ieee_channels = channels; priv->ieee_rates = rates; iwl4965_init_hw_rates(priv, rates); - for (i = 0, geo_ch = channels; i < priv->channel_count; i++) { + for (i = 0; i < priv->channel_count; i++) { ch = &priv->channel_info[i]; - if (!is_channel_valid(ch)) { - IWL_DEBUG_INFO("Channel %d [%sGHz] is restricted -- " - "skipping.\n", - ch->channel, is_channel_a_band(ch) ? - "5.2" : "2.4"); + /* FIXME: might be removed if scan is OK */ + if (!is_channel_valid(ch)) continue; - } - if (is_channel_a_band(ch)) { - geo_ch = &priv->bands[IEEE80211_BAND_5GHZ].channels[priv->bands[IEEE80211_BAND_5GHZ].n_channels++]; - } else - geo_ch = &priv->bands[IEEE80211_BAND_2GHZ].channels[priv->bands[IEEE80211_BAND_2GHZ].n_channels++]; + if (is_channel_a_band(ch)) + sband = &priv->bands[IEEE80211_BAND_5GHZ]; + else + sband = &priv->bands[IEEE80211_BAND_2GHZ]; - geo_ch->center_freq = ieee80211chan2mhz(ch->channel); + geo_ch = &sband->channels[sband->n_channels++]; + + geo_ch->center_freq = ieee80211_channel_to_frequency(ch->channel); geo_ch->max_power = ch->max_power_avg; geo_ch->max_antenna_gain = 0xff; geo_ch->hw_value = ch->channel; @@ -5827,8 +5828,19 @@ static int iwl4965_init_geos(struct iwl4965_priv *priv) if (ch->max_power_avg > priv->max_channel_txpower_limit) priv->max_channel_txpower_limit = ch->max_power_avg; - } else + } else { geo_ch->flags |= IEEE80211_CHAN_DISABLED; + } + + /* Save flags for reg domain usage */ + geo_ch->orig_flags = geo_ch->flags; + + IWL_DEBUG_INFO("Channel %d Freq=%d[%sGHz] %s flag=0%X\n", + ch->channel, geo_ch->center_freq, + is_channel_a_band(ch) ? "5.2" : "2.4", + geo_ch->flags & IEEE80211_CHAN_DISABLED ? + "restricted" : "valid", + geo_ch->flags); } if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) && priv->is_abg) { -- cgit v1.2.1 From 17744ff6ae7eafe33dac9772f2ef9ab5fb738db8 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Sun, 2 Mar 2008 01:52:00 +0200 Subject: iwlwifi: Fix 52 rate report in rx status This patch fixes reporting rate in RX packets in 52 band. The rate was updated from CCK rate index instead of OFDM rate 6M Most of the patch is collateral clean up Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-debug.h | 17 +- drivers/net/wireless/iwlwifi/iwl-3945.c | 231 ++++++++++++++++++++---- drivers/net/wireless/iwlwifi/iwl-3945.h | 20 --- drivers/net/wireless/iwlwifi/iwl-4965-debug.h | 16 ++ drivers/net/wireless/iwlwifi/iwl-4965-rs.c | 6 +- drivers/net/wireless/iwlwifi/iwl-4965-rs.h | 2 +- drivers/net/wireless/iwlwifi/iwl-4965.c | 250 ++++++++++++++++++++++---- drivers/net/wireless/iwlwifi/iwl-4965.h | 10 -- drivers/net/wireless/iwlwifi/iwl3945-base.c | 182 ------------------- drivers/net/wireless/iwlwifi/iwl4965-base.c | 181 ------------------- 10 files changed, 449 insertions(+), 466 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-debug.h b/drivers/net/wireless/iwlwifi/iwl-3945-debug.h index f853c6b9f76e..28ecfe8d39a3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-debug.h @@ -40,6 +40,15 @@ do { if (iwl3945_debug_level & (level)) \ do { if ((iwl3945_debug_level & (level)) && net_ratelimit()) \ printk(KERN_ERR DRV_NAME": %c %s " fmt, \ in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0) + +static inline void iwl3945_print_hex_dump(int level, void *p, u32 len) +{ + if (!(iwl3945_debug_level & level)) + return; + + print_hex_dump(KERN_DEBUG, "iwl data: ", DUMP_PREFIX_OFFSET, 16, 1, + p, len, 1); +} #else static inline void IWL_DEBUG(int level, const char *fmt, ...) { @@ -47,7 +56,12 @@ static inline void IWL_DEBUG(int level, const char *fmt, ...) static inline void IWL_DEBUG_LIMIT(int level, const char *fmt, ...) { } -#endif /* CONFIG_IWL3945_DEBUG */ +static inline void iwl3945_print_hex_dump(int level, void *p, u32 len) +{ +} +#endif /* CONFIG_IWL3945_DEBUG */ + + /* * To use the debug system; @@ -143,6 +157,7 @@ static inline void IWL_DEBUG_LIMIT(int level, const char *fmt, ...) IWL_DEBUG_LIMIT(IWL_DL_ASSOC | IWL_DL_INFO, f, ## a) #define IWL_DEBUG_HT(f, a...) IWL_DEBUG(IWL_DL_HT, f, ## a) #define IWL_DEBUG_STATS(f, a...) IWL_DEBUG(IWL_DL_STATS, f, ## a) +#define IWL_DEBUG_STATS_LIMIT(f, a...) IWL_DEBUG_LIMIT(IWL_DL_STATS, f, ## a) #define IWL_DEBUG_TX_REPLY(f, a...) IWL_DEBUG(IWL_DL_TX_REPLY, f, ## a) #define IWL_DEBUG_QOS(f, a...) IWL_DEBUG(IWL_DL_QOS, f, ## a) #define IWL_DEBUG_RADIO(f, a...) IWL_DEBUG(IWL_DL_RADIO, f, ## a) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 82d282730b75..63e832cdba75 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -183,6 +183,16 @@ void iwl3945_disable_events(struct iwl3945_priv *priv) } +static int iwl3945_hwrate_to_plcp_idx(u8 plcp) +{ + int idx; + + for (idx = 0; idx < IWL_RATE_COUNT; idx++) + if (iwl3945_rates[idx].plcp == plcp) + return idx; + return -1; +} + /** * iwl3945_get_antenna_flags - Get antenna flags for RXON command * @priv: eeprom and antenna fields are used to determine antenna flags @@ -238,6 +248,156 @@ void iwl3945_hw_rx_statistics(struct iwl3945_priv *priv, struct iwl3945_rx_mem_b priv->last_statistics_time = jiffies; } +/****************************************************************************** + * + * Misc. internal state and helper functions + * + ******************************************************************************/ +#ifdef CONFIG_IWL3945_DEBUG + +/** + * iwl3945_report_frame - dump frame to syslog during debug sessions + * + * You may hack this function to show different aspects of received frames, + * including selective frame dumps. + * group100 parameter selects whether to show 1 out of 100 good frames. + */ +static void iwl3945_dbg_report_frame(struct iwl3945_priv *priv, + struct iwl3945_rx_packet *pkt, + struct ieee80211_hdr *header, int group100) +{ + u32 to_us; + u32 print_summary = 0; + u32 print_dump = 0; /* set to 1 to dump all frames' contents */ + u32 hundred = 0; + u32 dataframe = 0; + u16 fc; + u16 seq_ctl; + u16 channel; + u16 phy_flags; + u16 length; + u16 status; + u16 bcn_tmr; + u32 tsf_low; + u64 tsf; + u8 rssi; + u8 agc; + u16 sig_avg; + u16 noise_diff; + struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt); + struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); + struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); + u8 *data = IWL_RX_DATA(pkt); + + /* MAC header */ + fc = le16_to_cpu(header->frame_control); + seq_ctl = le16_to_cpu(header->seq_ctrl); + + /* metadata */ + channel = le16_to_cpu(rx_hdr->channel); + phy_flags = le16_to_cpu(rx_hdr->phy_flags); + length = le16_to_cpu(rx_hdr->len); + + /* end-of-frame status and timestamp */ + status = le32_to_cpu(rx_end->status); + bcn_tmr = le32_to_cpu(rx_end->beacon_timestamp); + tsf_low = le64_to_cpu(rx_end->timestamp) & 0x0ffffffff; + tsf = le64_to_cpu(rx_end->timestamp); + + /* signal statistics */ + rssi = rx_stats->rssi; + agc = rx_stats->agc; + sig_avg = le16_to_cpu(rx_stats->sig_avg); + noise_diff = le16_to_cpu(rx_stats->noise_diff); + + to_us = !compare_ether_addr(header->addr1, priv->mac_addr); + + /* if data frame is to us and all is good, + * (optionally) print summary for only 1 out of every 100 */ + if (to_us && (fc & ~IEEE80211_FCTL_PROTECTED) == + (IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) { + dataframe = 1; + if (!group100) + print_summary = 1; /* print each frame */ + else if (priv->framecnt_to_us < 100) { + priv->framecnt_to_us++; + print_summary = 0; + } else { + priv->framecnt_to_us = 0; + print_summary = 1; + hundred = 1; + } + } else { + /* print summary for all other frames */ + print_summary = 1; + } + + if (print_summary) { + char *title; + u32 rate; + + if (hundred) + title = "100Frames"; + else if (fc & IEEE80211_FCTL_RETRY) + title = "Retry"; + else if (ieee80211_is_assoc_response(fc)) + title = "AscRsp"; + else if (ieee80211_is_reassoc_response(fc)) + title = "RasRsp"; + else if (ieee80211_is_probe_response(fc)) { + title = "PrbRsp"; + print_dump = 1; /* dump frame contents */ + } else if (ieee80211_is_beacon(fc)) { + title = "Beacon"; + print_dump = 1; /* dump frame contents */ + } else if (ieee80211_is_atim(fc)) + title = "ATIM"; + else if (ieee80211_is_auth(fc)) + title = "Auth"; + else if (ieee80211_is_deauth(fc)) + title = "DeAuth"; + else if (ieee80211_is_disassoc(fc)) + title = "DisAssoc"; + else + title = "Frame"; + + rate = iwl3945_hwrate_to_plcp_idx(rx_hdr->rate); + if (rate == -1) + rate = 0; + else + rate = iwl3945_rates[rate].ieee / 2; + + /* print frame summary. + * MAC addresses show just the last byte (for brevity), + * but you can hack it to show more, if you'd like to. */ + if (dataframe) + IWL_DEBUG_RX("%s: mhd=0x%04x, dst=0x%02x, " + "len=%u, rssi=%d, chnl=%d, rate=%u, \n", + title, fc, header->addr1[5], + length, rssi, channel, rate); + else { + /* src/dst addresses assume managed mode */ + IWL_DEBUG_RX("%s: 0x%04x, dst=0x%02x, " + "src=0x%02x, rssi=%u, tim=%lu usec, " + "phy=0x%02x, chnl=%d\n", + title, fc, header->addr1[5], + header->addr3[5], rssi, + tsf_low - priv->scan_start_tsf, + phy_flags, channel); + } + } + if (print_dump) + iwl3945_print_hex_dump(IWL_DL_RX, data, length); +} +#else +static inline void iwl3945_dbg_report_frame(struct iwl3945_priv *priv, + struct iwl3945_rx_packet *pkt, + struct ieee80211_hdr *header, int group100) +{ +} +#endif + + static void iwl3945_add_radiotap(struct iwl3945_priv *priv, struct sk_buff *skb, struct iwl3945_rx_frame_hdr *rx_hdr, @@ -376,24 +536,28 @@ static void iwl3945_handle_data_packet(struct iwl3945_priv *priv, int is_data, static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv, struct iwl3945_rx_mem_buffer *rxb) { + struct ieee80211_hdr *header; + struct ieee80211_rx_status rx_status; struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data; struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt); struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); - struct ieee80211_hdr *header; + int snr; u16 rx_stats_sig_avg = le16_to_cpu(rx_stats->sig_avg); u16 rx_stats_noise_diff = le16_to_cpu(rx_stats->noise_diff); - struct ieee80211_rx_status stats = { - .mactime = le64_to_cpu(rx_end->timestamp), - .freq = ieee80211chan2mhz(le16_to_cpu(rx_hdr->channel)), - .band = (rx_hdr->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? - IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ, - .antenna = 0, - .rate_idx = iwl3945_rate_index_from_plcp(rx_hdr->rate), - .flag = 0, - }; u8 network_packet; - int snr; + + rx_status.antenna = 0; + rx_status.flag = 0; + rx_status.mactime = le64_to_cpu(rx_end->timestamp); + rx_status.freq = ieee80211chan2mhz(le16_to_cpu(rx_hdr->channel)); + rx_status.band = (rx_hdr->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? + IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; + + rx_status.rate_idx = iwl3945_hwrate_to_plcp_idx(rx_hdr->rate); + + if (rx_status.band == IEEE80211_BAND_5GHZ) + rx_status.rate_idx -= IWL_FIRST_OFDM_RATE; if ((unlikely(rx_stats->phy_count > 20))) { IWL_DEBUG_DROP @@ -409,12 +573,12 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv, } if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) { - iwl3945_handle_data_packet(priv, 1, rxb, &stats); + iwl3945_handle_data_packet(priv, 1, rxb, &rx_status); return; } /* Convert 3945's rssi indicator to dBm */ - stats.ssi = rx_stats->rssi - IWL_RSSI_OFFSET; + rx_status.ssi = rx_stats->rssi - IWL_RSSI_OFFSET; /* Set default noise value to -127 */ if (priv->last_rx_noise == 0) @@ -430,50 +594,47 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv, * signal-to-noise ratio (SNR) is (sig_avg / noise_diff). * Convert linear SNR to dB SNR, then subtract that from rssi dBm * to obtain noise level in dBm. - * Calculate stats.signal (quality indicator in %) based on SNR. */ + * Calculate rx_status.signal (quality indicator in %) based on SNR. */ if (rx_stats_noise_diff) { snr = rx_stats_sig_avg / rx_stats_noise_diff; - stats.noise = stats.ssi - iwl3945_calc_db_from_ratio(snr); - stats.signal = iwl3945_calc_sig_qual(stats.ssi, stats.noise); + rx_status.noise = rx_status.ssi - + iwl3945_calc_db_from_ratio(snr); + rx_status.signal = iwl3945_calc_sig_qual(rx_status.ssi, + rx_status.noise); /* If noise info not available, calculate signal quality indicator (%) * using just the dBm signal level. */ } else { - stats.noise = priv->last_rx_noise; - stats.signal = iwl3945_calc_sig_qual(stats.ssi, 0); + rx_status.noise = priv->last_rx_noise; + rx_status.signal = iwl3945_calc_sig_qual(rx_status.ssi, 0); } IWL_DEBUG_STATS("Rssi %d noise %d qual %d sig_avg %d noise_diff %d\n", - stats.ssi, stats.noise, stats.signal, + rx_status.ssi, rx_status.noise, rx_status.signal, rx_stats_sig_avg, rx_stats_noise_diff); - /* can be covered by iwl3945_report_frame() in most cases */ -/* IWL_DEBUG_RX("RX status: 0x%08X\n", rx_end->status); */ - header = (struct ieee80211_hdr *)IWL_RX_DATA(pkt); network_packet = iwl3945_is_network_packet(priv, header); -#ifdef CONFIG_IWL3945_DEBUG - if (iwl3945_debug_level & IWL_DL_STATS && net_ratelimit()) - IWL_DEBUG_STATS - ("[%c] %d RSSI: %d Signal: %u, Noise: %u, Rate: %u\n", - network_packet ? '*' : ' ', - le16_to_cpu(rx_hdr->channel), - stats.ssi, stats.ssi, - stats.ssi, stats.rate_idx); + IWL_DEBUG_STATS_LIMIT("[%c] %d RSSI:%d Signal:%u, Noise:%u, Rate:%u\n", + network_packet ? '*' : ' ', + le16_to_cpu(rx_hdr->channel), + rx_status.ssi, rx_status.ssi, + rx_status.ssi, rx_status.rate_idx); +#ifdef CONFIG_IWL3945_DEBUG if (iwl3945_debug_level & (IWL_DL_RX)) /* Set "1" to report good data frames in groups of 100 */ - iwl3945_report_frame(priv, pkt, header, 1); + iwl3945_dbg_report_frame(priv, pkt, header, 1); #endif if (network_packet) { priv->last_beacon_time = le32_to_cpu(rx_end->beacon_timestamp); priv->last_tsf = le64_to_cpu(rx_end->timestamp); - priv->last_rx_rssi = stats.ssi; - priv->last_rx_noise = stats.noise; + priv->last_rx_rssi = rx_status.ssi; + priv->last_rx_noise = rx_status.noise; } switch (le16_to_cpu(header->frame_control) & IEEE80211_FCTL_FTYPE) { @@ -560,7 +721,7 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv, } } - iwl3945_handle_data_packet(priv, 0, rxb, &stats); + iwl3945_handle_data_packet(priv, 0, rxb, &rx_status); break; case IEEE80211_FTYPE_CTL: @@ -577,7 +738,7 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv, print_mac(mac2, header->addr2), print_mac(mac3, header->addr3)); else - iwl3945_handle_data_packet(priv, 1, rxb, &stats); + iwl3945_handle_data_packet(priv, 1, rxb, &rx_status); break; } } diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index d36ae0045c57..d281e42964d5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -558,16 +558,6 @@ extern int iwl3945_is_network_packet(struct iwl3945_priv *priv, struct ieee80211_hdr *header); extern int iwl3945_power_init_handle(struct iwl3945_priv *priv); extern int iwl3945_eeprom_init(struct iwl3945_priv *priv); -#ifdef CONFIG_IWL3945_DEBUG -extern void iwl3945_report_frame(struct iwl3945_priv *priv, - struct iwl3945_rx_packet *pkt, - struct ieee80211_hdr *header, int group100); -#else -static inline void iwl3945_report_frame(struct iwl3945_priv *priv, - struct iwl3945_rx_packet *pkt, - struct ieee80211_hdr *header, - int group100) {} -#endif extern void iwl3945_handle_data_packet_monitor(struct iwl3945_priv *priv, struct iwl3945_rx_mem_buffer *rxb, void *data, short len, @@ -949,16 +939,6 @@ static inline int is_channel_ibss(const struct iwl3945_channel_info *ch) return ((ch->flags & EEPROM_CHANNEL_IBSS)) ? 1 : 0; } -static inline int iwl3945_rate_index_from_plcp(int plcp) -{ - int i; - - for (i = 0; i < IWL_RATE_COUNT; i++) - if (iwl3945_rates[i].plcp == plcp) - return i; - return -1; -} - extern const struct iwl3945_channel_info *iwl3945_get_channel_info( const struct iwl3945_priv *priv, enum ieee80211_band band, u16 channel); diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-debug.h b/drivers/net/wireless/iwlwifi/iwl-4965-debug.h index 36696bbf170c..baf07c715cf8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-debug.h @@ -40,15 +40,30 @@ do { if (iwl4965_debug_level & (level)) \ do { if ((iwl4965_debug_level & (level)) && net_ratelimit()) \ printk(KERN_ERR DRV_NAME": %c %s " fmt, \ in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0) + +static inline void iwl4965_print_hex_dump(int level, void *p, u32 len) +{ + if (!(iwl4965_debug_level & level)) + return; + + print_hex_dump(KERN_DEBUG, "iwl data: ", DUMP_PREFIX_OFFSET, 16, 1, + p, len, 1); +} #else + static inline void IWL_DEBUG(int level, const char *fmt, ...) { } static inline void IWL_DEBUG_LIMIT(int level, const char *fmt, ...) { } +static inline void iwl4965_print_hex_dump(int level, void *p, u32 len) +{ +} #endif /* CONFIG_IWL4965_DEBUG */ + + /* * To use the debug system; * @@ -143,6 +158,7 @@ static inline void IWL_DEBUG_LIMIT(int level, const char *fmt, ...) IWL_DEBUG_LIMIT(IWL_DL_ASSOC | IWL_DL_INFO, f, ## a) #define IWL_DEBUG_HT(f, a...) IWL_DEBUG(IWL_DL_HT, f, ## a) #define IWL_DEBUG_STATS(f, a...) IWL_DEBUG(IWL_DL_STATS, f, ## a) +#define IWL_DEBUG_STATS_LIMIT(f, a...) IWL_DEBUG_LIMIT(IWL_DL_STATS, f, ## a) #define IWL_DEBUG_TX_REPLY(f, a...) IWL_DEBUG(IWL_DL_TX_REPLY, f, ## a) #define IWL_DEBUG_QOS(f, a...) IWL_DEBUG(IWL_DL_QOS, f, ## a) #define IWL_DEBUG_RADIO(f, a...) IWL_DEBUG(IWL_DL_RADIO, f, ## a) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c index 46d85fd07faa..cf7b569a2229 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c @@ -570,7 +570,7 @@ static int rs_get_tbl_info_from_mcs(const struct iwl4965_rate *mcs_rate, int index; u32 ant_msk; - index = iwl4965_rate_index_from_plcp(mcs_rate->rate_n_flags); + index = iwl4965_hwrate_to_plcp_idx(mcs_rate->rate_n_flags); if (index == IWL_RATE_INVALID) { *rate_idx = -1; @@ -1921,7 +1921,7 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv, tbl = &(lq_sta->lq_info[active_tbl]); /* Revert to "active" rate and throughput info */ - index = iwl4965_rate_index_from_plcp( + index = iwl4965_hwrate_to_plcp_idx( tbl->current_rate.rate_n_flags); current_tpt = lq_sta->last_tpt; @@ -2077,7 +2077,7 @@ static void rs_rate_scale_perform(struct iwl4965_priv *priv, rs_rate_scale_clear_window(&(tbl->win[i])); /* Use new "search" start rate */ - index = iwl4965_rate_index_from_plcp( + index = iwl4965_hwrate_to_plcp_idx( tbl->current_rate.rate_n_flags); IWL_DEBUG_HT("Switch current mcs: %X index: %d\n", diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.h b/drivers/net/wireless/iwlwifi/iwl-4965-rs.h index 13b6c72eeb73..911f21396fd0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.h @@ -259,7 +259,7 @@ static inline u8 iwl4965_get_prev_ieee_rate(u8 rate_index) return rate; } -extern int iwl4965_rate_index_from_plcp(int plcp); +extern int iwl4965_hwrate_to_plcp_idx(u32 rate_n_flags); /** * iwl4965_fill_rs_info - Fill an output text buffer with the rate representation diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index a9c30bcb65b8..8b9c419e094e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -122,6 +122,35 @@ static u8 is_single_stream(struct iwl4965_priv *priv) return 0; } +int iwl4965_hwrate_to_plcp_idx(u32 rate_n_flags) +{ + int idx = 0; + + /* 4965 HT rate format */ + if (rate_n_flags & RATE_MCS_HT_MSK) { + idx = (rate_n_flags & 0xff); + + if (idx >= IWL_RATE_MIMO_6M_PLCP) + idx = idx - IWL_RATE_MIMO_6M_PLCP; + + idx += IWL_FIRST_OFDM_RATE; + /* skip 9M not supported in ht*/ + if (idx >= IWL_RATE_9M_INDEX) + idx += 1; + if ((idx >= IWL_FIRST_OFDM_RATE) && (idx <= IWL_LAST_OFDM_RATE)) + return idx; + + /* 4965 legacy rate format, search for match in table */ + } else { + for (idx = 0; idx < ARRAY_SIZE(iwl4965_rates); idx++) + if (iwl4965_rates[idx].plcp == (rate_n_flags & 0xFF)) + return idx; + } + + return -1; +} + + /* * Determine how many receiver/antenna chains to use. * More provides better reception via diversity. Fewer saves power. @@ -3523,6 +3552,160 @@ static void iwl4965_update_ps_mode(struct iwl4965_priv *priv, u16 ps_bit, u8 *ad } } } +#ifdef CONFIG_IWL4965_DEBUG + +/** + * iwl4965_dbg_report_frame - dump frame to syslog during debug sessions + * + * You may hack this function to show different aspects of received frames, + * including selective frame dumps. + * group100 parameter selects whether to show 1 out of 100 good frames. + * + * TODO: This was originally written for 3945, need to audit for + * proper operation with 4965. + */ +static void iwl4965_dbg_report_frame(struct iwl4965_priv *priv, + struct iwl4965_rx_packet *pkt, + struct ieee80211_hdr *header, int group100) +{ + u32 to_us; + u32 print_summary = 0; + u32 print_dump = 0; /* set to 1 to dump all frames' contents */ + u32 hundred = 0; + u32 dataframe = 0; + u16 fc; + u16 seq_ctl; + u16 channel; + u16 phy_flags; + int rate_sym; + u16 length; + u16 status; + u16 bcn_tmr; + u32 tsf_low; + u64 tsf; + u8 rssi; + u8 agc; + u16 sig_avg; + u16 noise_diff; + struct iwl4965_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt); + struct iwl4965_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); + struct iwl4965_rx_frame_end *rx_end = IWL_RX_END(pkt); + u8 *data = IWL_RX_DATA(pkt); + + if (likely(!(iwl4965_debug_level & IWL_DL_RX))) + return; + + /* MAC header */ + fc = le16_to_cpu(header->frame_control); + seq_ctl = le16_to_cpu(header->seq_ctrl); + + /* metadata */ + channel = le16_to_cpu(rx_hdr->channel); + phy_flags = le16_to_cpu(rx_hdr->phy_flags); + rate_sym = rx_hdr->rate; + length = le16_to_cpu(rx_hdr->len); + + /* end-of-frame status and timestamp */ + status = le32_to_cpu(rx_end->status); + bcn_tmr = le32_to_cpu(rx_end->beacon_timestamp); + tsf_low = le64_to_cpu(rx_end->timestamp) & 0x0ffffffff; + tsf = le64_to_cpu(rx_end->timestamp); + + /* signal statistics */ + rssi = rx_stats->rssi; + agc = rx_stats->agc; + sig_avg = le16_to_cpu(rx_stats->sig_avg); + noise_diff = le16_to_cpu(rx_stats->noise_diff); + + to_us = !compare_ether_addr(header->addr1, priv->mac_addr); + + /* if data frame is to us and all is good, + * (optionally) print summary for only 1 out of every 100 */ + if (to_us && (fc & ~IEEE80211_FCTL_PROTECTED) == + (IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) { + dataframe = 1; + if (!group100) + print_summary = 1; /* print each frame */ + else if (priv->framecnt_to_us < 100) { + priv->framecnt_to_us++; + print_summary = 0; + } else { + priv->framecnt_to_us = 0; + print_summary = 1; + hundred = 1; + } + } else { + /* print summary for all other frames */ + print_summary = 1; + } + + if (print_summary) { + char *title; + int rate_idx; + u32 bitrate; + + if (hundred) + title = "100Frames"; + else if (fc & IEEE80211_FCTL_RETRY) + title = "Retry"; + else if (ieee80211_is_assoc_response(fc)) + title = "AscRsp"; + else if (ieee80211_is_reassoc_response(fc)) + title = "RasRsp"; + else if (ieee80211_is_probe_response(fc)) { + title = "PrbRsp"; + print_dump = 1; /* dump frame contents */ + } else if (ieee80211_is_beacon(fc)) { + title = "Beacon"; + print_dump = 1; /* dump frame contents */ + } else if (ieee80211_is_atim(fc)) + title = "ATIM"; + else if (ieee80211_is_auth(fc)) + title = "Auth"; + else if (ieee80211_is_deauth(fc)) + title = "DeAuth"; + else if (ieee80211_is_disassoc(fc)) + title = "DisAssoc"; + else + title = "Frame"; + + rate_idx = iwl4965_hwrate_to_plcp_idx(rate_sym); + if (unlikely(rate_idx == -1)) + bitrate = 0; + else + bitrate = iwl4965_rates[rate_idx].ieee / 2; + + /* print frame summary. + * MAC addresses show just the last byte (for brevity), + * but you can hack it to show more, if you'd like to. */ + if (dataframe) + IWL_DEBUG_RX("%s: mhd=0x%04x, dst=0x%02x, " + "len=%u, rssi=%d, chnl=%d, rate=%u, \n", + title, fc, header->addr1[5], + length, rssi, channel, bitrate); + else { + /* src/dst addresses assume managed mode */ + IWL_DEBUG_RX("%s: 0x%04x, dst=0x%02x, " + "src=0x%02x, rssi=%u, tim=%lu usec, " + "phy=0x%02x, chnl=%d\n", + title, fc, header->addr1[5], + header->addr3[5], rssi, + tsf_low - priv->scan_start_tsf, + phy_flags, channel); + } + } + if (print_dump) + iwl4965_print_hex_dump(IWL_DL_RX, data, length); +} +#else +static inline void iwl4965_dbg_report_frame(struct iwl4965_priv *priv, + struct iwl4965_rx_packet *pkt, + struct ieee80211_hdr *header, + int group100) +{ +} +#endif + #define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6) @@ -3531,6 +3714,8 @@ static void iwl4965_update_ps_mode(struct iwl4965_priv *priv, u16 ps_bit, u8 *ad static void iwl4965_rx_reply_rx(struct iwl4965_priv *priv, struct iwl4965_rx_mem_buffer *rxb) { + struct ieee80211_hdr *header; + struct ieee80211_rx_status rx_status; struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data; /* Use phy data (Rx signal strength, etc.) contained within * this rx packet for legacy frames, @@ -3541,27 +3726,29 @@ static void iwl4965_rx_reply_rx(struct iwl4965_priv *priv, (struct iwl4965_rx_phy_res *)&priv->last_phy_res[1]; __le32 *rx_end; unsigned int len = 0; - struct ieee80211_hdr *header; u16 fc; - struct ieee80211_rx_status stats = { - .mactime = le64_to_cpu(rx_start->timestamp), - .freq = ieee80211chan2mhz(le16_to_cpu(rx_start->channel)), - .band = - (rx_start->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? - IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ, - .antenna = 0, - .rate_idx = iwl4965_rate_index_from_plcp( - le32_to_cpu(rx_start->rate_n_flags)), - .flag = 0, - }; u8 network_packet; + rx_status.mactime = le64_to_cpu(rx_start->timestamp); + rx_status.freq = ieee80211chan2mhz(le16_to_cpu(rx_start->channel)); + rx_status.band = (rx_start->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? + IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; + rx_status.rate_idx = iwl4965_hwrate_to_plcp_idx( + le32_to_cpu(rx_start->rate_n_flags)); + + if (rx_status.band == IEEE80211_BAND_5GHZ) + rx_status.rate_idx -= IWL_FIRST_OFDM_RATE; + + rx_status.antenna = 0; + rx_status.flag = 0; + if ((unlikely(rx_start->cfg_phy_cnt > 20))) { IWL_DEBUG_DROP ("dsp size out of range [0,20]: " "%d/n", rx_start->cfg_phy_cnt); return; } + if (!include_phy) { if (priv->last_phy_res[0]) rx_start = (struct iwl4965_rx_phy_res *) @@ -3580,7 +3767,7 @@ static void iwl4965_rx_reply_rx(struct iwl4965_priv *priv, + rx_start->cfg_phy_cnt); len = le16_to_cpu(rx_start->byte_count); - rx_end = (__le32 *) (pkt->u.raw + rx_start->cfg_phy_cnt + + rx_end = (__le32 *)(pkt->u.raw + rx_start->cfg_phy_cnt + sizeof(struct iwl4965_rx_phy_res) + len); } else { struct iwl4965_rx_mpdu_res_start *amsdu = @@ -3603,7 +3790,7 @@ static void iwl4965_rx_reply_rx(struct iwl4965_priv *priv, priv->ucode_beacon_time = le32_to_cpu(rx_start->beacon_time_stamp); /* Find max signal strength (dBm) among 3 antenna/receiver chains */ - stats.ssi = iwl4965_calc_rssi(rx_start); + rx_status.ssi = iwl4965_calc_rssi(rx_start); /* Meaningful noise values are available only from beacon statistics, * which are gathered only when associated, and indicate noise @@ -3611,32 +3798,29 @@ static void iwl4965_rx_reply_rx(struct iwl4965_priv *priv, * Ignore these noise values while scanning (other channels) */ if (iwl4965_is_associated(priv) && !test_bit(STATUS_SCANNING, &priv->status)) { - stats.noise = priv->last_rx_noise; - stats.signal = iwl4965_calc_sig_qual(stats.ssi, stats.noise); + rx_status.noise = priv->last_rx_noise; + rx_status.signal = iwl4965_calc_sig_qual(rx_status.ssi, + rx_status.noise); } else { - stats.noise = IWL_NOISE_MEAS_NOT_AVAILABLE; - stats.signal = iwl4965_calc_sig_qual(stats.ssi, 0); + rx_status.noise = IWL_NOISE_MEAS_NOT_AVAILABLE; + rx_status.signal = iwl4965_calc_sig_qual(rx_status.ssi, 0); } /* Reset beacon noise level if not associated. */ if (!iwl4965_is_associated(priv)) priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE; -#ifdef CONFIG_IWL4965_DEBUG - /* TODO: Parts of iwl4965_report_frame are broken for 4965 */ - if (iwl4965_debug_level & (IWL_DL_RX)) - /* Set "1" to report good data frames in groups of 100 */ - iwl4965_report_frame(priv, pkt, header, 1); - - if (iwl4965_debug_level & (IWL_DL_RX | IWL_DL_STATS)) - IWL_DEBUG_RX("Rssi %d, noise %d, qual %d, TSF %lu\n", - stats.ssi, stats.noise, stats.signal, - (long unsigned int)le64_to_cpu(rx_start->timestamp)); -#endif + /* Set "1" to report good data frames in groups of 100 */ + /* FIXME: need to optimze the call: */ + iwl4965_dbg_report_frame(priv, pkt, header, 1); + + IWL_DEBUG_STATS_LIMIT("Rssi %d, noise %d, qual %d, TSF %llu\n", + rx_status.ssi, rx_status.noise, rx_status.signal, + rx_status.mactime); network_packet = iwl4965_is_network_packet(priv, header); if (network_packet) { - priv->last_rx_rssi = stats.ssi; + priv->last_rx_rssi = rx_status.ssi; priv->last_beacon_time = priv->ucode_beacon_time; priv->last_tsf = le64_to_cpu(rx_start->timestamp); } @@ -3739,7 +3923,7 @@ static void iwl4965_rx_reply_rx(struct iwl4965_priv *priv, return; } } - iwl4965_handle_data_packet(priv, 0, include_phy, rxb, &stats); + iwl4965_handle_data_packet(priv, 0, include_phy, rxb, &rx_status); break; case IEEE80211_FTYPE_CTL: @@ -3748,7 +3932,7 @@ static void iwl4965_rx_reply_rx(struct iwl4965_priv *priv, case IEEE80211_STYPE_BACK_REQ: IWL_DEBUG_HT("IEEE80211_STYPE_BACK_REQ arrived\n"); iwl4965_handle_data_packet(priv, 0, include_phy, - rxb, &stats); + rxb, &rx_status); break; default: break; @@ -3778,7 +3962,7 @@ static void iwl4965_rx_reply_rx(struct iwl4965_priv *priv, print_mac(mac3, header->addr3)); else iwl4965_handle_data_packet(priv, 1, include_phy, rxb, - &stats); + &rx_status); break; } default: diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index cc0745bfd1fb..4b3def31a9c1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -633,16 +633,6 @@ extern int iwl4965_is_network_packet(struct iwl4965_priv *priv, struct ieee80211_hdr *header); extern int iwl4965_power_init_handle(struct iwl4965_priv *priv); extern int iwl4965_eeprom_init(struct iwl4965_priv *priv); -#ifdef CONFIG_IWL4965_DEBUG -extern void iwl4965_report_frame(struct iwl4965_priv *priv, - struct iwl4965_rx_packet *pkt, - struct ieee80211_hdr *header, int group100); -#else -static inline void iwl4965_report_frame(struct iwl4965_priv *priv, - struct iwl4965_rx_packet *pkt, - struct ieee80211_hdr *header, - int group100) {} -#endif extern void iwl4965_handle_data_packet_monitor(struct iwl4965_priv *priv, struct iwl4965_rx_mem_buffer *rxb, void *data, short len, diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 0cafbd42d84c..7a72048b0f42 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -162,17 +162,6 @@ static const char *iwl3945_escape_essid(const char *essid, u8 essid_len) return escaped; } -static void iwl3945_print_hex_dump(int level, void *p, u32 len) -{ -#ifdef CONFIG_IWL3945_DEBUG - if (!(iwl3945_debug_level & level)) - return; - - print_hex_dump(KERN_DEBUG, "iwl data: ", DUMP_PREFIX_OFFSET, 16, 1, - p, len, 1); -#endif -} - /*************** DMA-QUEUE-GENERAL-FUNCTIONS ***** * DMA services * @@ -1630,151 +1619,6 @@ int iwl3945_eeprom_init(struct iwl3945_priv *priv) return 0; } -/****************************************************************************** - * - * Misc. internal state and helper functions - * - ******************************************************************************/ -#ifdef CONFIG_IWL3945_DEBUG - -/** - * iwl3945_report_frame - dump frame to syslog during debug sessions - * - * You may hack this function to show different aspects of received frames, - * including selective frame dumps. - * group100 parameter selects whether to show 1 out of 100 good frames. - */ -void iwl3945_report_frame(struct iwl3945_priv *priv, - struct iwl3945_rx_packet *pkt, - struct ieee80211_hdr *header, int group100) -{ - u32 to_us; - u32 print_summary = 0; - u32 print_dump = 0; /* set to 1 to dump all frames' contents */ - u32 hundred = 0; - u32 dataframe = 0; - u16 fc; - u16 seq_ctl; - u16 channel; - u16 phy_flags; - int rate_sym; - u16 length; - u16 status; - u16 bcn_tmr; - u32 tsf_low; - u64 tsf; - u8 rssi; - u8 agc; - u16 sig_avg; - u16 noise_diff; - struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt); - struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); - struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); - u8 *data = IWL_RX_DATA(pkt); - - /* MAC header */ - fc = le16_to_cpu(header->frame_control); - seq_ctl = le16_to_cpu(header->seq_ctrl); - - /* metadata */ - channel = le16_to_cpu(rx_hdr->channel); - phy_flags = le16_to_cpu(rx_hdr->phy_flags); - rate_sym = rx_hdr->rate; - length = le16_to_cpu(rx_hdr->len); - - /* end-of-frame status and timestamp */ - status = le32_to_cpu(rx_end->status); - bcn_tmr = le32_to_cpu(rx_end->beacon_timestamp); - tsf_low = le64_to_cpu(rx_end->timestamp) & 0x0ffffffff; - tsf = le64_to_cpu(rx_end->timestamp); - - /* signal statistics */ - rssi = rx_stats->rssi; - agc = rx_stats->agc; - sig_avg = le16_to_cpu(rx_stats->sig_avg); - noise_diff = le16_to_cpu(rx_stats->noise_diff); - - to_us = !compare_ether_addr(header->addr1, priv->mac_addr); - - /* if data frame is to us and all is good, - * (optionally) print summary for only 1 out of every 100 */ - if (to_us && (fc & ~IEEE80211_FCTL_PROTECTED) == - (IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) { - dataframe = 1; - if (!group100) - print_summary = 1; /* print each frame */ - else if (priv->framecnt_to_us < 100) { - priv->framecnt_to_us++; - print_summary = 0; - } else { - priv->framecnt_to_us = 0; - print_summary = 1; - hundred = 1; - } - } else { - /* print summary for all other frames */ - print_summary = 1; - } - - if (print_summary) { - char *title; - u32 rate; - - if (hundred) - title = "100Frames"; - else if (fc & IEEE80211_FCTL_RETRY) - title = "Retry"; - else if (ieee80211_is_assoc_response(fc)) - title = "AscRsp"; - else if (ieee80211_is_reassoc_response(fc)) - title = "RasRsp"; - else if (ieee80211_is_probe_response(fc)) { - title = "PrbRsp"; - print_dump = 1; /* dump frame contents */ - } else if (ieee80211_is_beacon(fc)) { - title = "Beacon"; - print_dump = 1; /* dump frame contents */ - } else if (ieee80211_is_atim(fc)) - title = "ATIM"; - else if (ieee80211_is_auth(fc)) - title = "Auth"; - else if (ieee80211_is_deauth(fc)) - title = "DeAuth"; - else if (ieee80211_is_disassoc(fc)) - title = "DisAssoc"; - else - title = "Frame"; - - rate = iwl3945_rate_index_from_plcp(rate_sym); - if (rate == -1) - rate = 0; - else - rate = iwl3945_rates[rate].ieee / 2; - - /* print frame summary. - * MAC addresses show just the last byte (for brevity), - * but you can hack it to show more, if you'd like to. */ - if (dataframe) - IWL_DEBUG_RX("%s: mhd=0x%04x, dst=0x%02x, " - "len=%u, rssi=%d, chnl=%d, rate=%u, \n", - title, fc, header->addr1[5], - length, rssi, channel, rate); - else { - /* src/dst addresses assume managed mode */ - IWL_DEBUG_RX("%s: 0x%04x, dst=0x%02x, " - "src=0x%02x, rssi=%u, tim=%lu usec, " - "phy=0x%02x, chnl=%d\n", - title, fc, header->addr1[5], - header->addr3[5], rssi, - tsf_low - priv->scan_start_tsf, - phy_flags, channel); - } - } - if (print_dump) - iwl3945_print_hex_dump(IWL_DL_RX, data, length); -} -#endif - static void iwl3945_unset_hw_setting(struct iwl3945_priv *priv) { if (priv->hw_setting.shared_virt) @@ -7895,31 +7739,6 @@ static DEVICE_ATTR(measurement, S_IRUSR | S_IWUSR, show_measurement, store_measurement); #endif /* CONFIG_IWL3945_SPECTRUM_MEASUREMENT */ -static ssize_t show_rate(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct iwl3945_priv *priv = dev_get_drvdata(d); - unsigned long flags; - int i; - - spin_lock_irqsave(&priv->sta_lock, flags); - if (priv->iw_mode == IEEE80211_IF_TYPE_STA) - i = priv->stations[IWL_AP_ID].current_rate.s.rate; - else - i = priv->stations[IWL_STA_ID].current_rate.s.rate; - spin_unlock_irqrestore(&priv->sta_lock, flags); - - i = iwl3945_rate_index_from_plcp(i); - if (i == -1) - return sprintf(buf, "0\n"); - - return sprintf(buf, "%d%s\n", - (iwl3945_rates[i].ieee >> 1), - (iwl3945_rates[i].ieee & 0x1) ? ".5" : ""); -} - -static DEVICE_ATTR(rate, S_IRUSR, show_rate, NULL); - static ssize_t store_retry_rate(struct device *d, struct device_attribute *attr, const char *buf, size_t count) @@ -8210,7 +8029,6 @@ static struct attribute *iwl3945_sysfs_entries[] = { &dev_attr_measurement.attr, #endif &dev_attr_power_level.attr, - &dev_attr_rate.attr, &dev_attr_retry_rate.attr, &dev_attr_rf_kill.attr, &dev_attr_rs_window.attr, diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 46a43ff51526..2ed69376c96e 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -161,17 +161,6 @@ static const char *iwl4965_escape_essid(const char *essid, u8 essid_len) return escaped; } -static void iwl4965_print_hex_dump(int level, void *p, u32 len) -{ -#ifdef CONFIG_IWL4965_DEBUG - if (!(iwl4965_debug_level & level)) - return; - - print_hex_dump(KERN_DEBUG, "iwl data: ", DUMP_PREFIX_OFFSET, 16, 1, - p, len, 1); -#endif -} - /*************** DMA-QUEUE-GENERAL-FUNCTIONS ***** * DMA services * @@ -1551,34 +1540,6 @@ unsigned int iwl4965_fill_beacon_frame(struct iwl4965_priv *priv, return priv->ibss_beacon->len; } -int iwl4965_rate_index_from_plcp(int plcp) -{ - int i = 0; - - /* 4965 HT rate format */ - if (plcp & RATE_MCS_HT_MSK) { - i = (plcp & 0xff); - - if (i >= IWL_RATE_MIMO_6M_PLCP) - i = i - IWL_RATE_MIMO_6M_PLCP; - - i += IWL_FIRST_OFDM_RATE; - /* skip 9M not supported in ht*/ - if (i >= IWL_RATE_9M_INDEX) - i += 1; - if ((i >= IWL_FIRST_OFDM_RATE) && - (i <= IWL_LAST_OFDM_RATE)) - return i; - - /* 4965 legacy rate format, search for match in table */ - } else { - for (i = 0; i < ARRAY_SIZE(iwl4965_rates); i++) - if (iwl4965_rates[i].plcp == (plcp &0xFF)) - return i; - } - return -1; -} - static u8 iwl4965_rate_get_lowest_plcp(int rate_mask) { u8 i; @@ -1712,148 +1673,6 @@ done: * Misc. internal state and helper functions * ******************************************************************************/ -#ifdef CONFIG_IWL4965_DEBUG - -/** - * iwl4965_report_frame - dump frame to syslog during debug sessions - * - * You may hack this function to show different aspects of received frames, - * including selective frame dumps. - * group100 parameter selects whether to show 1 out of 100 good frames. - * - * TODO: This was originally written for 3945, need to audit for - * proper operation with 4965. - */ -void iwl4965_report_frame(struct iwl4965_priv *priv, - struct iwl4965_rx_packet *pkt, - struct ieee80211_hdr *header, int group100) -{ - u32 to_us; - u32 print_summary = 0; - u32 print_dump = 0; /* set to 1 to dump all frames' contents */ - u32 hundred = 0; - u32 dataframe = 0; - u16 fc; - u16 seq_ctl; - u16 channel; - u16 phy_flags; - int rate_sym; - u16 length; - u16 status; - u16 bcn_tmr; - u32 tsf_low; - u64 tsf; - u8 rssi; - u8 agc; - u16 sig_avg; - u16 noise_diff; - struct iwl4965_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt); - struct iwl4965_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); - struct iwl4965_rx_frame_end *rx_end = IWL_RX_END(pkt); - u8 *data = IWL_RX_DATA(pkt); - - /* MAC header */ - fc = le16_to_cpu(header->frame_control); - seq_ctl = le16_to_cpu(header->seq_ctrl); - - /* metadata */ - channel = le16_to_cpu(rx_hdr->channel); - phy_flags = le16_to_cpu(rx_hdr->phy_flags); - rate_sym = rx_hdr->rate; - length = le16_to_cpu(rx_hdr->len); - - /* end-of-frame status and timestamp */ - status = le32_to_cpu(rx_end->status); - bcn_tmr = le32_to_cpu(rx_end->beacon_timestamp); - tsf_low = le64_to_cpu(rx_end->timestamp) & 0x0ffffffff; - tsf = le64_to_cpu(rx_end->timestamp); - - /* signal statistics */ - rssi = rx_stats->rssi; - agc = rx_stats->agc; - sig_avg = le16_to_cpu(rx_stats->sig_avg); - noise_diff = le16_to_cpu(rx_stats->noise_diff); - - to_us = !compare_ether_addr(header->addr1, priv->mac_addr); - - /* if data frame is to us and all is good, - * (optionally) print summary for only 1 out of every 100 */ - if (to_us && (fc & ~IEEE80211_FCTL_PROTECTED) == - (IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) { - dataframe = 1; - if (!group100) - print_summary = 1; /* print each frame */ - else if (priv->framecnt_to_us < 100) { - priv->framecnt_to_us++; - print_summary = 0; - } else { - priv->framecnt_to_us = 0; - print_summary = 1; - hundred = 1; - } - } else { - /* print summary for all other frames */ - print_summary = 1; - } - - if (print_summary) { - char *title; - u32 rate; - - if (hundred) - title = "100Frames"; - else if (fc & IEEE80211_FCTL_RETRY) - title = "Retry"; - else if (ieee80211_is_assoc_response(fc)) - title = "AscRsp"; - else if (ieee80211_is_reassoc_response(fc)) - title = "RasRsp"; - else if (ieee80211_is_probe_response(fc)) { - title = "PrbRsp"; - print_dump = 1; /* dump frame contents */ - } else if (ieee80211_is_beacon(fc)) { - title = "Beacon"; - print_dump = 1; /* dump frame contents */ - } else if (ieee80211_is_atim(fc)) - title = "ATIM"; - else if (ieee80211_is_auth(fc)) - title = "Auth"; - else if (ieee80211_is_deauth(fc)) - title = "DeAuth"; - else if (ieee80211_is_disassoc(fc)) - title = "DisAssoc"; - else - title = "Frame"; - - rate = iwl4965_rate_index_from_plcp(rate_sym); - if (rate == -1) - rate = 0; - else - rate = iwl4965_rates[rate].ieee / 2; - - /* print frame summary. - * MAC addresses show just the last byte (for brevity), - * but you can hack it to show more, if you'd like to. */ - if (dataframe) - IWL_DEBUG_RX("%s: mhd=0x%04x, dst=0x%02x, " - "len=%u, rssi=%d, chnl=%d, rate=%u, \n", - title, fc, header->addr1[5], - length, rssi, channel, rate); - else { - /* src/dst addresses assume managed mode */ - IWL_DEBUG_RX("%s: 0x%04x, dst=0x%02x, " - "src=0x%02x, rssi=%u, tim=%lu usec, " - "phy=0x%02x, chnl=%d\n", - title, fc, header->addr1[5], - header->addr3[5], rssi, - tsf_low - priv->scan_start_tsf, - phy_flags, channel); - } - } - if (print_dump) - iwl4965_print_hex_dump(IWL_DL_RX, data, length); -} -#endif static void iwl4965_unset_hw_setting(struct iwl4965_priv *priv) { -- cgit v1.2.1 From 9e1228d00a8e959dd3f4d0bd7949fda1ce11b314 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Mon, 3 Mar 2008 12:15:39 +0100 Subject: libertas: convert KEY_MATERIAL to a direct command The struct enc_key probably wants to die too, but that can come later. Signed-off-by: David Woodhouse Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/assoc.c | 12 +-- drivers/net/wireless/libertas/cmd.c | 127 +++++++++++++++++++------------- drivers/net/wireless/libertas/cmd.h | 2 + drivers/net/wireless/libertas/cmdresp.c | 59 --------------- drivers/net/wireless/libertas/hostcmd.h | 3 +- 5 files changed, 81 insertions(+), 122 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c index 75f6191e718d..7fe37bedf313 100644 --- a/drivers/net/wireless/libertas/assoc.c +++ b/drivers/net/wireless/libertas/assoc.c @@ -349,11 +349,7 @@ static int assoc_helper_wpa_keys(struct lbs_private *priv, if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) { clear_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags); - ret = lbs_prepare_and_send_command(priv, - CMD_802_11_KEY_MATERIAL, - CMD_ACT_SET, - CMD_OPTION_WAITFORRSP, - 0, assoc_req); + ret = lbs_cmd_802_11_key_material(priv, CMD_ACT_SET, assoc_req); assoc_req->flags = flags; } @@ -363,11 +359,7 @@ static int assoc_helper_wpa_keys(struct lbs_private *priv, if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)) { clear_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags); - ret = lbs_prepare_and_send_command(priv, - CMD_802_11_KEY_MATERIAL, - CMD_ACT_SET, - CMD_OPTION_WAITFORRSP, - 0, assoc_req); + ret = lbs_cmd_802_11_key_material(priv, CMD_ACT_SET, assoc_req); assoc_req->flags = flags; } diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index 3f9074df91e4..34edc7d11da8 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -338,75 +338,103 @@ int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action, return ret; } -static void set_one_wpa_key(struct MrvlIEtype_keyParamSet * pkeyparamset, - struct enc_key * pkey) +static void set_one_wpa_key(struct MrvlIEtype_keyParamSet *keyparam, + struct enc_key *key) { lbs_deb_enter(LBS_DEB_CMD); - if (pkey->flags & KEY_INFO_WPA_ENABLED) { - pkeyparamset->keyinfo |= cpu_to_le16(KEY_INFO_WPA_ENABLED); - } - if (pkey->flags & KEY_INFO_WPA_UNICAST) { - pkeyparamset->keyinfo |= cpu_to_le16(KEY_INFO_WPA_UNICAST); - } - if (pkey->flags & KEY_INFO_WPA_MCAST) { - pkeyparamset->keyinfo |= cpu_to_le16(KEY_INFO_WPA_MCAST); - } + if (key->flags & KEY_INFO_WPA_ENABLED) + keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_ENABLED); + if (key->flags & KEY_INFO_WPA_UNICAST) + keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_UNICAST); + if (key->flags & KEY_INFO_WPA_MCAST) + keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_MCAST); - pkeyparamset->type = cpu_to_le16(TLV_TYPE_KEY_MATERIAL); - pkeyparamset->keytypeid = cpu_to_le16(pkey->type); - pkeyparamset->keylen = cpu_to_le16(pkey->len); - memcpy(pkeyparamset->key, pkey->key, pkey->len); - pkeyparamset->length = cpu_to_le16( sizeof(pkeyparamset->keytypeid) - + sizeof(pkeyparamset->keyinfo) - + sizeof(pkeyparamset->keylen) - + sizeof(pkeyparamset->key)); + keyparam->type = cpu_to_le16(TLV_TYPE_KEY_MATERIAL); + keyparam->keytypeid = cpu_to_le16(key->type); + keyparam->keylen = cpu_to_le16(key->len); + memcpy(keyparam->key, key->key, key->len); + + /* Length field doesn't include the {type,length} header */ + keyparam->length = cpu_to_le16(sizeof(*keyparam) - 4); lbs_deb_leave(LBS_DEB_CMD); } -static int lbs_cmd_802_11_key_material(struct lbs_private *priv, - struct cmd_ds_command *cmd, - u16 cmd_action, - u32 cmd_oid, void *pdata_buf) +int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action, + struct assoc_request *assoc) { - struct cmd_ds_802_11_key_material *pkeymaterial = - &cmd->params.keymaterial; - struct assoc_request * assoc_req = pdata_buf; + struct cmd_ds_802_11_key_material cmd; int ret = 0; int index = 0; lbs_deb_enter(LBS_DEB_CMD); - cmd->command = cpu_to_le16(CMD_802_11_KEY_MATERIAL); - pkeymaterial->action = cpu_to_le16(cmd_action); + cmd.action = cpu_to_le16(cmd_action); + cmd.hdr.size = cpu_to_le16(sizeof(cmd)); if (cmd_action == CMD_ACT_GET) { - cmd->size = cpu_to_le16(S_DS_GEN + sizeof (pkeymaterial->action)); - ret = 0; - goto done; - } + cmd.hdr.size = cpu_to_le16(S_DS_GEN + 2); + } else { + memset(cmd.keyParamSet, 0, sizeof(cmd.keyParamSet)); - memset(&pkeymaterial->keyParamSet, 0, sizeof(pkeymaterial->keyParamSet)); + if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc->flags)) { + set_one_wpa_key(&cmd.keyParamSet[index], + &assoc->wpa_unicast_key); + index++; + } - if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) { - set_one_wpa_key(&pkeymaterial->keyParamSet[index], - &assoc_req->wpa_unicast_key); - index++; - } + if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc->flags)) { + set_one_wpa_key(&cmd.keyParamSet[index], + &assoc->wpa_mcast_key); + index++; + } - if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)) { - set_one_wpa_key(&pkeymaterial->keyParamSet[index], - &assoc_req->wpa_mcast_key); - index++; + /* The common header and as many keys as we included */ + cmd.hdr.size = cpu_to_le16(offsetof(typeof(cmd), + keyParamSet[index])); } + ret = lbs_cmd_with_response(priv, CMD_802_11_KEY_MATERIAL, &cmd); + /* Copy the returned key to driver private data */ + if (!ret && cmd_action == CMD_ACT_GET) { + void *buf_ptr = cmd.keyParamSet; + void *resp_end = &(&cmd)[1]; + + while (buf_ptr < resp_end) { + struct MrvlIEtype_keyParamSet *keyparam = buf_ptr; + struct enc_key *key; + uint16_t param_set_len = le16_to_cpu(keyparam->length); + uint16_t key_len = le16_to_cpu(keyparam->keylen); + uint16_t key_flags = le16_to_cpu(keyparam->keyinfo); + uint16_t key_type = le16_to_cpu(keyparam->keytypeid); + void *end; + + end = (void *)keyparam + sizeof(keyparam->type) + + sizeof(keyparam->length) + param_set_len; + + /* Make sure we don't access past the end of the IEs */ + if (end > resp_end) + break; - cmd->size = cpu_to_le16( S_DS_GEN - + sizeof (pkeymaterial->action) - + (index * sizeof(struct MrvlIEtype_keyParamSet))); + if (key_flags & KEY_INFO_WPA_UNICAST) + key = &priv->wpa_unicast_key; + else if (key_flags & KEY_INFO_WPA_MCAST) + key = &priv->wpa_mcast_key; + else + break; - ret = 0; + /* Copy returned key into driver */ + memset(key, 0, sizeof(struct enc_key)); + if (key_len > sizeof(key->key)) + break; + key->type = key_type; + key->flags = key_flags; + key->len = key_len; + memcpy(key->key, keyparam->key, key->len); + + buf_ptr = end + 1; + } + } -done: lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); return ret; } @@ -1435,11 +1463,6 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, ret = lbs_cmd_80211_ad_hoc_stop(priv, cmdptr); break; - case CMD_802_11_KEY_MATERIAL: - ret = lbs_cmd_802_11_key_material(priv, cmdptr, cmd_action, - cmd_oid, pdata_buf); - break; - case CMD_802_11_PAIRWISE_TSC: break; case CMD_802_11_GROUP_TSC: diff --git a/drivers/net/wireless/libertas/cmd.h b/drivers/net/wireless/libertas/cmd.h index b9ab85cc7913..d250e6bc0609 100644 --- a/drivers/net/wireless/libertas/cmd.h +++ b/drivers/net/wireless/libertas/cmd.h @@ -57,5 +57,7 @@ int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action, struct assoc_request *assoc); int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action, uint16_t *enable); +int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action, + struct assoc_request *assoc); #endif /* _LBS_CMD_H */ diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c index 5d90b83f28eb..b96fe58ec495 100644 --- a/drivers/net/wireless/libertas/cmdresp.c +++ b/drivers/net/wireless/libertas/cmdresp.c @@ -204,61 +204,6 @@ static int lbs_ret_802_11_snmp_mib(struct lbs_private *priv, return 0; } -static int lbs_ret_802_11_key_material(struct lbs_private *priv, - struct cmd_ds_command *resp) -{ - struct cmd_ds_802_11_key_material *pkeymaterial = - &resp->params.keymaterial; - u16 action = le16_to_cpu(pkeymaterial->action); - - lbs_deb_enter(LBS_DEB_CMD); - - /* Copy the returned key to driver private data */ - if (action == CMD_ACT_GET) { - u8 * buf_ptr = (u8 *) &pkeymaterial->keyParamSet; - u8 * resp_end = (u8 *) (resp + le16_to_cpu(resp->size)); - - while (buf_ptr < resp_end) { - struct MrvlIEtype_keyParamSet * pkeyparamset = - (struct MrvlIEtype_keyParamSet *) buf_ptr; - struct enc_key * pkey; - u16 param_set_len = le16_to_cpu(pkeyparamset->length); - u16 key_len = le16_to_cpu(pkeyparamset->keylen); - u16 key_flags = le16_to_cpu(pkeyparamset->keyinfo); - u16 key_type = le16_to_cpu(pkeyparamset->keytypeid); - u8 * end; - - end = (u8 *) pkeyparamset + sizeof (pkeyparamset->type) - + sizeof (pkeyparamset->length) - + param_set_len; - /* Make sure we don't access past the end of the IEs */ - if (end > resp_end) - break; - - if (key_flags & KEY_INFO_WPA_UNICAST) - pkey = &priv->wpa_unicast_key; - else if (key_flags & KEY_INFO_WPA_MCAST) - pkey = &priv->wpa_mcast_key; - else - break; - - /* Copy returned key into driver */ - memset(pkey, 0, sizeof(struct enc_key)); - if (key_len > sizeof(pkey->key)) - break; - pkey->type = key_type; - pkey->flags = key_flags; - pkey->len = key_len; - memcpy(pkey->key, pkeyparamset->key, pkey->len); - - buf_ptr = end + 1; - } - } - - lbs_deb_enter(LBS_DEB_CMD); - return 0; -} - static int lbs_ret_802_11_mac_address(struct lbs_private *priv, struct cmd_ds_command *resp) { @@ -475,10 +420,6 @@ static inline int handle_cmd_response(struct lbs_private *priv, ret = lbs_ret_80211_ad_hoc_stop(priv, resp); break; - case CMD_RET(CMD_802_11_KEY_MATERIAL): - ret = lbs_ret_802_11_key_material(priv, resp); - break; - case CMD_RET(CMD_802_11_EEPROM_ACCESS): ret = lbs_ret_802_11_eeprom_access(priv, resp); break; diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h index d35b015b6657..0a36748b8bfc 100644 --- a/drivers/net/wireless/libertas/hostcmd.h +++ b/drivers/net/wireless/libertas/hostcmd.h @@ -572,6 +572,8 @@ struct cmd_ds_host_sleep { } __attribute__ ((packed)); struct cmd_ds_802_11_key_material { + struct cmd_header hdr; + __le16 action; struct MrvlIEtype_keyParamSet keyParamSet[2]; } __attribute__ ((packed)); @@ -712,7 +714,6 @@ struct cmd_ds_command { struct cmd_ds_802_11_rssi_rsp rssirsp; struct cmd_ds_802_11_disassociate dassociate; struct cmd_ds_802_11_mac_address macadd; - struct cmd_ds_802_11_key_material keymaterial; struct cmd_ds_mac_reg_access macreg; struct cmd_ds_bbp_reg_access bbpreg; struct cmd_ds_rf_reg_access rfreg; -- cgit v1.2.1 From c5562e98332511c3e4d7f807ae4dd85f6db2a7e6 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Mon, 3 Mar 2008 12:16:42 +0100 Subject: libertas: add LED control TLV to types.h Signed-off-by: David Woodhouse Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/types.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/libertas/types.h b/drivers/net/wireless/libertas/types.h index f0d57958b34b..4031be420862 100644 --- a/drivers/net/wireless/libertas/types.h +++ b/drivers/net/wireless/libertas/types.h @@ -239,4 +239,17 @@ struct mrvlietypes_ledgpio { struct led_pin ledpin[1]; } __attribute__ ((packed)); +struct led_bhv { + uint8_t firmwarestate; + uint8_t led; + uint8_t ledstate; + uint8_t ledarg; +} __attribute__ ((packed)); + + +struct mrvlietypes_ledbhv { + struct mrvlietypesheader header; + struct led_bhv ledbhv[1]; +} __attribute__ ((packed)); + #endif -- cgit v1.2.1 From fa62f99cf80af9c65bfc0f731d780e03e3ce6ede Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Mon, 3 Mar 2008 12:18:03 +0100 Subject: libertas: convert 802_11_SCAN to a direct command Signed-off-by: David Woodhouse Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/cmd.c | 4 -- drivers/net/wireless/libertas/cmdresp.c | 4 -- drivers/net/wireless/libertas/hostcmd.h | 16 +++-- drivers/net/wireless/libertas/scan.c | 122 +++++++++++--------------------- drivers/net/wireless/libertas/scan.h | 54 +------------- 5 files changed, 53 insertions(+), 147 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index 34edc7d11da8..445c6dc09786 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -1382,10 +1382,6 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, ret = lbs_cmd_802_11_ps_mode(priv, cmdptr, cmd_action); break; - case CMD_802_11_SCAN: - ret = lbs_cmd_80211_scan(priv, cmdptr, pdata_buf); - break; - case CMD_MAC_CONTROL: ret = lbs_cmd_mac_control(priv, cmdptr); break; diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c index b96fe58ec495..15e4ebdcd477 100644 --- a/drivers/net/wireless/libertas/cmdresp.c +++ b/drivers/net/wireless/libertas/cmdresp.c @@ -352,10 +352,6 @@ static inline int handle_cmd_response(struct lbs_private *priv, ret = lbs_ret_reg_access(priv, respcmd, resp); break; - case CMD_RET(CMD_802_11_SCAN): - ret = lbs_ret_80211_scan(priv, resp); - break; - case CMD_RET(CMD_802_11_GET_LOG): ret = lbs_ret_get_log(priv, resp); break; diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h index 0a36748b8bfc..56bc1aa2bb00 100644 --- a/drivers/net/wireless/libertas/hostcmd.h +++ b/drivers/net/wireless/libertas/hostcmd.h @@ -174,9 +174,11 @@ struct cmd_ds_802_11_subscribe_event { * Define data structure for CMD_802_11_SCAN */ struct cmd_ds_802_11_scan { - u8 bsstype; - u8 bssid[ETH_ALEN]; - u8 tlvbuffer[1]; + struct cmd_header hdr; + + uint8_t bsstype; + uint8_t bssid[ETH_ALEN]; + uint8_t tlvbuffer[0]; #if 0 mrvlietypes_ssidparamset_t ssidParamSet; mrvlietypes_chanlistparamset_t ChanListParamSet; @@ -185,9 +187,11 @@ struct cmd_ds_802_11_scan { }; struct cmd_ds_802_11_scan_rsp { + struct cmd_header hdr; + __le16 bssdescriptsize; - u8 nr_sets; - u8 bssdesc_and_tlvbuffer[1]; + uint8_t nr_sets; + uint8_t bssdesc_and_tlvbuffer[0]; }; struct cmd_ds_802_11_get_log { @@ -691,8 +695,6 @@ struct cmd_ds_command { /* command Body */ union { struct cmd_ds_802_11_ps_mode psmode; - struct cmd_ds_802_11_scan scan; - struct cmd_ds_802_11_scan_rsp scanresp; struct cmd_ds_mac_control macctrl; struct cmd_ds_802_11_associate associate; struct cmd_ds_802_11_deauthenticate deauth; diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c index 7d4f3afa8cc5..9f9c7d9c8bd2 100644 --- a/drivers/net/wireless/libertas/scan.c +++ b/drivers/net/wireless/libertas/scan.c @@ -20,6 +20,7 @@ #include "dev.h" #include "scan.h" #include "join.h" +#include "cmd.h" //! Approximate amount of data needed to pass a scan result back to iwlist #define MAX_SCAN_CELL_SIZE (IW_EV_ADDR_LEN \ @@ -39,10 +40,9 @@ //! Memory needed to store a max number/size SSID TLV for a firmware scan #define SSID_TLV_MAX_SIZE (1 * sizeof(struct mrvlietypes_ssidparamset)) -//! Maximum memory needed for a lbs_scan_cmd_config with all TLVs at max -#define MAX_SCAN_CFG_ALLOC (sizeof(struct lbs_scan_cmd_config) \ - + CHAN_TLV_MAX_SIZE \ - + SSID_TLV_MAX_SIZE) +//! Maximum memory needed for a cmd_ds_802_11_scan with all TLVs at max +#define MAX_SCAN_CFG_ALLOC (sizeof(struct cmd_ds_802_11_scan) \ + + CHAN_TLV_MAX_SIZE + SSID_TLV_MAX_SIZE) //! The maximum number of channels the firmware can scan per command #define MRVDRV_MAX_CHANNELS_PER_SCAN 14 @@ -64,8 +64,8 @@ static const u8 zeromac[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static const u8 bcastmac[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; - - +static int lbs_ret_80211_scan(struct lbs_private *priv, unsigned long dummy, + struct cmd_header *resp); /*********************************************************************/ /* */ @@ -492,24 +492,22 @@ static int lbs_scan_add_rates_tlv(u8 *tlv) * Generate the CMD_802_11_SCAN command with the proper tlv * for a bunch of channels. */ -static int lbs_do_scan(struct lbs_private *priv, - u8 bsstype, - struct chanscanparamset *chan_list, - int chan_count, - const struct lbs_ioctl_user_scan_cfg *user_cfg) +static int lbs_do_scan(struct lbs_private *priv, uint8_t bsstype, + struct chanscanparamset *chan_list, int chan_count, + const struct lbs_ioctl_user_scan_cfg *user_cfg) { int ret = -ENOMEM; - struct lbs_scan_cmd_config *scan_cmd; - u8 *tlv; /* pointer into our current, growing TLV storage area */ + struct cmd_ds_802_11_scan *scan_cmd; + uint8_t *tlv; /* pointer into our current, growing TLV storage area */ - lbs_deb_enter_args(LBS_DEB_SCAN, "bsstype %d, chanlist[].chan %d, " - "chan_count %d", - bsstype, chan_list[0].channumber, chan_count); + lbs_deb_enter_args(LBS_DEB_SCAN, "bsstype %d, chanlist[].chan %d, chan_count %d", + bsstype, chan_list[0].channumber, chan_count); /* create the fixed part for scan command */ scan_cmd = kzalloc(MAX_SCAN_CFG_ALLOC, GFP_KERNEL); if (scan_cmd == NULL) goto out; + tlv = scan_cmd->tlvbuffer; if (user_cfg) memcpy(scan_cmd->bssid, user_cfg->bssid, ETH_ALEN); @@ -523,13 +521,16 @@ static int lbs_do_scan(struct lbs_private *priv, tlv += lbs_scan_add_rates_tlv(tlv); /* This is the final data we are about to send */ - scan_cmd->tlvbufferlen = tlv - scan_cmd->tlvbuffer; - lbs_deb_hex(LBS_DEB_SCAN, "SCAN_CMD", (void *)scan_cmd, 1+6); + scan_cmd->hdr.size = cpu_to_le16(tlv - (uint8_t *)scan_cmd); + lbs_deb_hex(LBS_DEB_SCAN, "SCAN_CMD", (void *)scan_cmd, + sizeof(*scan_cmd)); lbs_deb_hex(LBS_DEB_SCAN, "SCAN_TLV", scan_cmd->tlvbuffer, - scan_cmd->tlvbufferlen); + tlv - scan_cmd->tlvbuffer); + + ret = __lbs_cmd(priv, CMD_802_11_SCAN, &scan_cmd->hdr, + le16_to_cpu(scan_cmd->hdr.size), + lbs_ret_80211_scan, 0); - ret = lbs_prepare_and_send_command(priv, CMD_802_11_SCAN, 0, - CMD_OPTION_WAITFORRSP, 0, scan_cmd); out: kfree(scan_cmd); lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); @@ -1484,44 +1485,6 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info, /*********************************************************************/ -/** - * @brief Prepare a scan command to be sent to the firmware - * - * Called via lbs_prepare_and_send_command(priv, CMD_802_11_SCAN, ...) - * from cmd.c - * - * Sends a fixed length data part (specifying the BSS type and BSSID filters) - * as well as a variable number/length of TLVs to the firmware. - * - * @param priv A pointer to struct lbs_private structure - * @param cmd A pointer to cmd_ds_command structure to be sent to - * firmware with the cmd_DS_801_11_SCAN structure - * @param pdata_buf Void pointer cast of a lbs_scan_cmd_config struct used - * to set the fields/TLVs for the command sent to firmware - * - * @return 0 or -1 - */ -int lbs_cmd_80211_scan(struct lbs_private *priv, - struct cmd_ds_command *cmd, void *pdata_buf) -{ - struct cmd_ds_802_11_scan *pscan = &cmd->params.scan; - struct lbs_scan_cmd_config *pscancfg = pdata_buf; - - lbs_deb_enter(LBS_DEB_SCAN); - - /* Set fixed field variables in scan command */ - pscan->bsstype = pscancfg->bsstype; - memcpy(pscan->bssid, pscancfg->bssid, ETH_ALEN); - memcpy(pscan->tlvbuffer, pscancfg->tlvbuffer, pscancfg->tlvbufferlen); - - /* size is equal to the sizeof(fixed portions) + the TLV len + header */ - cmd->size = cpu_to_le16(sizeof(pscan->bsstype) + ETH_ALEN - + pscancfg->tlvbufferlen + S_DS_GEN); - - lbs_deb_leave(LBS_DEB_SCAN); - return 0; -} - /** * @brief This function handles the command response of scan * @@ -1548,13 +1511,14 @@ int lbs_cmd_80211_scan(struct lbs_private *priv, * * @return 0 or -1 */ -int lbs_ret_80211_scan(struct lbs_private *priv, struct cmd_ds_command *resp) +static int lbs_ret_80211_scan(struct lbs_private *priv, unsigned long dummy, + struct cmd_header *resp) { - struct cmd_ds_802_11_scan_rsp *pscan; + struct cmd_ds_802_11_scan_rsp *scanresp = (void *)resp; struct bss_descriptor * iter_bss; struct bss_descriptor * safe; - u8 *pbssinfo; - u16 scanrespsize; + uint8_t *bssinfo; + uint16_t scanrespsize; int bytesleft; int idx; int tlvbufsize; @@ -1571,48 +1535,45 @@ int lbs_ret_80211_scan(struct lbs_private *priv, struct cmd_ds_command *resp) clear_bss_descriptor(iter_bss); } - pscan = &resp->params.scanresp; - - if (pscan->nr_sets > MAX_NETWORK_COUNT) { - lbs_deb_scan( - "SCAN_RESP: too many scan results (%d, max %d)!!\n", - pscan->nr_sets, MAX_NETWORK_COUNT); + if (scanresp->nr_sets > MAX_NETWORK_COUNT) { + lbs_deb_scan("SCAN_RESP: too many scan results (%d, max %d)\n", + scanresp->nr_sets, MAX_NETWORK_COUNT); ret = -1; goto done; } - bytesleft = le16_to_cpu(pscan->bssdescriptsize); + bytesleft = le16_to_cpu(scanresp->bssdescriptsize); lbs_deb_scan("SCAN_RESP: bssdescriptsize %d\n", bytesleft); scanrespsize = le16_to_cpu(resp->size); - lbs_deb_scan("SCAN_RESP: scan results %d\n", pscan->nr_sets); + lbs_deb_scan("SCAN_RESP: scan results %d\n", scanresp->nr_sets); - pbssinfo = pscan->bssdesc_and_tlvbuffer; + bssinfo = scanresp->bssdesc_and_tlvbuffer; /* The size of the TLV buffer is equal to the entire command response * size (scanrespsize) minus the fixed fields (sizeof()'s), the * BSS Descriptions (bssdescriptsize as bytesLef) and the command * response header (S_DS_GEN) */ - tlvbufsize = scanrespsize - (bytesleft + sizeof(pscan->bssdescriptsize) - + sizeof(pscan->nr_sets) + tlvbufsize = scanrespsize - (bytesleft + sizeof(scanresp->bssdescriptsize) + + sizeof(scanresp->nr_sets) + S_DS_GEN); /* - * Process each scan response returned (pscan->nr_sets). Save + * Process each scan response returned (scanresp->nr_sets). Save * the information in the newbssentry and then insert into the * driver scan table either as an update to an existing entry * or as an addition at the end of the table */ - for (idx = 0; idx < pscan->nr_sets && bytesleft; idx++) { + for (idx = 0; idx < scanresp->nr_sets && bytesleft; idx++) { struct bss_descriptor new; - struct bss_descriptor * found = NULL; - struct bss_descriptor * oldest = NULL; + struct bss_descriptor *found = NULL; + struct bss_descriptor *oldest = NULL; DECLARE_MAC_BUF(mac); /* Process the data fields and IEs returned for this BSS */ memset(&new, 0, sizeof (struct bss_descriptor)); - if (lbs_process_bss(&new, &pbssinfo, &bytesleft) != 0) { + if (lbs_process_bss(&new, &bssinfo, &bytesleft) != 0) { /* error parsing the scan response, skipped */ lbs_deb_scan("SCAN_RESP: process_bss returned ERROR\n"); continue; @@ -1647,8 +1608,7 @@ int lbs_ret_80211_scan(struct lbs_private *priv, struct cmd_ds_command *resp) continue; } - lbs_deb_scan("SCAN_RESP: BSSID %s\n", - print_mac(mac, new.bssid)); + lbs_deb_scan("SCAN_RESP: BSSID %s\n", print_mac(mac, new.bssid)); /* Copy the locally created newbssentry to the scan table */ memcpy(found, &new, offsetof(struct bss_descriptor, list)); diff --git a/drivers/net/wireless/libertas/scan.h b/drivers/net/wireless/libertas/scan.h index 319f70dde350..10d1196acf78 100644 --- a/drivers/net/wireless/libertas/scan.h +++ b/drivers/net/wireless/libertas/scan.h @@ -17,56 +17,15 @@ */ #define LBS_IOCTL_USER_SCAN_CHAN_MAX 50 -//! Infrastructure BSS scan type in lbs_scan_cmd_config +//! Infrastructure BSS scan type in cmd_ds_802_11_scan #define LBS_SCAN_BSS_TYPE_BSS 1 -//! Adhoc BSS scan type in lbs_scan_cmd_config +//! Adhoc BSS scan type in cmd_ds_802_11_scan #define LBS_SCAN_BSS_TYPE_IBSS 2 -//! Adhoc or Infrastructure BSS scan type in lbs_scan_cmd_config, no filter +//! Adhoc or Infrastructure BSS scan type in cmd_ds_802_11_scan, no filter #define LBS_SCAN_BSS_TYPE_ANY 3 -/** - * @brief Structure used internally in the wlan driver to configure a scan. - * - * Sent to the command processing module to configure the firmware - * scan command prepared by lbs_cmd_80211_scan. - * - * @sa lbs_scan_networks - * - */ -struct lbs_scan_cmd_config { - /** - * @brief BSS type to be sent in the firmware command - * - * Field can be used to restrict the types of networks returned in the - * scan. valid settings are: - * - * - LBS_SCAN_BSS_TYPE_BSS (infrastructure) - * - LBS_SCAN_BSS_TYPE_IBSS (adhoc) - * - LBS_SCAN_BSS_TYPE_ANY (unrestricted, adhoc and infrastructure) - */ - u8 bsstype; - - /** - * @brief Specific BSSID used to filter scan results in the firmware - */ - u8 bssid[ETH_ALEN]; - - /** - * @brief length of TLVs sent in command starting at tlvBuffer - */ - int tlvbufferlen; - - /** - * @brief SSID TLV(s) and ChanList TLVs to be sent in the firmware command - * - * @sa TLV_TYPE_CHANLIST, mrvlietypes_chanlistparamset_t - * @sa TLV_TYPE_SSID, mrvlietypes_ssidparamset_t - */ - u8 tlvbuffer[1]; //!< SSID TLV(s) and ChanList TLVs are stored here -}; - /** * @brief IOCTL channel sub-structure sent in lbs_ioctl_user_scan_cfg * @@ -179,13 +138,6 @@ int lbs_find_best_network_ssid(struct lbs_private *priv, u8 *out_ssid, int lbs_send_specific_ssid_scan(struct lbs_private *priv, u8 *ssid, u8 ssid_len, u8 clear_ssid); -int lbs_cmd_80211_scan(struct lbs_private *priv, - struct cmd_ds_command *cmd, - void *pdata_buf); - -int lbs_ret_80211_scan(struct lbs_private *priv, - struct cmd_ds_command *resp); - int lbs_scan_networks(struct lbs_private *priv, const struct lbs_ioctl_user_scan_cfg *puserscanin, int full_scan); -- cgit v1.2.1 From f137e05468f2a648aba11377dc824d788683dff4 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Mon, 3 Mar 2008 12:18:59 +0100 Subject: libertas: clean up scan.c, remove zeromac and bcastmac Should be purely cosmetic apart from the removal of the two pointless MAC addresses. Signed-off-by: David Woodhouse Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/scan.c | 415 +++++++++++++++-------------------- 1 file changed, 181 insertions(+), 234 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c index 9f9c7d9c8bd2..99f11a56d84e 100644 --- a/drivers/net/wireless/libertas/scan.c +++ b/drivers/net/wireless/libertas/scan.c @@ -61,9 +61,6 @@ //! Scan time specified in the channel TLV for each channel for active scans #define MRVDRV_ACTIVE_SCAN_CHAN_TIME 100 -static const u8 zeromac[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -static const u8 bcastmac[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; - static int lbs_ret_80211_scan(struct lbs_private *priv, unsigned long dummy, struct cmd_header *resp); @@ -90,7 +87,7 @@ static void lbs_unset_basic_rate_flags(u8 *rates, size_t len) } -static inline void clear_bss_descriptor (struct bss_descriptor * bss) +static inline void clear_bss_descriptor(struct bss_descriptor *bss) { /* Don't blow away ->list, just BSS data */ memset(bss, 0, offsetof(struct bss_descriptor, list)); @@ -104,7 +101,8 @@ static inline void clear_bss_descriptor (struct bss_descriptor * bss) * * @return 0: ssid is same, otherwise is different */ -int lbs_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len) +int lbs_ssid_cmp(uint8_t *ssid1, uint8_t ssid1_len, uint8_t *ssid2, + uint8_t ssid2_len) { if (ssid1_len != ssid2_len) return -1; @@ -113,73 +111,66 @@ int lbs_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len) } static inline int match_bss_no_security(struct lbs_802_11_security *secinfo, - struct bss_descriptor * match_bss) + struct bss_descriptor *match_bss) { - if ( !secinfo->wep_enabled - && !secinfo->WPAenabled + if (!secinfo->wep_enabled && !secinfo->WPAenabled && !secinfo->WPA2enabled && match_bss->wpa_ie[0] != MFIE_TYPE_GENERIC && match_bss->rsn_ie[0] != MFIE_TYPE_RSN - && !(match_bss->capability & WLAN_CAPABILITY_PRIVACY)) { + && !(match_bss->capability & WLAN_CAPABILITY_PRIVACY)) return 1; - } - return 0; + else + return 0; } static inline int match_bss_static_wep(struct lbs_802_11_security *secinfo, - struct bss_descriptor * match_bss) + struct bss_descriptor *match_bss) { - if ( secinfo->wep_enabled - && !secinfo->WPAenabled - && !secinfo->WPA2enabled - && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) { + if (secinfo->wep_enabled && !secinfo->WPAenabled + && !secinfo->WPA2enabled + && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) return 1; - } - return 0; + else + return 0; } static inline int match_bss_wpa(struct lbs_802_11_security *secinfo, - struct bss_descriptor * match_bss) + struct bss_descriptor *match_bss) { - if ( !secinfo->wep_enabled - && secinfo->WPAenabled - && (match_bss->wpa_ie[0] == MFIE_TYPE_GENERIC) - /* privacy bit may NOT be set in some APs like LinkSys WRT54G - && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) { - */ - ) { + if (!secinfo->wep_enabled && secinfo->WPAenabled + && (match_bss->wpa_ie[0] == MFIE_TYPE_GENERIC) + /* privacy bit may NOT be set in some APs like LinkSys WRT54G + && (match_bss->capability & WLAN_CAPABILITY_PRIVACY) */ + ) return 1; - } - return 0; + else + return 0; } static inline int match_bss_wpa2(struct lbs_802_11_security *secinfo, - struct bss_descriptor * match_bss) + struct bss_descriptor *match_bss) { - if ( !secinfo->wep_enabled - && secinfo->WPA2enabled - && (match_bss->rsn_ie[0] == MFIE_TYPE_RSN) - /* privacy bit may NOT be set in some APs like LinkSys WRT54G - && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) { - */ - ) { + if (!secinfo->wep_enabled && secinfo->WPA2enabled + && (match_bss->rsn_ie[0] == MFIE_TYPE_RSN) + /* privacy bit may NOT be set in some APs like LinkSys WRT54G + && (match_bss->capability & WLAN_CAPABILITY_PRIVACY) */ + ) return 1; - } - return 0; + else + return 0; } static inline int match_bss_dynamic_wep(struct lbs_802_11_security *secinfo, - struct bss_descriptor * match_bss) + struct bss_descriptor *match_bss) { - if ( !secinfo->wep_enabled - && !secinfo->WPAenabled - && !secinfo->WPA2enabled - && (match_bss->wpa_ie[0] != MFIE_TYPE_GENERIC) - && (match_bss->rsn_ie[0] != MFIE_TYPE_RSN) - && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) { + if (!secinfo->wep_enabled && !secinfo->WPAenabled + && !secinfo->WPA2enabled + && (match_bss->wpa_ie[0] != MFIE_TYPE_GENERIC) + && (match_bss->rsn_ie[0] != MFIE_TYPE_RSN) + && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) return 1; - } - return 0; + else + return 0; } static inline int is_same_network(struct bss_descriptor *src, @@ -214,7 +205,7 @@ static inline int is_same_network(struct bss_descriptor *src, * @return Index in scantable, or error code if negative */ static int is_network_compatible(struct lbs_private *priv, - struct bss_descriptor * bss, u8 mode) + struct bss_descriptor *bss, uint8_t mode) { int matched = 0; @@ -228,43 +219,39 @@ static int is_network_compatible(struct lbs_private *priv, } else if ((matched = match_bss_static_wep(&priv->secinfo, bss))) { goto done; } else if ((matched = match_bss_wpa(&priv->secinfo, bss))) { - lbs_deb_scan( - "is_network_compatible() WPA: wpa_ie 0x%x " - "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s " - "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0], - priv->secinfo.wep_enabled ? "e" : "d", - priv->secinfo.WPAenabled ? "e" : "d", - priv->secinfo.WPA2enabled ? "e" : "d", - (bss->capability & WLAN_CAPABILITY_PRIVACY)); + lbs_deb_scan("is_network_compatible() WPA: wpa_ie 0x%x " + "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s " + "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0], + priv->secinfo.wep_enabled ? "e" : "d", + priv->secinfo.WPAenabled ? "e" : "d", + priv->secinfo.WPA2enabled ? "e" : "d", + (bss->capability & WLAN_CAPABILITY_PRIVACY)); goto done; } else if ((matched = match_bss_wpa2(&priv->secinfo, bss))) { - lbs_deb_scan( - "is_network_compatible() WPA2: wpa_ie 0x%x " - "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s " - "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0], - priv->secinfo.wep_enabled ? "e" : "d", - priv->secinfo.WPAenabled ? "e" : "d", - priv->secinfo.WPA2enabled ? "e" : "d", - (bss->capability & WLAN_CAPABILITY_PRIVACY)); + lbs_deb_scan("is_network_compatible() WPA2: wpa_ie 0x%x " + "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s " + "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0], + priv->secinfo.wep_enabled ? "e" : "d", + priv->secinfo.WPAenabled ? "e" : "d", + priv->secinfo.WPA2enabled ? "e" : "d", + (bss->capability & WLAN_CAPABILITY_PRIVACY)); goto done; } else if ((matched = match_bss_dynamic_wep(&priv->secinfo, bss))) { - lbs_deb_scan( - "is_network_compatible() dynamic WEP: " - "wpa_ie 0x%x wpa2_ie 0x%x privacy 0x%x\n", - bss->wpa_ie[0], bss->rsn_ie[0], - (bss->capability & WLAN_CAPABILITY_PRIVACY)); + lbs_deb_scan("is_network_compatible() dynamic WEP: " + "wpa_ie 0x%x wpa2_ie 0x%x privacy 0x%x\n", + bss->wpa_ie[0], bss->rsn_ie[0], + (bss->capability & WLAN_CAPABILITY_PRIVACY)); goto done; } /* bss security settings don't match those configured on card */ - lbs_deb_scan( - "is_network_compatible() FAILED: wpa_ie 0x%x " - "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s privacy 0x%x\n", - bss->wpa_ie[0], bss->rsn_ie[0], - priv->secinfo.wep_enabled ? "e" : "d", - priv->secinfo.WPAenabled ? "e" : "d", - priv->secinfo.WPA2enabled ? "e" : "d", - (bss->capability & WLAN_CAPABILITY_PRIVACY)); + lbs_deb_scan("is_network_compatible() FAILED: wpa_ie 0x%x " + "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s privacy 0x%x\n", + bss->wpa_ie[0], bss->rsn_ie[0], + priv->secinfo.wep_enabled ? "e" : "d", + priv->secinfo.WPAenabled ? "e" : "d", + priv->secinfo.WPA2enabled ? "e" : "d", + (bss->capability & WLAN_CAPABILITY_PRIVACY)); done: lbs_deb_leave_args(LBS_DEB_SCAN, "matched: %d", matched); @@ -311,16 +298,15 @@ void lbs_scan_worker(struct work_struct *work) * @return void */ static int lbs_scan_create_channel_list(struct lbs_private *priv, - struct chanscanparamset * scanchanlist, - u8 filteredscan) + struct chanscanparamset *scanchanlist, + uint8_t filteredscan) { - struct region_channel *scanregion; struct chan_freq_power *cfp; int rgnidx; int chanidx; int nextchan; - u8 scantype; + uint8_t scantype; chanidx = 0; @@ -331,9 +317,8 @@ static int lbs_scan_create_channel_list(struct lbs_private *priv, scantype = CMD_SCAN_TYPE_ACTIVE; for (rgnidx = 0; rgnidx < ARRAY_SIZE(priv->region_channel); rgnidx++) { - if (priv->enable11d && - (priv->connect_status != LBS_CONNECTED) && - (priv->mesh_connect_status != LBS_CONNECTED)) { + if (priv->enable11d && (priv->connect_status != LBS_CONNECTED) + && (priv->mesh_connect_status != LBS_CONNECTED)) { /* Scan all the supported chan for the first scan */ if (!priv->universal_channel[rgnidx].valid) continue; @@ -348,45 +333,30 @@ static int lbs_scan_create_channel_list(struct lbs_private *priv, scanregion = &priv->region_channel[rgnidx]; } - for (nextchan = 0; - nextchan < scanregion->nrcfp; nextchan++, chanidx++) { + for (nextchan = 0; nextchan < scanregion->nrcfp; nextchan++, chanidx++) { + struct chanscanparamset *chan = &scanchanlist[chanidx]; cfp = scanregion->CFP + nextchan; - if (priv->enable11d) { - scantype = - lbs_get_scan_type_11d(cfp->channel, - &priv-> - parsed_region_chan); - } + if (priv->enable11d) + scantype = lbs_get_scan_type_11d(cfp->channel, + &priv->parsed_region_chan); - switch (scanregion->band) { - case BAND_B: - case BAND_G: - default: - scanchanlist[chanidx].radiotype = - CMD_SCAN_RADIO_TYPE_BG; - break; - } + if (scanregion->band == BAND_B || scanregion->band == BAND_G) + chan->radiotype = CMD_SCAN_RADIO_TYPE_BG; if (scantype == CMD_SCAN_TYPE_PASSIVE) { - scanchanlist[chanidx].maxscantime = - cpu_to_le16(MRVDRV_PASSIVE_SCAN_CHAN_TIME); - scanchanlist[chanidx].chanscanmode.passivescan = - 1; + chan->maxscantime = cpu_to_le16(MRVDRV_PASSIVE_SCAN_CHAN_TIME); + chan->chanscanmode.passivescan = 1; } else { - scanchanlist[chanidx].maxscantime = - cpu_to_le16(MRVDRV_ACTIVE_SCAN_CHAN_TIME); - scanchanlist[chanidx].chanscanmode.passivescan = - 0; + chan->maxscantime = cpu_to_le16(MRVDRV_ACTIVE_SCAN_CHAN_TIME); + chan->chanscanmode.passivescan = 0; } - scanchanlist[chanidx].channumber = cfp->channel; + chan->channumber = cfp->channel; - if (filteredscan) { - scanchanlist[chanidx].chanscanmode. - disablechanfilt = 1; - } + if (filteredscan) + chan->chanscanmode.disablechanfilt = 1; } } return chanidx; @@ -400,11 +370,11 @@ static int lbs_scan_create_channel_list(struct lbs_private *priv, * length 06 00 * ssid 4d 4e 54 45 53 54 */ -static int lbs_scan_add_ssid_tlv(u8 *tlv, - const struct lbs_ioctl_user_scan_cfg *user_cfg) +static int lbs_scan_add_ssid_tlv(uint8_t *tlv, + const struct lbs_ioctl_user_scan_cfg *user_cfg) { - struct mrvlietypes_ssidparamset *ssid_tlv = - (struct mrvlietypes_ssidparamset *)tlv; + struct mrvlietypes_ssidparamset *ssid_tlv = (void *)tlv; + ssid_tlv->header.type = cpu_to_le16(TLV_TYPE_SSID); ssid_tlv->header.len = cpu_to_le16(user_cfg->ssid_len); memcpy(ssid_tlv->ssid, user_cfg->ssid, user_cfg->ssid_len); @@ -437,13 +407,12 @@ static int lbs_scan_add_ssid_tlv(u8 *tlv, * channel 13 00 0d 00 00 00 64 00 * */ -static int lbs_scan_add_chanlist_tlv(u8 *tlv, - struct chanscanparamset *chan_list, - int chan_count) +static int lbs_scan_add_chanlist_tlv(uint8_t *tlv, + struct chanscanparamset *chan_list, + int chan_count) { - size_t size = sizeof(struct chanscanparamset) * chan_count; - struct mrvlietypes_chanlistparamset *chan_tlv = - (struct mrvlietypes_chanlistparamset *) tlv; + size_t size = sizeof(struct chanscanparamset) *chan_count; + struct mrvlietypes_chanlistparamset *chan_tlv = (void *)tlv; chan_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST); memcpy(chan_tlv->chanscanparam, chan_list, size); @@ -462,11 +431,10 @@ static int lbs_scan_add_chanlist_tlv(u8 *tlv, * The rates are in lbs_bg_rates[], but for the 802.11b * rates the high bit isn't set. */ -static int lbs_scan_add_rates_tlv(u8 *tlv) +static int lbs_scan_add_rates_tlv(uint8_t *tlv) { int i; - struct mrvlietypes_ratesparamset *rate_tlv = - (struct mrvlietypes_ratesparamset *) tlv; + struct mrvlietypes_ratesparamset *rate_tlv = (void *)tlv; rate_tlv->header.type = cpu_to_le16(TLV_TYPE_RATES); tlv += sizeof(rate_tlv->header); @@ -554,14 +522,14 @@ out: * @return 0 or < 0 if error */ int lbs_scan_networks(struct lbs_private *priv, - const struct lbs_ioctl_user_scan_cfg *user_cfg, - int full_scan) + const struct lbs_ioctl_user_scan_cfg *user_cfg, + int full_scan) { int ret = -ENOMEM; struct chanscanparamset *chan_list; struct chanscanparamset *curr_chans; int chan_count; - u8 bsstype = CMD_BSS_TYPE_ANY; + uint8_t bsstype = CMD_BSS_TYPE_ANY; int numchannels = MRVDRV_CHANNELS_PER_SCAN_CMD; int filteredscan = 0; union iwreq_data wrqu; @@ -571,8 +539,7 @@ int lbs_scan_networks(struct lbs_private *priv, DECLARE_MAC_BUF(mac); #endif - lbs_deb_enter_args(LBS_DEB_SCAN, "full_scan %d", - full_scan); + lbs_deb_enter_args(LBS_DEB_SCAN, "full_scan %d", full_scan); /* Cancel any partial outstanding partial scans if this scan * is a full scan. @@ -584,26 +551,24 @@ int lbs_scan_networks(struct lbs_private *priv, if (user_cfg) { if (user_cfg->bsstype) bsstype = user_cfg->bsstype; - if (compare_ether_addr(user_cfg->bssid, &zeromac[0]) != 0) { + if (!is_zero_ether_addr(user_cfg->bssid)) { numchannels = MRVDRV_MAX_CHANNELS_PER_SCAN; filteredscan = 1; } } - lbs_deb_scan("numchannels %d, bsstype %d, " - "filteredscan %d\n", - numchannels, bsstype, filteredscan); + lbs_deb_scan("numchannels %d, bsstype %d, filteredscan %d\n", + numchannels, bsstype, filteredscan); /* Create list of channels to scan */ chan_list = kzalloc(sizeof(struct chanscanparamset) * - LBS_IOCTL_USER_SCAN_CHAN_MAX, GFP_KERNEL); + LBS_IOCTL_USER_SCAN_CHAN_MAX, GFP_KERNEL); if (!chan_list) { lbs_pr_alert("SCAN: chan_list empty\n"); goto out; } /* We want to scan all channels */ - chan_count = lbs_scan_create_channel_list(priv, chan_list, - filteredscan); + chan_count = lbs_scan_create_channel_list(priv, chan_list, filteredscan); netif_stop_queue(priv->dev); netif_carrier_off(priv->dev); @@ -630,9 +595,9 @@ int lbs_scan_networks(struct lbs_private *priv, while (chan_count) { int to_scan = min(numchannels, chan_count); lbs_deb_scan("scanning %d of %d channels\n", - to_scan, chan_count); + to_scan, chan_count); ret = lbs_do_scan(priv, bsstype, curr_chans, - to_scan, user_cfg); + to_scan, user_cfg); if (ret) { lbs_pr_err("SCAN_CMD failed\n"); goto out2; @@ -641,8 +606,7 @@ int lbs_scan_networks(struct lbs_private *priv, chan_count -= to_scan; /* somehow schedule the next part of the scan */ - if (chan_count && - !full_scan && + if (chan_count && !full_scan && !priv->surpriseremoved) { /* -1 marks just that we're currently scanning */ if (priv->scan_channel < 0) @@ -651,7 +615,7 @@ int lbs_scan_networks(struct lbs_private *priv, priv->scan_channel += to_scan; cancel_delayed_work(&priv->scan_work); queue_delayed_work(priv->work_thread, &priv->scan_work, - msecs_to_jiffies(300)); + msecs_to_jiffies(300)); /* skip over GIWSCAN event */ goto out; } @@ -666,8 +630,8 @@ int lbs_scan_networks(struct lbs_private *priv, lbs_deb_scan("scan table:\n"); list_for_each_entry(iter, &priv->network_list, list) lbs_deb_scan("%02d: BSSID %s, RSSI %d, SSID '%s'\n", - i++, print_mac(mac, iter->bssid), (s32) iter->rssi, - escape_essid(iter->ssid, iter->ssid_len)); + i++, print_mac(mac, iter->bssid), (int)iter->rssi, + escape_essid(iter->ssid, iter->ssid_len)); mutex_unlock(&priv->lock); #endif @@ -712,7 +676,7 @@ out: * @return 0 or -1 */ static int lbs_process_bss(struct bss_descriptor *bss, - u8 ** pbeaconinfo, int *bytesleft) + uint8_t **pbeaconinfo, int *bytesleft) { struct ieeetypes_fhparamset *pFH; struct ieeetypes_dsparamset *pDS; @@ -720,9 +684,9 @@ static int lbs_process_bss(struct bss_descriptor *bss, struct ieeetypes_ibssparamset *pibss; DECLARE_MAC_BUF(mac); struct ieeetypes_countryinfoset *pcountryinfo; - u8 *pos, *end, *p; - u8 n_ex_rates = 0, got_basic_rates = 0, n_basic_rates = 0; - u16 beaconsize = 0; + uint8_t *pos, *end, *p; + uint8_t n_ex_rates = 0, got_basic_rates = 0, n_basic_rates = 0; + uint16_t beaconsize = 0; int ret; lbs_deb_enter(LBS_DEB_SCAN); @@ -794,12 +758,11 @@ static int lbs_process_bss(struct bss_descriptor *bss, /* process variable IE */ while (pos <= end - 2) { - struct ieee80211_info_element * elem = - (struct ieee80211_info_element *) pos; + struct ieee80211_info_element * elem = (void *)pos; if (pos + elem->len > end) { lbs_deb_scan("process_bss: error in processing IE, " - "bytes left < IE length\n"); + "bytes left < IE length\n"); break; } @@ -813,7 +776,7 @@ static int lbs_process_bss(struct bss_descriptor *bss, break; case MFIE_TYPE_RATES: - n_basic_rates = min_t(u8, MAX_RATES, elem->len); + n_basic_rates = min_t(uint8_t, MAX_RATES, elem->len); memcpy(bss->rates, elem->data, n_basic_rates); got_basic_rates = 1; lbs_deb_scan("got RATES IE\n"); @@ -854,19 +817,16 @@ static int lbs_process_bss(struct bss_descriptor *bss, lbs_deb_scan("got COUNTRY IE\n"); if (pcountryinfo->len < sizeof(pcountryinfo->countrycode) || pcountryinfo->len > 254) { - lbs_deb_scan("process_bss: 11D- Err " - "CountryInfo len %d, min %zd, max 254\n", - pcountryinfo->len, - sizeof(pcountryinfo->countrycode)); + lbs_deb_scan("process_bss: 11D- Err CountryInfo len %d, min %zd, max 254\n", + pcountryinfo->len, sizeof(pcountryinfo->countrycode)); ret = -1; goto done; } - memcpy(&bss->countryinfo, - pcountryinfo, pcountryinfo->len + 2); + memcpy(&bss->countryinfo, pcountryinfo, pcountryinfo->len + 2); lbs_deb_hex(LBS_DEB_SCAN, "process_bss: 11d countryinfo", - (u8 *) pcountryinfo, - (u32) (pcountryinfo->len + 2)); + (uint8_t *) pcountryinfo, + (int) (pcountryinfo->len + 2)); break; case MFIE_TYPE_RATES_EX: @@ -890,26 +850,19 @@ static int lbs_process_bss(struct bss_descriptor *bss, case MFIE_TYPE_GENERIC: if (elem->len >= 4 && - elem->data[0] == 0x00 && - elem->data[1] == 0x50 && - elem->data[2] == 0xf2 && - elem->data[3] == 0x01) { - bss->wpa_ie_len = min(elem->len + 2, - MAX_WPA_IE_LEN); + elem->data[0] == 0x00 && elem->data[1] == 0x50 && + elem->data[2] == 0xf2 && elem->data[3] == 0x01) { + bss->wpa_ie_len = min(elem->len + 2, MAX_WPA_IE_LEN); memcpy(bss->wpa_ie, elem, bss->wpa_ie_len); lbs_deb_scan("got WPA IE\n"); - lbs_deb_hex(LBS_DEB_SCAN, "WPA IE", bss->wpa_ie, - elem->len); + lbs_deb_hex(LBS_DEB_SCAN, "WPA IE", bss->wpa_ie, elem->len); } else if (elem->len >= MARVELL_MESH_IE_LENGTH && - elem->data[0] == 0x00 && - elem->data[1] == 0x50 && - elem->data[2] == 0x43 && - elem->data[3] == 0x04) { + elem->data[0] == 0x00 && elem->data[1] == 0x50 && + elem->data[2] == 0x43 && elem->data[3] == 0x04) { lbs_deb_scan("got mesh IE\n"); bss->mesh = 1; } else { - lbs_deb_scan("got generiec IE: " - "%02x:%02x:%02x:%02x, len %d\n", + lbs_deb_scan("got generic IE: %02x:%02x:%02x:%02x, len %d\n", elem->data[0], elem->data[1], elem->data[2], elem->data[3], elem->len); @@ -921,12 +874,12 @@ static int lbs_process_bss(struct bss_descriptor *bss, bss->rsn_ie_len = min(elem->len + 2, MAX_WPA_IE_LEN); memcpy(bss->rsn_ie, elem, bss->rsn_ie_len); lbs_deb_hex(LBS_DEB_SCAN, "process_bss: RSN_IE", - bss->rsn_ie, elem->len); + bss->rsn_ie, elem->len); break; default: lbs_deb_scan("got IE 0x%04x, len %d\n", - elem->id, elem->len); + elem->id, elem->len); break; } @@ -956,18 +909,17 @@ done: * @return index in BSSID list, or error return code (< 0) */ struct bss_descriptor *lbs_find_bssid_in_list(struct lbs_private *priv, - u8 * bssid, u8 mode) + uint8_t *bssid, uint8_t mode) { - struct bss_descriptor * iter_bss; - struct bss_descriptor * found_bss = NULL; + struct bss_descriptor *iter_bss; + struct bss_descriptor *found_bss = NULL; lbs_deb_enter(LBS_DEB_SCAN); if (!bssid) goto out; - lbs_deb_hex(LBS_DEB_SCAN, "looking for", - bssid, ETH_ALEN); + lbs_deb_hex(LBS_DEB_SCAN, "looking for", bssid, ETH_ALEN); /* Look through the scan table for a compatible match. The loop will * continue past a matched bssid that is not compatible in case there @@ -1009,10 +961,11 @@ out: * @return index in BSSID list */ struct bss_descriptor *lbs_find_ssid_in_list(struct lbs_private *priv, - u8 *ssid, u8 ssid_len, u8 * bssid, u8 mode, - int channel) + uint8_t *ssid, uint8_t ssid_len, + uint8_t *bssid, uint8_t mode, + int channel) { - u8 bestrssi = 0; + uint8_t bestrssi = 0; struct bss_descriptor * iter_bss = NULL; struct bss_descriptor * found_bss = NULL; struct bss_descriptor * tmp_oldest = NULL; @@ -1027,7 +980,7 @@ struct bss_descriptor *lbs_find_ssid_in_list(struct lbs_private *priv, tmp_oldest = iter_bss; if (lbs_ssid_cmp(iter_bss->ssid, iter_bss->ssid_len, - ssid, ssid_len) != 0) + ssid, ssid_len) != 0) continue; /* ssid doesn't match */ if (bssid && compare_ether_addr(iter_bss->bssid, bssid) != 0) continue; /* bssid doesn't match */ @@ -1077,13 +1030,12 @@ out: * * @return index in BSSID list */ -static struct bss_descriptor *lbs_find_best_ssid_in_list( - struct lbs_private *priv, - u8 mode) +static struct bss_descriptor *lbs_find_best_ssid_in_list(struct lbs_private *priv, + uint8_t mode) { - u8 bestrssi = 0; - struct bss_descriptor * iter_bss; - struct bss_descriptor * best_bss = NULL; + uint8_t bestrssi = 0; + struct bss_descriptor *iter_bss; + struct bss_descriptor *best_bss = NULL; lbs_deb_enter(LBS_DEB_SCAN); @@ -1125,11 +1077,12 @@ static struct bss_descriptor *lbs_find_best_ssid_in_list( * * @return 0--success, otherwise--fail */ -int lbs_find_best_network_ssid(struct lbs_private *priv, - u8 *out_ssid, u8 *out_ssid_len, u8 preferred_mode, u8 *out_mode) +int lbs_find_best_network_ssid(struct lbs_private *priv, uint8_t *out_ssid, + uint8_t *out_ssid_len, uint8_t preferred_mode, + uint8_t *out_mode) { int ret = -1; - struct bss_descriptor * found; + struct bss_descriptor *found; lbs_deb_enter(LBS_DEB_SCAN); @@ -1164,14 +1117,14 @@ out: * * @return 0-success, otherwise fail */ -int lbs_send_specific_ssid_scan(struct lbs_private *priv, - u8 *ssid, u8 ssid_len, u8 clear_ssid) +int lbs_send_specific_ssid_scan(struct lbs_private *priv, uint8_t *ssid, + uint8_t ssid_len, uint8_t clear_ssid) { struct lbs_ioctl_user_scan_cfg scancfg; int ret = 0; lbs_deb_enter_args(LBS_DEB_SCAN, "SSID '%s', clear %d", - escape_essid(ssid, ssid_len), clear_ssid); + escape_essid(ssid, ssid_len), clear_ssid); if (!ssid_len) goto out; @@ -1205,17 +1158,17 @@ out: #define MAX_CUSTOM_LEN 64 static inline char *lbs_translate_scan(struct lbs_private *priv, - char *start, char *stop, - struct bss_descriptor *bss) + char *start, char *stop, + struct bss_descriptor *bss) { struct chan_freq_power *cfp; char *current_val; /* For rates */ struct iw_event iwe; /* Temporary buffer */ int j; -#define PERFECT_RSSI ((u8)50) -#define WORST_RSSI ((u8)0) -#define RSSI_DIFF ((u8)(PERFECT_RSSI - WORST_RSSI)) - u8 rssi; +#define PERFECT_RSSI ((uint8_t)50) +#define WORST_RSSI ((uint8_t)0) +#define RSSI_DIFF ((uint8_t)(PERFECT_RSSI - WORST_RSSI)) + uint8_t rssi; lbs_deb_enter(LBS_DEB_SCAN); @@ -1235,7 +1188,7 @@ static inline char *lbs_translate_scan(struct lbs_private *priv, /* SSID */ iwe.cmd = SIOCGIWESSID; iwe.u.data.flags = 1; - iwe.u.data.length = min((u32) bss->ssid_len, (u32) IW_ESSID_MAX_SIZE); + iwe.u.data.length = min((uint32_t) bss->ssid_len, (uint32_t) IW_ESSID_MAX_SIZE); start = iwe_stream_add_point(start, stop, &iwe, bss->ssid); /* Mode */ @@ -1256,28 +1209,26 @@ static inline char *lbs_translate_scan(struct lbs_private *priv, rssi = iwe.u.qual.level - MRVDRV_NF_DEFAULT_SCAN_VALUE; iwe.u.qual.qual = - (100 * RSSI_DIFF * RSSI_DIFF - (PERFECT_RSSI - rssi) * - (15 * (RSSI_DIFF) + 62 * (PERFECT_RSSI - rssi))) / - (RSSI_DIFF * RSSI_DIFF); + (100 * RSSI_DIFF * RSSI_DIFF - (PERFECT_RSSI - rssi) * + (15 * (RSSI_DIFF) + 62 * (PERFECT_RSSI - rssi))) / + (RSSI_DIFF * RSSI_DIFF); if (iwe.u.qual.qual > 100) iwe.u.qual.qual = 100; if (priv->NF[TYPE_BEACON][TYPE_NOAVG] == 0) { iwe.u.qual.noise = MRVDRV_NF_DEFAULT_SCAN_VALUE; } else { - iwe.u.qual.noise = - CAL_NF(priv->NF[TYPE_BEACON][TYPE_NOAVG]); + iwe.u.qual.noise = CAL_NF(priv->NF[TYPE_BEACON][TYPE_NOAVG]); } /* Locally created ad-hoc BSSs won't have beacons if this is the * only station in the adhoc network; so get signal strength * from receive statistics. */ - if ((priv->mode == IW_MODE_ADHOC) - && priv->adhoccreate + if ((priv->mode == IW_MODE_ADHOC) && priv->adhoccreate && !lbs_ssid_cmp(priv->curbssparams.ssid, - priv->curbssparams.ssid_len, - bss->ssid, bss->ssid_len)) { + priv->curbssparams.ssid_len, + bss->ssid, bss->ssid_len)) { int snr, nf; snr = priv->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE; nf = priv->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE; @@ -1308,14 +1259,13 @@ static inline char *lbs_translate_scan(struct lbs_private *priv, current_val = iwe_stream_add_value(start, current_val, stop, &iwe, IW_EV_PARAM_LEN); } - if ((bss->mode == IW_MODE_ADHOC) + if ((bss->mode == IW_MODE_ADHOC) && priv->adhoccreate && !lbs_ssid_cmp(priv->curbssparams.ssid, - priv->curbssparams.ssid_len, - bss->ssid, bss->ssid_len) - && priv->adhoccreate) { + priv->curbssparams.ssid_len, + bss->ssid, bss->ssid_len)) { iwe.u.bitrate.value = 22 * 500000; current_val = iwe_stream_add_value(start, current_val, - stop, &iwe, IW_EV_PARAM_LEN); + stop, &iwe, IW_EV_PARAM_LEN); } /* Check if we added any event */ if((current_val - start) > IW_EV_LCP_LEN) @@ -1344,8 +1294,7 @@ static inline char *lbs_translate_scan(struct lbs_private *priv, char *p = custom; iwe.cmd = IWEVCUSTOM; - p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), - "mesh-type: olpc"); + p += snprintf(p, MAX_CUSTOM_LEN, "mesh-type: olpc"); iwe.u.data.length = p - custom; if (iwe.u.data.length) start = iwe_stream_add_point(start, stop, &iwe, custom); @@ -1368,7 +1317,7 @@ out: * @return 0 --success, otherwise fail */ int lbs_set_scan(struct net_device *dev, struct iw_request_info *info, - struct iw_param *wrqu, char *extra) + struct iw_param *wrqu, char *extra) { struct lbs_private *priv = dev->priv; @@ -1392,7 +1341,7 @@ int lbs_set_scan(struct net_device *dev, struct iw_request_info *info, if (!delayed_work_pending(&priv->scan_work)) queue_delayed_work(priv->work_thread, &priv->scan_work, - msecs_to_jiffies(50)); + msecs_to_jiffies(50)); /* set marker that currently a scan is taking place */ priv->scan_channel = -1; @@ -1415,15 +1364,15 @@ int lbs_set_scan(struct net_device *dev, struct iw_request_info *info, * @return 0 --success, otherwise fail */ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info, - struct iw_point *dwrq, char *extra) + struct iw_point *dwrq, char *extra) { #define SCAN_ITEM_SIZE 128 struct lbs_private *priv = dev->priv; int err = 0; char *ev = extra; char *stop = ev + dwrq->length; - struct bss_descriptor * iter_bss; - struct bss_descriptor * safe; + struct bss_descriptor *iter_bss; + struct bss_descriptor *safe; lbs_deb_enter(LBS_DEB_SCAN); @@ -1432,14 +1381,13 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info, return -EAGAIN; /* Update RSSI if current BSS is a locally created ad-hoc BSS */ - if ((priv->mode == IW_MODE_ADHOC) && priv->adhoccreate) { + if ((priv->mode == IW_MODE_ADHOC) && priv->adhoccreate) lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0, - CMD_OPTION_WAITFORRSP, 0, NULL); - } + CMD_OPTION_WAITFORRSP, 0, NULL); mutex_lock(&priv->lock); list_for_each_entry_safe (iter_bss, safe, &priv->network_list, list) { - char * next_ev; + char *next_ev; unsigned long stale_time; if (stop - ev < SCAN_ITEM_SIZE) { @@ -1454,8 +1402,7 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info, /* Prune old an old scan result */ stale_time = iter_bss->last_scanned + DEFAULT_MAX_SCAN_AGE; if (time_after(jiffies, stale_time)) { - list_move_tail (&iter_bss->list, - &priv->network_free_list); + list_move_tail(&iter_bss->list, &priv->network_free_list); clear_bss_descriptor(iter_bss); continue; } @@ -1515,8 +1462,8 @@ static int lbs_ret_80211_scan(struct lbs_private *priv, unsigned long dummy, struct cmd_header *resp) { struct cmd_ds_802_11_scan_rsp *scanresp = (void *)resp; - struct bss_descriptor * iter_bss; - struct bss_descriptor * safe; + struct bss_descriptor *iter_bss; + struct bss_descriptor *safe; uint8_t *bssinfo; uint16_t scanrespsize; int bytesleft; -- cgit v1.2.1 From 72e77a8a7921d952bdef2468d9315616eca6b464 Mon Sep 17 00:00:00 2001 From: Luis Carlos Cobo Date: Mon, 3 Mar 2008 12:32:15 -0800 Subject: zd1211rw: support for mesh interface and beaconing The previously unused CR_CAM_MODE register is set to MODE_AP_WDS. This makes the driver ack mesh (WDS) frames. It does not affect Infra functionality of the driver. Previously missing beaconing support has been added. This might also help implement a currently missing ah-hoc mode. Support for interrupts from the device have been added, but we are not handling most of them. Mesh interfaces are considered associated as long as the interface is up. Signed-off-by: Luis Carlos Cobo Signed-off-by: John W. Linville --- drivers/net/wireless/zd1211rw/zd_chip.c | 1 + drivers/net/wireless/zd1211rw/zd_chip.h | 8 ++++ drivers/net/wireless/zd1211rw/zd_mac.c | 75 ++++++++++++++++++++++++++++++++- drivers/net/wireless/zd1211rw/zd_mac.h | 3 ++ drivers/net/wireless/zd1211rw/zd_usb.c | 11 ++++- 5 files changed, 94 insertions(+), 4 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c index db96adf90ae2..0acb5c345734 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.c +++ b/drivers/net/wireless/zd1211rw/zd_chip.c @@ -809,6 +809,7 @@ static int hw_init_hmac(struct zd_chip *chip) { CR_AFTER_PNP, 0x1 }, { CR_WEP_PROTECT, 0x114 }, { CR_IFS_VALUE, IFS_VALUE_DEFAULT }, + { CR_CAM_MODE, MODE_AP_WDS}, }; ZD_ASSERT(mutex_is_locked(&chip->mutex)); diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h index 5b6e3a3751ba..f8c061a9b6ec 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.h +++ b/drivers/net/wireless/zd1211rw/zd_chip.h @@ -489,6 +489,7 @@ enum { #define CR_RX_OFFSET CTL_REG(0x065c) +#define CR_BCN_LENGTH CTL_REG(0x0664) #define CR_PHY_DELAY CTL_REG(0x066C) #define CR_BCN_FIFO CTL_REG(0x0670) #define CR_SNIFFER_ON CTL_REG(0x0674) @@ -545,6 +546,8 @@ enum { #define RX_FILTER_CTRL (RX_FILTER_RTS | RX_FILTER_CTS | \ RX_FILTER_CFEND | RX_FILTER_CFACK) +#define BCN_MODE_IBSS 0x2000000 + /* Monitor mode sets filter to 0xfffff */ #define CR_ACK_TIMEOUT_EXT CTL_REG(0x0690) @@ -578,6 +581,11 @@ enum { /* CAM: Continuous Access Mode (power management) */ #define CR_CAM_MODE CTL_REG(0x0700) +#define MODE_IBSS 0x0 +#define MODE_AP 0x1 +#define MODE_STA 0x2 +#define MODE_AP_WDS 0x3 + #define CR_CAM_ROLL_TB_LOW CTL_REG(0x0704) #define CR_CAM_ROLL_TB_HIGH CTL_REG(0x0708) #define CR_CAM_ADDRESS CTL_REG(0x070C) diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index f90f03f676de..69c45ca99051 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -475,6 +475,46 @@ 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) +{ + struct zd_mac *mac = zd_hw_mac(hw); + 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); + while (tmp & 0x2) { + zd_ioread32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, &tmp); + 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; + } + } + 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); + + for (j = 0 ; j < beacon->len; j++) + zd_iowrite32(&mac->chip, CR_BCN_FIFO, + *((u8 *)(beacon->data + j))); + + for (j = 0; j < 4; j++) + zd_iowrite32(&mac->chip, CR_BCN_FIFO, 0x0); + + 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 | + (full_len << 19)); +} + static int fill_ctrlset(struct zd_mac *mac, struct sk_buff *skb, struct ieee80211_tx_control *control) @@ -709,6 +749,7 @@ static int zd_op_add_interface(struct ieee80211_hw *hw, switch (conf->type) { case IEEE80211_IF_TYPE_MNTR: + case IEEE80211_IF_TYPE_MESH_POINT: case IEEE80211_IF_TYPE_STA: mac->type = conf->type; break; @@ -738,15 +779,43 @@ static int zd_op_config_interface(struct ieee80211_hw *hw, struct ieee80211_if_conf *conf) { struct zd_mac *mac = zd_hw_mac(hw); + int associated; + + if (mac->type == IEEE80211_IF_TYPE_MESH_POINT) { + 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 | + hw->conf.beacon_int); + } + } else + associated = is_valid_ether_addr(conf->bssid); spin_lock_irq(&mac->lock); - mac->associated = is_valid_ether_addr(conf->bssid); + mac->associated = associated; spin_unlock_irq(&mac->lock); /* TODO: do hardware bssid filtering */ return 0; } +void zd_process_intr(struct work_struct *work) +{ + u16 int_status; + struct zd_mac *mac = container_of(work, struct zd_mac, process_intr); + + int_status = le16_to_cpu(*(u16 *)(mac->intr_buffer+4)); + if (int_status & INT_CFG_NEXT_BCN) { + if (net_ratelimit()) + dev_dbg_f(zd_mac_dev(mac), "INT_CFG_NEXT_BCN\n"); + } else + dev_dbg_f(zd_mac_dev(mac), "Unsupported interrupt\n"); + + zd_chip_enable_hwint(&mac->chip); +} + + static void set_multicast_hash_handler(struct work_struct *work) { struct zd_mac *mac = @@ -912,7 +981,8 @@ struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf) hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &mac->band; - hw->flags = IEEE80211_HW_RX_INCLUDES_FCS; + hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | + IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE; hw->max_rssi = 100; hw->max_signal = 100; @@ -926,6 +996,7 @@ struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf) INIT_WORK(&mac->set_multicast_hash_work, set_multicast_hash_handler); INIT_WORK(&mac->set_rts_cts_work, set_rts_cts_work); INIT_WORK(&mac->set_rx_filter_work, set_rx_filter_handler); + INIT_WORK(&mac->process_intr, zd_process_intr); SET_IEEE80211_DEV(hw, &intf->dev); return hw; diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h index 67dea9739c8f..71170244d2c9 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.h +++ b/drivers/net/wireless/zd1211rw/zd_mac.h @@ -172,12 +172,15 @@ struct zd_tx_skb_control_block { struct zd_mac { struct zd_chip chip; spinlock_t lock; + spinlock_t intr_lock; struct ieee80211_hw *hw; struct housekeeping housekeeping; struct work_struct set_multicast_hash_work; struct work_struct set_rts_cts_work; struct work_struct set_rx_filter_work; + struct work_struct process_intr; struct zd_mc_hash multicast_hash; + u8 intr_buffer[USB_MAX_EP_INT_BUFFER]; u8 regdomain; u8 default_regdomain; int type; diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index 7942b15acfe7..e34675c2f8fc 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c @@ -97,6 +97,7 @@ MODULE_DEVICE_TABLE(usb, usb_ids); #define FW_ZD1211B_PREFIX "zd1211/zd1211b_" /* USB device initialization */ +static void int_urb_complete(struct urb *urb); static int request_fw_file( const struct firmware **fw, const char *name, struct device *device) @@ -336,11 +337,18 @@ static inline void handle_regs_int(struct urb *urb) struct zd_usb *usb = urb->context; struct zd_usb_interrupt *intr = &usb->intr; int len; + u16 int_num; ZD_ASSERT(in_interrupt()); spin_lock(&intr->lock); - if (intr->read_regs_enabled) { + int_num = le16_to_cpu(*(u16 *)(urb->transfer_buffer+2)); + if (int_num == CR_INTERRUPT) { + struct zd_mac *mac = zd_hw_mac(zd_usb_to_hw(urb->context)); + memcpy(&mac->intr_buffer, urb->transfer_buffer, + USB_MAX_EP_INT_BUFFER); + schedule_work(&mac->process_intr); + } else if (intr->read_regs_enabled) { intr->read_regs.length = len = urb->actual_length; if (len > sizeof(intr->read_regs.buffer)) @@ -351,7 +359,6 @@ static inline void handle_regs_int(struct urb *urb) goto out; } - dev_dbg_f(urb_dev(urb), "regs interrupt ignored\n"); out: spin_unlock(&intr->lock); } -- cgit v1.2.1 From 8daeef9717598f638e6fa8ea12770173d2dea771 Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Thu, 28 Feb 2008 14:40:00 -0500 Subject: ath5k: Add RF2413 srev values * Add RF2413 srev values and a new entry on ath5k_radio enum for it since it differs from RF5413 (it's not like 5112-2112). Changes-licensed-under: ISC Signed-off-by: Nick Kossifidis Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/ath5k.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath5k/ath5k.h b/drivers/net/wireless/ath5k/ath5k.h index 18223d9833f1..25c8e989d700 100644 --- a/drivers/net/wireless/ath5k/ath5k.h +++ b/drivers/net/wireless/ath5k/ath5k.h @@ -140,7 +140,8 @@ enum ath5k_radio { AR5K_RF5110 = 0, AR5K_RF5111 = 1, AR5K_RF5112 = 2, - AR5K_RF5413 = 3, + AR5K_RF2413 = 3, + AR5K_RF5413 = 4, }; /* @@ -168,12 +169,15 @@ struct ath5k_srev_name { #define AR5K_SREV_VER_AR5212 0x50 #define AR5K_SREV_VER_AR5213 0x55 #define AR5K_SREV_VER_AR5213A 0x59 +#define AR5K_SREV_VER_AR2413 0x78 +#define AR5K_SREV_VER_AR2414 0x79 #define AR5K_SREV_VER_AR2424 0xa0 #define AR5K_SREV_VER_AR5424 0xa3 #define AR5K_SREV_VER_AR5413 0xa4 #define AR5K_SREV_VER_AR5414 0xa5 #define AR5K_SREV_VER_AR5416 0xc0 /* ? */ #define AR5K_SREV_VER_AR5418 0xca +#define AR5K_SREV_VER_AR2425 0xe2 #define AR5K_SREV_RAD_5110 0x00 #define AR5K_SREV_RAD_5111 0x10 @@ -183,8 +187,9 @@ struct ath5k_srev_name { #define AR5K_SREV_RAD_5112A 0x35 #define AR5K_SREV_RAD_2112 0x40 #define AR5K_SREV_RAD_2112A 0x45 +#define AR5K_SREV_RAD_SC0 0x56 /* Found on 2413/2414 */ #define AR5K_SREV_RAD_SC1 0x63 /* Found on 5413/5414 */ -#define AR5K_SREV_RAD_SC2 0xa2 /* Found on 2424/5424 */ +#define AR5K_SREV_RAD_SC2 0xa2 /* Found on 2424-5/5424 */ #define AR5K_SREV_RAD_5133 0xc0 /* MIMO found on 5418 */ /* IEEE defs */ -- cgit v1.2.1 From f714dd6d452af8fda700d67dc67163c6ad9d4569 Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Thu, 28 Feb 2008 14:43:51 -0500 Subject: ath5k: Add RF2413 initial settings * Add initial settings for RF2413 Changes-licensed-under: ISC Signed-off-by: Nick Kossifidis Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/initvals.c | 233 +++++++++++++++++++++++++++++++++- drivers/net/wireless/ath5k/phy.c | 163 +++++++++++++++++++++++- 2 files changed, 392 insertions(+), 4 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath5k/initvals.c b/drivers/net/wireless/ath5k/initvals.c index cfcb1fe7bd34..fdbab2f08178 100644 --- a/drivers/net/wireless/ath5k/initvals.c +++ b/drivers/net/wireless/ath5k/initvals.c @@ -678,8 +678,8 @@ static const struct ath5k_ini ar5212_ini[] = { { AR5K_PHY(644), 0x00806333 }, { AR5K_PHY(645), 0x00106c10 }, { AR5K_PHY(646), 0x009c4060 }, - /*{ AR5K_PHY(647), 0x1483800a },*/ /* Old value */ { AR5K_PHY(647), 0x1483800a }, + /* { AR5K_PHY(648), 0x018830c6 },*/ /* 2413 */ { AR5K_PHY(648), 0x01831061 }, { AR5K_PHY(649), 0x00000400 }, /*{ AR5K_PHY(650), 0x000001b5 },*/ @@ -1081,6 +1081,207 @@ static const struct ath5k_ini_mode rf5413_ini_mode_end[] = { { 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0 } }, }; +/* Initial mode-specific settings for RF2413/2414 (Written after ar5212_ini) */ +/* XXX: No dumps for turbog yet, so turbog is the same with g here with some + * minor tweaking based on dumps from other chips */ +static const struct ath5k_ini_mode rf2413_ini_mode_end[] = { + { AR5K_TXCFG, + /* b g gTurbo */ + { 0x00000015, 0x00000015, 0x00000015 } }, + { AR5K_USEC_5211, + { 0x04e01395, 0x12e013ab, 0x098813cf } }, + { AR5K_PHY(10), + { 0x05020000, 0x0a020001, 0x0a020001 } }, + { AR5K_PHY(13), + { 0x00000e00, 0x00000e00, 0x00000e00 } }, + { AR5K_PHY(14), + { 0x0000000a, 0x0000000a, 0x0000000a } }, + { AR5K_PHY(18), + { 0x001a6a64, 0x001a6a64, 0x001a6a64 } }, + { AR5K_PHY(20), + { 0x0de8b0da, 0x0c98b0da, 0x0c98b0da } }, + { AR5K_PHY_SIG, + { 0x7ee80d2e, 0x7ec80d2e, 0x7ec80d2e } }, + { AR5K_PHY_AGCCOARSE, + { 0x3137665e, 0x3139605e, 0x3139605e } }, + { AR5K_PHY(27), + { 0x050cb081, 0x050cb081, 0x050cb081 } }, + { AR5K_PHY_RX_DELAY, + { 0x0000044c, 0x00000898, 0x000007d0 } }, + { AR5K_PHY_FRAME_CTL_5211, + { 0xf7b80d00, 0xf7b81000, 0xf7b81000 } }, + { AR5K_PHY_CCKTXCTL, + { 0x00000000, 0x00000000, 0x00000000 } }, + { AR5K_PHY(642), + { 0xd03e6788, 0xd03e6788, 0xd03e6788 } }, + { AR5K_PHY_GAIN_2GHZ, + { 0x0042c140, 0x0042c140, 0x0042c140 } }, + { 0xa21c, + { 0x1863800a, 0x1883800a, 0x1883800a } }, + { AR5K_DCU_FP, + { 0x000003e0, 0x000003e0, 0x000003e0 } }, + { 0x8060, + { 0x0000000f, 0x0000000f, 0x0000000f } }, + { 0x8118, + { 0x00000000, 0x00000000, 0x00000000 } }, + { 0x811c, + { 0x00000000, 0x00000000, 0x00000000 } }, + { 0x8120, + { 0x00000000, 0x00000000, 0x00000000 } }, + { 0x8124, + { 0x00000000, 0x00000000, 0x00000000 } }, + { 0x8128, + { 0x00000000, 0x00000000, 0x00000000 } }, + { 0x812c, + { 0x00000000, 0x00000000, 0x00000000 } }, + { 0x8130, + { 0x00000000, 0x00000000, 0x00000000 } }, + { 0x8134, + { 0x00000000, 0x00000000, 0x00000000 } }, + { 0x8138, + { 0x00000000, 0x00000000, 0x00000000 } }, + { 0x813c, + { 0x00000000, 0x00000000, 0x00000000 } }, + { 0x8140, + { 0x800000a8, 0x800000a8, 0x800000a8 } }, + { 0x8144, + { 0x00000000, 0x00000000, 0x00000000 } }, + { AR5K_PHY_AGC, + { 0x00000000, 0x00000000, 0x00000000 } }, + { AR5K_PHY(11), + { 0x0000a000, 0x0000a000, 0x0000a000 } }, + { AR5K_PHY(15), + { 0x00200400, 0x00200400, 0x00200400 } }, + { AR5K_PHY(19), + { 0x1284233c, 0x1284233c, 0x1284233c } }, + { AR5K_PHY_SCR, + { 0x0000001f, 0x0000001f, 0x0000001f } }, + { AR5K_PHY_SLMT, + { 0x00000080, 0x00000080, 0x00000080 } }, + { AR5K_PHY_SCAL, + { 0x0000000e, 0x0000000e, 0x0000000e } }, + { AR5K_PHY(86), + { 0x000000ff, 0x000000ff, 0x000000ff } }, + { AR5K_PHY(96), + { 0x00000000, 0x00000000, 0x00000000 } }, + { AR5K_PHY(97), + { 0x02800000, 0x02800000, 0x02800000 } }, + { AR5K_PHY(104), + { 0x00000000, 0x00000000, 0x00000000 } }, + { AR5K_PHY(120), + { 0x00000000, 0x00000000, 0x00000000 } }, + { AR5K_PHY(121), + { 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa } }, + { AR5K_PHY(122), + { 0x3c466478, 0x3c466478, 0x3c466478 } }, + { AR5K_PHY(123), + { 0x000000aa, 0x000000aa, 0x000000aa } }, + { AR5K_PHY_SCLOCK, + { 0x0000000c, 0x0000000c, 0x0000000c } }, + { AR5K_PHY_SDELAY, + { 0x000000ff, 0x000000ff, 0x000000ff } }, + { AR5K_PHY_SPENDING, + { 0x00000014, 0x00000014, 0x00000014 } }, + { 0xa228, + { 0x000009b5, 0x000009b5, 0x000009b5 } }, + { 0xa23c, + { 0x93c889af, 0x93c889af, 0x93c889af } }, + { 0xa24c, + { 0x00000001, 0x00000001, 0x00000001 } }, + { 0xa250, + { 0x0000a000, 0x0000a000, 0x0000a000 } }, + { 0xa254, + { 0x00000000, 0x00000000, 0x00000000 } }, + { 0xa258, + { 0x0cc75380, 0x0cc75380, 0x0cc75380 } }, + { 0xa25c, + { 0x0f0f0f01, 0x0f0f0f01, 0x0f0f0f01 } }, + { 0xa260, + { 0x5f690f01, 0x5f690f01, 0x5f690f01 } }, + { 0xa264, + { 0x00418a11, 0x00418a11, 0x00418a11 } }, + { 0xa268, + { 0x00000000, 0x00000000, 0x00000000 } }, + { 0xa26c, + { 0x0c30c16a, 0x0c30c16a, 0x0c30c16a } }, + { 0xa270, + { 0x00820820, 0x00820820, 0x00820820 } }, + { 0xa274, + { 0x001b7caa, 0x001b7caa, 0x001b7caa } }, + { 0xa278, + { 0x1ce739ce, 0x1ce739ce, 0x1ce739ce } }, + { 0xa27c, + { 0x051701ce, 0x051701ce, 0x051701ce } }, + { 0xa300, + { 0x18010000, 0x18010000, 0x18010000 } }, + { 0xa304, + { 0x30032602, 0x30032602, 0x30032602 } }, + { 0xa308, + { 0x48073e06, 0x48073e06, 0x48073e06 } }, + { 0xa30c, + { 0x560b4c0a, 0x560b4c0a, 0x560b4c0a } }, + { 0xa310, + { 0x641a600f, 0x641a600f, 0x641a600f } }, + { 0xa314, + { 0x784f6e1b, 0x784f6e1b, 0x784f6e1b } }, + { 0xa318, + { 0x868f7c5a, 0x868f7c5a, 0x868f7c5a } }, + { 0xa31c, + { 0x8ecf865b, 0x8ecf865b, 0x8ecf865b } }, + { 0xa320, + { 0x9d4f970f, 0x9d4f970f, 0x9d4f970f } }, + { 0xa324, + { 0xa5cfa18f, 0xa5cfa18f, 0xa5cfa18f } }, + { 0xa328, + { 0xb55faf1f, 0xb55faf1f, 0xb55faf1f } }, + { 0xa32c, + { 0xbddfb99f, 0xbddfb99f, 0xbddfb99f } }, + { 0xa330, + { 0xcd7fc73f, 0xcd7fc73f, 0xcd7fc73f } }, + { 0xa334, + { 0xd5ffd1bf, 0xd5ffd1bf, 0xd5ffd1bf } }, + { 0xa338, + { 0x00000000, 0x00000000, 0x00000000 } }, + { 0xa33c, + { 0x00000000, 0x00000000, 0x00000000 } }, + { 0xa340, + { 0x00000000, 0x00000000, 0x00000000 } }, + { 0xa344, + { 0x00000000, 0x00000000, 0x00000000 } }, + { 0xa348, + { 0x3fffffff, 0x3fffffff, 0x3fffffff } }, + { 0xa34c, + { 0x3fffffff, 0x3fffffff, 0x3fffffff } }, + { 0xa350, + { 0x3fffffff, 0x3fffffff, 0x3fffffff } }, + { 0xa354, + { 0x0003ffff, 0x0003ffff, 0x0003ffff } }, + { 0xa358, + { 0x79a8aa1f, 0x79a8aa1f, 0x79a8aa1f } }, + { 0xa35c, + { 0x066c420f, 0x066c420f, 0x066c420f } }, + { 0xa360, + { 0x0f282207, 0x0f282207, 0x0f282207 } }, + { 0xa364, + { 0x17601685, 0x17601685, 0x17601685 } }, + { 0xa368, + { 0x1f801104, 0x1f801104, 0x1f801104 } }, + { 0xa36c, + { 0x37a00c03, 0x37a00c03, 0x37a00c03 } }, + { 0xa370, + { 0x3fc40883, 0x3fc40883, 0x3fc40883 } }, + { 0xa374, + { 0x57c00803, 0x57c00803, 0x57c00803 } }, + { 0xa378, + { 0x5fd80682, 0x5fd80682, 0x5fd80682 } }, + { 0xa37c, + { 0x7fe00482, 0x7fe00482, 0x7fe00482 } }, + { 0xa380, + { 0x7f3c7bba, 0x7f3c7bba, 0x7f3c7bba } }, + { 0xa384, + { 0xf3307ff0, 0xf3307ff0, 0xf3307ff0 } }, +}; + /* * Initial BaseBand Gain settings for RF5111/5112 (AR5210 comes with * RF5110 only so initial BB Gain settings are included in AR5K_AR5210_INI) @@ -1290,29 +1491,57 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel) /* Second set of mode-specific settings */ if (ah->ah_radio == AR5K_RF5111){ + ath5k_hw_ini_mode_registers(ah, ARRAY_SIZE(ar5212_rf5111_ini_mode_end), ar5212_rf5111_ini_mode_end, mode); + /* Baseband gain table */ ath5k_hw_ini_registers(ah, ARRAY_SIZE(rf5111_ini_bbgain), rf5111_ini_bbgain, change_channel); + } else if (ah->ah_radio == AR5K_RF5112){ + ath5k_hw_ini_mode_registers(ah, ARRAY_SIZE(ar5212_rf5112_ini_mode_end), ar5212_rf5112_ini_mode_end, mode); - /* Baseband gain table */ + ath5k_hw_ini_registers(ah, ARRAY_SIZE(rf5112_ini_bbgain), rf5112_ini_bbgain, change_channel); + } else if (ah->ah_radio == AR5K_RF5413){ + ath5k_hw_ini_mode_registers(ah, ARRAY_SIZE(rf5413_ini_mode_end), rf5413_ini_mode_end, mode); + + ath5k_hw_ini_registers(ah, + ARRAY_SIZE(rf5112_ini_bbgain), + rf5112_ini_bbgain, change_channel); + + } else if (ah->ah_radio == AR5K_RF2413) { + + if (mode < 2) { + ATH5K_ERR(ah->ah_sc, + "unsupported channel mode: %d\n", mode); + return -EINVAL; + } + mode = mode - 2; + + /* Override a setting from ar5212_ini */ + ath5k_hw_reg_write(ah, 0x018830c6, AR5K_PHY(648)); + + ath5k_hw_ini_mode_registers(ah, + ARRAY_SIZE(rf2413_ini_mode_end), + rf2413_ini_mode_end, mode); + /* Baseband gain table */ ath5k_hw_ini_registers(ah, ARRAY_SIZE(rf5112_ini_bbgain), rf5112_ini_bbgain, change_channel); + } /* For AR5211 */ } else if (ah->ah_version == AR5K_AR5211) { diff --git a/drivers/net/wireless/ath5k/phy.c b/drivers/net/wireless/ath5k/phy.c index 405195ffb24d..f108b08ff4af 100644 --- a/drivers/net/wireless/ath5k/phy.c +++ b/drivers/net/wireless/ath5k/phy.c @@ -666,6 +666,75 @@ static const struct ath5k_ini_rf rfregs_5413[] = { { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } }, }; +/* RF2413/2414 mode-specific init registers */ +static const struct ath5k_ini_rf rfregs_2413[] = { + { 1, AR5K_RF_BUFFER_CONTROL_4, + { 0x00000020, 0x00000020, 0x00000020 } }, + { 2, AR5K_RF_BUFFER_CONTROL_3, + { 0x02001408, 0x02001408, 0x02001408 } }, + { 3, AR5K_RF_BUFFER_CONTROL_6, + { 0x00e020c0, 0x00e020c0, 0x00e020c0 } }, + { 6, AR5K_RF_BUFFER, + { 0xf0000000, 0xf0000000, 0xf0000000 } }, + { 6, AR5K_RF_BUFFER, + { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, AR5K_RF_BUFFER, + { 0x03000000, 0x03000000, 0x03000000 } }, + { 6, AR5K_RF_BUFFER, + { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, AR5K_RF_BUFFER, + { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, AR5K_RF_BUFFER, + { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, AR5K_RF_BUFFER, + { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, AR5K_RF_BUFFER, + { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, AR5K_RF_BUFFER, + { 0x40400000, 0x40400000, 0x40400000 } }, + { 6, AR5K_RF_BUFFER, + { 0x65050000, 0x65050000, 0x65050000 } }, + { 6, AR5K_RF_BUFFER, + { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, AR5K_RF_BUFFER, + { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, AR5K_RF_BUFFER, + { 0x00420000, 0x00420000, 0x00420000 } }, + { 6, AR5K_RF_BUFFER, + { 0x00b50000, 0x00b50000, 0x00b50000 } }, + { 6, AR5K_RF_BUFFER, + { 0x00030000, 0x00030000, 0x00030000 } }, + { 6, AR5K_RF_BUFFER, + { 0x00f70000, 0x00f70000, 0x00f70000 } }, + { 6, AR5K_RF_BUFFER, + { 0x009d0000, 0x009d0000, 0x009d0000 } }, + { 6, AR5K_RF_BUFFER, + { 0x00220000, 0x00220000, 0x00220000 } }, + { 6, AR5K_RF_BUFFER, + { 0x04220000, 0x04220000, 0x04220000 } }, + { 6, AR5K_RF_BUFFER, + { 0x00230018, 0x00230018, 0x00230018 } }, + { 6, AR5K_RF_BUFFER, + { 0x00280050, 0x00280050, 0x00280050 } }, + { 6, AR5K_RF_BUFFER, + { 0x005000c3, 0x005000c3, 0x005000c3 } }, + { 6, AR5K_RF_BUFFER, + { 0x0004007f, 0x0004007f, 0x0004007f } }, + { 6, AR5K_RF_BUFFER, + { 0x00000458, 0x00000458, 0x00000458 } }, + { 6, AR5K_RF_BUFFER, + { 0x00000000, 0x00000000, 0x00000000 } }, + { 6, AR5K_RF_BUFFER, + { 0x0000c000, 0x0000c000, 0x0000c000 } }, + { 6, AR5K_RF_BUFFER_CONTROL_5, + { 0x00400230, 0x00400230, 0x00400230 } }, + { 7, AR5K_RF_BUFFER, + { 0x00006400, 0x00006400, 0x00006400 } }, + { 7, AR5K_RF_BUFFER, + { 0x00000800, 0x00000800, 0x00000800 } }, + { 7, AR5K_RF_BUFFER_CONTROL_2, + { 0x0000000e, 0x0000000e, 0x0000000e } }, +}; /* Initial RF Gain settings for RF5112 */ static const struct ath5k_ini_rfgain rfgain_5112[] = { @@ -805,6 +874,74 @@ static const struct ath5k_ini_rfgain rfgain_5413[] = { { AR5K_RF_GAIN(63), { 0x000000f9, 0x000000f9 } }, }; +/* Initial RF Gain settings for RF2413 */ +static const struct ath5k_ini_rfgain rfgain_2413[] = { + { AR5K_RF_GAIN(0), { 0x00000000 } }, + { AR5K_RF_GAIN(1), { 0x00000040 } }, + { AR5K_RF_GAIN(2), { 0x00000080 } }, + { AR5K_RF_GAIN(3), { 0x00000181 } }, + { AR5K_RF_GAIN(4), { 0x000001c1 } }, + { AR5K_RF_GAIN(5), { 0x00000001 } }, + { AR5K_RF_GAIN(6), { 0x00000041 } }, + { AR5K_RF_GAIN(7), { 0x00000081 } }, + { AR5K_RF_GAIN(8), { 0x00000168 } }, + { AR5K_RF_GAIN(9), { 0x000001a8 } }, + { AR5K_RF_GAIN(10), { 0x000001e8 } }, + { AR5K_RF_GAIN(11), { 0x00000028 } }, + { AR5K_RF_GAIN(12), { 0x00000068 } }, + { AR5K_RF_GAIN(13), { 0x00000189 } }, + { AR5K_RF_GAIN(14), { 0x000001c9 } }, + { AR5K_RF_GAIN(15), { 0x00000009 } }, + { AR5K_RF_GAIN(16), { 0x00000049 } }, + { AR5K_RF_GAIN(17), { 0x00000089 } }, + { AR5K_RF_GAIN(18), { 0x00000190 } }, + { AR5K_RF_GAIN(19), { 0x000001d0 } }, + { AR5K_RF_GAIN(20), { 0x00000010 } }, + { AR5K_RF_GAIN(21), { 0x00000050 } }, + { AR5K_RF_GAIN(22), { 0x00000090 } }, + { AR5K_RF_GAIN(23), { 0x00000191 } }, + { AR5K_RF_GAIN(24), { 0x000001d1 } }, + { AR5K_RF_GAIN(25), { 0x00000011 } }, + { AR5K_RF_GAIN(26), { 0x00000051 } }, + { AR5K_RF_GAIN(27), { 0x00000091 } }, + { AR5K_RF_GAIN(28), { 0x00000178 } }, + { AR5K_RF_GAIN(29), { 0x000001b8 } }, + { AR5K_RF_GAIN(30), { 0x000001f8 } }, + { AR5K_RF_GAIN(31), { 0x00000038 } }, + { AR5K_RF_GAIN(32), { 0x00000078 } }, + { AR5K_RF_GAIN(33), { 0x00000199 } }, + { AR5K_RF_GAIN(34), { 0x000001d9 } }, + { AR5K_RF_GAIN(35), { 0x00000019 } }, + { AR5K_RF_GAIN(36), { 0x00000059 } }, + { AR5K_RF_GAIN(37), { 0x00000099 } }, + { AR5K_RF_GAIN(38), { 0x000000d9 } }, + { AR5K_RF_GAIN(39), { 0x000000f9 } }, + { AR5K_RF_GAIN(40), { 0x000000f9 } }, + { AR5K_RF_GAIN(41), { 0x000000f9 } }, + { AR5K_RF_GAIN(42), { 0x000000f9 } }, + { AR5K_RF_GAIN(43), { 0x000000f9 } }, + { AR5K_RF_GAIN(44), { 0x000000f9 } }, + { AR5K_RF_GAIN(45), { 0x000000f9 } }, + { AR5K_RF_GAIN(46), { 0x000000f9 } }, + { AR5K_RF_GAIN(47), { 0x000000f9 } }, + { AR5K_RF_GAIN(48), { 0x000000f9 } }, + { AR5K_RF_GAIN(49), { 0x000000f9 } }, + { AR5K_RF_GAIN(50), { 0x000000f9 } }, + { AR5K_RF_GAIN(51), { 0x000000f9 } }, + { AR5K_RF_GAIN(52), { 0x000000f9 } }, + { AR5K_RF_GAIN(53), { 0x000000f9 } }, + { AR5K_RF_GAIN(54), { 0x000000f9 } }, + { AR5K_RF_GAIN(55), { 0x000000f9 } }, + { AR5K_RF_GAIN(56), { 0x000000f9 } }, + { AR5K_RF_GAIN(57), { 0x000000f9 } }, + { AR5K_RF_GAIN(58), { 0x000000f9 } }, + { AR5K_RF_GAIN(59), { 0x000000f9 } }, + { AR5K_RF_GAIN(60), { 0x000000f9 } }, + { AR5K_RF_GAIN(61), { 0x000000f9 } }, + { AR5K_RF_GAIN(62), { 0x000000f9 } }, + { AR5K_RF_GAIN(63), { 0x000000f9 } }, +}; + static const struct ath5k_gain_opt rfgain_opt_5112 = { 1, 8, @@ -1226,8 +1363,21 @@ static int ath5k_hw_rf5413_rfregs(struct ath5k_hw *ah, rf = ah->ah_rf_banks; - rf_ini = rfregs_5413; - rf_size = ARRAY_SIZE(rfregs_5413); + if (ah->ah_radio == AR5K_RF5413) { + rf_ini = rfregs_5413; + rf_size = ARRAY_SIZE(rfregs_5413); + } else if (ah->ah_radio == AR5K_RF2413) { + rf_ini = rfregs_2413; + rf_size = ARRAY_SIZE(rfregs_2413); + if (mode < 2) { + ATH5K_ERR(ah->ah_sc, + "invalid channel mode: %i\n", mode); + return -EINVAL; + } + mode = mode - 2; + } else { + return -EINVAL; + } /* Copy values to modify them */ for (i = 0; i < rf_size; i++) { @@ -1286,6 +1436,10 @@ int ath5k_hw_rfregs(struct ath5k_hw *ah, struct ieee80211_channel *channel, ah->ah_rf_banks_size = sizeof(rfregs_5413); func = ath5k_hw_rf5413_rfregs; break; + case AR5K_RF2413: + ah->ah_rf_banks_size = sizeof(rfregs_2413); + func = ath5k_hw_rf5413_rfregs; + break; default: return -EINVAL; } @@ -1324,6 +1478,11 @@ int ath5k_hw_rfgain(struct ath5k_hw *ah, unsigned int freq) ath5k_rfg = rfgain_5413; size = ARRAY_SIZE(rfgain_5413); break; + case AR5K_RF2413: + ath5k_rfg = rfgain_2413; + size = ARRAY_SIZE(rfgain_2413); + freq = 0; /* only 2Ghz */ + break; default: return -EINVAL; } -- cgit v1.2.1 From 0af2256319959aaca95959a493ed2282edaaae3e Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Thu, 28 Feb 2008 14:49:05 -0500 Subject: ath5k: Identify RF2413 and deal with PHY_SPENDING * Attach RF2413. * Propertly handle different AR5K_PHY_SPENDING settings for each RF chip by adding a field in ath5k_hw. This way we won't have to check inside hw_reset (see next patch). Changes-licensed-under: ISC Signed-off-by: Nick Kossifidis Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/ath5k.h | 1 + drivers/net/wireless/ath5k/hw.c | 27 +++++++++++++++++++++++++-- drivers/net/wireless/ath5k/reg.h | 4 +++- 3 files changed, 29 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath5k/ath5k.h b/drivers/net/wireless/ath5k/ath5k.h index 25c8e989d700..c0b65961f55f 100644 --- a/drivers/net/wireless/ath5k/ath5k.h +++ b/drivers/net/wireless/ath5k/ath5k.h @@ -966,6 +966,7 @@ struct ath5k_hw { u16 ah_phy_revision; u16 ah_radio_5ghz_revision; u16 ah_radio_2ghz_revision; + u32 ah_phy_spending; enum ath5k_version ah_version; enum ath5k_radio ah_radio; diff --git a/drivers/net/wireless/ath5k/hw.c b/drivers/net/wireless/ath5k/hw.c index eec2b806a0de..f4d383e956a0 100644 --- a/drivers/net/wireless/ath5k/hw.c +++ b/drivers/net/wireless/ath5k/hw.c @@ -208,7 +208,7 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) /* Identify single chip solutions */ if((srev <= AR5K_SREV_VER_AR5414) && - (srev >= AR5K_SREV_VER_AR2424)) { + (srev >= AR5K_SREV_VER_AR2413)) { ah->ah_single_chip = true; } else { ah->ah_single_chip = false; @@ -223,10 +223,33 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) ah->ah_radio = AR5K_RF5110; } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5112) { ah->ah_radio = AR5K_RF5111; - } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC1) { + ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5111; + } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC0) { + ah->ah_radio = AR5K_RF5112; + + if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5112A) { + ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112; + } else { + ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A; + } + + } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC1) { + ah->ah_radio = AR5K_RF2413; + ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A; } else { + ah->ah_radio = AR5K_RF5413; + + if (ah->ah_mac_srev <= AR5K_SREV_VER_AR5424 && + ah->ah_mac_srev >= AR5K_SREV_VER_AR2424) + ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5424; + else if (ah->ah_mac_srev >= AR5K_SREV_VER_AR2425) + ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112; + else + ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A; + + } ah->ah_phy = AR5K_PHY(0); diff --git a/drivers/net/wireless/ath5k/reg.h b/drivers/net/wireless/ath5k/reg.h index 2f41c8398602..30629b3e37c2 100644 --- a/drivers/net/wireless/ath5k/reg.h +++ b/drivers/net/wireless/ath5k/reg.h @@ -1923,7 +1923,9 @@ after DFS is enabled */ #define AR5K_PHY_SDELAY_32MHZ 0x000000ff #define AR5K_PHY_SPENDING 0x99f8 #define AR5K_PHY_SPENDING_RF5111 0x00000018 -#define AR5K_PHY_SPENDING_RF5112 0x00000014 +#define AR5K_PHY_SPENDING_RF5112 0x00000014 /* <- i 've only seen this on 2425 dumps ! */ +#define AR5K_PHY_SPENDING_RF5112A 0x0000000e /* but since i only have 5112A-based chips */ +#define AR5K_PHY_SPENDING_RF5424 0x00000012 /* to test it might be also for old 5112. */ /* * Misc PHY/radio registers [5110 - 5111] -- cgit v1.2.1 From 903b474efabab6a4ce697063c367afd8e2ad83f3 Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Thu, 28 Feb 2008 14:50:50 -0500 Subject: ath5k: more RF2413 stuff * Add AR5K_RF2413 to radio check during hw_reset so it doesn't complain * Write ah_phy_spending value we set during attach instead of checking each time for radio revision * Skip txpower setup for RF2413 because it can't transmit with it (weird thing is that RF5413 has no problem with it). Changes-licensed-under: ISC Signed-off-by: Nick Kossifidis Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/hw.c | 7 +++---- drivers/net/wireless/ath5k/phy.c | 9 +++++++++ 2 files changed, 12 insertions(+), 4 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath5k/hw.c b/drivers/net/wireless/ath5k/hw.c index f4d383e956a0..bd1513d1460b 100644 --- a/drivers/net/wireless/ath5k/hw.c +++ b/drivers/net/wireless/ath5k/hw.c @@ -640,7 +640,8 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, if (ah->ah_version != AR5K_AR5210) { if (ah->ah_radio != AR5K_RF5111 && ah->ah_radio != AR5K_RF5112 && - ah->ah_radio != AR5K_RF5413) { + ah->ah_radio != AR5K_RF5413 && + ah->ah_radio != AR5K_RF2413) { ATH5K_ERR(ah->ah_sc, "invalid phy radio: %u\n", ah->ah_radio); return -EINVAL; @@ -1002,9 +1003,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, ath5k_hw_reg_write(ah, AR5K_PHY_SCAL_32MHZ, AR5K_PHY_SCAL); ath5k_hw_reg_write(ah, AR5K_PHY_SCLOCK_32MHZ, AR5K_PHY_SCLOCK); ath5k_hw_reg_write(ah, AR5K_PHY_SDELAY_32MHZ, AR5K_PHY_SDELAY); - ath5k_hw_reg_write(ah, ah->ah_radio == AR5K_RF5111 ? - AR5K_PHY_SPENDING_RF5111 : AR5K_PHY_SPENDING_RF5112, - AR5K_PHY_SPENDING); + ath5k_hw_reg_write(ah, ah->ah_phy_spending, AR5K_PHY_SPENDING); } /* diff --git a/drivers/net/wireless/ath5k/phy.c b/drivers/net/wireless/ath5k/phy.c index f108b08ff4af..40efd4d3b54c 100644 --- a/drivers/net/wireless/ath5k/phy.c +++ b/drivers/net/wireless/ath5k/phy.c @@ -2178,6 +2178,15 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, return -EINVAL; } + /* + * RF2413 for some reason can't + * transmit anything if we call + * this funtion, so we skip it + * until we fix txpower. + */ + if (ah->ah_radio == AR5K_RF2413) + return 0; + /* Reset TX power values */ memset(&ah->ah_txpower, 0, sizeof(ah->ah_txpower)); ah->ah_txpower.txp_tpc = tpc; -- cgit v1.2.1 From 74693a7f3096a52ecbf477d31dc4c595bf27a8d3 Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Thu, 28 Feb 2008 14:51:40 -0500 Subject: ath5k: Remove RF5413 from rf gain optimization functions * Since RF2413 it seems that RF_BUFFER settings are different (notice that the last part -"bank 7" or whatever- is smaller than in 5111/5112). So until we know what's going on we assume there is no gain optimization stuff in post-5112 chips. Changes-licensed-under: ISC Signed-off-by: Nick Kossifidis Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/phy.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath5k/phy.c b/drivers/net/wireless/ath5k/phy.c index 40efd4d3b54c..ee1dc0fc6ea2 100644 --- a/drivers/net/wireless/ath5k/phy.c +++ b/drivers/net/wireless/ath5k/phy.c @@ -1092,7 +1092,6 @@ static s32 ath5k_hw_rfregs_gain_adjust(struct ath5k_hw *ah) go = &rfgain_opt_5111; break; case AR5K_RF5112: - case AR5K_RF5413: /* ??? */ go = &rfgain_opt_5112; break; default: @@ -1557,7 +1556,6 @@ int ath5k_hw_set_rfgain_opt(struct ath5k_hw *ah) ah->ah_gain.g_active = 1; break; case AR5K_RF5112: - case AR5K_RF5413: /* ??? */ ah->ah_gain.g_step_idx = rfgain_opt_5112.go_default; ah->ah_gain.g_step = &rfgain_opt_5112.go_step[ah->ah_gain.g_step_idx]; -- cgit v1.2.1 From 56c9054f16ecb62bd83e9c55032522604d2f626c Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Thu, 28 Feb 2008 16:20:52 -0500 Subject: ath5k: Fixes for PCI-E cards * Fix nic_wakeup for PCI-E chips (don't set AR5K_RESET_CTL_PCI bit) * Fix dma size setting for PCI-E chips (thanx to Bob Copeland). Changes-licensed-under: ISC Signed-off-by: Nick Kossifidis Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/ath5k.h | 10 +++++----- drivers/net/wireless/ath5k/hw.c | 39 ++++++++++++++++++++++++++++---------- 2 files changed, 34 insertions(+), 15 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath5k/ath5k.h b/drivers/net/wireless/ath5k/ath5k.h index c0b65961f55f..04efceef95a8 100644 --- a/drivers/net/wireless/ath5k/ath5k.h +++ b/drivers/net/wireless/ath5k/ath5k.h @@ -171,13 +171,13 @@ struct ath5k_srev_name { #define AR5K_SREV_VER_AR5213A 0x59 #define AR5K_SREV_VER_AR2413 0x78 #define AR5K_SREV_VER_AR2414 0x79 -#define AR5K_SREV_VER_AR2424 0xa0 -#define AR5K_SREV_VER_AR5424 0xa3 +#define AR5K_SREV_VER_AR2424 0xa0 /* PCI-E */ +#define AR5K_SREV_VER_AR5424 0xa3 /* PCI-E */ #define AR5K_SREV_VER_AR5413 0xa4 #define AR5K_SREV_VER_AR5414 0xa5 -#define AR5K_SREV_VER_AR5416 0xc0 /* ? */ -#define AR5K_SREV_VER_AR5418 0xca -#define AR5K_SREV_VER_AR2425 0xe2 +#define AR5K_SREV_VER_AR5416 0xc0 /* PCI-E */ +#define AR5K_SREV_VER_AR5418 0xca /* PCI-E */ +#define AR5K_SREV_VER_AR2425 0xe2 /* PCI-E */ #define AR5K_SREV_RAD_5110 0x00 #define AR5K_SREV_RAD_5111 0x10 diff --git a/drivers/net/wireless/ath5k/hw.c b/drivers/net/wireless/ath5k/hw.c index bd1513d1460b..b275b1f234a5 100644 --- a/drivers/net/wireless/ath5k/hw.c +++ b/drivers/net/wireless/ath5k/hw.c @@ -300,7 +300,8 @@ err: */ static int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) { - u32 turbo, mode, clock; + struct pci_dev *pdev = ah->ah_sc->pdev; + u32 turbo, mode, clock, bus_flags; int ret; turbo = 0; @@ -377,9 +378,15 @@ static int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) AR5K_PHY_TURBO); } - /* ...reset chipset and PCI device */ - if (ah->ah_single_chip == false && ath5k_hw_nic_reset(ah, - AR5K_RESET_CTL_CHIP | AR5K_RESET_CTL_PCI)) { + /* reseting PCI on PCI-E cards results card to hang + * and always return 0xffff... so we ingore that flag + * for PCI-E cards */ + bus_flags = (pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI; + + /* Reset chipset */ + ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | + AR5K_RESET_CTL_BASEBAND | bus_flags); + if (ret) { ATH5K_ERR(ah->ah_sc, "failed to reset the MAC Chip + PCI\n"); return -EIO; } @@ -588,7 +595,8 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, struct ieee80211_channel *channel, bool change_channel) { struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - u32 data, s_seq, s_ant, s_led[3]; + struct pci_dev *pdev = ah->ah_sc->pdev; + u32 data, s_seq, s_ant, s_led[3], dma_size; unsigned int i, mode, freq, ee_mode, ant[2]; int ret; @@ -900,13 +908,24 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, /* * Set Rx/Tx DMA Configuration - *(passing dma size not available on 5210) + * + * Set maximum DMA size (512) except for PCI-E cards since + * it causes rx overruns and tx errors (tested on 5424 but since + * rx overruns also occur on 5416/5418 with madwifi we set 128 + * for all PCI-E cards to be safe). + * + * In dumps this is 128 for allchips. + * + * XXX: need to check 5210 for this + * TODO: Check out tx triger level, it's always 64 on dumps but I + * guess we can tweak it and see how it goes ;-) */ + dma_size = (pdev->is_pcie) ? AR5K_DMASIZE_128B : AR5K_DMASIZE_512B; if (ah->ah_version != AR5K_AR5210) { - AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG, AR5K_TXCFG_SDMAMR, - AR5K_DMASIZE_512B | AR5K_TXCFG_DMASIZE); - AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_SDMAMW, - AR5K_DMASIZE_512B); + AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG, + AR5K_TXCFG_SDMAMR, dma_size); + AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG, + AR5K_RXCFG_SDMAMW, dma_size); } /* -- cgit v1.2.1 From c87cdfd270e8fb24ba1b707c83da499b87ef1ade Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Fri, 7 Mar 2008 11:48:21 -0500 Subject: ath5k: Make some changes to follow register dumps. Make some changes which mimic what we see in register dumps. This patch does not add a helper to ath5k_hw_reset(). It does seem clear we need a re-shuffle around ath5k_hw_reset() though as code in there is lengthy and already hitting 80-char limit. This can be dealt with later though. Changes-licensed-under: ISC Signed-off-by: Nick Kossifidis Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/hw.c | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath5k/hw.c b/drivers/net/wireless/ath5k/hw.c index b275b1f234a5..3c399604f30e 100644 --- a/drivers/net/wireless/ath5k/hw.c +++ b/drivers/net/wireless/ath5k/hw.c @@ -724,15 +724,26 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, /* * Write some more initial register settings */ - if (ah->ah_version > AR5K_AR5211){ /* found on 5213+ */ + if (ah->ah_version == AR5K_AR5212) { ath5k_hw_reg_write(ah, 0x0002a002, AR5K_PHY(11)); if (channel->hw_value == CHANNEL_G) - ath5k_hw_reg_write(ah, 0x00f80d80, AR5K_PHY(83)); /* 0x00fc0ec0 */ + if (ah->ah_mac_srev < AR5K_SREV_VER_AR2413) + ath5k_hw_reg_write(ah, 0x00f80d80, + AR5K_PHY(83)); + else if (ah->ah_mac_srev < AR5K_SREV_VER_AR2424) + ath5k_hw_reg_write(ah, 0x00380140, + AR5K_PHY(83)); + else if (ah->ah_mac_srev < AR5K_SREV_VER_AR2425) + ath5k_hw_reg_write(ah, 0x00fc0ec0, + AR5K_PHY(83)); + else /* 2425 */ + ath5k_hw_reg_write(ah, 0x00fc0fc0, + AR5K_PHY(83)); else - ath5k_hw_reg_write(ah, 0x00000000, AR5K_PHY(83)); + ath5k_hw_reg_write(ah, 0x00000000, + AR5K_PHY(83)); - ath5k_hw_reg_write(ah, 0x000001b5, 0xa228); /* 0x000009b5 */ ath5k_hw_reg_write(ah, 0x000009b5, 0xa228); ath5k_hw_reg_write(ah, 0x0000000f, 0x8060); ath5k_hw_reg_write(ah, 0x00000000, 0xa254); @@ -1015,6 +1026,8 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, /* * Set the 32MHz reference clock on 5212 phy clock sleep register + * + * TODO: Find out how to switch to external 32Khz clock to save power */ if (ah->ah_version == AR5K_AR5212) { ath5k_hw_reg_write(ah, AR5K_PHY_SCR_32MHZ, AR5K_PHY_SCR); @@ -1025,6 +1038,14 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, ath5k_hw_reg_write(ah, ah->ah_phy_spending, AR5K_PHY_SPENDING); } + if (ah->ah_version == AR5K_AR5212) { + ath5k_hw_reg_write(ah, 0x000100aa, 0x8118); + ath5k_hw_reg_write(ah, 0x00003210, 0x811c); + ath5k_hw_reg_write(ah, 0x00000052, 0x8108); + if (ah->ah_mac_srev >= AR5K_SREV_VER_AR2413) + ath5k_hw_reg_write(ah, 0x00000004, 0x8120); + } + /* * Disable beacons and reset the register */ @@ -2269,8 +2290,8 @@ void ath5k_hw_set_associd(struct ath5k_hw *ah, const u8 *bssid, u16 assoc_id) * Set simple BSSID mask on 5212 */ if (ah->ah_version == AR5K_AR5212) { - ath5k_hw_reg_write(ah, 0xfffffff, AR5K_BSS_IDM0); - ath5k_hw_reg_write(ah, 0xfffffff, AR5K_BSS_IDM1); + ath5k_hw_reg_write(ah, 0xffffffff, AR5K_BSS_IDM0); + ath5k_hw_reg_write(ah, 0xffffffff, AR5K_BSS_IDM1); } /* @@ -2415,6 +2436,8 @@ void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah) { ATH5K_TRACE(ah->ah_sc); AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); + + /* TODO: ANI Support */ } /* @@ -2424,6 +2447,8 @@ void ath5k_hw_stop_pcu_recv(struct ath5k_hw *ah) { ATH5K_TRACE(ah->ah_sc); AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); + + /* TODO: ANI Support */ } /* -- cgit v1.2.1 From bb0c9dc27e8fa360e108e6e96860da620a7c5d04 Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Fri, 7 Mar 2008 11:52:51 -0500 Subject: ath5k: Add 2413 to srev_names so that it shows up during module load Add 2413 to srev_names so that it shows up during module load. This is based on the new patch 7 which did not introduce a helper on ath5k_hw_reset(). Changes-licensed-under: 3-clause-BSD Signed-off-by: Nick Kossifidis Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/base.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index 393b5f3c25a7..fc4db8834c36 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -118,6 +118,8 @@ static struct ath5k_srev_name srev_names[] = { { "5212", AR5K_VERSION_VER, AR5K_SREV_VER_AR5212 }, { "5213", AR5K_VERSION_VER, AR5K_SREV_VER_AR5213 }, { "5213A", AR5K_VERSION_VER, AR5K_SREV_VER_AR5213A }, + { "2413", AR5K_VERSION_VER, AR5K_SREV_VER_AR2413 }, + { "2414", AR5K_VERSION_VER, AR5K_SREV_VER_AR2414 }, { "2424", AR5K_VERSION_VER, AR5K_SREV_VER_AR2424 }, { "5424", AR5K_VERSION_VER, AR5K_SREV_VER_AR5424 }, { "5413", AR5K_VERSION_VER, AR5K_SREV_VER_AR5413 }, @@ -132,6 +134,7 @@ static struct ath5k_srev_name srev_names[] = { { "5112A", AR5K_VERSION_RAD, AR5K_SREV_RAD_5112A }, { "2112", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112 }, { "2112A", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112A }, + { "SChip", AR5K_VERSION_RAD, AR5K_SREV_RAD_SC0 }, { "SChip", AR5K_VERSION_RAD, AR5K_SREV_RAD_SC1 }, { "SChip", AR5K_VERSION_RAD, AR5K_SREV_RAD_SC2 }, { "5133", AR5K_VERSION_RAD, AR5K_SREV_RAD_5133 }, -- cgit v1.2.1 From e6f5b934fba8c44c87c551e066aa7ca6fde2939e Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Wed, 5 Mar 2008 21:18:49 +0100 Subject: b43: Add QOS support This adds QOS support to the b43 driver. QOS can be disabled on driver level with a module parameter for debugging purposes. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/b43.h | 37 +++++++++ drivers/net/wireless/b43/dma.c | 90 +++++++++----------- drivers/net/wireless/b43/dma.h | 3 + drivers/net/wireless/b43/main.c | 180 +++++++++++++++++++++++++++++++++++++++- drivers/net/wireless/b43/main.h | 4 + drivers/net/wireless/b43/xmit.c | 27 ------ drivers/net/wireless/b43/xmit.h | 12 --- 7 files changed, 262 insertions(+), 91 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index 33459d61a717..55031463c396 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -99,6 +99,8 @@ #define B43_MMIO_TSF_2 0x636 /* core rev < 3 only */ #define B43_MMIO_TSF_3 0x638 /* core rev < 3 only */ #define B43_MMIO_RNG 0x65A +#define B43_MMIO_IFSCTL 0x688 /* Interframe space control */ +#define B43_MMIO_IFSCTL_USE_EDCF 0x0004 #define B43_MMIO_POWERUP_DELAY 0x6A8 /* SPROM boardflags_lo values */ @@ -621,6 +623,35 @@ struct b43_key { u8 algorithm; }; +/* SHM offsets to the QOS data structures for the 4 different queues. */ +#define B43_QOS_PARAMS(queue) (B43_SHM_SH_EDCFQ + \ + (B43_NR_QOSPARAMS * sizeof(u16) * (queue))) +#define B43_QOS_BACKGROUND B43_QOS_PARAMS(0) +#define B43_QOS_BESTEFFORT B43_QOS_PARAMS(1) +#define B43_QOS_VIDEO B43_QOS_PARAMS(2) +#define B43_QOS_VOICE B43_QOS_PARAMS(3) + +/* QOS parameter hardware data structure offsets. */ +#define B43_NR_QOSPARAMS 22 +enum { + B43_QOSPARAM_TXOP = 0, + B43_QOSPARAM_CWMIN, + B43_QOSPARAM_CWMAX, + B43_QOSPARAM_CWCUR, + B43_QOSPARAM_AIFS, + B43_QOSPARAM_BSLOTS, + B43_QOSPARAM_REGGAP, + B43_QOSPARAM_STATUS, +}; + +/* QOS parameters for a queue. */ +struct b43_qos_params { + /* The QOS parameters */ + struct ieee80211_tx_queue_params p; + /* Does this need to get uploaded to hardware? */ + bool need_hw_update; +}; + struct b43_wldev; /* Data structure for the WLAN parts (802.11 cores) of the b43 chip. */ @@ -673,6 +704,12 @@ struct b43_wl { struct sk_buff *current_beacon; bool beacon0_uploaded; bool beacon1_uploaded; + + /* The current QOS parameters for the 4 queues. + * This is protected by the irq_lock. */ + struct b43_qos_params qos_params[4]; + /* Workqueue for updating QOS parameters in hardware. */ + struct work_struct qos_update_work; }; /* In-memory representation of a cached microcode file. */ diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index 3dfb28a34be9..c8ead465497a 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c @@ -291,52 +291,6 @@ static inline int request_slot(struct b43_dmaring *ring) return slot; } -/* Mac80211-queue to b43-ring mapping */ -static struct b43_dmaring *priority_to_txring(struct b43_wldev *dev, - int queue_priority) -{ - struct b43_dmaring *ring; - -/*FIXME: For now we always run on TX-ring-1 */ - return dev->dma.tx_ring1; - - /* 0 = highest priority */ - switch (queue_priority) { - default: - B43_WARN_ON(1); - /* fallthrough */ - case 0: - ring = dev->dma.tx_ring3; - break; - case 1: - ring = dev->dma.tx_ring2; - break; - case 2: - ring = dev->dma.tx_ring1; - break; - case 3: - ring = dev->dma.tx_ring0; - break; - } - - return ring; -} - -/* b43-ring to mac80211-queue mapping */ -static inline int txring_to_priority(struct b43_dmaring *ring) -{ - static const u8 idx_to_prio[] = { 3, 2, 1, 0, }; - unsigned int index; - -/*FIXME: have only one queue, for now */ - return 0; - - index = ring->index; - if (B43_WARN_ON(index >= ARRAY_SIZE(idx_to_prio))) - index = 0; - return idx_to_prio[index]; -} - static u16 b43_dmacontroller_base(enum b43_dmatype type, int controller_idx) { static const u16 map64[] = { @@ -1272,6 +1226,37 @@ static inline int should_inject_overflow(struct b43_dmaring *ring) return 0; } +/* Static mapping of mac80211's queues (priorities) to b43 DMA rings. */ +static struct b43_dmaring * select_ring_by_priority(struct b43_wldev *dev, + u8 queue_prio) +{ + struct b43_dmaring *ring; + + if (b43_modparam_qos) { + /* 0 = highest priority */ + switch (queue_prio) { + default: + B43_WARN_ON(1); + /* fallthrough */ + case 0: + ring = dev->dma.tx_ring3; /* AC_VO */ + break; + case 1: + ring = dev->dma.tx_ring2; /* AC_VI */ + break; + case 2: + ring = dev->dma.tx_ring1; /* AC_BE */ + break; + case 3: + ring = dev->dma.tx_ring0; /* AC_BK */ + break; + } + } else + ring = dev->dma.tx_ring1; + + return ring; +} + int b43_dma_tx(struct b43_wldev *dev, struct sk_buff *skb, struct ieee80211_tx_control *ctl) { @@ -1294,7 +1279,7 @@ int b43_dma_tx(struct b43_wldev *dev, hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA); } else { /* Decide by priority where to put this frame. */ - ring = priority_to_txring(dev, ctl->queue); + ring = select_ring_by_priority(dev, ctl->queue); } spin_lock_irqsave(&ring->lock, flags); @@ -1309,6 +1294,11 @@ int b43_dma_tx(struct b43_wldev *dev, * That would be a mac80211 bug. */ B43_WARN_ON(ring->stopped); + /* Assign the queue number to the ring (if not already done before) + * so TX status handling can use it. The queue to ring mapping is + * static, so we don't need to store it per frame. */ + ring->queue_prio = ctl->queue; + err = dma_tx_fragment(ring, skb, ctl); if (unlikely(err == -ENOKEY)) { /* Drop this packet, as we don't have the encryption key @@ -1325,7 +1315,7 @@ int b43_dma_tx(struct b43_wldev *dev, if ((free_slots(ring) < SLOTS_PER_PACKET) || should_inject_overflow(ring)) { /* This TX ring is full. */ - ieee80211_stop_queue(dev->wl->hw, txring_to_priority(ring)); + ieee80211_stop_queue(dev->wl->hw, ctl->queue); ring->stopped = 1; if (b43_debug(dev, B43_DBG_DMAVERBOSE)) { b43dbg(dev->wl, "Stopped TX ring %d\n", ring->index); @@ -1404,7 +1394,7 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev, dev->stats.last_tx = jiffies; if (ring->stopped) { B43_WARN_ON(free_slots(ring) < SLOTS_PER_PACKET); - ieee80211_wake_queue(dev->wl->hw, txring_to_priority(ring)); + ieee80211_wake_queue(dev->wl->hw, ring->queue_prio); ring->stopped = 0; if (b43_debug(dev, B43_DBG_DMAVERBOSE)) { b43dbg(dev->wl, "Woke up TX ring %d\n", ring->index); @@ -1425,7 +1415,7 @@ void b43_dma_get_tx_stats(struct b43_wldev *dev, for (i = 0; i < nr_queues; i++) { data = &(stats->data[i]); - ring = priority_to_txring(dev, i); + ring = select_ring_by_priority(dev, i); spin_lock_irqsave(&ring->lock, flags); data->len = ring->used_slots / SLOTS_PER_PACKET; diff --git a/drivers/net/wireless/b43/dma.h b/drivers/net/wireless/b43/dma.h index c0d6b69e6501..9336286d97a7 100644 --- a/drivers/net/wireless/b43/dma.h +++ b/drivers/net/wireless/b43/dma.h @@ -245,6 +245,9 @@ struct b43_dmaring { enum b43_dmatype type; /* Boolean. Is this ring stopped at ieee80211 level? */ bool stopped; + /* The QOS priority assigned to this ring. Only used for TX rings. + * This is the mac80211 "queue" value. */ + u8 queue_prio; /* Lock, only used for TX. */ spinlock_t lock; struct b43_wldev *dev; diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index c93b62fb5f65..dbacb58d9527 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -78,6 +78,11 @@ static int modparam_nohwcrypt; module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444); MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); +int b43_modparam_qos = 1; +module_param_named(qos, b43_modparam_qos, int, 0444); +MODULE_PARM_DESC(qos, "Enable QOS support (default on)"); + + static const struct ssb_device_id b43_ssb_tbl[] = { SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 5), SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 6), @@ -2708,10 +2713,178 @@ out: return NETDEV_TX_OK; } +/* Locking: wl->irq_lock */ +static void b43_qos_params_upload(struct b43_wldev *dev, + const struct ieee80211_tx_queue_params *p, + u16 shm_offset) +{ + u16 params[B43_NR_QOSPARAMS]; + int cw_min, cw_max, aifs, bslots, tmp; + unsigned int i; + + const u16 aCWmin = 0x0001; + const u16 aCWmax = 0x03FF; + + /* Calculate the default values for the parameters, if needed. */ + switch (shm_offset) { + case B43_QOS_VOICE: + aifs = (p->aifs == -1) ? 2 : p->aifs; + cw_min = (p->cw_min == 0) ? ((aCWmin + 1) / 4 - 1) : p->cw_min; + cw_max = (p->cw_max == 0) ? ((aCWmin + 1) / 2 - 1) : p->cw_max; + break; + case B43_QOS_VIDEO: + aifs = (p->aifs == -1) ? 2 : p->aifs; + cw_min = (p->cw_min == 0) ? ((aCWmin + 1) / 2 - 1) : p->cw_min; + cw_max = (p->cw_max == 0) ? aCWmin : p->cw_max; + break; + case B43_QOS_BESTEFFORT: + aifs = (p->aifs == -1) ? 3 : p->aifs; + cw_min = (p->cw_min == 0) ? aCWmin : p->cw_min; + cw_max = (p->cw_max == 0) ? aCWmax : p->cw_max; + break; + case B43_QOS_BACKGROUND: + aifs = (p->aifs == -1) ? 7 : p->aifs; + cw_min = (p->cw_min == 0) ? aCWmin : p->cw_min; + cw_max = (p->cw_max == 0) ? aCWmax : p->cw_max; + break; + default: + B43_WARN_ON(1); + return; + } + if (cw_min <= 0) + cw_min = aCWmin; + if (cw_max <= 0) + cw_max = aCWmin; + bslots = b43_read16(dev, B43_MMIO_RNG) % cw_min; + + memset(¶ms, 0, sizeof(params)); + + params[B43_QOSPARAM_TXOP] = p->txop * 32; + params[B43_QOSPARAM_CWMIN] = cw_min; + params[B43_QOSPARAM_CWMAX] = cw_max; + params[B43_QOSPARAM_CWCUR] = cw_min; + params[B43_QOSPARAM_AIFS] = aifs; + params[B43_QOSPARAM_BSLOTS] = bslots; + params[B43_QOSPARAM_REGGAP] = bslots + aifs; + + for (i = 0; i < ARRAY_SIZE(params); i++) { + if (i == B43_QOSPARAM_STATUS) { + tmp = b43_shm_read16(dev, B43_SHM_SHARED, + shm_offset + (i * 2)); + /* Mark the parameters as updated. */ + tmp |= 0x100; + b43_shm_write16(dev, B43_SHM_SHARED, + shm_offset + (i * 2), + tmp); + } else { + b43_shm_write16(dev, B43_SHM_SHARED, + shm_offset + (i * 2), + params[i]); + } + } +} + +/* Update the QOS parameters in hardware. */ +static void b43_qos_update(struct b43_wldev *dev) +{ + struct b43_wl *wl = dev->wl; + struct b43_qos_params *params; + unsigned long flags; + unsigned int i; + + /* Mapping of mac80211 queues to b43 SHM offsets. */ + static const u16 qos_shm_offsets[] = { + [0] = B43_QOS_VOICE, + [1] = B43_QOS_VIDEO, + [2] = B43_QOS_BESTEFFORT, + [3] = B43_QOS_BACKGROUND, + }; + BUILD_BUG_ON(ARRAY_SIZE(qos_shm_offsets) != ARRAY_SIZE(wl->qos_params)); + + b43_mac_suspend(dev); + spin_lock_irqsave(&wl->irq_lock, flags); + + for (i = 0; i < ARRAY_SIZE(wl->qos_params); i++) { + params = &(wl->qos_params[i]); + if (params->need_hw_update) { + b43_qos_params_upload(dev, &(params->p), + qos_shm_offsets[i]); + params->need_hw_update = 0; + } + } + + spin_unlock_irqrestore(&wl->irq_lock, flags); + b43_mac_enable(dev); +} + +static void b43_qos_clear(struct b43_wl *wl) +{ + struct b43_qos_params *params; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(wl->qos_params); i++) { + params = &(wl->qos_params[i]); + + memset(&(params->p), 0, sizeof(params->p)); + params->p.aifs = -1; + params->need_hw_update = 1; + } +} + +/* Initialize the core's QOS capabilities */ +static void b43_qos_init(struct b43_wldev *dev) +{ + struct b43_wl *wl = dev->wl; + unsigned int i; + + /* Upload the current QOS parameters. */ + for (i = 0; i < ARRAY_SIZE(wl->qos_params); i++) + wl->qos_params[i].need_hw_update = 1; + b43_qos_update(dev); + + /* Enable QOS support. */ + b43_hf_write(dev, b43_hf_read(dev) | B43_HF_EDCF); + b43_write16(dev, B43_MMIO_IFSCTL, + b43_read16(dev, B43_MMIO_IFSCTL) + | B43_MMIO_IFSCTL_USE_EDCF); +} + +static void b43_qos_update_work(struct work_struct *work) +{ + struct b43_wl *wl = container_of(work, struct b43_wl, qos_update_work); + struct b43_wldev *dev; + + mutex_lock(&wl->mutex); + dev = wl->current_dev; + if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED))) + b43_qos_update(dev); + mutex_unlock(&wl->mutex); +} + static int b43_op_conf_tx(struct ieee80211_hw *hw, - int queue, + int _queue, const struct ieee80211_tx_queue_params *params) { + struct b43_wl *wl = hw_to_b43_wl(hw); + unsigned long flags; + unsigned int queue = (unsigned int)_queue; + struct b43_qos_params *p; + + if (queue >= ARRAY_SIZE(wl->qos_params)) { + /* Queue not available or don't support setting + * params on this queue. Return success to not + * confuse mac80211. */ + return 0; + } + + spin_lock_irqsave(&wl->irq_lock, flags); + p = &(wl->qos_params[queue]); + memcpy(&(p->p), params, sizeof(p->p)); + p->need_hw_update = 1; + spin_unlock_irqrestore(&wl->irq_lock, flags); + + queue_work(hw->workqueue, &wl->qos_update_work); + return 0; } @@ -3732,6 +3905,7 @@ static int b43_op_start(struct ieee80211_hw *hw) memset(wl->mac_addr, 0, ETH_ALEN); wl->filter_flags = 0; wl->radiotap_enabled = 0; + b43_qos_clear(wl); /* First register RFkill. * LEDs that are registered later depend on it. */ @@ -3773,6 +3947,7 @@ static void b43_op_stop(struct ieee80211_hw *hw) struct b43_wldev *dev = wl->current_dev; b43_rfkill_exit(dev); + cancel_work_sync(&(wl->qos_update_work)); mutex_lock(&wl->mutex); if (b43_status(dev) >= B43_STAT_STARTED) @@ -4133,7 +4308,7 @@ static int b43_wireless_init(struct ssb_device *dev) hw->max_signal = 100; hw->max_rssi = -110; hw->max_noise = -110; - hw->queues = 1; /* FIXME: hardware has more queues */ + hw->queues = b43_modparam_qos ? 4 : 1; SET_IEEE80211_DEV(hw, dev->dev); if (is_valid_ether_addr(sprom->et1mac)) SET_IEEE80211_PERM_ADDR(hw, sprom->et1mac); @@ -4149,6 +4324,7 @@ static int b43_wireless_init(struct ssb_device *dev) spin_lock_init(&wl->shm_lock); mutex_init(&wl->mutex); INIT_LIST_HEAD(&wl->devlist); + INIT_WORK(&wl->qos_update_work, b43_qos_update_work); ssb_set_devtypedata(dev, wl); b43info(wl, "Broadcom %04X WLAN found\n", dev->bus->chip_id); diff --git a/drivers/net/wireless/b43/main.h b/drivers/net/wireless/b43/main.h index 24a79f5d6ff5..1197975f9207 100644 --- a/drivers/net/wireless/b43/main.h +++ b/drivers/net/wireless/b43/main.h @@ -38,6 +38,10 @@ /* Magic helper macro to pad structures. Ignore those above. It's magic. */ #define PAD_BYTES(nr_bytes) P4D_BYTES( __LINE__ , (nr_bytes)) + +extern int b43_modparam_qos; + + /* Lightweight function to convert a frequency (in Mhz) to a channel number. */ static inline u8 b43_freq_to_channel_5ghz(int freq) { diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index 187c11bee0f1..ec10a8e182f9 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c @@ -705,30 +705,3 @@ void b43_tx_resume(struct b43_wldev *dev) { b43_dma_tx_resume(dev); } - -#if 0 -static void upload_qos_parms(struct b43_wldev *dev, - const u16 * parms, u16 offset) -{ - int i; - - for (i = 0; i < B43_NR_QOSPARMS; i++) { - b43_shm_write16(dev, B43_SHM_SHARED, - offset + (i * 2), parms[i]); - } -} -#endif - -/* Initialize the QoS parameters */ -void b43_qos_init(struct b43_wldev *dev) -{ - /* FIXME: This function must probably be called from the mac80211 - * config callback. */ - return; - - b43_hf_write(dev, b43_hf_read(dev) | B43_HF_EDCF); - //FIXME kill magic - b43_write16(dev, 0x688, b43_read16(dev, 0x688) | 0x4); - - /*TODO: We might need some stack support here to get the values. */ -} diff --git a/drivers/net/wireless/b43/xmit.h b/drivers/net/wireless/b43/xmit.h index 41765039552b..bf58a8a85258 100644 --- a/drivers/net/wireless/b43/xmit.h +++ b/drivers/net/wireless/b43/xmit.h @@ -302,18 +302,6 @@ void b43_handle_hwtxstatus(struct b43_wldev *dev, void b43_tx_suspend(struct b43_wldev *dev); void b43_tx_resume(struct b43_wldev *dev); -#define B43_NR_QOSPARMS 22 -enum { - B43_QOSPARM_TXOP = 0, - B43_QOSPARM_CWMIN, - B43_QOSPARM_CWMAX, - B43_QOSPARM_CWCUR, - B43_QOSPARM_AIFS, - B43_QOSPARM_BSLOTS, - B43_QOSPARM_REGGAP, - B43_QOSPARM_STATUS, -}; -void b43_qos_init(struct b43_wldev *dev); /* Helper functions for converting the key-table index from "firmware-format" * to "raw-format" and back. The firmware API changed for this at some revision. -- cgit v1.2.1 From b27faf8ebf256429df8851477e02609448c0781f Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Thu, 6 Mar 2008 16:32:46 +0100 Subject: b43: Rename the DMA ring pointers Rename the DMA ring pointers to have more descriptive and standard names. Also remove the 6th unused TX ring. We can add it back later, if we need it. The unused TX-status rx-ring is also removed, as that's only used by legacy devices not supported by this driver anyway. This is no functional change, except less memory allocation for the removed rings. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/b43.h | 16 ++- drivers/net/wireless/b43/dma.c | 224 +++++++++++++--------------------------- drivers/net/wireless/b43/main.c | 5 +- 3 files changed, 82 insertions(+), 163 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index 55031463c396..d40be1568517 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -589,15 +589,13 @@ struct b43_phy { /* Data structures for DMA transmission, per 80211 core. */ struct b43_dma { - struct b43_dmaring *tx_ring0; - struct b43_dmaring *tx_ring1; - struct b43_dmaring *tx_ring2; - struct b43_dmaring *tx_ring3; - struct b43_dmaring *tx_ring4; - struct b43_dmaring *tx_ring5; - - struct b43_dmaring *rx_ring0; - struct b43_dmaring *rx_ring3; /* only available on core.rev < 5 */ + struct b43_dmaring *tx_ring_AC_BK; /* Background */ + struct b43_dmaring *tx_ring_AC_BE; /* Best Effort */ + struct b43_dmaring *tx_ring_AC_VI; /* Video */ + struct b43_dmaring *tx_ring_AC_VO; /* Voice */ + struct b43_dmaring *tx_ring_mcast; /* Multicast */ + + struct b43_dmaring *rx_ring; }; /* Context information for a noise calculation (Link Quality). */ diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index c8ead465497a..3b1f0e76b9a4 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c @@ -879,15 +879,15 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, } /* Main cleanup function. */ -static void b43_destroy_dmaring(struct b43_dmaring *ring) +static void b43_destroy_dmaring(struct b43_dmaring *ring, + const char *ringname) { if (!ring) return; - b43dbg(ring->dev->wl, "DMA-%u 0x%04X (%s) max used slots: %d/%d\n", - (unsigned int)(ring->type), - ring->mmio_base, - (ring->tx) ? "TX" : "RX", ring->max_used_slots, ring->nr_slots); + b43dbg(ring->dev->wl, "DMA-%u %s max used slots: %d/%d\n", + (unsigned int)(ring->type), ringname, + ring->max_used_slots, ring->nr_slots); /* Device IRQs are disabled prior entering this function, * so no need to take care of concurrency with rx handler stuff. */ @@ -900,33 +900,26 @@ static void b43_destroy_dmaring(struct b43_dmaring *ring) kfree(ring); } +#define destroy_ring(dma, ring) do { \ + b43_destroy_dmaring((dma)->ring, __stringify(ring)); \ + (dma)->ring = NULL; \ + } while (0) + void b43_dma_free(struct b43_wldev *dev) { struct b43_dma *dma = &dev->dma; - b43_destroy_dmaring(dma->rx_ring3); - dma->rx_ring3 = NULL; - b43_destroy_dmaring(dma->rx_ring0); - dma->rx_ring0 = NULL; - - b43_destroy_dmaring(dma->tx_ring5); - dma->tx_ring5 = NULL; - b43_destroy_dmaring(dma->tx_ring4); - dma->tx_ring4 = NULL; - b43_destroy_dmaring(dma->tx_ring3); - dma->tx_ring3 = NULL; - b43_destroy_dmaring(dma->tx_ring2); - dma->tx_ring2 = NULL; - b43_destroy_dmaring(dma->tx_ring1); - dma->tx_ring1 = NULL; - b43_destroy_dmaring(dma->tx_ring0); - dma->tx_ring0 = NULL; + destroy_ring(dma, rx_ring); + destroy_ring(dma, tx_ring_AC_BK); + destroy_ring(dma, tx_ring_AC_BE); + destroy_ring(dma, tx_ring_AC_VI); + destroy_ring(dma, tx_ring_AC_VO); + destroy_ring(dma, tx_ring_mcast); } int b43_dma_init(struct b43_wldev *dev) { struct b43_dma *dma = &dev->dma; - struct b43_dmaring *ring; int err; u64 dmamask; enum b43_dmatype type; @@ -956,83 +949,57 @@ int b43_dma_init(struct b43_wldev *dev) err = -ENOMEM; /* setup TX DMA channels. */ - ring = b43_setup_dmaring(dev, 0, 1, type); - if (!ring) + dma->tx_ring_AC_BK = b43_setup_dmaring(dev, 0, 1, type); + if (!dma->tx_ring_AC_BK) goto out; - dma->tx_ring0 = ring; - ring = b43_setup_dmaring(dev, 1, 1, type); - if (!ring) - goto err_destroy_tx0; - dma->tx_ring1 = ring; + dma->tx_ring_AC_BE = b43_setup_dmaring(dev, 1, 1, type); + if (!dma->tx_ring_AC_BE) + goto err_destroy_bk; - ring = b43_setup_dmaring(dev, 2, 1, type); - if (!ring) - goto err_destroy_tx1; - dma->tx_ring2 = ring; + dma->tx_ring_AC_VI = b43_setup_dmaring(dev, 2, 1, type); + if (!dma->tx_ring_AC_VI) + goto err_destroy_be; - ring = b43_setup_dmaring(dev, 3, 1, type); - if (!ring) - goto err_destroy_tx2; - dma->tx_ring3 = ring; + dma->tx_ring_AC_VO = b43_setup_dmaring(dev, 3, 1, type); + if (!dma->tx_ring_AC_VO) + goto err_destroy_vi; - ring = b43_setup_dmaring(dev, 4, 1, type); - if (!ring) - goto err_destroy_tx3; - dma->tx_ring4 = ring; + dma->tx_ring_mcast = b43_setup_dmaring(dev, 4, 1, type); + if (!dma->tx_ring_mcast) + goto err_destroy_vo; - ring = b43_setup_dmaring(dev, 5, 1, type); - if (!ring) - goto err_destroy_tx4; - dma->tx_ring5 = ring; + /* setup RX DMA channel. */ + dma->rx_ring = b43_setup_dmaring(dev, 0, 0, type); + if (!dma->rx_ring) + goto err_destroy_mcast; - /* setup RX DMA channels. */ - ring = b43_setup_dmaring(dev, 0, 0, type); - if (!ring) - goto err_destroy_tx5; - dma->rx_ring0 = ring; - - if (dev->dev->id.revision < 5) { - ring = b43_setup_dmaring(dev, 3, 0, type); - if (!ring) - goto err_destroy_rx0; - dma->rx_ring3 = ring; - } + /* No support for the TX status DMA ring. */ + B43_WARN_ON(dev->dev->id.revision < 5); b43dbg(dev->wl, "%u-bit DMA initialized\n", (unsigned int)type); err = 0; - out: +out: return err; - err_destroy_rx0: - b43_destroy_dmaring(dma->rx_ring0); - dma->rx_ring0 = NULL; - err_destroy_tx5: - b43_destroy_dmaring(dma->tx_ring5); - dma->tx_ring5 = NULL; - err_destroy_tx4: - b43_destroy_dmaring(dma->tx_ring4); - dma->tx_ring4 = NULL; - err_destroy_tx3: - b43_destroy_dmaring(dma->tx_ring3); - dma->tx_ring3 = NULL; - err_destroy_tx2: - b43_destroy_dmaring(dma->tx_ring2); - dma->tx_ring2 = NULL; - err_destroy_tx1: - b43_destroy_dmaring(dma->tx_ring1); - dma->tx_ring1 = NULL; - err_destroy_tx0: - b43_destroy_dmaring(dma->tx_ring0); - dma->tx_ring0 = NULL; - goto out; +err_destroy_mcast: + destroy_ring(dma, tx_ring_mcast); +err_destroy_vo: + destroy_ring(dma, tx_ring_AC_VO); +err_destroy_vi: + destroy_ring(dma, tx_ring_AC_VI); +err_destroy_be: + destroy_ring(dma, tx_ring_AC_BE); +err_destroy_bk: + destroy_ring(dma, tx_ring_AC_BK); + return err; } /* Generate a cookie for the TX header. */ static u16 generate_cookie(struct b43_dmaring *ring, int slot) { - u16 cookie = 0x1000; + u16 cookie; /* Use the upper 4 bits of the cookie as * DMA controller ID and store the slot number @@ -1042,30 +1009,9 @@ static u16 generate_cookie(struct b43_dmaring *ring, int slot) * It can also not be 0xFFFF because that is special * for multicast frames. */ - switch (ring->index) { - case 0: - cookie = 0x1000; - break; - case 1: - cookie = 0x2000; - break; - case 2: - cookie = 0x3000; - break; - case 3: - cookie = 0x4000; - break; - case 4: - cookie = 0x5000; - break; - case 5: - cookie = 0x6000; - break; - default: - B43_WARN_ON(1); - } + cookie = (((u16)ring->index + 1) << 12); B43_WARN_ON(slot & ~0x0FFF); - cookie |= (u16) slot; + cookie |= (u16)slot; return cookie; } @@ -1079,22 +1025,19 @@ struct b43_dmaring *parse_cookie(struct b43_wldev *dev, u16 cookie, int *slot) switch (cookie & 0xF000) { case 0x1000: - ring = dma->tx_ring0; + ring = dma->tx_ring_AC_BK; break; case 0x2000: - ring = dma->tx_ring1; + ring = dma->tx_ring_AC_BE; break; case 0x3000: - ring = dma->tx_ring2; + ring = dma->tx_ring_AC_VI; break; case 0x4000: - ring = dma->tx_ring3; + ring = dma->tx_ring_AC_VO; break; case 0x5000: - ring = dma->tx_ring4; - break; - case 0x6000: - ring = dma->tx_ring5; + ring = dma->tx_ring_mcast; break; default: B43_WARN_ON(1); @@ -1239,20 +1182,20 @@ static struct b43_dmaring * select_ring_by_priority(struct b43_wldev *dev, B43_WARN_ON(1); /* fallthrough */ case 0: - ring = dev->dma.tx_ring3; /* AC_VO */ + ring = dev->dma.tx_ring_AC_VO; break; case 1: - ring = dev->dma.tx_ring2; /* AC_VI */ + ring = dev->dma.tx_ring_AC_VI; break; case 2: - ring = dev->dma.tx_ring1; /* AC_BE */ + ring = dev->dma.tx_ring_AC_BE; break; case 3: - ring = dev->dma.tx_ring0; /* AC_BK */ + ring = dev->dma.tx_ring_AC_BK; break; } } else - ring = dev->dma.tx_ring1; + ring = dev->dma.tx_ring_AC_BE; return ring; } @@ -1273,7 +1216,7 @@ int b43_dma_tx(struct b43_wldev *dev, hdr = (struct ieee80211_hdr *)skb->data; if (ctl->flags & IEEE80211_TXCTL_SEND_AFTER_DTIM) { /* The multicast ring will be sent after the DTIM */ - ring = dev->dma.tx_ring4; + ring = dev->dma.tx_ring_mcast; /* Set the more-data bit. Ucode will clear it on * the last frame for us. */ hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA); @@ -1441,25 +1384,6 @@ static void dma_rx(struct b43_dmaring *ring, int *slot) sync_descbuffer_for_cpu(ring, meta->dmaaddr, ring->rx_buffersize); skb = meta->skb; - if (ring->index == 3) { - /* We received an xmit status. */ - struct b43_hwtxstatus *hw = (struct b43_hwtxstatus *)skb->data; - int i = 0; - - while (hw->cookie == 0) { - if (i > 100) - break; - i++; - udelay(2); - barrier(); - } - b43_handle_hwtxstatus(ring->dev, hw); - /* recycle the descriptor buffer. */ - sync_descbuffer_for_device(ring, meta->dmaaddr, - ring->rx_buffersize); - - return; - } rxhdr = (struct b43_rxhdr_fw4 *)skb->data; len = le16_to_cpu(rxhdr->frame_len); if (len == 0) { @@ -1516,7 +1440,7 @@ static void dma_rx(struct b43_dmaring *ring, int *slot) skb_pull(skb, ring->frameoffset); b43_rx(ring->dev, skb, rxhdr); - drop: +drop: return; } @@ -1562,21 +1486,19 @@ static void b43_dma_tx_resume_ring(struct b43_dmaring *ring) void b43_dma_tx_suspend(struct b43_wldev *dev) { b43_power_saving_ctl_bits(dev, B43_PS_AWAKE); - b43_dma_tx_suspend_ring(dev->dma.tx_ring0); - b43_dma_tx_suspend_ring(dev->dma.tx_ring1); - b43_dma_tx_suspend_ring(dev->dma.tx_ring2); - b43_dma_tx_suspend_ring(dev->dma.tx_ring3); - b43_dma_tx_suspend_ring(dev->dma.tx_ring4); - b43_dma_tx_suspend_ring(dev->dma.tx_ring5); + b43_dma_tx_suspend_ring(dev->dma.tx_ring_AC_BK); + b43_dma_tx_suspend_ring(dev->dma.tx_ring_AC_BE); + b43_dma_tx_suspend_ring(dev->dma.tx_ring_AC_VI); + b43_dma_tx_suspend_ring(dev->dma.tx_ring_AC_VO); + b43_dma_tx_suspend_ring(dev->dma.tx_ring_mcast); } void b43_dma_tx_resume(struct b43_wldev *dev) { - b43_dma_tx_resume_ring(dev->dma.tx_ring5); - b43_dma_tx_resume_ring(dev->dma.tx_ring4); - b43_dma_tx_resume_ring(dev->dma.tx_ring3); - b43_dma_tx_resume_ring(dev->dma.tx_ring2); - b43_dma_tx_resume_ring(dev->dma.tx_ring1); - b43_dma_tx_resume_ring(dev->dma.tx_ring0); + b43_dma_tx_resume_ring(dev->dma.tx_ring_mcast); + b43_dma_tx_resume_ring(dev->dma.tx_ring_AC_VO); + b43_dma_tx_resume_ring(dev->dma.tx_ring_AC_VI); + b43_dma_tx_resume_ring(dev->dma.tx_ring_AC_BE); + b43_dma_tx_resume_ring(dev->dma.tx_ring_AC_BK); b43_power_saving_ctl_bits(dev, 0); } diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index dbacb58d9527..694e29570e5d 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -1594,11 +1594,10 @@ static void b43_interrupt_tasklet(struct b43_wldev *dev) /* Check the DMA reason registers for received data. */ if (dma_reason[0] & B43_DMAIRQ_RX_DONE) - b43_dma_rx(dev->dma.rx_ring0); - if (dma_reason[3] & B43_DMAIRQ_RX_DONE) - b43_dma_rx(dev->dma.rx_ring3); + b43_dma_rx(dev->dma.rx_ring); B43_WARN_ON(dma_reason[1] & B43_DMAIRQ_RX_DONE); B43_WARN_ON(dma_reason[2] & B43_DMAIRQ_RX_DONE); + B43_WARN_ON(dma_reason[3] & B43_DMAIRQ_RX_DONE); B43_WARN_ON(dma_reason[4] & B43_DMAIRQ_RX_DONE); B43_WARN_ON(dma_reason[5] & B43_DMAIRQ_RX_DONE); -- cgit v1.2.1 From 57df40d278df552ad5fb4926fa05d06065c8150c Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Fri, 7 Mar 2008 15:50:02 +0100 Subject: b43: Add TX statistics debugging counters This adds a few debugging counters, that are useful for debugging the "card does not transmit" or "connection is unstable" kind of problems. It's also useful for tuning an RC algorithm. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/dma.c | 88 +++++++++++++++++++++++++++++++++++------- drivers/net/wireless/b43/dma.h | 8 +++- 2 files changed, 80 insertions(+), 16 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index 3b1f0e76b9a4..8e9497c526af 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c @@ -38,6 +38,7 @@ #include #include #include +#include /* 32bit DMA ops. */ @@ -878,6 +879,17 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, goto out; } +#define divide(a, b) ({ \ + typeof(a) __a = a; \ + do_div(__a, b); \ + __a; \ + }) + +#define modulo(a, b) ({ \ + typeof(a) __a = a; \ + do_div(__a, b); \ + }) + /* Main cleanup function. */ static void b43_destroy_dmaring(struct b43_dmaring *ring, const char *ringname) @@ -885,9 +897,34 @@ static void b43_destroy_dmaring(struct b43_dmaring *ring, if (!ring) return; - b43dbg(ring->dev->wl, "DMA-%u %s max used slots: %d/%d\n", - (unsigned int)(ring->type), ringname, - ring->max_used_slots, ring->nr_slots); +#ifdef CONFIG_B43_DEBUG + { + /* Print some statistics. */ + u64 failed_packets = ring->nr_failed_tx_packets; + u64 succeed_packets = ring->nr_succeed_tx_packets; + u64 nr_packets = failed_packets + succeed_packets; + u64 permille_failed = 0, average_tries = 0; + + if (nr_packets) + permille_failed = divide(failed_packets * 1000, nr_packets); + if (nr_packets) + average_tries = divide(ring->nr_total_packet_tries * 100, nr_packets); + + b43dbg(ring->dev->wl, "DMA-%u %s: " + "Used slots %d/%d, Failed frames %llu/%llu = %llu.%01llu%%, " + "Average tries %llu.%02llu\n", + (unsigned int)(ring->type), ringname, + ring->max_used_slots, + ring->nr_slots, + (unsigned long long)failed_packets, + (unsigned long long)succeed_packets, + (unsigned long long)divide(permille_failed, 10), + (unsigned long long)modulo(permille_failed, 10), + (unsigned long long)divide(average_tries, 100), + (unsigned long long)modulo(average_tries, 100)); + } +#endif /* DEBUG */ + /* Device IRQs are disabled prior entering this function, * so no need to take care of concurrency with rx handler stuff. */ @@ -1270,6 +1307,38 @@ out_unlock: return err; } +static void b43_fill_txstatus_report(struct b43_dmaring *ring, + struct ieee80211_tx_status *report, + const struct b43_txstatus *status) +{ + bool frame_failed = 0; + + if (status->acked) { + /* The frame was ACKed. */ + report->flags |= IEEE80211_TX_STATUS_ACK; + } else { + /* The frame was not ACKed... */ + if (!(report->control.flags & IEEE80211_TXCTL_NO_ACK)) { + /* ...but we expected an ACK. */ + frame_failed = 1; + report->excessive_retries = 1; + } + } + if (status->frame_count == 0) { + /* The frame was not transmitted at all. */ + report->retry_count = 0; + } else { + report->retry_count = status->frame_count - 1; +#ifdef CONFIG_B43_DEBUG + if (frame_failed) + ring->nr_failed_tx_packets++; + else + ring->nr_succeed_tx_packets++; + ring->nr_total_packet_tries += status->frame_count; +#endif /* DEBUG */ + } +} + void b43_dma_handle_txstatus(struct b43_wldev *dev, const struct b43_txstatus *status) { @@ -1304,18 +1373,7 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev, * status of the transmission. * Some fields of txstat are already filled in dma_tx(). */ - if (status->acked) { - meta->txstat.flags |= IEEE80211_TX_STATUS_ACK; - } else { - if (!(meta->txstat.control.flags - & IEEE80211_TXCTL_NO_ACK)) - meta->txstat.excessive_retries = 1; - } - if (status->frame_count == 0) { - /* The frame was not transmitted at all. */ - meta->txstat.retry_count = 0; - } else - meta->txstat.retry_count = status->frame_count - 1; + b43_fill_txstatus_report(ring, &(meta->txstat), status); ieee80211_tx_status_irqsafe(dev->wl->hw, meta->skb, &(meta->txstat)); /* skb is freed by ieee80211_tx_status_irqsafe() */ diff --git a/drivers/net/wireless/b43/dma.h b/drivers/net/wireless/b43/dma.h index 9336286d97a7..ea27085dec0e 100644 --- a/drivers/net/wireless/b43/dma.h +++ b/drivers/net/wireless/b43/dma.h @@ -256,7 +256,13 @@ struct b43_dmaring { int max_used_slots; /* Last time we injected a ring overflow. */ unsigned long last_injected_overflow; -#endif /* CONFIG_B43_DEBUG */ + /* Statistics: Number of successfully transmitted packets */ + u64 nr_succeed_tx_packets; + /* Statistics: Number of failed TX packets */ + u64 nr_failed_tx_packets; + /* Statistics: Total number of TX plus all retries. */ + u64 nr_total_packet_tries; +#endif /* CONFIG_B43_DEBUG */ }; static inline u32 b43_dma_read(struct b43_dmaring *ring, u16 offset) -- cgit v1.2.1 From 87d96114a73dfa323c12c77a2ea9f96f0020c690 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Fri, 7 Mar 2008 19:52:24 +0100 Subject: b43: Fix failed frames status report typo This fixes a typo in the status report. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index 8e9497c526af..663aed4e9e05 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c @@ -917,7 +917,7 @@ static void b43_destroy_dmaring(struct b43_dmaring *ring, ring->max_used_slots, ring->nr_slots, (unsigned long long)failed_packets, - (unsigned long long)succeed_packets, + (unsigned long long)nr_packets, (unsigned long long)divide(permille_failed, 10), (unsigned long long)modulo(permille_failed, 10), (unsigned long long)divide(average_tries, 100), -- cgit v1.2.1 From 134eb5d327270c5d3816f8d812e68aa27a335ca8 Mon Sep 17 00:00:00 2001 From: Guy Cohen Date: Tue, 4 Mar 2008 18:09:25 -0800 Subject: iwlwifi: 802.11n spec removes AUTO offset for FAT channel This patch adapts to 802.11 patch and remove AUTO offset for FAT channel Signed-off-by: Guy Cohen Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965.c | 8 +++----- drivers/net/wireless/iwlwifi/iwl-4965.h | 9 ++++----- drivers/net/wireless/iwlwifi/iwl4965-base.c | 10 ++++++++-- 3 files changed, 15 insertions(+), 12 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 8b9c419e094e..bb8f00272af3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -4416,7 +4416,7 @@ static u8 iwl4965_is_channel_extension(struct iwl4965_priv *priv, if (!is_channel_valid(ch_info)) return 0; - if (extension_chan_offset == IWL_EXT_CHANNEL_OFFSET_AUTO) + if (extension_chan_offset == IWL_EXT_CHANNEL_OFFSET_NONE) return 0; if ((ch_info->fat_extension_channel == extension_chan_offset) || @@ -4433,7 +4433,7 @@ static u8 iwl4965_is_fat_tx_allowed(struct iwl4965_priv *priv, if ((!iwl_ht_conf->is_ht) || (iwl_ht_conf->supported_chan_width != IWL_CHANNEL_WIDTH_40MHZ) || - (iwl_ht_conf->extension_chan_offset == IWL_EXT_CHANNEL_OFFSET_AUTO)) + (iwl_ht_conf->extension_chan_offset == IWL_EXT_CHANNEL_OFFSET_NONE)) return 0; if (sta_ht_inf) { @@ -4478,9 +4478,7 @@ void iwl4965_set_rxon_ht(struct iwl4965_priv *priv, struct iwl_ht_info *ht_info) case IWL_EXT_CHANNEL_OFFSET_BELOW: rxon->flags |= RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK; break; - case IWL_EXT_CHANNEL_OFFSET_AUTO: - rxon->flags &= ~RXON_FLG_CHANNEL_MODE_MIXED_MSK; - break; + case IWL_EXT_CHANNEL_OFFSET_NONE: default: rxon->flags &= ~RXON_FLG_CHANNEL_MODE_MIXED_MSK; break; diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index 4b3def31a9c1..de79816c0068 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -798,11 +798,10 @@ struct iwl4965_kw { #define IWL_OPERATION_MODE_MIXED 2 #define IWL_OPERATION_MODE_20MHZ 3 -#define IWL_EXT_CHANNEL_OFFSET_AUTO 0 -#define IWL_EXT_CHANNEL_OFFSET_ABOVE 1 -#define IWL_EXT_CHANNEL_OFFSET_ 2 -#define IWL_EXT_CHANNEL_OFFSET_BELOW 3 -#define IWL_EXT_CHANNEL_OFFSET_MAX 4 +#define IWL_EXT_CHANNEL_OFFSET_NONE 0 +#define IWL_EXT_CHANNEL_OFFSET_ABOVE 1 +#define IWL_EXT_CHANNEL_OFFSET_RESERVE1 2 +#define IWL_EXT_CHANNEL_OFFSET_BELOW 3 #define NRG_NUM_PREV_STAT_L 20 #define NUM_RX_CHAINS (3) diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 2ed69376c96e..b0f6044fd6eb 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -7957,15 +7957,21 @@ static void iwl4965_ht_info_fill(struct ieee80211_conf *conf, iwl_conf->is_green_field = !!(ht_conf->cap & IEEE80211_HT_CAP_GRN_FLD); iwl_conf->max_amsdu_size = !!(ht_conf->cap & IEEE80211_HT_CAP_MAX_AMSDU); + iwl_conf->supported_chan_width = !!(ht_conf->cap & IEEE80211_HT_CAP_SUP_WIDTH); + iwl_conf->extension_chan_offset = + ht_bss_conf->bss_cap & IEEE80211_HT_IE_CHA_SEC_OFFSET; + /* If no above or below channel supplied disable FAT channel */ + if (iwl_conf->extension_chan_offset != IWL_EXT_CHANNEL_OFFSET_ABOVE && + iwl_conf->extension_chan_offset != IWL_EXT_CHANNEL_OFFSET_BELOW) + iwl_conf->supported_chan_width = 0; + iwl_conf->tx_mimo_ps_mode = (u8)((ht_conf->cap & IEEE80211_HT_CAP_MIMO_PS) >> 2); memcpy(iwl_conf->supp_mcs_set, ht_conf->supp_mcs_set, 16); iwl_conf->control_channel = ht_bss_conf->primary_channel; - iwl_conf->extension_chan_offset = - ht_bss_conf->bss_cap & IEEE80211_HT_IE_CHA_SEC_OFFSET; iwl_conf->tx_chan_width = !!(ht_bss_conf->bss_cap & IEEE80211_HT_IE_CHA_WIDTH); iwl_conf->ht_protection = -- cgit v1.2.1 From 4c424e4cc7bc9d3c4c22b408904c36b44afddc3e Mon Sep 17 00:00:00 2001 From: Ron Rindjunsky Date: Tue, 4 Mar 2008 18:09:27 -0800 Subject: iwlwifi: use mac80211_tx_control_flags This patch makes use of the new mac80211_tx_control_flags and tx_rate to pass Tx data, regular and 11n, from the HW tx response into the rate scaling. Signed-off-by: Ron Rindjunsky Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965-rs.c | 50 ++++++++++++++--------------- drivers/net/wireless/iwlwifi/iwl-4965.c | 34 ++++++++++++++++++-- drivers/net/wireless/iwlwifi/iwl-4965.h | 3 ++ drivers/net/wireless/iwlwifi/iwl4965-base.c | 9 +++--- 4 files changed, 64 insertions(+), 32 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c index cf7b569a2229..306fbdc6e62f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c @@ -823,6 +823,7 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct iwl4965_priv *priv = (struct iwl4965_priv *)priv_rate; struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); + struct ieee80211_hw *hw = local_to_hw(local); struct iwl4965_rate_scale_data *window = NULL; struct iwl4965_rate_scale_data *search_win = NULL; struct iwl4965_rate tx_mcs; @@ -884,17 +885,6 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, search_win = (struct iwl4965_rate_scale_data *) &(search_tbl->win[0]); - tx_mcs.rate_n_flags = tx_resp->control.tx_rate->hw_value; - - rs_get_tbl_info_from_mcs(&tx_mcs, priv->band, - &tbl_type, &rs_index); - if ((rs_index < 0) || (rs_index >= IWL_RATE_COUNT)) { - IWL_DEBUG_RATE("bad rate index at: %d rate 0x%X\n", - rs_index, tx_mcs.rate_n_flags); - rcu_read_unlock(); - return; - } - /* * Ignore this Tx frame response if its initial rate doesn't match * that of latest Link Quality command. There may be stragglers @@ -903,12 +893,28 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, * to check "search" mode, or a prior "search" mode after we've moved * to a new "search" mode (which might become the new "active" mode). */ - if (retries && - (tx_mcs.rate_n_flags != - le32_to_cpu(table->rs_table[0].rate_n_flags))) { - IWL_DEBUG_RATE("initial rate does not match 0x%x 0x%x\n", - tx_mcs.rate_n_flags, - le32_to_cpu(table->rs_table[0].rate_n_flags)); + tx_mcs.rate_n_flags = le32_to_cpu(table->rs_table[0].rate_n_flags); + rs_get_tbl_info_from_mcs(&tx_mcs, priv->band, &tbl_type, &rs_index); + if (priv->band == IEEE80211_BAND_5GHZ) + rs_index -= IWL_FIRST_OFDM_RATE; + + if ((tx_resp->control.tx_rate == NULL) || + (tbl_type.is_SGI ^ + !!(tx_resp->control.flags & IEEE80211_TXCTL_SHORT_GI)) || + (tbl_type.is_fat ^ + !!(tx_resp->control.flags & IEEE80211_TXCTL_40_MHZ_WIDTH)) || + (tbl_type.is_dup ^ + !!(tx_resp->control.flags & IEEE80211_TXCTL_DUP_DATA)) || + (tbl_type.antenna_type ^ + tx_resp->control.antenna_sel_tx) || + (!!(tx_mcs.rate_n_flags & RATE_MCS_HT_MSK) ^ + !!(tx_resp->control.flags & IEEE80211_TXCTL_OFDM_HT)) || + (!!(tx_mcs.rate_n_flags & RATE_MCS_GF_MSK) ^ + !!(tx_resp->control.flags & IEEE80211_TXCTL_GREEN_FIELD)) || + (hw->wiphy->bands[priv->band]->bitrates[rs_index].bitrate != + tx_resp->control.tx_rate->bitrate)) { + IWL_DEBUG_RATE("initial rate does not match 0x%x\n", + tx_mcs.rate_n_flags); rcu_read_unlock(); return; } @@ -959,14 +965,8 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, * if Tx was successful first try, use original rate, * else look up the rate that was, finally, successful. */ - if (!tx_resp->retry_count) - tx_mcs.rate_n_flags = tx_resp->control.tx_rate->hw_value; - else - tx_mcs.rate_n_flags = - le32_to_cpu(table->rs_table[index].rate_n_flags); - - rs_get_tbl_info_from_mcs(&tx_mcs, priv->band, - &tbl_type, &rs_index); + tx_mcs.rate_n_flags = le32_to_cpu(table->rs_table[index].rate_n_flags); + rs_get_tbl_info_from_mcs(&tx_mcs, priv->band, &tbl_type, &rs_index); /* Update frame history window with "success" if Tx got ACKed ... */ if (tx_resp->flags & IEEE80211_TX_STATUS_ACK) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index bb8f00272af3..05ad5a9a1a55 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -150,6 +150,35 @@ int iwl4965_hwrate_to_plcp_idx(u32 rate_n_flags) return -1; } +/** + * translate ucode response to mac80211 tx status control values + */ +void iwl4965_hwrate_to_tx_control(struct iwl4965_priv *priv, u32 rate_n_flags, + struct ieee80211_tx_control *control) +{ + int rate_index; + + control->antenna_sel_tx = + ((rate_n_flags & RATE_MCS_ANT_AB_MSK) >> RATE_MCS_ANT_A_POS); + if (rate_n_flags & RATE_MCS_HT_MSK) + control->flags |= IEEE80211_TXCTL_OFDM_HT; + if (rate_n_flags & RATE_MCS_GF_MSK) + control->flags |= IEEE80211_TXCTL_GREEN_FIELD; + if (rate_n_flags & RATE_MCS_FAT_MSK) + control->flags |= IEEE80211_TXCTL_40_MHZ_WIDTH; + if (rate_n_flags & RATE_MCS_DUP_MSK) + control->flags |= IEEE80211_TXCTL_DUP_DATA; + if (rate_n_flags & RATE_MCS_SGI_MSK) + control->flags |= IEEE80211_TXCTL_SHORT_GI; + /* since iwl4965_hwrate_to_plcp_idx is band indifferent, we always use + * IEEE80211_BAND_2GHZ band as it contains all the rates */ + rate_index = iwl4965_hwrate_to_plcp_idx(rate_n_flags); + if (rate_index == -1) + control->tx_rate = NULL; + else + control->tx_rate = + &priv->bands[IEEE80211_BAND_2GHZ].bitrates[rate_index]; +} /* * Determine how many receiver/antenna chains to use. @@ -4084,9 +4113,8 @@ static int iwl4965_tx_status_reply_compressed_ba(struct iwl4965_priv *priv, tx_status->flags |= IEEE80211_TX_STATUS_AMPDU; tx_status->ampdu_ack_map = successes; tx_status->ampdu_ack_len = agg->frame_count; - /* FIXME Wrong rate - tx_status->control.tx_rate = agg->rate_n_flags; - */ + iwl4965_hwrate_to_tx_control(priv, agg->rate_n_flags, + &tx_status->control); IWL_DEBUG_TX_REPLY("Bitmap %llx\n", bitmap); diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index de79816c0068..5c605129dfbd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -757,6 +757,9 @@ extern int iwl4965_set_fat_chan_info(struct iwl4965_priv *priv, const struct iwl4965_eeprom_channel *eeprom_ch, u8 fat_extension_channel); extern void iwl4965_rf_kill_ct_config(struct iwl4965_priv *priv); +extern void iwl4965_hwrate_to_tx_control(struct iwl4965_priv *priv, + u32 rate_n_flags, + struct ieee80211_tx_control *control); #ifdef CONFIG_IWL4965_HT void iwl4965_init_ht_hw_capab(struct ieee80211_ht_info *ht_info, diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index b0f6044fd6eb..f273395d4a3e 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -3410,9 +3410,9 @@ static int iwl4965_tx_status_reply_tx(struct iwl4965_priv *priv, tx_status->control.flags &= ~IEEE80211_TXCTL_AMPDU; tx_status->flags = iwl4965_is_tx_success(status)? IEEE80211_TX_STATUS_ACK : 0; - /* FIXME Wrong Rate - tx_status->control.tx_rate = - iwl4965_hw_get_rate_n_flags(tx_resp->rate_n_flags); */ + iwl4965_hwrate_to_tx_control(priv, + le32_to_cpu(tx_resp->rate_n_flags), + &tx_status->control); /* FIXME: code repetition end */ IWL_DEBUG_TX_REPLY("1 Frame 0x%x failure :%d\n", @@ -3569,9 +3569,10 @@ static void iwl4965_rx_reply_tx(struct iwl4965_priv *priv, tx_status->queue_number = status; tx_status->queue_length = tx_resp->bt_kill_count; tx_status->queue_length |= tx_resp->failure_rts; - tx_status->flags = iwl4965_is_tx_success(status) ? IEEE80211_TX_STATUS_ACK : 0; + iwl4965_hwrate_to_tx_control(priv, le32_to_cpu(tx_resp->rate_n_flags), + &tx_status->control); IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) rate_n_flags 0x%x " "retries %d\n", txq_id, iwl4965_get_tx_fail_reason(status), -- cgit v1.2.1 From 6f83eaa170c05324fb33668eace007ea24c277d2 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Tue, 4 Mar 2008 18:09:28 -0800 Subject: iwlwifi: extract iwl-csr.h This patch extract CSR Register definition into separate header files as most of the definition are commons to both 3945 and 4965. Definitions specific for 3945 and 4965 are properly prefixed Signed-off-by: Tomas Winkler Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-hw.h | 135 ----------------- drivers/net/wireless/iwlwifi/iwl-3945.c | 18 +-- drivers/net/wireless/iwlwifi/iwl-3945.h | 3 +- drivers/net/wireless/iwlwifi/iwl-4965-hw.h | 131 ----------------- drivers/net/wireless/iwlwifi/iwl-4965.c | 6 +- drivers/net/wireless/iwlwifi/iwl-4965.h | 1 + drivers/net/wireless/iwlwifi/iwl-csr.h | 217 ++++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl3945-base.c | 4 +- drivers/net/wireless/iwlwifi/iwl4965-base.c | 4 +- 9 files changed, 236 insertions(+), 283 deletions(-) create mode 100644 drivers/net/wireless/iwlwifi/iwl-csr.h (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h index 6693767adc9f..269224ba23b6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h @@ -321,141 +321,6 @@ struct iwl3945_eeprom { #define PCI_REG_WUM8 0x0E8 #define PCI_CFG_PMC_PME_FROM_D3COLD_SUPPORT (0x80000000) -/*=== CSR (control and status registers) ===*/ -#define CSR_BASE (0x000) - -#define CSR_HW_IF_CONFIG_REG (CSR_BASE+0x000) /* hardware interface config */ -#define CSR_INT_COALESCING (CSR_BASE+0x004) /* accum ints, 32-usec units */ -#define CSR_INT (CSR_BASE+0x008) /* host interrupt status/ack */ -#define CSR_INT_MASK (CSR_BASE+0x00c) /* host interrupt enable */ -#define CSR_FH_INT_STATUS (CSR_BASE+0x010) /* busmaster int status/ack*/ -#define CSR_GPIO_IN (CSR_BASE+0x018) /* read external chip pins */ -#define CSR_RESET (CSR_BASE+0x020) /* busmaster enable, NMI, etc*/ -#define CSR_GP_CNTRL (CSR_BASE+0x024) - -/* - * Hardware revision info - * Bit fields: - * 31-8: Reserved - * 7-4: Type of device: 0x0 = 4965, 0xd = 3945 - * 3-2: Revision step: 0 = A, 1 = B, 2 = C, 3 = D - * 1-0: "Dash" value, as in A-1, etc. - */ -#define CSR_HW_REV (CSR_BASE+0x028) - -/* EEPROM reads */ -#define CSR_EEPROM_REG (CSR_BASE+0x02c) -#define CSR_EEPROM_GP (CSR_BASE+0x030) -#define CSR_GP_UCODE (CSR_BASE+0x044) -#define CSR_UCODE_DRV_GP1 (CSR_BASE+0x054) -#define CSR_UCODE_DRV_GP1_SET (CSR_BASE+0x058) -#define CSR_UCODE_DRV_GP1_CLR (CSR_BASE+0x05c) -#define CSR_UCODE_DRV_GP2 (CSR_BASE+0x060) -#define CSR_GIO_CHICKEN_BITS (CSR_BASE+0x100) - -/* Analog phase-lock-loop configuration (3945 only) - * Set bit 24. */ -#define CSR_ANA_PLL_CFG (CSR_BASE+0x20c) - -/* Bits for CSR_HW_IF_CONFIG_REG */ -#define CSR_HW_IF_CONFIG_REG_BIT_ALMAGOR_MB (0x00000100) -#define CSR_HW_IF_CONFIG_REG_BIT_ALMAGOR_MM (0x00000200) -#define CSR_HW_IF_CONFIG_REG_BIT_SKU_MRC (0x00000400) -#define CSR_HW_IF_CONFIG_REG_BIT_BOARD_TYPE (0x00000800) -#define CSR_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A (0x00000000) -#define CSR_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B (0x00001000) -#define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM (0x00200000) - -/* interrupt flags in INTA, set by uCode or hardware (e.g. dma), - * acknowledged (reset) by host writing "1" to flagged bits. */ -#define CSR_INT_BIT_FH_RX (1 << 31) /* Rx DMA, cmd responses, FH_INT[17:16] */ -#define CSR_INT_BIT_HW_ERR (1 << 29) /* DMA hardware error FH_INT[31] */ -#define CSR_INT_BIT_DNLD (1 << 28) /* uCode Download */ -#define CSR_INT_BIT_FH_TX (1 << 27) /* Tx DMA FH_INT[1:0] */ -#define CSR_INT_BIT_SCD (1 << 26) /* TXQ pointer advanced */ -#define CSR_INT_BIT_SW_ERR (1 << 25) /* uCode error */ -#define CSR_INT_BIT_RF_KILL (1 << 7) /* HW RFKILL switch GP_CNTRL[27] toggled */ -#define CSR_INT_BIT_CT_KILL (1 << 6) /* Critical temp (chip too hot) rfkill */ -#define CSR_INT_BIT_SW_RX (1 << 3) /* Rx, command responses, 3945 */ -#define CSR_INT_BIT_WAKEUP (1 << 1) /* NIC controller waking up (pwr mgmt) */ -#define CSR_INT_BIT_ALIVE (1 << 0) /* uCode interrupts once it initializes */ - -#define CSR_INI_SET_MASK (CSR_INT_BIT_FH_RX | \ - CSR_INT_BIT_HW_ERR | \ - CSR_INT_BIT_FH_TX | \ - CSR_INT_BIT_SW_ERR | \ - CSR_INT_BIT_RF_KILL | \ - CSR_INT_BIT_SW_RX | \ - CSR_INT_BIT_WAKEUP | \ - CSR_INT_BIT_ALIVE) - -/* interrupt flags in FH (flow handler) (PCI busmaster DMA) */ -#define CSR_FH_INT_BIT_ERR (1 << 31) /* Error */ -#define CSR_FH_INT_BIT_HI_PRIOR (1 << 30) /* High priority Rx, bypass coalescing */ -#define CSR_FH_INT_BIT_RX_CHNL2 (1 << 18) /* Rx channel 2 (3945 only) */ -#define CSR_FH_INT_BIT_RX_CHNL1 (1 << 17) /* Rx channel 1 */ -#define CSR_FH_INT_BIT_RX_CHNL0 (1 << 16) /* Rx channel 0 */ -#define CSR_FH_INT_BIT_TX_CHNL6 (1 << 6) /* Tx channel 6 (3945 only) */ -#define CSR_FH_INT_BIT_TX_CHNL1 (1 << 1) /* Tx channel 1 */ -#define CSR_FH_INT_BIT_TX_CHNL0 (1 << 0) /* Tx channel 0 */ - -#define CSR_FH_INT_RX_MASK (CSR_FH_INT_BIT_HI_PRIOR | \ - CSR_FH_INT_BIT_RX_CHNL2 | \ - CSR_FH_INT_BIT_RX_CHNL1 | \ - CSR_FH_INT_BIT_RX_CHNL0) - -#define CSR_FH_INT_TX_MASK (CSR_FH_INT_BIT_TX_CHNL6 | \ - CSR_FH_INT_BIT_TX_CHNL1 | \ - CSR_FH_INT_BIT_TX_CHNL0) - - -/* RESET */ -#define CSR_RESET_REG_FLAG_NEVO_RESET (0x00000001) -#define CSR_RESET_REG_FLAG_FORCE_NMI (0x00000002) -#define CSR_RESET_REG_FLAG_SW_RESET (0x00000080) -#define CSR_RESET_REG_FLAG_MASTER_DISABLED (0x00000100) -#define CSR_RESET_REG_FLAG_STOP_MASTER (0x00000200) - -/* GP (general purpose) CONTROL */ -#define CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY (0x00000001) -#define CSR_GP_CNTRL_REG_FLAG_INIT_DONE (0x00000004) -#define CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ (0x00000008) -#define CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP (0x00000010) - -#define CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN (0x00000001) - -#define CSR_GP_CNTRL_REG_MSK_POWER_SAVE_TYPE (0x07000000) -#define CSR_GP_CNTRL_REG_FLAG_MAC_POWER_SAVE (0x04000000) -#define CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW (0x08000000) - - -/* EEPROM REG */ -#define CSR_EEPROM_REG_READ_VALID_MSK (0x00000001) -#define CSR_EEPROM_REG_BIT_CMD (0x00000002) - -/* EEPROM GP */ -#define CSR_EEPROM_GP_VALID_MSK (0x00000006) -#define CSR_EEPROM_GP_BAD_SIGNATURE (0x00000000) -#define CSR_EEPROM_GP_IF_OWNER_MSK (0x00000180) - -/* UCODE DRV GP */ -#define CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP (0x00000001) -#define CSR_UCODE_SW_BIT_RFKILL (0x00000002) -#define CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED (0x00000004) -#define CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT (0x00000008) - -/* GPIO */ -#define CSR_GPIO_IN_BIT_AUX_POWER (0x00000200) -#define CSR_GPIO_IN_VAL_VAUX_PWR_SRC (0x00000000) -#define CSR_GPIO_IN_VAL_VMAIN_PWR_SRC CSR_GPIO_IN_BIT_AUX_POWER - -/* GI Chicken Bits */ -#define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX (0x00800000) -#define CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER (0x20000000) - -/* CSR_ANA_PLL_CFG */ -#define CSR_ANA_PLL_CFG_SH (0x00880300) - /*=== HBUS (Host-side Bus) ===*/ #define HBUS_BASE (0x400) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 63e832cdba75..0fca35650ad3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -1154,19 +1154,19 @@ int iwl3945_hw_nic_init(struct iwl3945_priv *priv) if (rev_id & PCI_CFG_REV_ID_BIT_RTP) IWL_DEBUG_INFO("RTP type \n"); else if (rev_id & PCI_CFG_REV_ID_BIT_BASIC_SKU) { - IWL_DEBUG_INFO("ALM-MB type\n"); + IWL_DEBUG_INFO("3945 RADIO-MB type\n"); iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG, - CSR_HW_IF_CONFIG_REG_BIT_ALMAGOR_MB); + CSR39_HW_IF_CONFIG_REG_BIT_3945_MB); } else { - IWL_DEBUG_INFO("ALM-MM type\n"); + IWL_DEBUG_INFO("3945 RADIO-MM type\n"); iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG, - CSR_HW_IF_CONFIG_REG_BIT_ALMAGOR_MM); + CSR39_HW_IF_CONFIG_REG_BIT_3945_MM); } if (EEPROM_SKU_CAP_OP_MODE_MRC == priv->eeprom.sku_cap) { IWL_DEBUG_INFO("SKU OP mode is mrc\n"); iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG, - CSR_HW_IF_CONFIG_REG_BIT_SKU_MRC); + CSR39_HW_IF_CONFIG_REG_BIT_SKU_MRC); } else IWL_DEBUG_INFO("SKU OP mode is basic\n"); @@ -1174,24 +1174,24 @@ int iwl3945_hw_nic_init(struct iwl3945_priv *priv) IWL_DEBUG_INFO("3945ABG revision is 0x%X\n", priv->eeprom.board_revision); iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG, - CSR_HW_IF_CONFIG_REG_BIT_BOARD_TYPE); + CSR39_HW_IF_CONFIG_REG_BIT_BOARD_TYPE); } else { IWL_DEBUG_INFO("3945ABG revision is 0x%X\n", priv->eeprom.board_revision); iwl3945_clear_bit(priv, CSR_HW_IF_CONFIG_REG, - CSR_HW_IF_CONFIG_REG_BIT_BOARD_TYPE); + CSR39_HW_IF_CONFIG_REG_BIT_BOARD_TYPE); } if (priv->eeprom.almgor_m_version <= 1) { iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG, - CSR_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A); + CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A); IWL_DEBUG_INFO("Card M type A version is 0x%X\n", priv->eeprom.almgor_m_version); } else { IWL_DEBUG_INFO("Card M type B version is 0x%X\n", priv->eeprom.almgor_m_version); iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG, - CSR_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B); + CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B); } spin_unlock_irqrestore(&priv->lock, flags); diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index d281e42964d5..1701e0b9b877 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -40,8 +40,9 @@ extern struct pci_device_id iwl3945_hw_card_ids[]; #define DRV_NAME "iwl3945" -#include "iwl-3945-hw.h" +#include "iwl-csr.h" #include "iwl-prph.h" +#include "iwl-3945-hw.h" #include "iwl-3945-debug.h" /* Default noise level to report when noise measurement is not available. diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h index cc726215ab93..7e8cc9928b55 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h @@ -410,137 +410,6 @@ struct iwl4965_eeprom { #define PCI_REG_WUM8 0x0E8 #define PCI_CFG_PMC_PME_FROM_D3COLD_SUPPORT (0x80000000) -/*=== CSR (control and status registers) ===*/ -#define CSR_BASE (0x000) - -#define CSR_HW_IF_CONFIG_REG (CSR_BASE+0x000) /* hardware interface config */ -#define CSR_INT_COALESCING (CSR_BASE+0x004) /* accum ints, 32-usec units */ -#define CSR_INT (CSR_BASE+0x008) /* host interrupt status/ack */ -#define CSR_INT_MASK (CSR_BASE+0x00c) /* host interrupt enable */ -#define CSR_FH_INT_STATUS (CSR_BASE+0x010) /* busmaster int status/ack*/ -#define CSR_GPIO_IN (CSR_BASE+0x018) /* read external chip pins */ -#define CSR_RESET (CSR_BASE+0x020) /* busmaster enable, NMI, etc*/ -#define CSR_GP_CNTRL (CSR_BASE+0x024) - -/* - * Hardware revision info - * Bit fields: - * 31-8: Reserved - * 7-4: Type of device: 0x0 = 4965, 0xd = 3945 - * 3-2: Revision step: 0 = A, 1 = B, 2 = C, 3 = D - * 1-0: "Dash" value, as in A-1, etc. - * - * NOTE: Revision step affects calculation of CCK txpower for 4965. - */ -#define CSR_HW_REV (CSR_BASE+0x028) - -/* EEPROM reads */ -#define CSR_EEPROM_REG (CSR_BASE+0x02c) -#define CSR_EEPROM_GP (CSR_BASE+0x030) -#define CSR_GP_UCODE (CSR_BASE+0x044) -#define CSR_UCODE_DRV_GP1 (CSR_BASE+0x054) -#define CSR_UCODE_DRV_GP1_SET (CSR_BASE+0x058) -#define CSR_UCODE_DRV_GP1_CLR (CSR_BASE+0x05c) -#define CSR_UCODE_DRV_GP2 (CSR_BASE+0x060) -#define CSR_GIO_CHICKEN_BITS (CSR_BASE+0x100) - -/* - * Indicates hardware rev, to determine CCK backoff for txpower calculation. - * Bit fields: - * 3-2: 0 = A, 1 = B, 2 = C, 3 = D step - */ -#define CSR_HW_REV_WA_REG (CSR_BASE+0x22C) - -/* Hardware interface configuration bits */ -#define CSR_HW_IF_CONFIG_REG_BIT_KEDRON_R (0x00000010) -#define CSR_HW_IF_CONFIG_REG_MSK_BOARD_VER (0x00000C00) -#define CSR_HW_IF_CONFIG_REG_BIT_MAC_SI (0x00000100) -#define CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI (0x00000200) -#define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM (0x00200000) - -/* interrupt flags in INTA, set by uCode or hardware (e.g. dma), - * acknowledged (reset) by host writing "1" to flagged bits. */ -#define CSR_INT_BIT_FH_RX (1 << 31) /* Rx DMA, cmd responses, FH_INT[17:16] */ -#define CSR_INT_BIT_HW_ERR (1 << 29) /* DMA hardware error FH_INT[31] */ -#define CSR_INT_BIT_DNLD (1 << 28) /* uCode Download */ -#define CSR_INT_BIT_FH_TX (1 << 27) /* Tx DMA FH_INT[1:0] */ -#define CSR_INT_BIT_SCD (1 << 26) /* TXQ pointer advanced */ -#define CSR_INT_BIT_SW_ERR (1 << 25) /* uCode error */ -#define CSR_INT_BIT_RF_KILL (1 << 7) /* HW RFKILL switch GP_CNTRL[27] toggled */ -#define CSR_INT_BIT_CT_KILL (1 << 6) /* Critical temp (chip too hot) rfkill */ -#define CSR_INT_BIT_SW_RX (1 << 3) /* Rx, command responses, 3945 */ -#define CSR_INT_BIT_WAKEUP (1 << 1) /* NIC controller waking up (pwr mgmt) */ -#define CSR_INT_BIT_ALIVE (1 << 0) /* uCode interrupts once it initializes */ - -#define CSR_INI_SET_MASK (CSR_INT_BIT_FH_RX | \ - CSR_INT_BIT_HW_ERR | \ - CSR_INT_BIT_FH_TX | \ - CSR_INT_BIT_SW_ERR | \ - CSR_INT_BIT_RF_KILL | \ - CSR_INT_BIT_SW_RX | \ - CSR_INT_BIT_WAKEUP | \ - CSR_INT_BIT_ALIVE) - -/* interrupt flags in FH (flow handler) (PCI busmaster DMA) */ -#define CSR_FH_INT_BIT_ERR (1 << 31) /* Error */ -#define CSR_FH_INT_BIT_HI_PRIOR (1 << 30) /* High priority Rx, bypass coalescing */ -#define CSR_FH_INT_BIT_RX_CHNL1 (1 << 17) /* Rx channel 1 */ -#define CSR_FH_INT_BIT_RX_CHNL0 (1 << 16) /* Rx channel 0 */ -#define CSR_FH_INT_BIT_TX_CHNL1 (1 << 1) /* Tx channel 1 */ -#define CSR_FH_INT_BIT_TX_CHNL0 (1 << 0) /* Tx channel 0 */ - -#define CSR_FH_INT_RX_MASK (CSR_FH_INT_BIT_HI_PRIOR | \ - CSR_FH_INT_BIT_RX_CHNL1 | \ - CSR_FH_INT_BIT_RX_CHNL0) - -#define CSR_FH_INT_TX_MASK (CSR_FH_INT_BIT_TX_CHNL1 | \ - CSR_FH_INT_BIT_TX_CHNL0) - - -/* RESET */ -#define CSR_RESET_REG_FLAG_NEVO_RESET (0x00000001) -#define CSR_RESET_REG_FLAG_FORCE_NMI (0x00000002) -#define CSR_RESET_REG_FLAG_SW_RESET (0x00000080) -#define CSR_RESET_REG_FLAG_MASTER_DISABLED (0x00000100) -#define CSR_RESET_REG_FLAG_STOP_MASTER (0x00000200) - -/* GP (general purpose) CONTROL */ -#define CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY (0x00000001) -#define CSR_GP_CNTRL_REG_FLAG_INIT_DONE (0x00000004) -#define CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ (0x00000008) -#define CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP (0x00000010) - -#define CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN (0x00000001) - -#define CSR_GP_CNTRL_REG_MSK_POWER_SAVE_TYPE (0x07000000) -#define CSR_GP_CNTRL_REG_FLAG_MAC_POWER_SAVE (0x04000000) -#define CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW (0x08000000) - - -/* EEPROM REG */ -#define CSR_EEPROM_REG_READ_VALID_MSK (0x00000001) -#define CSR_EEPROM_REG_BIT_CMD (0x00000002) - -/* EEPROM GP */ -#define CSR_EEPROM_GP_VALID_MSK (0x00000006) -#define CSR_EEPROM_GP_BAD_SIGNATURE (0x00000000) -#define CSR_EEPROM_GP_IF_OWNER_MSK (0x00000180) - -/* UCODE DRV GP */ -#define CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP (0x00000001) -#define CSR_UCODE_SW_BIT_RFKILL (0x00000002) -#define CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED (0x00000004) -#define CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT (0x00000008) - -/* GPIO */ -#define CSR_GPIO_IN_BIT_AUX_POWER (0x00000200) -#define CSR_GPIO_IN_VAL_VAUX_PWR_SRC (0x00000000) -#define CSR_GPIO_IN_VAL_VMAIN_PWR_SRC CSR_GPIO_IN_BIT_AUX_POWER - -/* GI Chicken Bits */ -#define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX (0x00800000) -#define CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER (0x20000000) - /*=== HBUS (Host-side Bus) ===*/ #define HBUS_BASE (0x400) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 05ad5a9a1a55..2da153331a7d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -604,9 +604,9 @@ int iwl4965_hw_nic_init(struct iwl4965_priv *priv) /* set CSR_HW_CONFIG_REG for uCode use */ iwl4965_set_bit(priv, CSR_HW_IF_CONFIG_REG, - CSR_HW_IF_CONFIG_REG_BIT_KEDRON_R | - CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | - CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); + CSR49_HW_IF_CONFIG_REG_BIT_4965_R | + CSR49_HW_IF_CONFIG_REG_BIT_RADIO_SI | + CSR49_HW_IF_CONFIG_REG_BIT_MAC_SI); rc = iwl4965_grab_nic_access(priv); if (rc < 0) { diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index 5c605129dfbd..a782c454e0dd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -41,6 +41,7 @@ extern struct pci_device_id iwl4965_hw_card_ids[]; #define DRV_NAME "iwl4965" #include "iwl-4965-hw.h" +#include "iwl-csr.h" #include "iwl-prph.h" #include "iwl-4965-debug.h" diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h new file mode 100644 index 000000000000..276ba2816041 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h @@ -0,0 +1,217 @@ +/****************************************************************************** + * + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, + * USA + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * Contact Information: + * James P. Ketrenos + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + * BSD LICENSE + * + * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ +/*=== CSR (control and status registers) ===*/ +#define CSR_BASE (0x000) + +#define CSR_HW_IF_CONFIG_REG (CSR_BASE+0x000) /* hardware interface config */ +#define CSR_INT_COALESCING (CSR_BASE+0x004) /* accum ints, 32-usec units */ +#define CSR_INT (CSR_BASE+0x008) /* host interrupt status/ack */ +#define CSR_INT_MASK (CSR_BASE+0x00c) /* host interrupt enable */ +#define CSR_FH_INT_STATUS (CSR_BASE+0x010) /* busmaster int status/ack*/ +#define CSR_GPIO_IN (CSR_BASE+0x018) /* read external chip pins */ +#define CSR_RESET (CSR_BASE+0x020) /* busmaster enable, NMI, etc*/ +#define CSR_GP_CNTRL (CSR_BASE+0x024) + +/* + * Hardware revision info + * Bit fields: + * 31-8: Reserved + * 7-4: Type of device: 0x0 = 4965, 0xd = 3945 + * 3-2: Revision step: 0 = A, 1 = B, 2 = C, 3 = D + * 1-0: "Dash" value, as in A-1, etc. + * + * NOTE: Revision step affects calculation of CCK txpower for 4965. + */ +#define CSR_HW_REV (CSR_BASE+0x028) + +/* EEPROM reads */ +#define CSR_EEPROM_REG (CSR_BASE+0x02c) +#define CSR_EEPROM_GP (CSR_BASE+0x030) +#define CSR_GP_UCODE (CSR_BASE+0x044) +#define CSR_UCODE_DRV_GP1 (CSR_BASE+0x054) +#define CSR_UCODE_DRV_GP1_SET (CSR_BASE+0x058) +#define CSR_UCODE_DRV_GP1_CLR (CSR_BASE+0x05c) +#define CSR_UCODE_DRV_GP2 (CSR_BASE+0x060) +#define CSR_GIO_CHICKEN_BITS (CSR_BASE+0x100) + +/* Analog phase-lock-loop configuration (3945 only) + * Set bit 24. */ +#define CSR_ANA_PLL_CFG (CSR_BASE+0x20c) +/* + * Indicates hardware rev, to determine CCK backoff for txpower calculation. + * Bit fields: + * 3-2: 0 = A, 1 = B, 2 = C, 3 = D step + */ +#define CSR_HW_REV_WA_REG (CSR_BASE+0x22C) + +/* Bits for CSR_HW_IF_CONFIG_REG */ +#define CSR49_HW_IF_CONFIG_REG_BIT_4965_R (0x00000010) +#define CSR49_HW_IF_CONFIG_REG_MSK_BOARD_VER (0x00000C00) +#define CSR49_HW_IF_CONFIG_REG_BIT_MAC_SI (0x00000100) +#define CSR49_HW_IF_CONFIG_REG_BIT_RADIO_SI (0x00000200) + +#define CSR39_HW_IF_CONFIG_REG_BIT_3945_MB (0x00000100) +#define CSR39_HW_IF_CONFIG_REG_BIT_3945_MM (0x00000200) +#define CSR39_HW_IF_CONFIG_REG_BIT_SKU_MRC (0x00000400) +#define CSR39_HW_IF_CONFIG_REG_BIT_BOARD_TYPE (0x00000800) +#define CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A (0x00000000) +#define CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B (0x00001000) + +#define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM (0x00200000) + +/* interrupt flags in INTA, set by uCode or hardware (e.g. dma), + * acknowledged (reset) by host writing "1" to flagged bits. */ +#define CSR_INT_BIT_FH_RX (1 << 31) /* Rx DMA, cmd responses, FH_INT[17:16] */ +#define CSR_INT_BIT_HW_ERR (1 << 29) /* DMA hardware error FH_INT[31] */ +#define CSR_INT_BIT_DNLD (1 << 28) /* uCode Download */ +#define CSR_INT_BIT_FH_TX (1 << 27) /* Tx DMA FH_INT[1:0] */ +#define CSR_INT_BIT_SCD (1 << 26) /* TXQ pointer advanced */ +#define CSR_INT_BIT_SW_ERR (1 << 25) /* uCode error */ +#define CSR_INT_BIT_RF_KILL (1 << 7) /* HW RFKILL switch GP_CNTRL[27] toggled */ +#define CSR_INT_BIT_CT_KILL (1 << 6) /* Critical temp (chip too hot) rfkill */ +#define CSR_INT_BIT_SW_RX (1 << 3) /* Rx, command responses, 3945 */ +#define CSR_INT_BIT_WAKEUP (1 << 1) /* NIC controller waking up (pwr mgmt) */ +#define CSR_INT_BIT_ALIVE (1 << 0) /* uCode interrupts once it initializes */ + +#define CSR_INI_SET_MASK (CSR_INT_BIT_FH_RX | \ + CSR_INT_BIT_HW_ERR | \ + CSR_INT_BIT_FH_TX | \ + CSR_INT_BIT_SW_ERR | \ + CSR_INT_BIT_RF_KILL | \ + CSR_INT_BIT_SW_RX | \ + CSR_INT_BIT_WAKEUP | \ + CSR_INT_BIT_ALIVE) + +/* interrupt flags in FH (flow handler) (PCI busmaster DMA) */ +#define CSR_FH_INT_BIT_ERR (1 << 31) /* Error */ +#define CSR_FH_INT_BIT_HI_PRIOR (1 << 30) /* High priority Rx, bypass coalescing */ +#define CSR39_FH_INT_BIT_RX_CHNL2 (1 << 18) /* Rx channel 2 (3945 only) */ +#define CSR_FH_INT_BIT_RX_CHNL1 (1 << 17) /* Rx channel 1 */ +#define CSR_FH_INT_BIT_RX_CHNL0 (1 << 16) /* Rx channel 0 */ +#define CSR39_FH_INT_BIT_TX_CHNL6 (1 << 6) /* Tx channel 6 (3945 only) */ +#define CSR_FH_INT_BIT_TX_CHNL1 (1 << 1) /* Tx channel 1 */ +#define CSR_FH_INT_BIT_TX_CHNL0 (1 << 0) /* Tx channel 0 */ + +#define CSR39_FH_INT_RX_MASK (CSR_FH_INT_BIT_HI_PRIOR | \ + CSR39_FH_INT_BIT_RX_CHNL2 | \ + CSR_FH_INT_BIT_RX_CHNL1 | \ + CSR_FH_INT_BIT_RX_CHNL0) + + +#define CSR39_FH_INT_TX_MASK (CSR39_FH_INT_BIT_TX_CHNL6 | \ + CSR_FH_INT_BIT_TX_CHNL1 | \ + CSR_FH_INT_BIT_TX_CHNL0) + +#define CSR49_FH_INT_RX_MASK (CSR_FH_INT_BIT_HI_PRIOR | \ + CSR_FH_INT_BIT_RX_CHNL1 | \ + CSR_FH_INT_BIT_RX_CHNL0) + +#define CSR49_FH_INT_TX_MASK (CSR_FH_INT_BIT_TX_CHNL1 | \ + CSR_FH_INT_BIT_TX_CHNL0) + + +/* RESET */ +#define CSR_RESET_REG_FLAG_NEVO_RESET (0x00000001) +#define CSR_RESET_REG_FLAG_FORCE_NMI (0x00000002) +#define CSR_RESET_REG_FLAG_SW_RESET (0x00000080) +#define CSR_RESET_REG_FLAG_MASTER_DISABLED (0x00000100) +#define CSR_RESET_REG_FLAG_STOP_MASTER (0x00000200) + +/* GP (general purpose) CONTROL */ +#define CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY (0x00000001) +#define CSR_GP_CNTRL_REG_FLAG_INIT_DONE (0x00000004) +#define CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ (0x00000008) +#define CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP (0x00000010) + +#define CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN (0x00000001) + +#define CSR_GP_CNTRL_REG_MSK_POWER_SAVE_TYPE (0x07000000) +#define CSR_GP_CNTRL_REG_FLAG_MAC_POWER_SAVE (0x04000000) +#define CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW (0x08000000) + + +/* EEPROM REG */ +#define CSR_EEPROM_REG_READ_VALID_MSK (0x00000001) +#define CSR_EEPROM_REG_BIT_CMD (0x00000002) + +/* EEPROM GP */ +#define CSR_EEPROM_GP_VALID_MSK (0x00000006) +#define CSR_EEPROM_GP_BAD_SIGNATURE (0x00000000) +#define CSR_EEPROM_GP_IF_OWNER_MSK (0x00000180) + +/* UCODE DRV GP */ +#define CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP (0x00000001) +#define CSR_UCODE_SW_BIT_RFKILL (0x00000002) +#define CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED (0x00000004) +#define CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT (0x00000008) + +/* GPIO */ +#define CSR_GPIO_IN_BIT_AUX_POWER (0x00000200) +#define CSR_GPIO_IN_VAL_VAUX_PWR_SRC (0x00000000) +#define CSR_GPIO_IN_VAL_VMAIN_PWR_SRC CSR_GPIO_IN_BIT_AUX_POWER + +/* GI Chicken Bits */ +#define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX (0x00800000) +#define CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER (0x20000000) + + diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 7a72048b0f42..cc71bdc80359 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -4570,9 +4570,9 @@ static void iwl3945_irq_tasklet(struct iwl3945_priv *priv) * atomic, make sure that inta covers all the interrupts that * we've discovered, even if FH interrupt came in just after * reading CSR_INT. */ - if (inta_fh & CSR_FH_INT_RX_MASK) + if (inta_fh & CSR39_FH_INT_RX_MASK) inta |= CSR_INT_BIT_FH_RX; - if (inta_fh & CSR_FH_INT_TX_MASK) + if (inta_fh & CSR39_FH_INT_TX_MASK) inta |= CSR_INT_BIT_FH_TX; /* Now service all interrupt bits discovered above. */ diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index f273395d4a3e..0c60f594dfe7 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -4918,9 +4918,9 @@ static void iwl4965_irq_tasklet(struct iwl4965_priv *priv) * atomic, make sure that inta covers all the interrupts that * we've discovered, even if FH interrupt came in just after * reading CSR_INT. */ - if (inta_fh & CSR_FH_INT_RX_MASK) + if (inta_fh & CSR49_FH_INT_RX_MASK) inta |= CSR_INT_BIT_FH_RX; - if (inta_fh & CSR_FH_INT_TX_MASK) + if (inta_fh & CSR49_FH_INT_TX_MASK) inta |= CSR_INT_BIT_FH_TX; /* Now service all interrupt bits discovered above. */ -- cgit v1.2.1 From 750fe6396614e267aeec0e2ff636740e2688d4d9 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Tue, 4 Mar 2008 18:09:29 -0800 Subject: iwlwifi: Move HBUS address to iwl-csr.h HBUS is accessed through CSR registers moved to iwl-csr.h Signed-off-by: Tomas Winkler Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-hw.h | 39 -------------------------- drivers/net/wireless/iwlwifi/iwl-4965-hw.h | 44 ------------------------------ drivers/net/wireless/iwlwifi/iwl-csr.h | 42 ++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 83 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h index 269224ba23b6..7dc19136f41a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h @@ -321,45 +321,6 @@ struct iwl3945_eeprom { #define PCI_REG_WUM8 0x0E8 #define PCI_CFG_PMC_PME_FROM_D3COLD_SUPPORT (0x80000000) -/*=== HBUS (Host-side Bus) ===*/ -#define HBUS_BASE (0x400) - -/* - * Registers for accessing device's internal SRAM memory (e.g. SCD SRAM - * structures, error log, event log, verifying uCode load). - * First write to address register, then read from or write to data register - * to complete the job. Once the address register is set up, accesses to - * data registers auto-increment the address by one dword. - * Bit usage for address registers (read or write): - * 0-31: memory address within device - */ -#define HBUS_TARG_MEM_RADDR (HBUS_BASE+0x00c) -#define HBUS_TARG_MEM_WADDR (HBUS_BASE+0x010) -#define HBUS_TARG_MEM_WDAT (HBUS_BASE+0x018) -#define HBUS_TARG_MEM_RDAT (HBUS_BASE+0x01c) - -/* - * Registers for accessing device's internal peripheral registers - * (e.g. SCD, BSM, etc.). First write to address register, - * then read from or write to data register to complete the job. - * Bit usage for address registers (read or write): - * 0-15: register address (offset) within device - * 24-25: (# bytes - 1) to read or write (e.g. 3 for dword) - */ -#define HBUS_TARG_PRPH_WADDR (HBUS_BASE+0x044) -#define HBUS_TARG_PRPH_RADDR (HBUS_BASE+0x048) -#define HBUS_TARG_PRPH_WDAT (HBUS_BASE+0x04c) -#define HBUS_TARG_PRPH_RDAT (HBUS_BASE+0x050) - -/* - * Per-Tx-queue write pointer (index, really!) (3945 and 4965). - * Indicates index to next TFD that driver will fill (1 past latest filled). - * Bit usage: - * 0-7: queue write index - * 11-8: queue selector - */ -#define HBUS_TARG_WRPTR (HBUS_BASE+0x060) - /* SCD (3945 Tx Frame Scheduler) */ #define SCD_BASE (CSR_BASE + 0x2E00) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h index 7e8cc9928b55..24413a479a3f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h @@ -410,50 +410,6 @@ struct iwl4965_eeprom { #define PCI_REG_WUM8 0x0E8 #define PCI_CFG_PMC_PME_FROM_D3COLD_SUPPORT (0x80000000) -/*=== HBUS (Host-side Bus) ===*/ -#define HBUS_BASE (0x400) - -/* - * Registers for accessing device's internal SRAM memory (e.g. SCD SRAM - * structures, error log, event log, verifying uCode load). - * First write to address register, then read from or write to data register - * to complete the job. Once the address register is set up, accesses to - * data registers auto-increment the address by one dword. - * Bit usage for address registers (read or write): - * 0-31: memory address within device - */ -#define HBUS_TARG_MEM_RADDR (HBUS_BASE+0x00c) -#define HBUS_TARG_MEM_WADDR (HBUS_BASE+0x010) -#define HBUS_TARG_MEM_WDAT (HBUS_BASE+0x018) -#define HBUS_TARG_MEM_RDAT (HBUS_BASE+0x01c) - -/* - * Registers for accessing device's internal peripheral registers - * (e.g. SCD, BSM, etc.). First write to address register, - * then read from or write to data register to complete the job. - * Bit usage for address registers (read or write): - * 0-15: register address (offset) within device - * 24-25: (# bytes - 1) to read or write (e.g. 3 for dword) - */ -#define HBUS_TARG_PRPH_WADDR (HBUS_BASE+0x044) -#define HBUS_TARG_PRPH_RADDR (HBUS_BASE+0x048) -#define HBUS_TARG_PRPH_WDAT (HBUS_BASE+0x04c) -#define HBUS_TARG_PRPH_RDAT (HBUS_BASE+0x050) - -/* - * Per-Tx-queue write pointer (index, really!) (3945 and 4965). - * Driver sets this to indicate index to next TFD that driver will fill - * (1 past latest filled). - * Bit usage: - * 0-7: queue write index (0-255) - * 11-8: queue selector (0-15) - */ -#define HBUS_TARG_WRPTR (HBUS_BASE+0x060) - -#define HBUS_TARG_MBX_C (HBUS_BASE+0x030) - -#define HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED (0x00000004) - #define TFD_QUEUE_SIZE_MAX (256) #define IWL_NUM_SCAN_RATES (2) diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index 276ba2816041..7016e5b41c58 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h @@ -214,4 +214,46 @@ #define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX (0x00800000) #define CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER (0x20000000) +/*=== HBUS (Host-side Bus) ===*/ +#define HBUS_BASE (0x400) +/* + * Registers for accessing device's internal SRAM memory (e.g. SCD SRAM + * structures, error log, event log, verifying uCode load). + * First write to address register, then read from or write to data register + * to complete the job. Once the address register is set up, accesses to + * data registers auto-increment the address by one dword. + * Bit usage for address registers (read or write): + * 0-31: memory address within device + */ +#define HBUS_TARG_MEM_RADDR (HBUS_BASE+0x00c) +#define HBUS_TARG_MEM_WADDR (HBUS_BASE+0x010) +#define HBUS_TARG_MEM_WDAT (HBUS_BASE+0x018) +#define HBUS_TARG_MEM_RDAT (HBUS_BASE+0x01c) + +/* + * Registers for accessing device's internal peripheral registers + * (e.g. SCD, BSM, etc.). First write to address register, + * then read from or write to data register to complete the job. + * Bit usage for address registers (read or write): + * 0-15: register address (offset) within device + * 24-25: (# bytes - 1) to read or write (e.g. 3 for dword) + */ +#define HBUS_TARG_PRPH_WADDR (HBUS_BASE+0x044) +#define HBUS_TARG_PRPH_RADDR (HBUS_BASE+0x048) +#define HBUS_TARG_PRPH_WDAT (HBUS_BASE+0x04c) +#define HBUS_TARG_PRPH_RDAT (HBUS_BASE+0x050) + +/* + * Per-Tx-queue write pointer (index, really!) (3945 and 4965). + * Indicates index to next TFD that driver will fill (1 past latest filled). + * Bit usage: + * 0-7: queue write index + * 11-8: queue selector + */ +#define HBUS_TARG_WRPTR (HBUS_BASE+0x060) +#define HBUS_TARG_MBX_C (HBUS_BASE+0x030) + +#define HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED (0x00000004) + + -- cgit v1.2.1 From 82b9a1213132aa53ddbcc459ed77a335d031cd2e Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Tue, 4 Mar 2008 18:09:30 -0800 Subject: iwlwifi: add struct iwl_cfg This patch introduces struct iwl_cfg. struct iwl_cfg defines static configuration for each device type and sku. It is passed as driver_data to the bus probe function. This patch also introduce new common header file iwl-core.h which will represent core functionality of iwlwifi driver 3945ABG uses separate iwl-3945-dev.h header file for now Signed-off-by: Tomas Winkler Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-core.h | 80 +++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-3945.c | 19 ++++++- drivers/net/wireless/iwlwifi/iwl-3945.h | 2 +- drivers/net/wireless/iwlwifi/iwl-4965.c | 10 +++- drivers/net/wireless/iwlwifi/iwl-4965.h | 2 +- drivers/net/wireless/iwlwifi/iwl-core.h | 81 ++++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl3945-base.c | 35 +++--------- drivers/net/wireless/iwlwifi/iwl4965-base.c | 11 ++-- 8 files changed, 203 insertions(+), 37 deletions(-) create mode 100644 drivers/net/wireless/iwlwifi/iwl-3945-core.h create mode 100644 drivers/net/wireless/iwlwifi/iwl-core.h (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-core.h b/drivers/net/wireless/iwlwifi/iwl-3945-core.h new file mode 100644 index 000000000000..bc12f97ba0b1 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-3945-core.h @@ -0,0 +1,80 @@ +/****************************************************************************** + * + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, + * USA + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * Contact Information: + * Tomas Winkler + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + * BSD LICENSE + * + * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef __iwl_3945_dev_h__ +#define __iwl_3945_dev_h__ + +#define IWL_PCI_DEVICE(dev, subdev, cfg) \ + .vendor = PCI_VENDOR_ID_INTEL, .device = (dev), \ + .subvendor = PCI_ANY_ID, .subdevice = (subdev), \ + .driver_data = (kernel_ulong_t)&(cfg) + +#define IWL_SKU_G 0x1 +#define IWL_SKU_A 0x2 + +struct iwl_3945_cfg { + const char *name; + const char *fw_name; + unsigned int sku; +}; + +#endif /* __iwl_dev_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 0fca35650ad3..b9097643a648 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -39,6 +39,7 @@ #include #include +#include "iwl-3945-core.h" #include "iwl-3945.h" #include "iwl-helpers.h" #include "iwl-3945-rs.h" @@ -2523,9 +2524,23 @@ void iwl3945_hw_cancel_deferred_work(struct iwl3945_priv *priv) cancel_delayed_work(&priv->thermal_periodic); } +static struct iwl_3945_cfg iwl3945_bg_cfg = { + .name = "3945BG", + .sku = IWL_SKU_G, +}; + +static struct iwl_3945_cfg iwl3945_abg_cfg = { + .name = "3945ABG", + .sku = IWL_SKU_A|IWL_SKU_G, +}; + struct pci_device_id iwl3945_hw_card_ids[] = { - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4222)}, - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4227)}, + {IWL_PCI_DEVICE(0x4222, 0x1005, iwl3945_bg_cfg)}, + {IWL_PCI_DEVICE(0x4222, 0x1034, iwl3945_bg_cfg)}, + {IWL_PCI_DEVICE(0x4222, 0x1044, iwl3945_bg_cfg)}, + {IWL_PCI_DEVICE(0x4227, 0x1014, iwl3945_bg_cfg)}, + {IWL_PCI_DEVICE(0x4222, PCI_ANY_ID, iwl3945_abg_cfg)}, + {IWL_PCI_DEVICE(0x4227, PCI_ANY_ID, iwl3945_abg_cfg)}, {0} }; diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 1701e0b9b877..fa89da2db3e1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -682,6 +682,7 @@ struct iwl3945_priv { struct ieee80211_hw *hw; struct ieee80211_channel *ieee_channels; struct ieee80211_rate *ieee_rates; + struct iwl_3945_cfg *cfg; /* device configuration */ /* temporary frame storage list */ struct list_head free_frames; @@ -820,7 +821,6 @@ struct iwl3945_priv { int is_open; u8 mac80211_registered; - int is_abg; u32 notif_missed_beacons; diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 2da153331a7d..8cf1b9ce4dab 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -38,6 +38,7 @@ #include #include +#include "iwl-core.h" #include "iwl-4965.h" #include "iwl-helpers.h" @@ -4820,9 +4821,14 @@ void iwl4965_hw_cancel_deferred_work(struct iwl4965_priv *priv) cancel_delayed_work(&priv->init_alive_start); } +static struct iwl_cfg iwl4965_agn_cfg = { + .name = "4965AGN", + .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, +}; + struct pci_device_id iwl4965_hw_card_ids[] = { - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4229)}, - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4230)}, + {IWL_PCI_DEVICE(0x4229, PCI_ANY_ID, iwl4965_agn_cfg)}, + {IWL_PCI_DEVICE(0x4230, PCI_ANY_ID, iwl4965_agn_cfg)}, {0} }; diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index a782c454e0dd..0bfd1b475897 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -967,6 +967,7 @@ struct iwl4965_priv { struct ieee80211_hw *hw; struct ieee80211_channel *ieee_channels; struct ieee80211_rate *ieee_rates; + struct iwl_cfg *cfg; /* temporary frame storage list */ struct list_head free_frames; @@ -1126,7 +1127,6 @@ struct iwl4965_priv { int is_open; u8 mac80211_registered; - int is_abg; u32 notif_missed_beacons; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h new file mode 100644 index 000000000000..e6449af590c2 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -0,0 +1,81 @@ +/****************************************************************************** + * + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, + * USA + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * Contact Information: + * Tomas Winkler + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + * BSD LICENSE + * + * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef __iwl_core_h__ +#define __iwl_core_h__ + +#define IWL_PCI_DEVICE(dev, subdev, cfg) \ + .vendor = PCI_VENDOR_ID_INTEL, .device = (dev), \ + .subvendor = PCI_ANY_ID, .subdevice = (subdev), \ + .driver_data = (kernel_ulong_t)&(cfg) + +#define IWL_SKU_G 0x1 +#define IWL_SKU_A 0x2 +#define IWL_SKU_N 0x8 + +struct iwl_cfg { + const char *name; + const char *fw_name; + unsigned int sku; +}; + +#endif /* __iwl_core_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index cc71bdc80359..0cdc7f84b5af 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -46,6 +46,7 @@ #include +#include "iwl-3945-core.h" #include "iwl-3945.h" #include "iwl-helpers.h" @@ -5267,12 +5268,13 @@ static int iwl3945_init_geos(struct iwl3945_priv *priv) geo_ch->flags); } - if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) && priv->is_abg) { + if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) && + priv->cfg->sku & IWL_SKU_A) { printk(KERN_INFO DRV_NAME ": Incorrectly detected BG card as ABG. Please send " "your PCI ID 0x%04X:0x%04X to maintainer.\n", priv->pci_dev->device, priv->pci_dev->subsystem_device); - priv->is_abg = 0; + priv->cfg->sku &= ~IWL_SKU_A; } printk(KERN_INFO DRV_NAME @@ -8067,9 +8069,9 @@ static struct ieee80211_ops iwl3945_hw_ops = { static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { int err = 0; - u32 pci_id; struct iwl3945_priv *priv; struct ieee80211_hw *hw; + struct iwl_3945_cfg *cfg = (struct iwl_3945_cfg *)(ent->driver_data); int i; DECLARE_MAC_BUF(mac); @@ -8105,6 +8107,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e priv->hw = hw; priv->pci_dev = pdev; + priv->cfg = cfg; /* Select antenna (may be helpful if only one antenna is connected) */ priv->antenna = (enum iwl3945_antenna)iwl3945_param_antenna; @@ -8194,32 +8197,8 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e priv->iw_mode = IEEE80211_IF_TYPE_STA; - pci_id = - (priv->pci_dev->device << 16) | priv->pci_dev->subsystem_device; - - switch (pci_id) { - case 0x42221005: /* 0x4222 0x8086 0x1005 is BG SKU */ - case 0x42221034: /* 0x4222 0x8086 0x1034 is BG SKU */ - case 0x42271014: /* 0x4227 0x8086 0x1014 is BG SKU */ - case 0x42221044: /* 0x4222 0x8086 0x1044 is BG SKU */ - priv->is_abg = 0; - break; - - /* - * Rest are assumed ABG SKU -- if this is not the - * case then the card will get the wrong 'Detected' - * line in the kernel log however the code that - * initializes the GEO table will detect no A-band - * channels and remove the is_abg mask. - */ - default: - priv->is_abg = 1; - break; - } - printk(KERN_INFO DRV_NAME - ": Detected Intel PRO/Wireless 3945%sBG Network Connection\n", - priv->is_abg ? "A" : ""); + ": Detected Intel Wireless WiFi Link %s\n", priv->cfg->name); /* Device-specific setup */ if (iwl3945_hw_set_hw_setting(priv)) { diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 0c60f594dfe7..af97e0bdf483 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -45,6 +45,7 @@ #include +#include "iwl-core.h" #include "iwl-4965.h" #include "iwl-helpers.h" @@ -5663,12 +5664,13 @@ static int iwl4965_init_geos(struct iwl4965_priv *priv) geo_ch->flags); } - if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) && priv->is_abg) { + if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) && + priv->cfg->sku & IWL_SKU_A) { printk(KERN_INFO DRV_NAME ": Incorrectly detected BG card as ABG. Please send " "your PCI ID 0x%04X:0x%04X to maintainer.\n", priv->pci_dev->device, priv->pci_dev->subsystem_device); - priv->is_abg = 0; + priv->cfg->sku &= ~IWL_SKU_A; } printk(KERN_INFO DRV_NAME @@ -8613,6 +8615,7 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e int err = 0; struct iwl4965_priv *priv; struct ieee80211_hw *hw; + struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); int i; DECLARE_MAC_BUF(mac); @@ -8646,6 +8649,7 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e IWL_DEBUG_INFO("*** LOAD DRIVER ***\n"); priv = hw->priv; priv->hw = hw; + priv->cfg = cfg; priv->pci_dev = pdev; priv->antenna = (enum iwl4965_antenna)iwl4965_param_antenna; @@ -8748,8 +8752,9 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e /* Choose which receivers/antennas to use */ iwl4965_set_rxon_chain(priv); + printk(KERN_INFO DRV_NAME - ": Detected Intel Wireless WiFi Link 4965AGN\n"); + ": Detected Intel Wireless WiFi Link %s\n", priv->cfg->name); /* Device-specific setup */ if (iwl4965_hw_set_hw_setting(priv)) { -- cgit v1.2.1 From 4bf775cdc08b8741f78fbf85e3d2e6bebe783d32 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Tue, 4 Mar 2008 18:09:31 -0800 Subject: iwlwifi: Take the fw file name from the iwl_cfg. This patch adds fw_name to iwl_cfg. This allows run time selection of needed fw/ucode file Signed-off-by: Tomas Winkler Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 2 ++ drivers/net/wireless/iwlwifi/iwl-3945.h | 6 ++++++ drivers/net/wireless/iwlwifi/iwl-4965.c | 1 + drivers/net/wireless/iwlwifi/iwl-4965.h | 7 +++++++ drivers/net/wireless/iwlwifi/iwl3945-base.c | 7 +------ drivers/net/wireless/iwlwifi/iwl4965-base.c | 7 +------ 6 files changed, 18 insertions(+), 12 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index b9097643a648..49b781104327 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -2526,11 +2526,13 @@ void iwl3945_hw_cancel_deferred_work(struct iwl3945_priv *priv) static struct iwl_3945_cfg iwl3945_bg_cfg = { .name = "3945BG", + .fw_name = "iwlwifi-3945" IWL3945_UCODE_API ".ucode", .sku = IWL_SKU_G, }; static struct iwl_3945_cfg iwl3945_abg_cfg = { .name = "3945ABG", + .fw_name = "iwlwifi-3945" IWL3945_UCODE_API ".ucode", .sku = IWL_SKU_A|IWL_SKU_G, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index fa89da2db3e1..a238e833251f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -45,6 +45,12 @@ extern struct pci_device_id iwl3945_hw_card_ids[]; #include "iwl-3945-hw.h" #include "iwl-3945-debug.h" +/* Change firmware file name, using "-" and incrementing number, + * *only* when uCode interface or architecture changes so that it + * is not compatible with earlier drivers. + * This number will also appear in << 8 position of 1st dword of uCode file */ +#define IWL3945_UCODE_API "-1" + /* Default noise level to report when noise measurement is not available. * This may be because we're: * 1) Not associated (4965, no beacon statistics being sent to driver) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 8cf1b9ce4dab..3e122a931f2d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -4823,6 +4823,7 @@ void iwl4965_hw_cancel_deferred_work(struct iwl4965_priv *priv) static struct iwl_cfg iwl4965_agn_cfg = { .name = "4965AGN", + .fw_name = "iwlwifi-4965" IWL4965_UCODE_API ".ucode", .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index 0bfd1b475897..057fa15d62fd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -45,6 +45,13 @@ extern struct pci_device_id iwl4965_hw_card_ids[]; #include "iwl-prph.h" #include "iwl-4965-debug.h" +/* Change firmware file name, using "-" and incrementing number, + * *only* when uCode interface or architecture changes so that it + * is not compatible with earlier drivers. + * This number will also appear in << 8 position of 1st dword of uCode file */ +#define IWL4965_UCODE_API "-1" + + /* Default noise level to report when noise measurement is not available. * This may be because we're: * 1) Not associated (4965, no beacon statistics being sent to driver) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 0cdc7f84b5af..a130f5d077f0 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -96,11 +96,6 @@ int iwl3945_param_queues_num = IWL_MAX_NUM_QUEUES; /* def: 8 Tx queues */ #define DRV_COPYRIGHT "Copyright(c) 2003-2007 Intel Corporation" #define DRV_VERSION IWLWIFI_VERSION -/* Change firmware file name, using "-" and incrementing number, - * *only* when uCode interface or architecture changes so that it - * is not compatible with earlier drivers. - * This number will also appear in << 8 position of 1st dword of uCode file */ -#define IWL3945_UCODE_API "-1" MODULE_DESCRIPTION(DRV_DESCRIPTION); MODULE_VERSION(DRV_VERSION); @@ -5621,7 +5616,7 @@ static int iwl3945_read_ucode(struct iwl3945_priv *priv) int ret = 0; const struct firmware *ucode_raw; /* firmware file name contains uCode/driver compatibility version */ - const char *name = "iwlwifi-3945" IWL3945_UCODE_API ".ucode"; + const char *name = priv->cfg->fw_name; u8 *src; size_t len; u32 ver, inst_size, data_size, init_size, init_data_size, boot_size; diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index af97e0bdf483..d362c4c82db2 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -95,11 +95,6 @@ int iwl4965_param_amsdu_size_8K; /* def: enable 8K amsdu size */ #define DRV_COPYRIGHT "Copyright(c) 2003-2007 Intel Corporation" #define DRV_VERSION IWLWIFI_VERSION -/* Change firmware file name, using "-" and incrementing number, - * *only* when uCode interface or architecture changes so that it - * is not compatible with earlier drivers. - * This number will also appear in << 8 position of 1st dword of uCode file */ -#define IWL4965_UCODE_API "-1" MODULE_DESCRIPTION(DRV_DESCRIPTION); MODULE_VERSION(DRV_VERSION); @@ -6019,7 +6014,7 @@ static int iwl4965_read_ucode(struct iwl4965_priv *priv) struct iwl4965_ucode *ucode; int ret; const struct firmware *ucode_raw; - const char *name = "iwlwifi-4965" IWL4965_UCODE_API ".ucode"; + const char *name = priv->cfg->fw_name; u8 *src; size_t len; u32 ver, inst_size, data_size, init_size, init_data_size, boot_size; -- cgit v1.2.1 From b716bb918f8f7967e361770eb1545d2b4bcffc26 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Tue, 4 Mar 2008 18:09:32 -0800 Subject: iwlwifi: Cancel scanning upon association This patch cancels an ongoing HW scan upon association. Not doing this resulted in instability in association. Signed-off-by: Emmanuel Grumbach Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl3945-base.c | 17 ++++++----------- drivers/net/wireless/iwlwifi/iwl4965-base.c | 17 ++++++----------- 2 files changed, 12 insertions(+), 22 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index a130f5d077f0..4aaced0b9f26 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -7004,6 +7004,12 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, if (conf == NULL) return -EIO; + if (priv->vif != vif) { + IWL_DEBUG_MAC80211("leave - priv->vif != vif\n"); + mutex_unlock(&priv->mutex); + return 0; + } + /* XXX: this MUST use conf->mac_addr */ if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) && @@ -7028,17 +7034,6 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw, if (unlikely(test_bit(STATUS_SCANNING, &priv->status)) && !(priv->hw->flags & IEEE80211_HW_NO_PROBE_FILTERING)) { */ - if (unlikely(test_bit(STATUS_SCANNING, &priv->status))) { - IWL_DEBUG_MAC80211("leave - scanning\n"); - mutex_unlock(&priv->mutex); - return 0; - } - - if (priv->vif != vif) { - IWL_DEBUG_MAC80211("leave - priv->vif != vif\n"); - mutex_unlock(&priv->mutex); - return 0; - } if (priv->iw_mode == IEEE80211_IF_TYPE_AP) { if (!conf->bssid) { diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index d362c4c82db2..5005c9513007 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -7424,6 +7424,12 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw, if (conf == NULL) return -EIO; + if (priv->vif != vif) { + IWL_DEBUG_MAC80211("leave - priv->vif != vif\n"); + mutex_unlock(&priv->mutex); + return 0; + } + if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) && (!conf->beacon || !conf->ssid_len)) { IWL_DEBUG_MAC80211 @@ -7446,17 +7452,6 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw, if (unlikely(test_bit(STATUS_SCANNING, &priv->status)) && !(priv->hw->flags & IEEE80211_HW_NO_PROBE_FILTERING)) { */ - if (unlikely(test_bit(STATUS_SCANNING, &priv->status))) { - IWL_DEBUG_MAC80211("leave - scanning\n"); - mutex_unlock(&priv->mutex); - return 0; - } - - if (priv->vif != vif) { - IWL_DEBUG_MAC80211("leave - priv->vif != vif\n"); - mutex_unlock(&priv->mutex); - return 0; - } if (priv->iw_mode == IEEE80211_IF_TYPE_AP) { if (!conf->bssid) { -- cgit v1.2.1 From f4d6082d53c588036a1c37891cb7d65088be13f5 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 5 Mar 2008 11:31:00 -0800 Subject: iwlwifi: fix locking unbalance in 4965 rate scale This patch fixes locking unbalance after adding rcu locking for sta Signed-off-by: Tomas Winkler Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965-rs.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c index 306fbdc6e62f..25e73864c2a4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c @@ -852,19 +852,18 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, sta = sta_info_get(local, hdr->addr1); - if (!sta || !sta->rate_ctrl_priv) { - rcu_read_unlock(); - return; - } + if (!sta || !sta->rate_ctrl_priv) + goto out; + lq_sta = (struct iwl4965_lq_sta *)sta->rate_ctrl_priv; if (!priv->lq_mngr.lq_ready) - return; + goto out; if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) && !lq_sta->ibss_sta_added) - return; + goto out; table = &lq_sta->lq; active_index = lq_sta->active_tbl; @@ -915,8 +914,7 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, tx_resp->control.tx_rate->bitrate)) { IWL_DEBUG_RATE("initial rate does not match 0x%x\n", tx_mcs.rate_n_flags); - rcu_read_unlock(); - return; + goto out; } /* Update frame history window with "failure" for each Tx retry. */ @@ -1025,6 +1023,7 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, /* See if there's a better rate or modulation mode to try. */ rs_rate_scale_perform(priv, dev, hdr, sta); +out: rcu_read_unlock(); return; } @@ -2229,8 +2228,7 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1) || !sta || !sta->rate_ctrl_priv) { sel->rate = rate_lowest(local, sband, sta); - rcu_read_unlock(); - return; + goto out; } lq_sta = (struct iwl4965_lq_sta *)sta->rate_ctrl_priv; @@ -2257,14 +2255,15 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, goto done; } - done: +done: if ((i < 0) || (i > IWL_RATE_COUNT)) { sel->rate = rate_lowest(local, sband, sta); - return; + goto out; } - rcu_read_unlock(); sel->rate = &priv->ieee_rates[i]; +out: + rcu_read_unlock(); } static void *rs_alloc_sta(void *priv, gfp_t gfp) -- cgit v1.2.1 From df48c3235c90095a2f7dbcaba444add363ffb0ef Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Thu, 6 Mar 2008 10:40:19 -0800 Subject: iwlwifi: add iwl-core module This patch adds iwl-core module to iwlwifi driver. This module will contain common code and infrastracture for iwlwifi driver Signed-off-by: Tomas Winkler Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/Kconfig | 5 +++ drivers/net/wireless/iwlwifi/Makefile | 3 ++ drivers/net/wireless/iwlwifi/iwl-core.c | 47 +++++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-core.h | 3 ++ drivers/net/wireless/iwlwifi/iwl4965-base.c | 8 +---- 5 files changed, 59 insertions(+), 7 deletions(-) create mode 100644 drivers/net/wireless/iwlwifi/iwl-core.c (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index 24c3e3ddafc6..5b7c0160e1fa 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig @@ -1,7 +1,12 @@ +config IWLCORE + tristate "Intel Wireless Wifi Core" + depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL + config IWL4965 tristate "Intel Wireless WiFi 4965AGN" depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL select FW_LOADER + select IWLCORE ---help--- Select to build the driver supporting the: diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 3bbd38358d53..6b85cca9b3f1 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile @@ -1,3 +1,6 @@ +obj-$(CONFIG_IWLCORE) += iwlcore.o +iwlcore-objs = iwl-core.o + obj-$(CONFIG_IWL3945) += iwl3945.o iwl3945-objs = iwl3945-base.o iwl-3945.o iwl-3945-rs.o diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c new file mode 100644 index 000000000000..675b34b696b4 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -0,0 +1,47 @@ +/****************************************************************************** + * + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, + * USA + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * Contact Information: + * Tomas Winkler + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + *****************************************************************************/ + +#include +#include +#include + +#include "iwl-4965-debug.h" +#include "iwl-core.h" + +MODULE_DESCRIPTION("iwl core"); +MODULE_VERSION(IWLWIFI_VERSION); +MODULE_AUTHOR(DRV_COPYRIGHT); +MODULE_LICENSE("GPL/BSD"); + +#ifdef CONFIG_IWL4965_DEBUG +u32 iwl4965_debug_level; +EXPORT_SYMBOL(iwl4965_debug_level); +#endif diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index e6449af590c2..bdd32f891683 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -63,6 +63,9 @@ #ifndef __iwl_core_h__ #define __iwl_core_h__ +#define IWLWIFI_VERSION "1.2.26k" +#define DRV_COPYRIGHT "Copyright(c) 2003-2008 Intel Corporation" + #define IWL_PCI_DEVICE(dev, subdev, cfg) \ .vendor = PCI_VENDOR_ID_INTEL, .device = (dev), \ .subvendor = PCI_ANY_ID, .subdevice = (subdev), \ diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 5005c9513007..af95626a6112 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -49,10 +49,6 @@ #include "iwl-4965.h" #include "iwl-helpers.h" -#ifdef CONFIG_IWL4965_DEBUG -u32 iwl4965_debug_level; -#endif - static int iwl4965_tx_queue_update_write_ptr(struct iwl4965_priv *priv, struct iwl4965_tx_queue *txq); @@ -91,9 +87,7 @@ int iwl4965_param_amsdu_size_8K; /* def: enable 8K amsdu size */ #define VS #endif -#define IWLWIFI_VERSION "1.2.26k" VD VS -#define DRV_COPYRIGHT "Copyright(c) 2003-2007 Intel Corporation" -#define DRV_VERSION IWLWIFI_VERSION +#define DRV_VERSION IWLWIFI_VERSION VD VS MODULE_DESCRIPTION(DRV_DESCRIPTION); -- cgit v1.2.1 From 34cf6ff6dd42cbc61fd652f893dcf71eed6052a5 Mon Sep 17 00:00:00 2001 From: Assaf Krauss Date: Thu, 6 Mar 2008 10:40:20 -0800 Subject: iwlwifi: Moving EEPROM handling in iwlcore module This patch move EEPROM code into iwl core module Signed-off-by: Assaf Krauss Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-eeprom.c | 205 +++++++++++++++ drivers/net/wireless/iwlwifi/iwl-eeprom.h | 399 ++++++++++++++++++++++++++++++ 2 files changed, 604 insertions(+) create mode 100644 drivers/net/wireless/iwlwifi/iwl-eeprom.c create mode 100644 drivers/net/wireless/iwlwifi/iwl-eeprom.h (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c new file mode 100644 index 000000000000..0064387dea91 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -0,0 +1,205 @@ +/****************************************************************************** + * + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, + * USA + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * Contact Information: + * Tomas Winkler + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + * BSD LICENSE + * + * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + + +#include +#include +#include +#include + +#include + +#include "iwl-4965-commands.h" +#include "iwl-4965.h" +#include "iwl-core.h" +#include "iwl-4965-debug.h" +#include "iwl-eeprom.h" +#include "iwl-4965-io.h" + +/****************************************************************************** + * + * EEPROM related functions + * +******************************************************************************/ + +int iwlcore_eeprom_verify_signature(struct iwl4965_priv *priv) +{ + u32 gp = iwl4965_read32(priv, CSR_EEPROM_GP); + if ((gp & CSR_EEPROM_GP_VALID_MSK) == CSR_EEPROM_GP_BAD_SIGNATURE) { + IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x", gp); + return -ENOENT; + } + return 0; +} +EXPORT_SYMBOL(iwlcore_eeprom_verify_signature); + +/* + * The device's EEPROM semaphore prevents conflicts between driver and uCode + * when accessing the EEPROM; each access is a series of pulses to/from the + * EEPROM chip, not a single event, so even reads could conflict if they + * weren't arbitrated by the semaphore. + */ +int iwlcore_eeprom_acquire_semaphore(struct iwl4965_priv *priv) +{ + u16 count; + int ret; + + for (count = 0; count < EEPROM_SEM_RETRY_LIMIT; count++) { + /* Request semaphore */ + iwl4965_set_bit(priv, CSR_HW_IF_CONFIG_REG, + CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); + + /* See if we got it */ + ret = iwl4965_poll_bit(priv, CSR_HW_IF_CONFIG_REG, + CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, + CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, + EEPROM_SEM_TIMEOUT); + if (ret >= 0) { + IWL_DEBUG_IO("Acquired semaphore after %d tries.\n", + count+1); + return ret; + } + } + + return ret; +} +EXPORT_SYMBOL(iwlcore_eeprom_acquire_semaphore); + +void iwlcore_eeprom_release_semaphore(struct iwl4965_priv *priv) +{ + iwl4965_clear_bit(priv, CSR_HW_IF_CONFIG_REG, + CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); + +} +EXPORT_SYMBOL(iwlcore_eeprom_release_semaphore); + + +/** + * iwl_eeprom_init - read EEPROM contents + * + * Load the EEPROM contents from adapter into priv->eeprom + * + * NOTE: This routine uses the non-debug IO access functions. + */ +int iwl_eeprom_init(struct iwl4965_priv *priv) +{ + u16 *e = (u16 *)&priv->eeprom; + u32 gp = iwl4965_read32(priv, CSR_EEPROM_GP); + u32 r; + int sz = sizeof(priv->eeprom); + int ret; + int i; + u16 addr; + + /* The EEPROM structure has several padding buffers within it + * and when adding new EEPROM maps is subject to programmer errors + * which may be very difficult to identify without explicitly + * checking the resulting size of the eeprom map. */ + BUILD_BUG_ON(sizeof(priv->eeprom) != IWL_EEPROM_IMAGE_SIZE); + + if ((gp & CSR_EEPROM_GP_VALID_MSK) == CSR_EEPROM_GP_BAD_SIGNATURE) { + IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x", gp); + return -ENOENT; + } + + /* Make sure driver (instead of uCode) is allowed to read EEPROM */ + ret = priv->cfg->ops->lib->eeprom_ops.acquire_semaphore(priv); + if (ret < 0) { + IWL_ERROR("Failed to acquire EEPROM semaphore.\n"); + return -ENOENT; + } + + /* eeprom is an array of 16bit values */ + for (addr = 0; addr < sz; addr += sizeof(u16)) { + _iwl4965_write32(priv, CSR_EEPROM_REG, addr << 1); + _iwl4965_clear_bit(priv, CSR_EEPROM_REG, CSR_EEPROM_REG_BIT_CMD); + + for (i = 0; i < IWL_EEPROM_ACCESS_TIMEOUT; + i += IWL_EEPROM_ACCESS_DELAY) { + r = _iwl4965_read_direct32(priv, CSR_EEPROM_REG); + if (r & CSR_EEPROM_REG_READ_VALID_MSK) + break; + udelay(IWL_EEPROM_ACCESS_DELAY); + } + + if (!(r & CSR_EEPROM_REG_READ_VALID_MSK)) { + IWL_ERROR("Time out reading EEPROM[%d]", addr); + ret = -ETIMEDOUT; + goto done; + } + e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16)); + } + ret = 0; + +done: + priv->cfg->ops->lib->eeprom_ops.release_semaphore(priv); + return ret; +} +EXPORT_SYMBOL(iwl_eeprom_init); + + +void iwl_eeprom_get_mac(const struct iwl4965_priv *priv, u8 *mac) +{ + memcpy(mac, priv->eeprom.mac_address, 6); +} +EXPORT_SYMBOL(iwl_eeprom_get_mac); + diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h new file mode 100644 index 000000000000..7827566dcc8b --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h @@ -0,0 +1,399 @@ +/****************************************************************************** + * + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, + * USA + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * Contact Information: + * Tomas Winkler + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + * BSD LICENSE + * + * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef __iwl_eeprom_h__ +#define __iwl_eeprom_h__ + +struct iwl4965_priv; + +/* + * EEPROM access time values: + * + * Driver initiates EEPROM read by writing byte address << 1 to CSR_EEPROM_REG, + * then clearing (with subsequent read/modify/write) CSR_EEPROM_REG bit + * CSR_EEPROM_REG_BIT_CMD (0x2). + * Driver then polls CSR_EEPROM_REG for CSR_EEPROM_REG_READ_VALID_MSK (0x1). + * When polling, wait 10 uSec between polling loops, up to a maximum 5000 uSec. + * Driver reads 16-bit value from bits 31-16 of CSR_EEPROM_REG. + */ +#define IWL_EEPROM_ACCESS_TIMEOUT 5000 /* uSec */ +#define IWL_EEPROM_ACCESS_DELAY 10 /* uSec */ + +#define IWL_EEPROM_SEM_TIMEOUT 10 /* milliseconds */ +#define IWL_EEPROM_SEM_RETRY_LIMIT 1000 /* number of attempts (not time) */ + + +/* + * Regulatory channel usage flags in EEPROM struct iwl4965_eeprom_channel.flags. + * + * IBSS and/or AP operation is allowed *only* on those channels with + * (VALID && IBSS && ACTIVE && !RADAR). This restriction is in place because + * RADAR detection is not supported by the 4965 driver, but is a + * requirement for establishing a new network for legal operation on channels + * requiring RADAR detection or restricting ACTIVE scanning. + * + * NOTE: "WIDE" flag does not indicate anything about "FAT" 40 MHz channels. + * It only indicates that 20 MHz channel use is supported; FAT channel + * usage is indicated by a separate set of regulatory flags for each + * FAT channel pair. + * + * NOTE: Using a channel inappropriately will result in a uCode error! + */ +#define IWL_NUM_TX_CALIB_GROUPS 5 +enum { + EEPROM_CHANNEL_VALID = (1 << 0), /* usable for this SKU/geo */ + EEPROM_CHANNEL_IBSS = (1 << 1), /* usable as an IBSS channel */ + /* Bit 2 Reserved */ + EEPROM_CHANNEL_ACTIVE = (1 << 3), /* active scanning allowed */ + EEPROM_CHANNEL_RADAR = (1 << 4), /* radar detection required */ + EEPROM_CHANNEL_WIDE = (1 << 5), /* 20 MHz channel okay */ + EEPROM_CHANNEL_NARROW = (1 << 6), /* 10 MHz channel (not used) */ + EEPROM_CHANNEL_DFS = (1 << 7), /* dynamic freq selection candidate */ +}; + +/* SKU Capabilities */ +#define EEPROM_SKU_CAP_SW_RF_KILL_ENABLE (1 << 0) +#define EEPROM_SKU_CAP_HW_RF_KILL_ENABLE (1 << 1) + +/* *regulatory* channel data format in eeprom, one for each channel. + * There are separate entries for FAT (40 MHz) vs. normal (20 MHz) channels. */ +struct iwl4965_eeprom_channel { + u8 flags; /* EEPROM_CHANNEL_* flags copied from EEPROM */ + s8 max_power_avg; /* max power (dBm) on this chnl, limit 31 */ +} __attribute__ ((packed)); + +/* 4965 has two radio transmitters (and 3 radio receivers) */ +#define EEPROM_TX_POWER_TX_CHAINS (2) + +/* 4965 has room for up to 8 sets of txpower calibration data */ +#define EEPROM_TX_POWER_BANDS (8) + +/* 4965 factory calibration measures txpower gain settings for + * each of 3 target output levels */ +#define EEPROM_TX_POWER_MEASUREMENTS (3) + +#define EEPROM_4965_TX_POWER_VERSION (2) + +/* 4965 driver does not work with txpower calibration version < 5. + * Look for this in calib_version member of struct iwl4965_eeprom. */ +#define EEPROM_TX_POWER_VERSION_NEW (5) + + +/* + * 4965 factory calibration data for one txpower level, on one channel, + * measured on one of the 2 tx chains (radio transmitter and associated + * antenna). EEPROM contains: + * + * 1) Temperature (degrees Celsius) of device when measurement was made. + * + * 2) Gain table index used to achieve the target measurement power. + * This refers to the "well-known" gain tables (see iwl-4965-hw.h). + * + * 3) Actual measured output power, in half-dBm ("34" = 17 dBm). + * + * 4) RF power amplifier detector level measurement (not used). + */ +struct iwl4965_eeprom_calib_measure { + u8 temperature; /* Device temperature (Celsius) */ + u8 gain_idx; /* Index into gain table */ + u8 actual_pow; /* Measured RF output power, half-dBm */ + s8 pa_det; /* Power amp detector level (not used) */ +} __attribute__ ((packed)); + + +/* + * 4965 measurement set for one channel. EEPROM contains: + * + * 1) Channel number measured + * + * 2) Measurements for each of 3 power levels for each of 2 radio transmitters + * (a.k.a. "tx chains") (6 measurements altogether) + */ +struct iwl4965_eeprom_calib_ch_info { + u8 ch_num; + struct iwl4965_eeprom_calib_measure + measurements[EEPROM_TX_POWER_TX_CHAINS] + [EEPROM_TX_POWER_MEASUREMENTS]; +} __attribute__ ((packed)); + +/* + * 4965 txpower subband info. + * + * For each frequency subband, EEPROM contains the following: + * + * 1) First and last channels within range of the subband. "0" values + * indicate that this sample set is not being used. + * + * 2) Sample measurement sets for 2 channels close to the range endpoints. + */ +struct iwl4965_eeprom_calib_subband_info { + u8 ch_from; /* channel number of lowest channel in subband */ + u8 ch_to; /* channel number of highest channel in subband */ + struct iwl4965_eeprom_calib_ch_info ch1; + struct iwl4965_eeprom_calib_ch_info ch2; +} __attribute__ ((packed)); + + +/* + * 4965 txpower calibration info. EEPROM contains: + * + * 1) Factory-measured saturation power levels (maximum levels at which + * tx power amplifier can output a signal without too much distortion). + * There is one level for 2.4 GHz band and one for 5 GHz band. These + * values apply to all channels within each of the bands. + * + * 2) Factory-measured power supply voltage level. This is assumed to be + * constant (i.e. same value applies to all channels/bands) while the + * factory measurements are being made. + * + * 3) Up to 8 sets of factory-measured txpower calibration values. + * These are for different frequency ranges, since txpower gain + * characteristics of the analog radio circuitry vary with frequency. + * + * Not all sets need to be filled with data; + * struct iwl4965_eeprom_calib_subband_info contains range of channels + * (0 if unused) for each set of data. + */ +struct iwl4965_eeprom_calib_info { + u8 saturation_power24; /* half-dBm (e.g. "34" = 17 dBm) */ + u8 saturation_power52; /* half-dBm */ + s16 voltage; /* signed */ + struct iwl4965_eeprom_calib_subband_info + band_info[EEPROM_TX_POWER_BANDS]; +} __attribute__ ((packed)); + + + +/* + * 4965 EEPROM map + */ +struct iwl4965_eeprom { + u8 reserved0[16]; +#define EEPROM_DEVICE_ID (2*0x08) /* 2 bytes */ + u16 device_id; /* abs.ofs: 16 */ + u8 reserved1[2]; +#define EEPROM_PMC (2*0x0A) /* 2 bytes */ + u16 pmc; /* abs.ofs: 20 */ + u8 reserved2[20]; +#define EEPROM_MAC_ADDRESS (2*0x15) /* 6 bytes */ + u8 mac_address[6]; /* abs.ofs: 42 */ + u8 reserved3[58]; +#define EEPROM_BOARD_REVISION (2*0x35) /* 2 bytes */ + u16 board_revision; /* abs.ofs: 106 */ + u8 reserved4[11]; +#define EEPROM_BOARD_PBA_NUMBER (2*0x3B+1) /* 9 bytes */ + u8 board_pba_number[9]; /* abs.ofs: 119 */ + u8 reserved5[8]; +#define EEPROM_VERSION (2*0x44) /* 2 bytes */ + u16 version; /* abs.ofs: 136 */ +#define EEPROM_SKU_CAP (2*0x45) /* 1 bytes */ + u8 sku_cap; /* abs.ofs: 138 */ +#define EEPROM_LEDS_MODE (2*0x45+1) /* 1 bytes */ + u8 leds_mode; /* abs.ofs: 139 */ +#define EEPROM_OEM_MODE (2*0x46) /* 2 bytes */ + u16 oem_mode; +#define EEPROM_WOWLAN_MODE (2*0x47) /* 2 bytes */ + u16 wowlan_mode; /* abs.ofs: 142 */ +#define EEPROM_LEDS_TIME_INTERVAL (2*0x48) /* 2 bytes */ + u16 leds_time_interval; /* abs.ofs: 144 */ +#define EEPROM_LEDS_OFF_TIME (2*0x49) /* 1 bytes */ + u8 leds_off_time; /* abs.ofs: 146 */ +#define EEPROM_LEDS_ON_TIME (2*0x49+1) /* 1 bytes */ + u8 leds_on_time; /* abs.ofs: 147 */ +#define EEPROM_ALMGOR_M_VERSION (2*0x4A) /* 1 bytes */ + u8 almgor_m_version; /* abs.ofs: 148 */ +#define EEPROM_ANTENNA_SWITCH_TYPE (2*0x4A+1) /* 1 bytes */ + u8 antenna_switch_type; /* abs.ofs: 149 */ + u8 reserved6[8]; +#define EEPROM_4965_BOARD_REVISION (2*0x4F) /* 2 bytes */ + u16 board_revision_4965; /* abs.ofs: 158 */ + u8 reserved7[13]; +#define EEPROM_4965_BOARD_PBA (2*0x56+1) /* 9 bytes */ + u8 board_pba_number_4965[9]; /* abs.ofs: 173 */ + u8 reserved8[10]; +#define EEPROM_REGULATORY_SKU_ID (2*0x60) /* 4 bytes */ + u8 sku_id[4]; /* abs.ofs: 192 */ + +/* + * Per-channel regulatory data. + * + * Each channel that *might* be supported by 3945 or 4965 has a fixed location + * in EEPROM containing EEPROM_CHANNEL_* usage flags (LSB) and max regulatory + * txpower (MSB). + * + * Entries immediately below are for 20 MHz channel width. FAT (40 MHz) + * channels (only for 4965, not supported by 3945) appear later in the EEPROM. + * + * 2.4 GHz channels 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 + */ +#define EEPROM_REGULATORY_BAND_1 (2*0x62) /* 2 bytes */ + u16 band_1_count; /* abs.ofs: 196 */ +#define EEPROM_REGULATORY_BAND_1_CHANNELS (2*0x63) /* 28 bytes */ + struct iwl4965_eeprom_channel band_1_channels[14]; /* abs.ofs: 196 */ + +/* + * 4.9 GHz channels 183, 184, 185, 187, 188, 189, 192, 196, + * 5.0 GHz channels 7, 8, 11, 12, 16 + * (4915-5080MHz) (none of these is ever supported) + */ +#define EEPROM_REGULATORY_BAND_2 (2*0x71) /* 2 bytes */ + u16 band_2_count; /* abs.ofs: 226 */ +#define EEPROM_REGULATORY_BAND_2_CHANNELS (2*0x72) /* 26 bytes */ + struct iwl4965_eeprom_channel band_2_channels[13]; /* abs.ofs: 228 */ + +/* + * 5.2 GHz channels 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64 + * (5170-5320MHz) + */ +#define EEPROM_REGULATORY_BAND_3 (2*0x7F) /* 2 bytes */ + u16 band_3_count; /* abs.ofs: 254 */ +#define EEPROM_REGULATORY_BAND_3_CHANNELS (2*0x80) /* 24 bytes */ + struct iwl4965_eeprom_channel band_3_channels[12]; /* abs.ofs: 256 */ + +/* + * 5.5 GHz channels 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 + * (5500-5700MHz) + */ +#define EEPROM_REGULATORY_BAND_4 (2*0x8C) /* 2 bytes */ + u16 band_4_count; /* abs.ofs: 280 */ +#define EEPROM_REGULATORY_BAND_4_CHANNELS (2*0x8D) /* 22 bytes */ + struct iwl4965_eeprom_channel band_4_channels[11]; /* abs.ofs: 282 */ + +/* + * 5.7 GHz channels 145, 149, 153, 157, 161, 165 + * (5725-5825MHz) + */ +#define EEPROM_REGULATORY_BAND_5 (2*0x98) /* 2 bytes */ + u16 band_5_count; /* abs.ofs: 304 */ +#define EEPROM_REGULATORY_BAND_5_CHANNELS (2*0x99) /* 12 bytes */ + struct iwl4965_eeprom_channel band_5_channels[6]; /* abs.ofs: 306 */ + + u8 reserved10[2]; + + +/* + * 2.4 GHz FAT channels 1 (5), 2 (6), 3 (7), 4 (8), 5 (9), 6 (10), 7 (11) + * + * The channel listed is the center of the lower 20 MHz half of the channel. + * The overall center frequency is actually 2 channels (10 MHz) above that, + * and the upper half of each FAT channel is centered 4 channels (20 MHz) away + * from the lower half; e.g. the upper half of FAT channel 1 is channel 5, + * and the overall FAT channel width centers on channel 3. + * + * NOTE: The RXON command uses 20 MHz channel numbers to specify the + * control channel to which to tune. RXON also specifies whether the + * control channel is the upper or lower half of a FAT channel. + * + * NOTE: 4965 does not support FAT channels on 2.4 GHz. + */ +#define EEPROM_REGULATORY_BAND_24_FAT_CHANNELS (2*0xA0) /* 14 bytes */ + struct iwl4965_eeprom_channel band_24_channels[7]; /* abs.ofs: 320 */ + u8 reserved11[2]; + +/* + * 5.2 GHz FAT channels 36 (40), 44 (48), 52 (56), 60 (64), + * 100 (104), 108 (112), 116 (120), 124 (128), 132 (136), 149 (153), 157 (161) + */ +#define EEPROM_REGULATORY_BAND_52_FAT_CHANNELS (2*0xA8) /* 22 bytes */ + struct iwl4965_eeprom_channel band_52_channels[11]; /* abs.ofs: 336 */ + u8 reserved12[6]; + +/* + * 4965 driver requires txpower calibration format version 5 or greater. + * Driver does not work with txpower calibration version < 5. + * This value is simply a 16-bit number, no major/minor versions here. + */ +#define EEPROM_CALIB_VERSION_OFFSET (2*0xB6) /* 2 bytes */ + u16 calib_version; /* abs.ofs: 364 */ + u8 reserved13[2]; + u8 reserved14[96]; /* abs.ofs: 368 */ + +/* + * 4965 Txpower calibration data. + */ +#define EEPROM_IWL_CALIB_TXPOWER_OFFSET (2*0xE8) /* 48 bytes */ + struct iwl4965_eeprom_calib_info calib_info; /* abs.ofs: 464 */ + + u8 reserved16[140]; /* fill out to full 1024 byte block */ + + +} __attribute__ ((packed)); + +#define IWL_EEPROM_IMAGE_SIZE 1024 + +/* End of EEPROM */ + +struct iwl_eeprom_ops { + int (*verify_signature) (struct iwl4965_priv *priv); + int (*acquire_semaphore) (struct iwl4965_priv *priv); + void (*release_semaphore) (struct iwl4965_priv *priv); +}; + + +void iwl_eeprom_get_mac(const struct iwl4965_priv *priv, u8 *mac); +int iwl_eeprom_init(struct iwl4965_priv *priv); + +int iwlcore_eeprom_verify_signature(struct iwl4965_priv *priv); +int iwlcore_eeprom_acquire_semaphore(struct iwl4965_priv *priv); +void iwlcore_eeprom_release_semaphore(struct iwl4965_priv *priv); + +#endif /* __iwl_eeprom_h__ */ -- cgit v1.2.1 From c54b679ddcd91604fd0d144cd793a0ddbd0ae03d Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Thu, 6 Mar 2008 17:36:53 -0800 Subject: iwlwifi: queue functions cleanup This patch moves 1. iwl_queue_inc_wrap and int iwl_queue_dec_wrap into iwl-helpers.h these two functions are identical to common for both iwl3956 and iwl4965 2. renames x2_queue_used to iwl3945_x2_queue_used 3. exports iwl3945_queue_space out of iwl3964-base.c Signed-off-by: Tomas Winkler Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.h | 3 ++ drivers/net/wireless/iwlwifi/iwl-helpers.h | 20 +++++++++++++ drivers/net/wireless/iwlwifi/iwl3945-base.c | 45 +++++++++-------------------- drivers/net/wireless/iwlwifi/iwl4965-base.c | 37 ++++++------------------ 4 files changed, 45 insertions(+), 60 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index a238e833251f..0ab22d366d93 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -116,6 +116,9 @@ struct iwl3945_queue { * space less than this */ } __attribute__ ((packed)); +int iwl3945_queue_space(const struct iwl3945_queue *q); +int iwl3945_x2_queue_used(const struct iwl3945_queue *q, int i); + #define MAX_NUM_OF_TBS (20) /* One for each TFD */ diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h index 8993cca81b40..736b88881b03 100644 --- a/drivers/net/wireless/iwlwifi/iwl-helpers.h +++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h @@ -254,6 +254,26 @@ static inline u8 iwl_get_dma_hi_address(dma_addr_t addr) return sizeof(addr) > sizeof(u32) ? (addr >> 16) >> 16 : 0; } +/** + * iwl_queue_inc_wrap - increment queue index, wrap back to beginning + * @index -- current index + * @n_bd -- total number of entries in queue (must be power of 2) + */ +static inline int iwl_queue_inc_wrap(int index, int n_bd) +{ + return ++index & (n_bd - 1); +} + +/** + * iwl_queue_dec_wrap - decrement queue index, wrap back to end + * @index -- current index + * @n_bd -- total number of entries in queue (must be power of 2) + */ +static inline int iwl_queue_dec_wrap(int index, int n_bd) +{ + return --index & (n_bd - 1); +} + /* TODO: Move fw_desc functions to iwl-pci.ko */ static inline void iwl_free_fw_desc(struct pci_dev *pci_dev, struct fw_desc *desc) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 4aaced0b9f26..39fd5440a248 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -183,7 +183,7 @@ static const char *iwl3945_escape_essid(const char *essid, u8 essid_len) * (#0-3) for data tx via EDCA. An additional 2 HCCA queues are unused. ***************************************************/ -static int iwl3945_queue_space(const struct iwl3945_queue *q) +int iwl3945_queue_space(const struct iwl3945_queue *q) { int s = q->read_ptr - q->write_ptr; @@ -199,33 +199,14 @@ static int iwl3945_queue_space(const struct iwl3945_queue *q) return s; } -/** - * iwl3945_queue_inc_wrap - increment queue index, wrap back to beginning - * @index -- current index - * @n_bd -- total number of entries in queue (must be power of 2) - */ -static inline int iwl3945_queue_inc_wrap(int index, int n_bd) -{ - return ++index & (n_bd - 1); -} - -/** - * iwl3945_queue_dec_wrap - increment queue index, wrap back to end - * @index -- current index - * @n_bd -- total number of entries in queue (must be power of 2) - */ -static inline int iwl3945_queue_dec_wrap(int index, int n_bd) -{ - return --index & (n_bd - 1); -} - -static inline int x2_queue_used(const struct iwl3945_queue *q, int i) +int iwl3945_x2_queue_used(const struct iwl3945_queue *q, int i) { return q->write_ptr > q->read_ptr ? (i >= q->read_ptr && i < q->write_ptr) : !(i < q->read_ptr && i >= q->write_ptr); } + static inline u8 get_cmd_index(struct iwl3945_queue *q, u32 index, int is_huge) { /* This is for scan command, the big buffer at end of command array */ @@ -246,8 +227,8 @@ static int iwl3945_queue_init(struct iwl3945_priv *priv, struct iwl3945_queue *q q->n_window = slots_num; q->id = id; - /* count must be power-of-two size, otherwise iwl3945_queue_inc_wrap - * and iwl3945_queue_dec_wrap are broken. */ + /* count must be power-of-two size, otherwise iwl_queue_inc_wrap + * and iwl_queue_dec_wrap are broken. */ BUG_ON(!is_power_of_2(count)); /* slots_num must be power-of-two size, otherwise @@ -347,7 +328,7 @@ int iwl3945_tx_queue_init(struct iwl3945_priv *priv, txq->need_update = 0; /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise - * iwl3945_queue_inc_wrap and iwl3945_queue_dec_wrap are broken. */ + * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */ BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1)); /* Initialize queue high/low-water, head/tail indexes */ @@ -378,7 +359,7 @@ void iwl3945_tx_queue_free(struct iwl3945_priv *priv, struct iwl3945_tx_queue *t /* first, empty all BD's */ for (; q->write_ptr != q->read_ptr; - q->read_ptr = iwl3945_queue_inc_wrap(q->read_ptr, q->n_bd)) + q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) iwl3945_hw_txq_free_tfd(priv, txq); len = sizeof(struct iwl3945_cmd) * q->n_window; @@ -717,7 +698,7 @@ static int iwl3945_enqueue_hcmd(struct iwl3945_priv *priv, struct iwl3945_host_c txq->need_update = 1; /* Increment and update queue's write index */ - q->write_ptr = iwl3945_queue_inc_wrap(q->write_ptr, q->n_bd); + q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); ret = iwl3945_tx_queue_update_write_ptr(priv, txq); spin_unlock_irqrestore(&priv->hcmd_lock, flags); @@ -2797,7 +2778,7 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, ieee80211_get_hdrlen(fc)); /* Tell device the write index *just past* this latest filled TFD */ - q->write_ptr = iwl3945_queue_inc_wrap(q->write_ptr, q->n_bd); + q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); rc = iwl3945_tx_queue_update_write_ptr(priv, txq); spin_unlock_irqrestore(&priv->lock, flags); @@ -3189,16 +3170,16 @@ static int iwl3945_tx_queue_reclaim(struct iwl3945_priv *priv, int txq_id, int i struct iwl3945_queue *q = &txq->q; int nfreed = 0; - if ((index >= q->n_bd) || (x2_queue_used(q, index) == 0)) { + if ((index >= q->n_bd) || (iwl3945_x2_queue_used(q, index) == 0)) { IWL_ERROR("Read index for DMA queue txq id (%d), index %d, " "is out of range [0-%d] %d %d.\n", txq_id, index, q->n_bd, q->write_ptr, q->read_ptr); return 0; } - for (index = iwl3945_queue_inc_wrap(index, q->n_bd); + for (index = iwl_queue_inc_wrap(index, q->n_bd); q->read_ptr != index; - q->read_ptr = iwl3945_queue_inc_wrap(q->read_ptr, q->n_bd)) { + q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { if (txq_id != IWL_CMD_QUEUE_NUM) { iwl3945_txstatus_to_ieee(priv, &(txq->txb[txq->q.read_ptr])); @@ -3245,7 +3226,7 @@ static void iwl3945_rx_reply_tx(struct iwl3945_priv *priv, struct iwl3945_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; u32 status = le32_to_cpu(tx_resp->status); - if ((index >= txq->q.n_bd) || (x2_queue_used(&txq->q, index) == 0)) { + if ((index >= txq->q.n_bd) || (iwl3945_x2_queue_used(&txq->q, index) == 0)) { IWL_ERROR("Read index for DMA queue txq_id (%d) index %d " "is out of range [0-%d] %d %d\n", txq_id, index, txq->q.n_bd, txq->q.write_ptr, diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index af95626a6112..28c64c39ef02 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -194,25 +194,6 @@ int iwl4965_queue_space(const struct iwl4965_queue *q) return s; } -/** - * iwl4965_queue_inc_wrap - increment queue index, wrap back to beginning - * @index -- current index - * @n_bd -- total number of entries in queue (must be power of 2) - */ -static inline int iwl4965_queue_inc_wrap(int index, int n_bd) -{ - return ++index & (n_bd - 1); -} - -/** - * iwl4965_queue_dec_wrap - decrement queue index, wrap back to end - * @index -- current index - * @n_bd -- total number of entries in queue (must be power of 2) - */ -static inline int iwl4965_queue_dec_wrap(int index, int n_bd) -{ - return --index & (n_bd - 1); -} static inline int x2_queue_used(const struct iwl4965_queue *q, int i) { @@ -241,8 +222,8 @@ static int iwl4965_queue_init(struct iwl4965_priv *priv, struct iwl4965_queue *q q->n_window = slots_num; q->id = id; - /* count must be power-of-two size, otherwise iwl4965_queue_inc_wrap - * and iwl4965_queue_dec_wrap are broken. */ + /* count must be power-of-two size, otherwise iwl_queue_inc_wrap + * and iwl_queue_dec_wrap are broken. */ BUG_ON(!is_power_of_2(count)); /* slots_num must be power-of-two size, otherwise @@ -342,7 +323,7 @@ int iwl4965_tx_queue_init(struct iwl4965_priv *priv, txq->need_update = 0; /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise - * iwl4965_queue_inc_wrap and iwl4965_queue_dec_wrap are broken. */ + * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */ BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1)); /* Initialize queue's high/low-water marks, and head/tail indexes */ @@ -373,7 +354,7 @@ void iwl4965_tx_queue_free(struct iwl4965_priv *priv, struct iwl4965_tx_queue *t /* first, empty all BD's */ for (; q->write_ptr != q->read_ptr; - q->read_ptr = iwl4965_queue_inc_wrap(q->read_ptr, q->n_bd)) + q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) iwl4965_hw_txq_free_tfd(priv, txq); len = sizeof(struct iwl4965_cmd) * q->n_window; @@ -714,7 +695,7 @@ static int iwl4965_enqueue_hcmd(struct iwl4965_priv *priv, struct iwl4965_host_c ret = iwl4965_tx_queue_update_wr_ptr(priv, txq, 0); /* Increment and update queue's write index */ - q->write_ptr = iwl4965_queue_inc_wrap(q->write_ptr, q->n_bd); + q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); iwl4965_tx_queue_update_write_ptr(priv, txq); spin_unlock_irqrestore(&priv->hcmd_lock, flags); @@ -2897,7 +2878,7 @@ static int iwl4965_tx_skb(struct iwl4965_priv *priv, iwl4965_tx_queue_update_wr_ptr(priv, txq, len); /* Tell device the write index *just past* this latest filled TFD */ - q->write_ptr = iwl4965_queue_inc_wrap(q->write_ptr, q->n_bd); + q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); rc = iwl4965_tx_queue_update_write_ptr(priv, txq); spin_unlock_irqrestore(&priv->lock, flags); @@ -3291,9 +3272,9 @@ int iwl4965_tx_queue_reclaim(struct iwl4965_priv *priv, int txq_id, int index) return 0; } - for (index = iwl4965_queue_inc_wrap(index, q->n_bd); + for (index = iwl_queue_inc_wrap(index, q->n_bd); q->read_ptr != index; - q->read_ptr = iwl4965_queue_inc_wrap(q->read_ptr, q->n_bd)) { + q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { if (txq_id != IWL_CMD_QUEUE_NUM) { iwl4965_txstatus_to_ieee(priv, &(txq->txb[txq->q.read_ptr])); @@ -3538,7 +3519,7 @@ static void iwl4965_rx_reply_tx(struct iwl4965_priv *priv, if (txq->q.read_ptr != (scd_ssn & 0xff)) { int freed; - index = iwl4965_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd); + index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd); IWL_DEBUG_TX_REPLY("Retry scheduler reclaim scd_ssn " "%d index %d\n", scd_ssn , index); freed = iwl4965_tx_queue_reclaim(priv, txq_id, index); -- cgit v1.2.1 From 28447f3cfdf72f6ea97b50cc1eefe35602107dff Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Thu, 6 Mar 2008 17:36:54 -0800 Subject: iwlwifi: Fix 3945 rate scaling This patch fix 3945 rate scaling after cfg80211 rate/band changes Signed-off-by: Tomas Winkler Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 45 ++++++++++++++---------------- drivers/net/wireless/iwlwifi/iwl-3945-rs.h | 2 +- 2 files changed, 22 insertions(+), 25 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index c4bfba6f3c2b..08604eb8291b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -158,9 +158,9 @@ static void iwl3945_clear_window(struct iwl3945_rate_scale_data *window) { window->data = 0; window->success_counter = 0; - window->success_ratio = IWL_INVALID_VALUE; + window->success_ratio = -1; window->counter = 0; - window->average_tpt = IWL_INVALID_VALUE; + window->average_tpt = IWL_INV_TPT; window->stamp = 0; } @@ -459,13 +459,13 @@ static void rs_tx_status(void *priv_rate, struct iwl3945_rs_sta *rs_sta; struct ieee80211_supported_band *sband; + IWL_DEBUG_RATE("enter\n"); + sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - IWL_DEBUG_RATE("enter\n"); retries = tx_resp->retry_count; - /* FIXME : this is wrong */ - first_index = &sband->bitrates[0] - tx_resp->control.tx_rate; + first_index = tx_resp->control.tx_rate->hw_value; if ((first_index < 0) || (first_index >= IWL_RATE_COUNT)) { IWL_DEBUG_RATE("leave: Rate out of bounds: %d\n", first_index); return; @@ -634,7 +634,7 @@ static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta, * */ static void rs_get_rate(void *priv_rate, struct net_device *dev, - struct ieee80211_supported_band *band, + struct ieee80211_supported_band *sband, struct sk_buff *skb, struct rate_selection *sel) { @@ -644,9 +644,9 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, int index; struct iwl3945_rs_sta *rs_sta; struct iwl3945_rate_scale_data *window = NULL; - int current_tpt = IWL_INVALID_VALUE; - int low_tpt = IWL_INVALID_VALUE; - int high_tpt = IWL_INVALID_VALUE; + int current_tpt = IWL_INV_TPT; + int low_tpt = IWL_INV_TPT; + int high_tpt = IWL_INV_TPT; u32 fail_count; s8 scale_action = 0; unsigned long flags; @@ -670,15 +670,15 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, is_multicast_ether_addr(hdr->addr1) || !sta || !sta->rate_ctrl_priv) { IWL_DEBUG_RATE("leave: No STA priv data to update!\n"); - sel->rate = rate_lowest(local, band, sta); + sel->rate = rate_lowest(local, sband, sta); rcu_read_unlock(); return; } - rate_mask = sta->supp_rates[band->band]; + rate_mask = sta->supp_rates[sband->band]; index = min(sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT - 1); - if (priv->band == IEEE80211_BAND_5GHZ) + if (sband->band == IEEE80211_BAND_5GHZ) rate_mask = rate_mask << IWL_FIRST_OFDM_RATE; rs_sta = (void *)sta->rate_ctrl_priv; @@ -710,7 +710,7 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, if (((fail_count <= IWL_RATE_MIN_FAILURE_TH) && (window->success_counter < IWL_RATE_MIN_SUCCESS_TH))) { - window->average_tpt = IWL_INVALID_VALUE; + window->average_tpt = IWL_INV_TPT; spin_unlock_irqrestore(&rs_sta->lock, flags); IWL_DEBUG_RATE("Invalid average_tpt on rate %d: " @@ -729,7 +729,7 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, current_tpt = window->average_tpt; high_low = iwl3945_get_adjacent_rate(rs_sta, index, rate_mask, - band->band); + sband->band); low = high_low & 0xff; high = (high_low >> 8) & 0xff; @@ -746,19 +746,16 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, if ((window->success_ratio < IWL_RATE_DECREASE_TH) || !current_tpt) { IWL_DEBUG_RATE("decrease rate because of low success_ratio\n"); scale_action = -1; - } else if ((low_tpt == IWL_INVALID_VALUE) && - (high_tpt == IWL_INVALID_VALUE)) + } else if ((low_tpt == IWL_INV_TPT) && (high_tpt == IWL_INV_TPT)) scale_action = 1; - else if ((low_tpt != IWL_INVALID_VALUE) && - (high_tpt != IWL_INVALID_VALUE) - && (low_tpt < current_tpt) - && (high_tpt < current_tpt)) { + else if ((low_tpt != IWL_INV_TPT) && (high_tpt != IWL_INV_TPT) && + (low_tpt < current_tpt) && (high_tpt < current_tpt)) { IWL_DEBUG_RATE("No action -- low [%d] & high [%d] < " "current_tpt [%d]\n", low_tpt, high_tpt, current_tpt); scale_action = 0; } else { - if (high_tpt != IWL_INVALID_VALUE) { + if (high_tpt != IWL_INV_TPT) { if (high_tpt > current_tpt) scale_action = 1; else { @@ -766,7 +763,7 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, ("decrease rate because of high tpt\n"); scale_action = -1; } - } else if (low_tpt != IWL_INVALID_VALUE) { + } else if (low_tpt != IWL_INV_TPT) { if (low_tpt > current_tpt) { IWL_DEBUG_RATE ("decrease rate because of low tpt\n"); @@ -808,7 +805,7 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, out: sta->last_txrate_idx = index; - if (priv->band == IEEE80211_BAND_5GHZ) + if (sband->band == IEEE80211_BAND_5GHZ) sta->txrate_idx = sta->last_txrate_idx - IWL_FIRST_OFDM_RATE; else sta->txrate_idx = sta->last_txrate_idx; @@ -817,7 +814,7 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, IWL_DEBUG_RATE("leave: %d\n", index); - sel->rate = &priv->ieee_rates[index]; + sel->rate = &sband->bitrates[sta->txrate_idx]; } static struct rate_control_ops rs_ops = { diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.h b/drivers/net/wireless/iwlwifi/iwl-3945-rs.h index 3c61f08febe6..b082a093ee26 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.h @@ -159,7 +159,7 @@ enum { #define IWL_RATES_MASK ((1 << IWL_RATE_COUNT) - 1) -#define IWL_INVALID_VALUE -1 +#define IWL_INV_TPT -1 #define IWL_MIN_RSSI_VAL -100 #define IWL_MAX_RSSI_VAL 0 -- cgit v1.2.1 From 91c066f27b6dacb6589fb5190af373fb9f993397 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Thu, 6 Mar 2008 17:36:55 -0800 Subject: iwlwifi: 3945 split tx_complete to command and packet function This patch 1. removes cmd completion from iwl3945_tx_queue_reclaim and creates iwl3945_cmd_queue_reclaim. 1. removes 11n relevant elements from this function 2. removes call to ieee80211_tx_status_irqsafe and uses ieee80211_tx_status only Signed-off-by: Tomas Winkler Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 117 ++++++++++++++++- drivers/net/wireless/iwlwifi/iwl3945-base.c | 188 +++++----------------------- 2 files changed, 148 insertions(+), 157 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 49b781104327..dc3d695bf096 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -227,14 +227,126 @@ __le32 iwl3945_get_antenna_flags(const struct iwl3945_priv *priv) return 0; /* "diversity" is default if error */ } +#ifdef CONFIG_IWL3945_DEBUG +#define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x + +static const char *iwl3945_get_tx_fail_reason(u32 status) +{ + switch (status & TX_STATUS_MSK) { + case TX_STATUS_SUCCESS: + return "SUCCESS"; + TX_STATUS_ENTRY(SHORT_LIMIT); + TX_STATUS_ENTRY(LONG_LIMIT); + TX_STATUS_ENTRY(FIFO_UNDERRUN); + TX_STATUS_ENTRY(MGMNT_ABORT); + TX_STATUS_ENTRY(NEXT_FRAG); + TX_STATUS_ENTRY(LIFE_EXPIRE); + TX_STATUS_ENTRY(DEST_PS); + TX_STATUS_ENTRY(ABORTED); + TX_STATUS_ENTRY(BT_RETRY); + TX_STATUS_ENTRY(STA_INVALID); + TX_STATUS_ENTRY(FRAG_DROPPED); + TX_STATUS_ENTRY(TID_DISABLE); + TX_STATUS_ENTRY(FRAME_FLUSHED); + TX_STATUS_ENTRY(INSUFFICIENT_CF_POLL); + TX_STATUS_ENTRY(TX_LOCKED); + TX_STATUS_ENTRY(NO_BEACON_ON_RADAR); + } + + return "UNKNOWN"; +} +#else +static inline const char *iwl3945_get_tx_fail_reason(u32 status) +{ + return ""; +} +#endif + + +/** + * iwl3945_tx_queue_reclaim - Reclaim Tx queue entries already Tx'd + * + * When FW advances 'R' index, all entries between old and new 'R' index + * need to be reclaimed. As result, some free space forms. If there is + * enough free space (> low mark), wake the stack that feeds us. + */ +static void iwl3945_tx_queue_reclaim(struct iwl3945_priv *priv, + int txq_id, int index) +{ + struct iwl3945_tx_queue *txq = &priv->txq[txq_id]; + struct iwl3945_queue *q = &txq->q; + struct iwl3945_tx_info *tx_info; + + BUG_ON(txq_id == IWL_CMD_QUEUE_NUM); + + for (index = iwl_queue_inc_wrap(index, q->n_bd); q->read_ptr != index; + q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { + + tx_info = &txq->txb[txq->q.read_ptr]; + ieee80211_tx_status(priv->hw, tx_info->skb[0], + &tx_info->status); + tx_info->skb[0] = NULL; + iwl3945_hw_txq_free_tfd(priv, txq); + } + + if (iwl3945_queue_space(q) > q->low_mark && (txq_id >= 0) && + (txq_id != IWL_CMD_QUEUE_NUM) && + priv->mac80211_registered) + ieee80211_wake_queue(priv->hw, txq_id); +} + +/** + * iwl3945_rx_reply_tx - Handle Tx response + */ +static void iwl3945_rx_reply_tx(struct iwl3945_priv *priv, + struct iwl3945_rx_mem_buffer *rxb) +{ + struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data; + u16 sequence = le16_to_cpu(pkt->hdr.sequence); + int txq_id = SEQ_TO_QUEUE(sequence); + int index = SEQ_TO_INDEX(sequence); + struct iwl3945_tx_queue *txq = &priv->txq[txq_id]; + struct ieee80211_tx_status *tx_status; + struct iwl3945_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; + u32 status = le32_to_cpu(tx_resp->status); + int rate_idx; + + if ((index >= txq->q.n_bd) || (iwl3945_x2_queue_used(&txq->q, index) == 0)) { + IWL_ERROR("Read index for DMA queue txq_id (%d) index %d " + "is out of range [0-%d] %d %d\n", txq_id, + index, txq->q.n_bd, txq->q.write_ptr, + txq->q.read_ptr); + return; + } + + tx_status = &(txq->txb[txq->q.read_ptr].status); + + tx_status->retry_count = tx_resp->failure_frame; + /* tx_status->rts_retry_count = tx_resp->failure_rts; */ + tx_status->flags = ((status & TX_STATUS_MSK) == TX_STATUS_SUCCESS) ? + IEEE80211_TX_STATUS_ACK : 0; + + IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) plcp rate %d retries %d\n", + txq_id, iwl3945_get_tx_fail_reason(status), status, + tx_resp->rate, tx_resp->failure_frame); + + rate_idx = iwl3945_hwrate_to_plcp_idx(tx_resp->rate); + tx_status->control.tx_rate = &priv->ieee_rates[rate_idx]; + IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index); + iwl3945_tx_queue_reclaim(priv, txq_id, index); + + if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK)) + IWL_ERROR("TODO: Implement Tx ABORT REQUIRED!!!\n"); +} + + + /***************************************************************************** * * Intel PRO/Wireless 3945ABG/BG Network Connection * * RX handler implementations * - * Used by iwl-base.c - * *****************************************************************************/ void iwl3945_hw_rx_statistics(struct iwl3945_priv *priv, struct iwl3945_rx_mem_buffer *rxb) @@ -2510,6 +2622,7 @@ unsigned int iwl3945_hw_get_beacon_cmd(struct iwl3945_priv *priv, void iwl3945_hw_rx_handler_setup(struct iwl3945_priv *priv) { + priv->rx_handlers[REPLY_TX] = iwl3945_rx_reply_tx; priv->rx_handlers[REPLY_3945_RX] = iwl3945_rx_reply_rx; } diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 39fd5440a248..ecf749c2dc0a 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2063,34 +2063,6 @@ int iwl3945_is_network_packet(struct iwl3945_priv *priv, struct ieee80211_hdr *h return 1; } -#define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x - -static const char *iwl3945_get_tx_fail_reason(u32 status) -{ - switch (status & TX_STATUS_MSK) { - case TX_STATUS_SUCCESS: - return "SUCCESS"; - TX_STATUS_ENTRY(SHORT_LIMIT); - TX_STATUS_ENTRY(LONG_LIMIT); - TX_STATUS_ENTRY(FIFO_UNDERRUN); - TX_STATUS_ENTRY(MGMNT_ABORT); - TX_STATUS_ENTRY(NEXT_FRAG); - TX_STATUS_ENTRY(LIFE_EXPIRE); - TX_STATUS_ENTRY(DEST_PS); - TX_STATUS_ENTRY(ABORTED); - TX_STATUS_ENTRY(BT_RETRY); - TX_STATUS_ENTRY(STA_INVALID); - TX_STATUS_ENTRY(FRAG_DROPPED); - TX_STATUS_ENTRY(TID_DISABLE); - TX_STATUS_ENTRY(FRAME_FLUSHED); - TX_STATUS_ENTRY(INSUFFICIENT_CF_POLL); - TX_STATUS_ENTRY(TX_LOCKED); - TX_STATUS_ENTRY(NO_BEACON_ON_RADAR); - } - - return "UNKNOWN"; -} - /** * iwl3945_scan_cancel - Cancel any currently executing HW scan * @@ -3138,125 +3110,6 @@ static int iwl3945_get_measurement(struct iwl3945_priv *priv, } #endif -static void iwl3945_txstatus_to_ieee(struct iwl3945_priv *priv, - struct iwl3945_tx_info *tx_sta) -{ - - tx_sta->status.ack_signal = 0; - tx_sta->status.excessive_retries = 0; - tx_sta->status.queue_length = 0; - tx_sta->status.queue_number = 0; - - if (in_interrupt()) - ieee80211_tx_status_irqsafe(priv->hw, - tx_sta->skb[0], &(tx_sta->status)); - else - ieee80211_tx_status(priv->hw, - tx_sta->skb[0], &(tx_sta->status)); - - tx_sta->skb[0] = NULL; -} - -/** - * iwl3945_tx_queue_reclaim - Reclaim Tx queue entries already Tx'd - * - * When FW advances 'R' index, all entries between old and new 'R' index - * need to be reclaimed. As result, some free space forms. If there is - * enough free space (> low mark), wake the stack that feeds us. - */ -static int iwl3945_tx_queue_reclaim(struct iwl3945_priv *priv, int txq_id, int index) -{ - struct iwl3945_tx_queue *txq = &priv->txq[txq_id]; - struct iwl3945_queue *q = &txq->q; - int nfreed = 0; - - if ((index >= q->n_bd) || (iwl3945_x2_queue_used(q, index) == 0)) { - IWL_ERROR("Read index for DMA queue txq id (%d), index %d, " - "is out of range [0-%d] %d %d.\n", txq_id, - index, q->n_bd, q->write_ptr, q->read_ptr); - return 0; - } - - for (index = iwl_queue_inc_wrap(index, q->n_bd); - q->read_ptr != index; - q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { - if (txq_id != IWL_CMD_QUEUE_NUM) { - iwl3945_txstatus_to_ieee(priv, - &(txq->txb[txq->q.read_ptr])); - iwl3945_hw_txq_free_tfd(priv, txq); - } else if (nfreed > 1) { - IWL_ERROR("HCMD skipped: index (%d) %d %d\n", index, - q->write_ptr, q->read_ptr); - queue_work(priv->workqueue, &priv->restart); - } - nfreed++; - } - - if (iwl3945_queue_space(q) > q->low_mark && (txq_id >= 0) && - (txq_id != IWL_CMD_QUEUE_NUM) && - priv->mac80211_registered) - ieee80211_wake_queue(priv->hw, txq_id); - - - return nfreed; -} - -static int iwl3945_is_tx_success(u32 status) -{ - return (status & 0xFF) == 0x1; -} - -/****************************************************************************** - * - * Generic RX handler implementations - * - ******************************************************************************/ -/** - * iwl3945_rx_reply_tx - Handle Tx response - */ -static void iwl3945_rx_reply_tx(struct iwl3945_priv *priv, - struct iwl3945_rx_mem_buffer *rxb) -{ - struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data; - u16 sequence = le16_to_cpu(pkt->hdr.sequence); - int txq_id = SEQ_TO_QUEUE(sequence); - int index = SEQ_TO_INDEX(sequence); - struct iwl3945_tx_queue *txq = &priv->txq[txq_id]; - struct ieee80211_tx_status *tx_status; - struct iwl3945_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; - u32 status = le32_to_cpu(tx_resp->status); - - if ((index >= txq->q.n_bd) || (iwl3945_x2_queue_used(&txq->q, index) == 0)) { - IWL_ERROR("Read index for DMA queue txq_id (%d) index %d " - "is out of range [0-%d] %d %d\n", txq_id, - index, txq->q.n_bd, txq->q.write_ptr, - txq->q.read_ptr); - return; - } - - tx_status = &(txq->txb[txq->q.read_ptr].status); - - tx_status->retry_count = tx_resp->failure_frame; - tx_status->queue_number = status; - tx_status->queue_length = tx_resp->bt_kill_count; - tx_status->queue_length |= tx_resp->failure_rts; - - tx_status->flags = - iwl3945_is_tx_success(status) ? IEEE80211_TX_STATUS_ACK : 0; - - IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) plcp rate %d retries %d\n", - txq_id, iwl3945_get_tx_fail_reason(status), status, - tx_resp->rate, tx_resp->failure_frame); - - IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index); - if (index != -1) - iwl3945_tx_queue_reclaim(priv, txq_id, index); - - if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK)) - IWL_ERROR("TODO: Implement Tx ABORT REQUIRED!!!\n"); -} - - static void iwl3945_rx_reply_alive(struct iwl3945_priv *priv, struct iwl3945_rx_mem_buffer *rxb) { @@ -3603,12 +3456,43 @@ static void iwl3945_setup_rx_handlers(struct iwl3945_priv *priv) priv->rx_handlers[SCAN_COMPLETE_NOTIFICATION] = iwl3945_rx_scan_complete_notif; priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl3945_rx_card_state_notif; - priv->rx_handlers[REPLY_TX] = iwl3945_rx_reply_tx; /* Set up hardware specific Rx handlers */ iwl3945_hw_rx_handler_setup(priv); } +/** + * iwl3945_cmd_queue_reclaim - Reclaim CMD queue entries + * When FW advances 'R' index, all entries between old and new 'R' index + * need to be reclaimed. + */ +static void iwl3945_cmd_queue_reclaim(struct iwl3945_priv *priv, + int txq_id, int index) +{ + struct iwl3945_tx_queue *txq = &priv->txq[txq_id]; + struct iwl3945_queue *q = &txq->q; + int nfreed = 0; + + if ((index >= q->n_bd) || (iwl3945_x2_queue_used(q, index) == 0)) { + IWL_ERROR("Read index for DMA queue txq id (%d), index %d, " + "is out of range [0-%d] %d %d.\n", txq_id, + index, q->n_bd, q->write_ptr, q->read_ptr); + return; + } + + for (index = iwl_queue_inc_wrap(index, q->n_bd); q->read_ptr != index; + q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { + if (nfreed > 1) { + IWL_ERROR("HCMD skipped: index (%d) %d %d\n", index, + q->write_ptr, q->read_ptr); + queue_work(priv->workqueue, &priv->restart); + break; + } + nfreed++; + } +} + + /** * iwl3945_tx_cmd_complete - Pull unused buffers off the queue and reclaim them * @rxb: Rx buffer to reclaim @@ -3628,12 +3512,6 @@ static void iwl3945_tx_cmd_complete(struct iwl3945_priv *priv, int cmd_index; struct iwl3945_cmd *cmd; - /* If a Tx command is being handled and it isn't in the actual - * command queue then there a command routing bug has been introduced - * in the queue management code. */ - if (txq_id != IWL_CMD_QUEUE_NUM) - IWL_ERROR("Error wrong command queue %d command id 0x%X\n", - txq_id, pkt->hdr.cmd); BUG_ON(txq_id != IWL_CMD_QUEUE_NUM); cmd_index = get_cmd_index(&priv->txq[IWL_CMD_QUEUE_NUM].q, index, huge); @@ -3647,7 +3525,7 @@ static void iwl3945_tx_cmd_complete(struct iwl3945_priv *priv, !cmd->meta.u.callback(priv, cmd, rxb->skb)) rxb->skb = NULL; - iwl3945_tx_queue_reclaim(priv, txq_id, index); + iwl3945_cmd_queue_reclaim(priv, txq_id, index); if (!(cmd->meta.flags & CMD_ASYNC)) { clear_bit(STATUS_HCMD_ACTIVE, &priv->status); -- cgit v1.2.1 From b095d03a7d724db7379b73f64b6035f7be2e0a7c Mon Sep 17 00:00:00 2001 From: Ron Rindjunsky Date: Thu, 6 Mar 2008 17:36:56 -0800 Subject: iwlwifi: grab NIC access when disabling aggregations This patch grabs NIC access inside iwl4965_tx_queue_agg_disable, instead of the caller doing it. The caller must still hold priv->lock when calling the function. Signed-off-by: Max Stepanov Signed-off-by: Emmanuel Grumbach Signed-off-by: Ron Rindjunsky Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965.c | 37 ++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 17 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 3e122a931f2d..4a7167dbc217 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -4138,16 +4138,23 @@ static void iwl4965_tx_queue_stop_scheduler(struct iwl4965_priv *priv, /** * txq_id must be greater than IWL_BACK_QUEUE_FIRST_ID + * priv->lock must be held by the caller */ static int iwl4965_tx_queue_agg_disable(struct iwl4965_priv *priv, u16 txq_id, u16 ssn_idx, u8 tx_fifo) { + int ret = 0; + if (IWL_BACK_QUEUE_FIRST_ID > txq_id) { IWL_WARNING("queue number too small: %d, must be > %d\n", txq_id, IWL_BACK_QUEUE_FIRST_ID); return -EINVAL; } + ret = iwl4965_grab_nic_access(priv); + if (ret) + return ret; + iwl4965_tx_queue_stop_scheduler(priv, txq_id); iwl4965_clear_bits_prph(priv, KDR_SCD_QUEUECHAIN_SEL, (1 << txq_id)); @@ -4161,6 +4168,8 @@ static int iwl4965_tx_queue_agg_disable(struct iwl4965_priv *priv, u16 txq_id, iwl4965_txq_ctx_deactivate(priv, txq_id); iwl4965_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0); + iwl4965_release_nic_access(priv); + return 0; } @@ -4630,7 +4639,7 @@ static int iwl4965_mac_ht_tx_agg_start(struct ieee80211_hw *hw, const u8 *da, int tx_fifo; int txq_id; int ssn = -1; - int rc = 0; + int ret = 0; unsigned long flags; struct iwl4965_tid_data *tid_data; DECLARE_MAC_BUF(mac); @@ -4663,12 +4672,12 @@ static int iwl4965_mac_ht_tx_agg_start(struct ieee80211_hw *hw, const u8 *da, spin_unlock_irqrestore(&priv->sta_lock, flags); *start_seq_num = ssn; - rc = iwl4965_tx_queue_agg_enable(priv, txq_id, tx_fifo, - sta_id, tid, ssn); - if (rc) - return rc; + ret = iwl4965_tx_queue_agg_enable(priv, txq_id, tx_fifo, + sta_id, tid, ssn); + if (ret) + return ret; - rc = 0; + ret = 0; if (tid_data->tfds_in_queue == 0) { printk(KERN_ERR "HW queue is empty\n"); tid_data->agg.state = IWL_AGG_ON; @@ -4678,7 +4687,7 @@ static int iwl4965_mac_ht_tx_agg_start(struct ieee80211_hw *hw, const u8 *da, tid_data->tfds_in_queue); tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA; } - return rc; + return ret; } static int iwl4965_mac_ht_tx_agg_stop(struct ieee80211_hw *hw, const u8 *da, @@ -4688,7 +4697,7 @@ static int iwl4965_mac_ht_tx_agg_stop(struct ieee80211_hw *hw, const u8 *da, struct iwl4965_priv *priv = hw->priv; int tx_fifo_id, txq_id, sta_id, ssn = -1; struct iwl4965_tid_data *tid_data; - int rc, write_ptr, read_ptr; + int ret, write_ptr, read_ptr; unsigned long flags; DECLARE_MAC_BUF(mac); @@ -4728,17 +4737,11 @@ static int iwl4965_mac_ht_tx_agg_stop(struct ieee80211_hw *hw, const u8 *da, priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; spin_lock_irqsave(&priv->lock, flags); - rc = iwl4965_grab_nic_access(priv); - if (rc) { - spin_unlock_irqrestore(&priv->lock, flags); - return rc; - } - rc = iwl4965_tx_queue_agg_disable(priv, txq_id, ssn, tx_fifo_id); - iwl4965_release_nic_access(priv); + ret = iwl4965_tx_queue_agg_disable(priv, txq_id, ssn, tx_fifo_id); spin_unlock_irqrestore(&priv->lock, flags); - if (rc) - return rc; + if (ret) + return ret; ieee80211_stop_tx_ba_cb_irqsafe(priv->hw, da, tid); -- cgit v1.2.1 From 19fd6e5510f6991148e2210753b58f0eab95e0f6 Mon Sep 17 00:00:00 2001 From: Bruno Randolf Date: Wed, 5 Mar 2008 18:35:23 +0900 Subject: ath5k: struct ath5k_desc cleanups * make struct ath5k_desc clearer by directly including unions of structures, which correspond to the hardware descriptors of different HW versions (5210 and 5212). before they were casted at onto ath5k_desc at different points (e.g. ds_hw[2]). * rename some structures and variable names to make their use clearer, e.g. struct ath5k_hw_4w_tx_desc to ath5k_hw_4w_tx_ctl. * substitute "old" with "5210" and "new" with "5212" (eg. rename ath5k_hw_proc_new_rx_status() to ath5k_hw_proc_5212_rx_status()) because old and new are relative and we might have a newer structure at some point. * unify structs ath5k_hw_old_rx_status and ath5k_hw_new_rx_status into one ath5k_hw_rx_status, because they only differ in the flags and masks. drivers/net/wireless/ath5k/ath5k.h: Changes-licensed-under: ISC drivers/net/wireless/ath5k/debug.c: Changes-licensed-under: GPL drivers/net/wireless/ath5k/hw.c: Changes-licensed-under: ISC drivers/net/wireless/ath5k/hw.h: Changes-licensed-under: ISC Signed-off-by: Bruno Randolf Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/ath5k.h | 23 ++-- drivers/net/wireless/ath5k/debug.c | 12 ++- drivers/net/wireless/ath5k/hw.c | 212 ++++++++++++++++++------------------- drivers/net/wireless/ath5k/hw.h | 150 +++++++++++++++----------- 4 files changed, 210 insertions(+), 187 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath5k/ath5k.h b/drivers/net/wireless/ath5k/ath5k.h index 04efceef95a8..2af7982f6f0d 100644 --- a/drivers/net/wireless/ath5k/ath5k.h +++ b/drivers/net/wireless/ath5k/ath5k.h @@ -273,12 +273,13 @@ enum ath5k_driver_mode { #define SHPREAMBLE_FLAG(_ix) \ (HAS_SHPREAMBLE(_ix) ? AR5K_SET_SHORT_PREAMBLE : 0) + /****************\ TX DEFINITIONS \****************/ /* - * Tx Descriptor + * TX Status */ struct ath5k_tx_status { u16 ts_seqnum; @@ -426,7 +427,7 @@ enum ath5k_dmasize { \****************/ /* - * Rx Descriptor + * RX Status */ struct ath5k_rx_status { u16 rs_datalen; @@ -457,8 +458,6 @@ struct ath5k_mib_stats { }; - - /**************************\ BEACON TIMERS DEFINITIONS \**************************/ @@ -500,20 +499,22 @@ struct ath5k_beacon_state { #define TSF_TO_TU(_tsf) (u32)((_tsf) >> 10) - /********************\ COMMON DEFINITIONS \********************/ /* - * Atheros descriptor + * Atheros hardware descriptor */ struct ath5k_desc { - u32 ds_link; - u32 ds_data; - u32 ds_ctl0; - u32 ds_ctl1; - u32 ds_hw[4]; + u32 ds_link; /* physical address of the next descriptor */ + u32 ds_data; /* physical address of data buffer (skb) */ + + union { + struct ath5k_hw_5210_tx_desc ds_tx5210; + struct ath5k_hw_5212_tx_desc ds_tx5212; + struct ath5k_hw_all_rx_desc ds_rx; + } ud; union { struct ath5k_rx_status rx; diff --git a/drivers/net/wireless/ath5k/debug.c b/drivers/net/wireless/ath5k/debug.c index 05bf4fb8f907..93014944f43f 100644 --- a/drivers/net/wireless/ath5k/debug.c +++ b/drivers/net/wireless/ath5k/debug.c @@ -500,11 +500,13 @@ static inline void ath5k_debug_printrxbuf(struct ath5k_buf *bf, int done) { struct ath5k_desc *ds = bf->desc; + struct ath5k_hw_all_rx_desc *rd = &ds->ud.ds_rx; printk(KERN_DEBUG "R (%p %llx) %08x %08x %08x %08x %08x %08x %c\n", ds, (unsigned long long)bf->daddr, - ds->ds_link, ds->ds_data, ds->ds_ctl0, ds->ds_ctl1, - ds->ds_hw[0], ds->ds_hw[1], + ds->ds_link, ds->ds_data, + rd->rx_ctl.rx_control_0, rd->rx_ctl.rx_control_1, + rd->u.rx_stat.rx_status_0, rd->u.rx_stat.rx_status_0, !done ? ' ' : (ds->ds_rxstat.rs_status == 0) ? '*' : '!'); } @@ -554,14 +556,16 @@ ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf, int done) { struct ath5k_desc *ds = bf->desc; + struct ath5k_hw_5212_tx_desc *td = &ds->ud.ds_tx5212; if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET))) return; printk(KERN_DEBUG "T (%p %llx) %08x %08x %08x %08x %08x %08x %08x " "%08x %c\n", ds, (unsigned long long)bf->daddr, ds->ds_link, - ds->ds_data, ds->ds_ctl0, ds->ds_ctl1, - ds->ds_hw[0], ds->ds_hw[1], ds->ds_hw[2], ds->ds_hw[3], + ds->ds_data, td->tx_ctl.tx_control_0, td->tx_ctl.tx_control_1, + td->tx_ctl.tx_control_2, td->tx_ctl.tx_control_3, + td->tx_stat.tx_status_0, td->tx_stat.tx_status_1, !done ? ' ' : (ds->ds_txstat.ts_status == 0) ? '*' : '!'); } diff --git a/drivers/net/wireless/ath5k/hw.c b/drivers/net/wireless/ath5k/hw.c index 3c399604f30e..f88adf52a1b2 100644 --- a/drivers/net/wireless/ath5k/hw.c +++ b/drivers/net/wireless/ath5k/hw.c @@ -54,8 +54,8 @@ static int ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *, struct ath5k_desc *, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int); static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *, struct ath5k_desc *); -static int ath5k_hw_proc_new_rx_status(struct ath5k_hw *, struct ath5k_desc *); -static int ath5k_hw_proc_old_rx_status(struct ath5k_hw *, struct ath5k_desc *); +static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *, struct ath5k_desc *); +static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *, struct ath5k_desc *); static int ath5k_hw_get_capabilities(struct ath5k_hw *); static int ath5k_eeprom_init(struct ath5k_hw *); @@ -174,9 +174,9 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) } if (ah->ah_version == AR5K_AR5212) - ah->ah_proc_rx_desc = ath5k_hw_proc_new_rx_status; + ah->ah_proc_rx_desc = ath5k_hw_proc_5212_rx_status; else if (ah->ah_version <= AR5K_AR5211) - ah->ah_proc_rx_desc = ath5k_hw_proc_old_rx_status; + ah->ah_proc_rx_desc = ath5k_hw_proc_5210_rx_status; /* Bring device out of sleep and reset it's units */ ret = ath5k_hw_nic_wakeup(ah, AR5K_INIT_MODE, true); @@ -3522,10 +3522,10 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, unsigned int rtscts_rate, unsigned int rtscts_duration) { u32 frame_type; - struct ath5k_hw_2w_tx_desc *tx_desc; + struct ath5k_hw_2w_tx_ctl *tx_ctl; unsigned int frame_len; - tx_desc = (struct ath5k_hw_2w_tx_desc *)&desc->ds_ctl0; + tx_ctl = &desc->ud.ds_tx5210.tx_ctl; /* * Validate input @@ -3544,12 +3544,8 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, return -EINVAL; } - /* Clear status descriptor */ - memset(desc->ds_hw, 0, sizeof(struct ath5k_hw_tx_status)); - - /* Initialize control descriptor */ - tx_desc->tx_control_0 = 0; - tx_desc->tx_control_1 = 0; + /* Clear descriptor */ + memset(&desc->ud.ds_tx5210, 0, sizeof(struct ath5k_hw_5210_tx_desc)); /* Setup control descriptor */ @@ -3561,7 +3557,7 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, if (frame_len & ~AR5K_2W_TX_DESC_CTL0_FRAME_LEN) return -EINVAL; - tx_desc->tx_control_0 = frame_len & AR5K_2W_TX_DESC_CTL0_FRAME_LEN; + tx_ctl->tx_control_0 = frame_len & AR5K_2W_TX_DESC_CTL0_FRAME_LEN; /* Verify and set buffer length */ @@ -3572,7 +3568,7 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, if (pkt_len & ~AR5K_2W_TX_DESC_CTL1_BUF_LEN) return -EINVAL; - tx_desc->tx_control_1 = pkt_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN; + tx_ctl->tx_control_1 = pkt_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN; /* * Verify and set header length @@ -3581,7 +3577,7 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, if (ah->ah_version == AR5K_AR5210) { if (hdr_len & ~AR5K_2W_TX_DESC_CTL0_HEADER_LEN) return -EINVAL; - tx_desc->tx_control_0 |= + tx_ctl->tx_control_0 |= AR5K_REG_SM(hdr_len, AR5K_2W_TX_DESC_CTL0_HEADER_LEN); } @@ -3597,19 +3593,19 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, frame_type = type /*<< 2 ?*/; } - tx_desc->tx_control_0 |= + tx_ctl->tx_control_0 |= AR5K_REG_SM(frame_type, AR5K_2W_TX_DESC_CTL0_FRAME_TYPE) | AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE); } else { - tx_desc->tx_control_0 |= + tx_ctl->tx_control_0 |= AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE) | AR5K_REG_SM(antenna_mode, AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT); - tx_desc->tx_control_1 |= + tx_ctl->tx_control_1 |= AR5K_REG_SM(type, AR5K_2W_TX_DESC_CTL1_FRAME_TYPE); } #define _TX_FLAGS(_c, _flag) \ if (flags & AR5K_TXDESC_##_flag) \ - tx_desc->tx_control_##_c |= \ + tx_ctl->tx_control_##_c |= \ AR5K_2W_TX_DESC_CTL##_c##_##_flag _TX_FLAGS(0, CLRDMASK); @@ -3624,9 +3620,9 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, * WEP crap */ if (key_index != AR5K_TXKEYIX_INVALID) { - tx_desc->tx_control_0 |= + tx_ctl->tx_control_0 |= AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID; - tx_desc->tx_control_1 |= + tx_ctl->tx_control_1 |= AR5K_REG_SM(key_index, AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX); } @@ -3636,7 +3632,7 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, */ if ((ah->ah_version == AR5K_AR5210) && (flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA))) - tx_desc->tx_control_1 |= rtscts_duration & + tx_ctl->tx_control_1 |= rtscts_duration & AR5K_2W_TX_DESC_CTL1_RTS_DURATION; return 0; @@ -3652,13 +3648,11 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, unsigned int antenna_mode, unsigned int flags, unsigned int rtscts_rate, unsigned int rtscts_duration) { - struct ath5k_hw_4w_tx_desc *tx_desc; - struct ath5k_hw_tx_status *tx_status; + struct ath5k_hw_4w_tx_ctl *tx_ctl; unsigned int frame_len; ATH5K_TRACE(ah->ah_sc); - tx_desc = (struct ath5k_hw_4w_tx_desc *)&desc->ds_ctl0; - tx_status = (struct ath5k_hw_tx_status *)&desc->ds_hw[2]; + tx_ctl = &desc->ud.ds_tx5212.tx_ctl; /* * Validate input @@ -3677,14 +3671,8 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, return -EINVAL; } - /* Clear status descriptor */ - memset(tx_status, 0, sizeof(struct ath5k_hw_tx_status)); - - /* Initialize control descriptor */ - tx_desc->tx_control_0 = 0; - tx_desc->tx_control_1 = 0; - tx_desc->tx_control_2 = 0; - tx_desc->tx_control_3 = 0; + /* Clear descriptor */ + memset(&desc->ud.ds_tx5212, 0, sizeof(struct ath5k_hw_5212_tx_desc)); /* Setup control descriptor */ @@ -3696,7 +3684,7 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN) return -EINVAL; - tx_desc->tx_control_0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN; + tx_ctl->tx_control_0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN; /* Verify and set buffer length */ @@ -3707,20 +3695,20 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, if (pkt_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN) return -EINVAL; - tx_desc->tx_control_1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN; + tx_ctl->tx_control_1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN; - tx_desc->tx_control_0 |= + tx_ctl->tx_control_0 |= AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) | AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT); - tx_desc->tx_control_1 |= AR5K_REG_SM(type, + tx_ctl->tx_control_1 |= AR5K_REG_SM(type, AR5K_4W_TX_DESC_CTL1_FRAME_TYPE); - tx_desc->tx_control_2 = AR5K_REG_SM(tx_tries0 + AR5K_TUNE_HWTXTRIES, + tx_ctl->tx_control_2 = AR5K_REG_SM(tx_tries0 + AR5K_TUNE_HWTXTRIES, AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0); - tx_desc->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0; + tx_ctl->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0; #define _TX_FLAGS(_c, _flag) \ if (flags & AR5K_TXDESC_##_flag) \ - tx_desc->tx_control_##_c |= \ + tx_ctl->tx_control_##_c |= \ AR5K_4W_TX_DESC_CTL##_c##_##_flag _TX_FLAGS(0, CLRDMASK); @@ -3736,8 +3724,8 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, * WEP crap */ if (key_index != AR5K_TXKEYIX_INVALID) { - tx_desc->tx_control_0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID; - tx_desc->tx_control_1 |= AR5K_REG_SM(key_index, + tx_ctl->tx_control_0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID; + tx_ctl->tx_control_1 |= AR5K_REG_SM(key_index, AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX); } @@ -3748,9 +3736,9 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, if ((flags & AR5K_TXDESC_RTSENA) && (flags & AR5K_TXDESC_CTSENA)) return -EINVAL; - tx_desc->tx_control_2 |= rtscts_duration & + tx_ctl->tx_control_2 |= rtscts_duration & AR5K_4W_TX_DESC_CTL2_RTS_DURATION; - tx_desc->tx_control_3 |= AR5K_REG_SM(rtscts_rate, + tx_ctl->tx_control_3 |= AR5K_REG_SM(rtscts_rate, AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE); } @@ -3765,7 +3753,7 @@ ath5k_hw_setup_xr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2, u_int tx_tries2, unsigned int tx_rate3, u_int tx_tries3) { - struct ath5k_hw_4w_tx_desc *tx_desc; + struct ath5k_hw_4w_tx_ctl *tx_ctl; /* * Rates can be 0 as long as the retry count is 0 too. @@ -3782,14 +3770,14 @@ ath5k_hw_setup_xr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, } if (ah->ah_version == AR5K_AR5212) { - tx_desc = (struct ath5k_hw_4w_tx_desc *)&desc->ds_ctl0; + tx_ctl = &desc->ud.ds_tx5212.tx_ctl; #define _XTX_TRIES(_n) \ if (tx_tries##_n) { \ - tx_desc->tx_control_2 |= \ + tx_ctl->tx_control_2 |= \ AR5K_REG_SM(tx_tries##_n, \ AR5K_4W_TX_DESC_CTL2_XMIT_TRIES##_n); \ - tx_desc->tx_control_3 |= \ + tx_ctl->tx_control_3 |= \ AR5K_REG_SM(tx_rate##_n, \ AR5K_4W_TX_DESC_CTL3_XMIT_RATE##_n); \ } @@ -3812,11 +3800,13 @@ ath5k_hw_setup_xr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah, struct ath5k_desc *desc) { + struct ath5k_hw_2w_tx_ctl *tx_ctl; struct ath5k_hw_tx_status *tx_status; - struct ath5k_hw_2w_tx_desc *tx_desc; - tx_desc = (struct ath5k_hw_2w_tx_desc *)&desc->ds_ctl0; - tx_status = (struct ath5k_hw_tx_status *)&desc->ds_hw[0]; + ATH5K_TRACE(ah->ah_sc); + + tx_ctl = &desc->ud.ds_tx5210.tx_ctl; + tx_status = &desc->ud.ds_tx5210.tx_stat; /* No frame has been send or error */ if (unlikely((tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE) == 0)) @@ -3838,7 +3828,7 @@ static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah, AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH); desc->ds_us.tx.ts_antenna = 1; desc->ds_us.tx.ts_status = 0; - desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_desc->tx_control_0, + desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_ctl->tx_control_0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE); if ((tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK) == 0){ @@ -3862,12 +3852,13 @@ static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah, static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah, struct ath5k_desc *desc) { + struct ath5k_hw_4w_tx_ctl *tx_ctl; struct ath5k_hw_tx_status *tx_status; - struct ath5k_hw_4w_tx_desc *tx_desc; ATH5K_TRACE(ah->ah_sc); - tx_desc = (struct ath5k_hw_4w_tx_desc *)&desc->ds_ctl0; - tx_status = (struct ath5k_hw_tx_status *)&desc->ds_hw[2]; + + tx_ctl = &desc->ud.ds_tx5212.tx_ctl; + tx_status = &desc->ud.ds_tx5212.tx_stat; /* No frame has been send or error */ if (unlikely((tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE) == 0)) @@ -3893,25 +3884,25 @@ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah, switch (AR5K_REG_MS(tx_status->tx_status_1, AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX)) { case 0: - desc->ds_us.tx.ts_rate = tx_desc->tx_control_3 & + desc->ds_us.tx.ts_rate = tx_ctl->tx_control_3 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0; break; case 1: - desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_desc->tx_control_3, + desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3, AR5K_4W_TX_DESC_CTL3_XMIT_RATE1); - desc->ds_us.tx.ts_longretry +=AR5K_REG_MS(tx_desc->tx_control_2, + desc->ds_us.tx.ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2, AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1); break; case 2: - desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_desc->tx_control_3, + desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3, AR5K_4W_TX_DESC_CTL3_XMIT_RATE2); - desc->ds_us.tx.ts_longretry +=AR5K_REG_MS(tx_desc->tx_control_2, + desc->ds_us.tx.ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2, AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2); break; case 3: - desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_desc->tx_control_3, + desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3, AR5K_4W_TX_DESC_CTL3_XMIT_RATE3); - desc->ds_us.tx.ts_longretry +=AR5K_REG_MS(tx_desc->tx_control_2, + desc->ds_us.tx.ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2, AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3); break; } @@ -3941,31 +3932,27 @@ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah, int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, u32 size, unsigned int flags) { - struct ath5k_rx_desc *rx_desc; + struct ath5k_hw_rx_ctl *rx_ctl; ATH5K_TRACE(ah->ah_sc); - rx_desc = (struct ath5k_rx_desc *)&desc->ds_ctl0; + rx_ctl = &desc->ud.ds_rx.rx_ctl; /* - *Clear ds_hw + * Clear the descriptor * If we don't clean the status descriptor, * while scanning we get too many results, * most of them virtual, after some secs * of scanning system hangs. M.F. */ - memset(desc->ds_hw, 0, sizeof(desc->ds_hw)); - - /*Initialize rx descriptor*/ - rx_desc->rx_control_0 = 0; - rx_desc->rx_control_1 = 0; + memset(&desc->ud.ds_rx, 0, sizeof(struct ath5k_hw_all_rx_desc)); /* Setup descriptor */ - rx_desc->rx_control_1 = size & AR5K_DESC_RX_CTL1_BUF_LEN; - if (unlikely(rx_desc->rx_control_1 != size)) + rx_ctl->rx_control_1 = size & AR5K_DESC_RX_CTL1_BUF_LEN; + if (unlikely(rx_ctl->rx_control_1 != size)) return -EINVAL; if (flags & AR5K_RXDESC_INTREQ) - rx_desc->rx_control_1 |= AR5K_DESC_RX_CTL1_INTREQ; + rx_ctl->rx_control_1 |= AR5K_DESC_RX_CTL1_INTREQ; return 0; } @@ -3973,15 +3960,15 @@ int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, /* * Proccess the rx status descriptor on 5210/5211 */ -static int ath5k_hw_proc_old_rx_status(struct ath5k_hw *ah, +static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah, struct ath5k_desc *desc) { - struct ath5k_hw_old_rx_status *rx_status; + struct ath5k_hw_rx_status *rx_status; - rx_status = (struct ath5k_hw_old_rx_status *)&desc->ds_hw[0]; + rx_status = &desc->ud.ds_rx.u.rx_stat; /* No frame received / not ready */ - if (unlikely((rx_status->rx_status_1 & AR5K_OLD_RX_DESC_STATUS1_DONE) + if (unlikely((rx_status->rx_status_1 & AR5K_5210_RX_DESC_STATUS1_DONE) == 0)) return -EINPROGRESS; @@ -3989,50 +3976,51 @@ static int ath5k_hw_proc_old_rx_status(struct ath5k_hw *ah, * Frame receive status */ desc->ds_us.rx.rs_datalen = rx_status->rx_status_0 & - AR5K_OLD_RX_DESC_STATUS0_DATA_LEN; + AR5K_5210_RX_DESC_STATUS0_DATA_LEN; desc->ds_us.rx.rs_rssi = AR5K_REG_MS(rx_status->rx_status_0, - AR5K_OLD_RX_DESC_STATUS0_RECEIVE_SIGNAL); + AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL); desc->ds_us.rx.rs_rate = AR5K_REG_MS(rx_status->rx_status_0, - AR5K_OLD_RX_DESC_STATUS0_RECEIVE_RATE); + AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE); desc->ds_us.rx.rs_antenna = rx_status->rx_status_0 & - AR5K_OLD_RX_DESC_STATUS0_RECEIVE_ANTENNA; + AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA; desc->ds_us.rx.rs_more = rx_status->rx_status_0 & - AR5K_OLD_RX_DESC_STATUS0_MORE; + AR5K_5210_RX_DESC_STATUS0_MORE; desc->ds_us.rx.rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1, - AR5K_OLD_RX_DESC_STATUS1_RECEIVE_TIMESTAMP); + AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP); desc->ds_us.rx.rs_status = 0; /* * Key table status */ - if (rx_status->rx_status_1 & AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX_VALID) + if (rx_status->rx_status_1 & AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID) desc->ds_us.rx.rs_keyix = AR5K_REG_MS(rx_status->rx_status_1, - AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX); + AR5K_5210_RX_DESC_STATUS1_KEY_INDEX); else desc->ds_us.rx.rs_keyix = AR5K_RXKEYIX_INVALID; /* * Receive/descriptor errors */ - if ((rx_status->rx_status_1 & AR5K_OLD_RX_DESC_STATUS1_FRAME_RECEIVE_OK) - == 0) { - if (rx_status->rx_status_1 & AR5K_OLD_RX_DESC_STATUS1_CRC_ERROR) + if ((rx_status->rx_status_1 & + AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK) == 0) { + if (rx_status->rx_status_1 & + AR5K_5210_RX_DESC_STATUS1_CRC_ERROR) desc->ds_us.rx.rs_status |= AR5K_RXERR_CRC; if (rx_status->rx_status_1 & - AR5K_OLD_RX_DESC_STATUS1_FIFO_OVERRUN) + AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN) desc->ds_us.rx.rs_status |= AR5K_RXERR_FIFO; if (rx_status->rx_status_1 & - AR5K_OLD_RX_DESC_STATUS1_PHY_ERROR) { + AR5K_5210_RX_DESC_STATUS1_PHY_ERROR) { desc->ds_us.rx.rs_status |= AR5K_RXERR_PHY; desc->ds_us.rx.rs_phyerr = AR5K_REG_MS(rx_status->rx_status_1, - AR5K_OLD_RX_DESC_STATUS1_PHY_ERROR); + AR5K_5210_RX_DESC_STATUS1_PHY_ERROR); } if (rx_status->rx_status_1 & - AR5K_OLD_RX_DESC_STATUS1_DECRYPT_CRC_ERROR) + AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR) desc->ds_us.rx.rs_status |= AR5K_RXERR_DECRYPT; } @@ -4042,20 +4030,20 @@ static int ath5k_hw_proc_old_rx_status(struct ath5k_hw *ah, /* * Proccess the rx status descriptor on 5212 */ -static int ath5k_hw_proc_new_rx_status(struct ath5k_hw *ah, +static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, struct ath5k_desc *desc) { - struct ath5k_hw_new_rx_status *rx_status; + struct ath5k_hw_rx_status *rx_status; struct ath5k_hw_rx_error *rx_err; ATH5K_TRACE(ah->ah_sc); - rx_status = (struct ath5k_hw_new_rx_status *)&desc->ds_hw[0]; + rx_status = &desc->ud.ds_rx.u.rx_stat; /* Overlay on error */ - rx_err = (struct ath5k_hw_rx_error *)&desc->ds_hw[0]; + rx_err = &desc->ud.ds_rx.u.rx_err; /* No frame received / not ready */ - if (unlikely((rx_status->rx_status_1 & AR5K_NEW_RX_DESC_STATUS1_DONE) + if (unlikely((rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_DONE) == 0)) return -EINPROGRESS; @@ -4063,25 +4051,25 @@ static int ath5k_hw_proc_new_rx_status(struct ath5k_hw *ah, * Frame receive status */ desc->ds_us.rx.rs_datalen = rx_status->rx_status_0 & - AR5K_NEW_RX_DESC_STATUS0_DATA_LEN; + AR5K_5212_RX_DESC_STATUS0_DATA_LEN; desc->ds_us.rx.rs_rssi = AR5K_REG_MS(rx_status->rx_status_0, - AR5K_NEW_RX_DESC_STATUS0_RECEIVE_SIGNAL); + AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL); desc->ds_us.rx.rs_rate = AR5K_REG_MS(rx_status->rx_status_0, - AR5K_NEW_RX_DESC_STATUS0_RECEIVE_RATE); + AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE); desc->ds_us.rx.rs_antenna = rx_status->rx_status_0 & - AR5K_NEW_RX_DESC_STATUS0_RECEIVE_ANTENNA; + AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA; desc->ds_us.rx.rs_more = rx_status->rx_status_0 & - AR5K_NEW_RX_DESC_STATUS0_MORE; + AR5K_5212_RX_DESC_STATUS0_MORE; desc->ds_us.rx.rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1, - AR5K_NEW_RX_DESC_STATUS1_RECEIVE_TIMESTAMP); + AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP); desc->ds_us.rx.rs_status = 0; /* * Key table status */ - if (rx_status->rx_status_1 & AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX_VALID) + if (rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID) desc->ds_us.rx.rs_keyix = AR5K_REG_MS(rx_status->rx_status_1, - AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX); + AR5K_5212_RX_DESC_STATUS1_KEY_INDEX); else desc->ds_us.rx.rs_keyix = AR5K_RXKEYIX_INVALID; @@ -4089,12 +4077,13 @@ static int ath5k_hw_proc_new_rx_status(struct ath5k_hw *ah, * Receive/descriptor errors */ if ((rx_status->rx_status_1 & - AR5K_NEW_RX_DESC_STATUS1_FRAME_RECEIVE_OK) == 0) { - if (rx_status->rx_status_1 & AR5K_NEW_RX_DESC_STATUS1_CRC_ERROR) + AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK) == 0) { + if (rx_status->rx_status_1 & + AR5K_5212_RX_DESC_STATUS1_CRC_ERROR) desc->ds_us.rx.rs_status |= AR5K_RXERR_CRC; if (rx_status->rx_status_1 & - AR5K_NEW_RX_DESC_STATUS1_PHY_ERROR) { + AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) { desc->ds_us.rx.rs_status |= AR5K_RXERR_PHY; desc->ds_us.rx.rs_phyerr = AR5K_REG_MS(rx_err->rx_error_1, @@ -4102,10 +4091,11 @@ static int ath5k_hw_proc_new_rx_status(struct ath5k_hw *ah, } if (rx_status->rx_status_1 & - AR5K_NEW_RX_DESC_STATUS1_DECRYPT_CRC_ERROR) + AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR) desc->ds_us.rx.rs_status |= AR5K_RXERR_DECRYPT; - if (rx_status->rx_status_1 & AR5K_NEW_RX_DESC_STATUS1_MIC_ERROR) + if (rx_status->rx_status_1 & + AR5K_5212_RX_DESC_STATUS1_MIC_ERROR) desc->ds_us.rx.rs_status |= AR5K_RXERR_MIC; } diff --git a/drivers/net/wireless/ath5k/hw.h b/drivers/net/wireless/ath5k/hw.h index d9a7c0973f53..64fca8dcb386 100644 --- a/drivers/net/wireless/ath5k/hw.h +++ b/drivers/net/wireless/ath5k/hw.h @@ -173,7 +173,10 @@ struct ath5k_eeprom_info { * (rX: reserved fields possibily used by future versions of the ar5k chipset) */ -struct ath5k_rx_desc { +/* + * common hardware RX control descriptor + */ +struct ath5k_hw_rx_ctl { u32 rx_control_0; /* RX control word 0 */ #define AR5K_DESC_RX_CTL0 0x00000000 @@ -185,69 +188,63 @@ struct ath5k_rx_desc { } __packed; /* - * 5210/5211 rx status descriptor + * common hardware RX status descriptor + * 5210/11 and 5212 differ only in the flags defined below */ -struct ath5k_hw_old_rx_status { +struct ath5k_hw_rx_status { u32 rx_status_0; /* RX status word 0 */ - -#define AR5K_OLD_RX_DESC_STATUS0_DATA_LEN 0x00000fff -#define AR5K_OLD_RX_DESC_STATUS0_MORE 0x00001000 -#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_RATE 0x00078000 -#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_RATE_S 15 -#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_SIGNAL 0x07f80000 -#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 19 -#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_ANTENNA 0x38000000 -#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_ANTENNA_S 27 - u32 rx_status_1; /* RX status word 1 */ - -#define AR5K_OLD_RX_DESC_STATUS1_DONE 0x00000001 -#define AR5K_OLD_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002 -#define AR5K_OLD_RX_DESC_STATUS1_CRC_ERROR 0x00000004 -#define AR5K_OLD_RX_DESC_STATUS1_FIFO_OVERRUN 0x00000008 -#define AR5K_OLD_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000010 -#define AR5K_OLD_RX_DESC_STATUS1_PHY_ERROR 0x000000e0 -#define AR5K_OLD_RX_DESC_STATUS1_PHY_ERROR_S 5 -#define AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX_VALID 0x00000100 -#define AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX 0x00007e00 -#define AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX_S 9 -#define AR5K_OLD_RX_DESC_STATUS1_RECEIVE_TIMESTAMP 0x0fff8000 -#define AR5K_OLD_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S 15 -#define AR5K_OLD_RX_DESC_STATUS1_KEY_CACHE_MISS 0x10000000 } __packed; +/* 5210/5211 */ +#define AR5K_5210_RX_DESC_STATUS0_DATA_LEN 0x00000fff +#define AR5K_5210_RX_DESC_STATUS0_MORE 0x00001000 +#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE 0x00078000 +#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE_S 15 +#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL 0x07f80000 +#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 19 +#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA 0x38000000 +#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA_S 27 +#define AR5K_5210_RX_DESC_STATUS1_DONE 0x00000001 +#define AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002 +#define AR5K_5210_RX_DESC_STATUS1_CRC_ERROR 0x00000004 +#define AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN 0x00000008 +#define AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000010 +#define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR 0x000000e0 +#define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR_S 5 +#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID 0x00000100 +#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX 0x00007e00 +#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_S 9 +#define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP 0x0fff8000 +#define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S 15 +#define AR5K_5210_RX_DESC_STATUS1_KEY_CACHE_MISS 0x10000000 + +/* 5212 */ +#define AR5K_5212_RX_DESC_STATUS0_DATA_LEN 0x00000fff +#define AR5K_5212_RX_DESC_STATUS0_MORE 0x00001000 +#define AR5K_5212_RX_DESC_STATUS0_DECOMP_CRC_ERROR 0x00002000 +#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE 0x000f8000 +#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE_S 15 +#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL 0x0ff00000 +#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 20 +#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA 0xf0000000 +#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA_S 28 +#define AR5K_5212_RX_DESC_STATUS1_DONE 0x00000001 +#define AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002 +#define AR5K_5212_RX_DESC_STATUS1_CRC_ERROR 0x00000004 +#define AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000008 +#define AR5K_5212_RX_DESC_STATUS1_PHY_ERROR 0x00000010 +#define AR5K_5212_RX_DESC_STATUS1_MIC_ERROR 0x00000020 +#define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID 0x00000100 +#define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX 0x0000fe00 +#define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_S 9 +#define AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP 0x7fff0000 +#define AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S 16 +#define AR5K_5212_RX_DESC_STATUS1_KEY_CACHE_MISS 0x80000000 + /* - * 5212 rx status descriptor + * common hardware RX error descriptor */ -struct ath5k_hw_new_rx_status { - u32 rx_status_0; /* RX status word 0 */ - -#define AR5K_NEW_RX_DESC_STATUS0_DATA_LEN 0x00000fff -#define AR5K_NEW_RX_DESC_STATUS0_MORE 0x00001000 -#define AR5K_NEW_RX_DESC_STATUS0_DECOMP_CRC_ERROR 0x00002000 -#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_RATE 0x000f8000 -#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_RATE_S 15 -#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_SIGNAL 0x0ff00000 -#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 20 -#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_ANTENNA 0xf0000000 -#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_ANTENNA_S 28 - - u32 rx_status_1; /* RX status word 1 */ - -#define AR5K_NEW_RX_DESC_STATUS1_DONE 0x00000001 -#define AR5K_NEW_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002 -#define AR5K_NEW_RX_DESC_STATUS1_CRC_ERROR 0x00000004 -#define AR5K_NEW_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000008 -#define AR5K_NEW_RX_DESC_STATUS1_PHY_ERROR 0x00000010 -#define AR5K_NEW_RX_DESC_STATUS1_MIC_ERROR 0x00000020 -#define AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX_VALID 0x00000100 -#define AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX 0x0000fe00 -#define AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX_S 9 -#define AR5K_NEW_RX_DESC_STATUS1_RECEIVE_TIMESTAMP 0x7fff0000 -#define AR5K_NEW_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S 16 -#define AR5K_NEW_RX_DESC_STATUS1_KEY_CACHE_MISS 0x80000000 -} __packed; - struct ath5k_hw_rx_error { u32 rx_error_0; /* RX error word 0 */ @@ -268,7 +265,10 @@ struct ath5k_hw_rx_error { #define AR5K_DESC_RX_PHY_ERROR_SERVICE 0xc0 #define AR5K_DESC_RX_PHY_ERROR_TRANSMITOVR 0xe0 -struct ath5k_hw_2w_tx_desc { +/* + * 5210/5211 hardware 2-word TX control descriptor + */ +struct ath5k_hw_2w_tx_ctl { u32 tx_control_0; /* TX control word 0 */ #define AR5K_2W_TX_DESC_CTL0_FRAME_LEN 0x00000fff @@ -314,9 +314,9 @@ struct ath5k_hw_2w_tx_desc { #define AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS 0x10 /* - * 5212 4-word tx control descriptor + * 5212 hardware 4-word TX control descriptor */ -struct ath5k_hw_4w_tx_desc { +struct ath5k_hw_4w_tx_ctl { u32 tx_control_0; /* TX control word 0 */ #define AR5K_4W_TX_DESC_CTL0_FRAME_LEN 0x00000fff @@ -374,7 +374,7 @@ struct ath5k_hw_4w_tx_desc { } __packed; /* - * Common tx status descriptor + * Common TX status descriptor */ struct ath5k_hw_tx_status { u32 tx_status_0; /* TX status word 0 */ @@ -414,6 +414,34 @@ struct ath5k_hw_tx_status { } __packed; +/* + * 5210/5211 hardware TX descriptor + */ +struct ath5k_hw_5210_tx_desc { + struct ath5k_hw_2w_tx_ctl tx_ctl; + struct ath5k_hw_tx_status tx_stat; +} __packed; + +/* + * 5212 hardware TX descriptor + */ +struct ath5k_hw_5212_tx_desc { + struct ath5k_hw_4w_tx_ctl tx_ctl; + struct ath5k_hw_tx_status tx_stat; +} __packed; + +/* + * common hardware RX descriptor + */ +struct ath5k_hw_all_rx_desc { + struct ath5k_hw_rx_ctl rx_ctl; + union { + struct ath5k_hw_rx_status rx_stat; + struct ath5k_hw_rx_error rx_err; + } u; +} __packed; + + /* * AR5K REGISTER ACCESS */ -- cgit v1.2.1 From b47f407bef0d5349dacf65cd3560a976609d4b45 Mon Sep 17 00:00:00 2001 From: Bruno Randolf Date: Wed, 5 Mar 2008 18:35:45 +0900 Subject: ath5k: move rx and tx status structures out of hardware descriptor move ath5k_tx_status and ath5k_rx_status structures out of the hardware descriptor since they are not accessed by the hardware at all. they just contain converted information from the hardware descriptor. since they are only used in the rx and tx tasklets there is also no use to keep them for each descriptor. drivers/net/wireless/ath5k/ath5k.h: Changes-licensed-under: ISC drivers/net/wireless/ath5k/base.c: Changes-licensed-under: 3-Clause-BSD drivers/net/wireless/ath5k/debug.c: Changes-licensed-under: GPL drivers/net/wireless/ath5k/debug.h: Changes-licensed-under: GPL drivers/net/wireless/ath5k/hw.c: Changes-licensed-under: ISC Signed-off-by: Bruno Randolf Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/ath5k.h | 16 ++--- drivers/net/wireless/ath5k/base.c | 74 +++++++++---------- drivers/net/wireless/ath5k/debug.c | 19 +++-- drivers/net/wireless/ath5k/debug.h | 6 +- drivers/net/wireless/ath5k/hw.c | 141 +++++++++++++++++++------------------ 5 files changed, 126 insertions(+), 130 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath5k/ath5k.h b/drivers/net/wireless/ath5k/ath5k.h index 2af7982f6f0d..b21830771ea5 100644 --- a/drivers/net/wireless/ath5k/ath5k.h +++ b/drivers/net/wireless/ath5k/ath5k.h @@ -505,6 +505,7 @@ struct ath5k_beacon_state { /* * Atheros hardware descriptor + * This is read and written to by the hardware */ struct ath5k_desc { u32 ds_link; /* physical address of the next descriptor */ @@ -515,15 +516,6 @@ struct ath5k_desc { struct ath5k_hw_5212_tx_desc ds_tx5212; struct ath5k_hw_all_rx_desc ds_rx; } ud; - - union { - struct ath5k_rx_status rx; - struct ath5k_tx_status tx; - } ds_us; - -#define ds_rxstat ds_us.rx -#define ds_txstat ds_us.tx - } __packed; #define AR5K_RXDESC_INTREQ 0x0020 @@ -1043,8 +1035,10 @@ struct ath5k_hw { int (*ah_setup_xtx_desc)(struct ath5k_hw *, struct ath5k_desc *, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int); - int (*ah_proc_tx_desc)(struct ath5k_hw *, struct ath5k_desc *); - int (*ah_proc_rx_desc)(struct ath5k_hw *, struct ath5k_desc *); + int (*ah_proc_tx_desc)(struct ath5k_hw *, struct ath5k_desc *, + struct ath5k_tx_status *); + int (*ah_proc_rx_desc)(struct ath5k_hw *, struct ath5k_desc *, + struct ath5k_rx_status *); }; /* diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index fc4db8834c36..73e7e613a3c9 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -283,7 +283,8 @@ static int ath5k_rx_start(struct ath5k_softc *sc); static void ath5k_rx_stop(struct ath5k_softc *sc); static unsigned int ath5k_rx_decrypted(struct ath5k_softc *sc, struct ath5k_desc *ds, - struct sk_buff *skb); + struct sk_buff *skb, + struct ath5k_rx_status *rs); static void ath5k_tasklet_rx(unsigned long data); /* Tx handling */ static void ath5k_tx_processq(struct ath5k_softc *sc, @@ -1563,8 +1564,7 @@ ath5k_txq_drainq(struct ath5k_softc *sc, struct ath5k_txq *txq) */ spin_lock_bh(&txq->lock); list_for_each_entry_safe(bf, bf0, &txq->q, list) { - ath5k_debug_printtxbuf(sc, bf, !sc->ah->ah_proc_tx_desc(sc->ah, - bf->desc)); + ath5k_debug_printtxbuf(sc, bf); ath5k_txbuf_free(sc, bf); @@ -1689,20 +1689,20 @@ ath5k_rx_stop(struct ath5k_softc *sc) static unsigned int ath5k_rx_decrypted(struct ath5k_softc *sc, struct ath5k_desc *ds, - struct sk_buff *skb) + struct sk_buff *skb, struct ath5k_rx_status *rs) { struct ieee80211_hdr *hdr = (void *)skb->data; unsigned int keyix, hlen = ieee80211_get_hdrlen_from_skb(skb); - if (!(ds->ds_rxstat.rs_status & AR5K_RXERR_DECRYPT) && - ds->ds_rxstat.rs_keyix != AR5K_RXKEYIX_INVALID) + if (!(rs->rs_status & AR5K_RXERR_DECRYPT) && + rs->rs_keyix != AR5K_RXKEYIX_INVALID) return RX_FLAG_DECRYPTED; /* Apparently when a default key is used to decrypt the packet the hw does not set the index used to decrypt. In such cases get the index from the packet. */ if ((le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_PROTECTED) && - !(ds->ds_rxstat.rs_status & AR5K_RXERR_DECRYPT) && + !(rs->rs_status & AR5K_RXERR_DECRYPT) && skb->len >= hlen + 4) { keyix = skb->data[hlen + 3] >> 6; @@ -1745,12 +1745,11 @@ static void ath5k_tasklet_rx(unsigned long data) { struct ieee80211_rx_status rxs = {}; + struct ath5k_rx_status rs = {}; struct sk_buff *skb; struct ath5k_softc *sc = (void *)data; struct ath5k_buf *bf; struct ath5k_desc *ds; - u16 len; - u8 stat; int ret; int hdrlen; int pad; @@ -1773,7 +1772,7 @@ ath5k_tasklet_rx(unsigned long data) if (unlikely(ds->ds_link == bf->daddr)) /* this is the end */ break; - ret = sc->ah->ah_proc_rx_desc(sc->ah, ds); + ret = sc->ah->ah_proc_rx_desc(sc->ah, ds, &rs); if (unlikely(ret == -EINPROGRESS)) break; else if (unlikely(ret)) { @@ -1782,16 +1781,15 @@ ath5k_tasklet_rx(unsigned long data) return; } - if (unlikely(ds->ds_rxstat.rs_more)) { + if (unlikely(rs.rs_more)) { ATH5K_WARN(sc, "unsupported jumbo\n"); goto next; } - stat = ds->ds_rxstat.rs_status; - if (unlikely(stat)) { - if (stat & AR5K_RXERR_PHY) + if (unlikely(rs.rs_status)) { + if (rs.rs_status & AR5K_RXERR_PHY) goto next; - if (stat & AR5K_RXERR_DECRYPT) { + if (rs.rs_status & AR5K_RXERR_DECRYPT) { /* * Decrypt error. If the error occurred * because there was no hardware key, then @@ -1802,30 +1800,29 @@ ath5k_tasklet_rx(unsigned long data) * * XXX do key cache faulting */ - if (ds->ds_rxstat.rs_keyix == - AR5K_RXKEYIX_INVALID && - !(stat & AR5K_RXERR_CRC)) + if (rs.rs_keyix == AR5K_RXKEYIX_INVALID && + !(rs.rs_status & AR5K_RXERR_CRC)) goto accept; } - if (stat & AR5K_RXERR_MIC) { + if (rs.rs_status & AR5K_RXERR_MIC) { rxs.flag |= RX_FLAG_MMIC_ERROR; goto accept; } /* let crypto-error packets fall through in MNTR */ - if ((stat & ~(AR5K_RXERR_DECRYPT|AR5K_RXERR_MIC)) || + if ((rs.rs_status & + ~(AR5K_RXERR_DECRYPT|AR5K_RXERR_MIC)) || sc->opmode != IEEE80211_IF_TYPE_MNTR) goto next; } accept: - len = ds->ds_rxstat.rs_datalen; - pci_dma_sync_single_for_cpu(sc->pdev, bf->skbaddr, len, - PCI_DMA_FROMDEVICE); + pci_dma_sync_single_for_cpu(sc->pdev, bf->skbaddr, + rs.rs_datalen, PCI_DMA_FROMDEVICE); pci_unmap_single(sc->pdev, bf->skbaddr, sc->rxbufsize, PCI_DMA_FROMDEVICE); bf->skb = NULL; - skb_put(skb, len); + skb_put(skb, rs.rs_datalen); /* * the hardware adds a padding to 4 byte boundaries between @@ -1848,7 +1845,7 @@ accept: * 32768usec (about 32ms). it might be necessary to move this to * the interrupt handler, like it is done in madwifi. */ - rxs.mactime = ath5k_extend_tsf(sc->ah, ds->ds_rxstat.rs_tstamp); + rxs.mactime = ath5k_extend_tsf(sc->ah, rs.rs_tstamp); rxs.flag |= RX_FLAG_TSFT; rxs.freq = sc->curchan->center_freq; @@ -1862,17 +1859,16 @@ accept: /* noise floor in dBm, from the last noise calibration */ rxs.noise = sc->ah->ah_noise_floor; /* signal level in dBm */ - rxs.ssi = rxs.noise + ds->ds_rxstat.rs_rssi; + rxs.ssi = rxs.noise + rs.rs_rssi; /* * "signal" is actually displayed as Link Quality by iwconfig * we provide a percentage based on rssi (assuming max rssi 64) */ - rxs.signal = ds->ds_rxstat.rs_rssi * 100 / 64; + rxs.signal = rs.rs_rssi * 100 / 64; - rxs.antenna = ds->ds_rxstat.rs_antenna; - rxs.rate_idx = ath5k_hw_to_driver_rix(sc, - ds->ds_rxstat.rs_rate); - rxs.flag |= ath5k_rx_decrypted(sc, ds, skb); + rxs.antenna = rs.rs_antenna; + rxs.rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate); + rxs.flag |= ath5k_rx_decrypted(sc, ds, skb, &rs); ath5k_debug_dump_skb(sc, skb, "RX ", 0); @@ -1881,7 +1877,7 @@ accept: ath5k_check_ibss_hw_merge(sc, skb); __ieee80211_rx(sc->hw, skb, &rxs); - sc->led_rxrate = ds->ds_rxstat.rs_rate; + sc->led_rxrate = rs.rs_rate; ath5k_led_event(sc, ATH_LED_RX); next: list_move_tail(&bf->list, &sc->rxbuf); @@ -1900,6 +1896,7 @@ static void ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) { struct ieee80211_tx_status txs = {}; + struct ath5k_tx_status ts = {}; struct ath5k_buf *bf, *bf0; struct ath5k_desc *ds; struct sk_buff *skb; @@ -1912,7 +1909,7 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) /* TODO only one segment */ pci_dma_sync_single_for_cpu(sc->pdev, sc->desc_daddr, sc->desc_len, PCI_DMA_FROMDEVICE); - ret = sc->ah->ah_proc_tx_desc(sc->ah, ds); + ret = sc->ah->ah_proc_tx_desc(sc->ah, ds, &ts); if (unlikely(ret == -EINPROGRESS)) break; else if (unlikely(ret)) { @@ -1927,17 +1924,16 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) PCI_DMA_TODEVICE); txs.control = bf->ctl; - txs.retry_count = ds->ds_txstat.ts_shortretry + - ds->ds_txstat.ts_longretry / 6; - if (unlikely(ds->ds_txstat.ts_status)) { + txs.retry_count = ts.ts_shortretry + ts.ts_longretry / 6; + if (unlikely(ts.ts_status)) { sc->ll_stats.dot11ACKFailureCount++; - if (ds->ds_txstat.ts_status & AR5K_TXERR_XRETRY) + if (ts.ts_status & AR5K_TXERR_XRETRY) txs.excessive_retries = 1; - else if (ds->ds_txstat.ts_status & AR5K_TXERR_FILT) + else if (ts.ts_status & AR5K_TXERR_FILT) txs.flags |= IEEE80211_TX_STATUS_TX_FILTERED; } else { txs.flags |= IEEE80211_TX_STATUS_ACK; - txs.ack_signal = ds->ds_txstat.ts_rssi; + txs.ack_signal = ts.ts_rssi; } ieee80211_tx_status(sc->hw, skb, &txs); diff --git a/drivers/net/wireless/ath5k/debug.c b/drivers/net/wireless/ath5k/debug.c index 93014944f43f..d3eb9e88c84d 100644 --- a/drivers/net/wireless/ath5k/debug.c +++ b/drivers/net/wireless/ath5k/debug.c @@ -497,7 +497,8 @@ ath5k_debug_dump_bands(struct ath5k_softc *sc) } static inline void -ath5k_debug_printrxbuf(struct ath5k_buf *bf, int done) +ath5k_debug_printrxbuf(struct ath5k_buf *bf, int done, + struct ath5k_rx_status *rs) { struct ath5k_desc *ds = bf->desc; struct ath5k_hw_all_rx_desc *rd = &ds->ud.ds_rx; @@ -507,7 +508,7 @@ ath5k_debug_printrxbuf(struct ath5k_buf *bf, int done) ds->ds_link, ds->ds_data, rd->rx_ctl.rx_control_0, rd->rx_ctl.rx_control_1, rd->u.rx_stat.rx_status_0, rd->u.rx_stat.rx_status_0, - !done ? ' ' : (ds->ds_rxstat.rs_status == 0) ? '*' : '!'); + !done ? ' ' : (rs->rs_status == 0) ? '*' : '!'); } void @@ -515,6 +516,7 @@ ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) { struct ath5k_desc *ds; struct ath5k_buf *bf; + struct ath5k_rx_status rs = {}; int status; if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET))) @@ -526,9 +528,9 @@ ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) spin_lock_bh(&sc->rxbuflock); list_for_each_entry(bf, &sc->rxbuf, list) { ds = bf->desc; - status = ah->ah_proc_rx_desc(ah, ds); + status = ah->ah_proc_rx_desc(ah, ds, &rs); if (!status) - ath5k_debug_printrxbuf(bf, status == 0); + ath5k_debug_printrxbuf(bf, status == 0, &rs); } spin_unlock_bh(&sc->rxbuflock); } @@ -552,21 +554,24 @@ ath5k_debug_dump_skb(struct ath5k_softc *sc, } void -ath5k_debug_printtxbuf(struct ath5k_softc *sc, - struct ath5k_buf *bf, int done) +ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf) { struct ath5k_desc *ds = bf->desc; struct ath5k_hw_5212_tx_desc *td = &ds->ud.ds_tx5212; + struct ath5k_tx_status ts = {}; + int done; if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET))) return; + done = sc->ah->ah_proc_tx_desc(sc->ah, bf->desc, &ts); + printk(KERN_DEBUG "T (%p %llx) %08x %08x %08x %08x %08x %08x %08x " "%08x %c\n", ds, (unsigned long long)bf->daddr, ds->ds_link, ds->ds_data, td->tx_ctl.tx_control_0, td->tx_ctl.tx_control_1, td->tx_ctl.tx_control_2, td->tx_ctl.tx_control_3, td->tx_stat.tx_status_0, td->tx_stat.tx_status_1, - !done ? ' ' : (ds->ds_txstat.ts_status == 0) ? '*' : '!'); + done ? ' ' : (ts.ts_status == 0) ? '*' : '!'); } #endif /* ifdef CONFIG_ATH5K_DEBUG */ diff --git a/drivers/net/wireless/ath5k/debug.h b/drivers/net/wireless/ath5k/debug.h index 8c0b5c57c76b..2cf8d18b10e3 100644 --- a/drivers/net/wireless/ath5k/debug.h +++ b/drivers/net/wireless/ath5k/debug.h @@ -160,8 +160,7 @@ ath5k_debug_dump_skb(struct ath5k_softc *sc, struct sk_buff *skb, const char *prefix, int tx); void -ath5k_debug_printtxbuf(struct ath5k_softc *sc, - struct ath5k_buf *bf, int done); +ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf); #else /* no debugging */ @@ -199,8 +198,7 @@ ath5k_debug_dump_skb(struct ath5k_softc *sc, struct sk_buff *skb, const char *prefix, int tx) {} static inline void -ath5k_debug_printtxbuf(struct ath5k_softc *sc, - struct ath5k_buf *bf, int done) {} +ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf) {} #endif /* ifdef CONFIG_ATH5K_DEBUG */ diff --git a/drivers/net/wireless/ath5k/hw.c b/drivers/net/wireless/ath5k/hw.c index f88adf52a1b2..a4e312d4226e 100644 --- a/drivers/net/wireless/ath5k/hw.c +++ b/drivers/net/wireless/ath5k/hw.c @@ -48,14 +48,18 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *, struct ath5k_desc *, static int ath5k_hw_setup_xr_tx_desc(struct ath5k_hw *, struct ath5k_desc *, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int); -static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *, struct ath5k_desc *); +static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *, struct ath5k_desc *, + struct ath5k_tx_status *); static int ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *, struct ath5k_desc *, unsigned int, unsigned int, enum ath5k_pkt_type, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int); -static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *, struct ath5k_desc *); -static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *, struct ath5k_desc *); -static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *, struct ath5k_desc *); +static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *, struct ath5k_desc *, + struct ath5k_tx_status *); +static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *, struct ath5k_desc *, + struct ath5k_rx_status *); +static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *, struct ath5k_desc *, + struct ath5k_rx_status *); static int ath5k_hw_get_capabilities(struct ath5k_hw *); static int ath5k_eeprom_init(struct ath5k_hw *); @@ -3798,7 +3802,7 @@ ath5k_hw_setup_xr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, * Proccess the tx status descriptor on 5210/5211 */ static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah, - struct ath5k_desc *desc) + struct ath5k_desc *desc, struct ath5k_tx_status *ts) { struct ath5k_hw_2w_tx_ctl *tx_ctl; struct ath5k_hw_tx_status *tx_status; @@ -3815,32 +3819,32 @@ static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah, /* * Get descriptor status */ - desc->ds_us.tx.ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0, + ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0, AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP); - desc->ds_us.tx.ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0, + ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0, AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT); - desc->ds_us.tx.ts_longretry = AR5K_REG_MS(tx_status->tx_status_0, + ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0, AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT); - /*TODO: desc->ds_us.tx.ts_virtcol + test*/ - desc->ds_us.tx.ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1, + /*TODO: ts->ts_virtcol + test*/ + ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1, AR5K_DESC_TX_STATUS1_SEQ_NUM); - desc->ds_us.tx.ts_rssi = AR5K_REG_MS(tx_status->tx_status_1, + ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1, AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH); - desc->ds_us.tx.ts_antenna = 1; - desc->ds_us.tx.ts_status = 0; - desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_ctl->tx_control_0, + ts->ts_antenna = 1; + ts->ts_status = 0; + ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE); if ((tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK) == 0){ if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES) - desc->ds_us.tx.ts_status |= AR5K_TXERR_XRETRY; + ts->ts_status |= AR5K_TXERR_XRETRY; if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN) - desc->ds_us.tx.ts_status |= AR5K_TXERR_FIFO; + ts->ts_status |= AR5K_TXERR_FIFO; if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED) - desc->ds_us.tx.ts_status |= AR5K_TXERR_FILT; + ts->ts_status |= AR5K_TXERR_FILT; } return 0; @@ -3850,7 +3854,7 @@ static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah, * Proccess a tx descriptor on 5212 */ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah, - struct ath5k_desc *desc) + struct ath5k_desc *desc, struct ath5k_tx_status *ts) { struct ath5k_hw_4w_tx_ctl *tx_ctl; struct ath5k_hw_tx_status *tx_status; @@ -3867,42 +3871,42 @@ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah, /* * Get descriptor status */ - desc->ds_us.tx.ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0, + ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0, AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP); - desc->ds_us.tx.ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0, + ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0, AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT); - desc->ds_us.tx.ts_longretry = AR5K_REG_MS(tx_status->tx_status_0, + ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0, AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT); - desc->ds_us.tx.ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1, + ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1, AR5K_DESC_TX_STATUS1_SEQ_NUM); - desc->ds_us.tx.ts_rssi = AR5K_REG_MS(tx_status->tx_status_1, + ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1, AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH); - desc->ds_us.tx.ts_antenna = (tx_status->tx_status_1 & + ts->ts_antenna = (tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_XMIT_ANTENNA) ? 2 : 1; - desc->ds_us.tx.ts_status = 0; + ts->ts_status = 0; switch (AR5K_REG_MS(tx_status->tx_status_1, AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX)) { case 0: - desc->ds_us.tx.ts_rate = tx_ctl->tx_control_3 & + ts->ts_rate = tx_ctl->tx_control_3 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0; break; case 1: - desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3, + ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3, AR5K_4W_TX_DESC_CTL3_XMIT_RATE1); - desc->ds_us.tx.ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2, + ts->ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2, AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1); break; case 2: - desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3, + ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3, AR5K_4W_TX_DESC_CTL3_XMIT_RATE2); - desc->ds_us.tx.ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2, + ts->ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2, AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2); break; case 3: - desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3, + ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3, AR5K_4W_TX_DESC_CTL3_XMIT_RATE3); - desc->ds_us.tx.ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2, + ts->ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2, AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3); break; } @@ -3910,13 +3914,13 @@ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah, if ((tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK) == 0){ if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES) - desc->ds_us.tx.ts_status |= AR5K_TXERR_XRETRY; + ts->ts_status |= AR5K_TXERR_XRETRY; if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN) - desc->ds_us.tx.ts_status |= AR5K_TXERR_FIFO; + ts->ts_status |= AR5K_TXERR_FIFO; if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED) - desc->ds_us.tx.ts_status |= AR5K_TXERR_FILT; + ts->ts_status |= AR5K_TXERR_FILT; } return 0; @@ -3961,7 +3965,7 @@ int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, * Proccess the rx status descriptor on 5210/5211 */ static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah, - struct ath5k_desc *desc) + struct ath5k_desc *desc, struct ath5k_rx_status *rs) { struct ath5k_hw_rx_status *rx_status; @@ -3975,28 +3979,29 @@ static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah, /* * Frame receive status */ - desc->ds_us.rx.rs_datalen = rx_status->rx_status_0 & + rs->rs_datalen = rx_status->rx_status_0 & AR5K_5210_RX_DESC_STATUS0_DATA_LEN; - desc->ds_us.rx.rs_rssi = AR5K_REG_MS(rx_status->rx_status_0, + rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0, AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL); - desc->ds_us.rx.rs_rate = AR5K_REG_MS(rx_status->rx_status_0, + rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0, AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE); - desc->ds_us.rx.rs_antenna = rx_status->rx_status_0 & + rs->rs_antenna = rx_status->rx_status_0 & AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA; - desc->ds_us.rx.rs_more = rx_status->rx_status_0 & + rs->rs_more = rx_status->rx_status_0 & AR5K_5210_RX_DESC_STATUS0_MORE; - desc->ds_us.rx.rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1, + /* TODO: this timestamp is 13 bit, later on we assume 15 bit */ + rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1, AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP); - desc->ds_us.rx.rs_status = 0; + rs->rs_status = 0; /* * Key table status */ if (rx_status->rx_status_1 & AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID) - desc->ds_us.rx.rs_keyix = AR5K_REG_MS(rx_status->rx_status_1, + rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1, AR5K_5210_RX_DESC_STATUS1_KEY_INDEX); else - desc->ds_us.rx.rs_keyix = AR5K_RXKEYIX_INVALID; + rs->rs_keyix = AR5K_RXKEYIX_INVALID; /* * Receive/descriptor errors @@ -4005,23 +4010,22 @@ static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah, AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK) == 0) { if (rx_status->rx_status_1 & AR5K_5210_RX_DESC_STATUS1_CRC_ERROR) - desc->ds_us.rx.rs_status |= AR5K_RXERR_CRC; + rs->rs_status |= AR5K_RXERR_CRC; if (rx_status->rx_status_1 & AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN) - desc->ds_us.rx.rs_status |= AR5K_RXERR_FIFO; + rs->rs_status |= AR5K_RXERR_FIFO; if (rx_status->rx_status_1 & AR5K_5210_RX_DESC_STATUS1_PHY_ERROR) { - desc->ds_us.rx.rs_status |= AR5K_RXERR_PHY; - desc->ds_us.rx.rs_phyerr = - AR5K_REG_MS(rx_status->rx_status_1, - AR5K_5210_RX_DESC_STATUS1_PHY_ERROR); + rs->rs_status |= AR5K_RXERR_PHY; + rs->rs_phyerr = AR5K_REG_MS(rx_status->rx_status_1, + AR5K_5210_RX_DESC_STATUS1_PHY_ERROR); } if (rx_status->rx_status_1 & AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR) - desc->ds_us.rx.rs_status |= AR5K_RXERR_DECRYPT; + rs->rs_status |= AR5K_RXERR_DECRYPT; } return 0; @@ -4031,7 +4035,7 @@ static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah, * Proccess the rx status descriptor on 5212 */ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, - struct ath5k_desc *desc) + struct ath5k_desc *desc, struct ath5k_rx_status *rs) { struct ath5k_hw_rx_status *rx_status; struct ath5k_hw_rx_error *rx_err; @@ -4050,28 +4054,28 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, /* * Frame receive status */ - desc->ds_us.rx.rs_datalen = rx_status->rx_status_0 & + rs->rs_datalen = rx_status->rx_status_0 & AR5K_5212_RX_DESC_STATUS0_DATA_LEN; - desc->ds_us.rx.rs_rssi = AR5K_REG_MS(rx_status->rx_status_0, + rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0, AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL); - desc->ds_us.rx.rs_rate = AR5K_REG_MS(rx_status->rx_status_0, + rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0, AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE); - desc->ds_us.rx.rs_antenna = rx_status->rx_status_0 & + rs->rs_antenna = rx_status->rx_status_0 & AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA; - desc->ds_us.rx.rs_more = rx_status->rx_status_0 & + rs->rs_more = rx_status->rx_status_0 & AR5K_5212_RX_DESC_STATUS0_MORE; - desc->ds_us.rx.rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1, + rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1, AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP); - desc->ds_us.rx.rs_status = 0; + rs->rs_status = 0; /* * Key table status */ if (rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID) - desc->ds_us.rx.rs_keyix = AR5K_REG_MS(rx_status->rx_status_1, + rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1, AR5K_5212_RX_DESC_STATUS1_KEY_INDEX); else - desc->ds_us.rx.rs_keyix = AR5K_RXKEYIX_INVALID; + rs->rs_keyix = AR5K_RXKEYIX_INVALID; /* * Receive/descriptor errors @@ -4080,23 +4084,22 @@ static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK) == 0) { if (rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_CRC_ERROR) - desc->ds_us.rx.rs_status |= AR5K_RXERR_CRC; + rs->rs_status |= AR5K_RXERR_CRC; if (rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) { - desc->ds_us.rx.rs_status |= AR5K_RXERR_PHY; - desc->ds_us.rx.rs_phyerr = - AR5K_REG_MS(rx_err->rx_error_1, - AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE); + rs->rs_status |= AR5K_RXERR_PHY; + rs->rs_phyerr = AR5K_REG_MS(rx_err->rx_error_1, + AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE); } if (rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR) - desc->ds_us.rx.rs_status |= AR5K_RXERR_DECRYPT; + rs->rs_status |= AR5K_RXERR_DECRYPT; if (rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_MIC_ERROR) - desc->ds_us.rx.rs_status |= AR5K_RXERR_MIC; + rs->rs_status |= AR5K_RXERR_MIC; } return 0; -- cgit v1.2.1 From e14296cabac60806606b4ebc1a83ee4697876346 Mon Sep 17 00:00:00 2001 From: Bruno Randolf Date: Wed, 5 Mar 2008 18:36:05 +0900 Subject: ath5k: add notes about rx timestamp add comments about the fact that we don't know when exactly the atheros hardware takes the RX timestamp. drivers/net/wireless/ath5k/base.c: Changes-licensed-under: 3-Clause-BSD Signed-off-by: Bruno Randolf Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/base.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index 73e7e613a3c9..5eacc7cdd9e3 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -1844,6 +1844,17 @@ accept: * 15bit only. that means TSF extension has to be done within * 32768usec (about 32ms). it might be necessary to move this to * the interrupt handler, like it is done in madwifi. + * + * Unfortunately we don't know when the hardware takes the rx + * timestamp (beginning of phy frame, data frame, end of rx?). + * The only thing we know is that it is hardware specific... + * On AR5213 it seems the rx timestamp is at the end of the + * frame, but i'm not sure. + * + * NOTE: mac80211 defines mactime at the beginning of the first + * data symbol. Since we don't have any time references it's + * impossible to comply to that. This affects IBSS merge only + * right now, so it's not too bad... */ rxs.mactime = ath5k_extend_tsf(sc->ah, rs.rs_tstamp); rxs.flag |= RX_FLAG_TSFT; -- cgit v1.2.1 From 6ba81c2c989291c5893014f84805ce9d196778b0 Mon Sep 17 00:00:00 2001 From: Bruno Randolf Date: Wed, 5 Mar 2008 18:36:26 +0900 Subject: ath5k: work around wrong beacon rx timestamp in IBSS mode atheros hardware has a problem with the rx timestamp of some IBSS beacons when they caused a TSF update (they have the same BSSID). the rx timestamp is wrong especially if the beacon frames get bigger than 78 byte (at least on AR5213 and AR5414 hardware). in that case ath5k_extend_tsf() will assume a rs_tstamp overflow and give us a timestamp too far in the past which will cause mac80211 to merge IBSS on every beacon (which is not necessary since the BSSID already matches). but in this case we know that the HW must have synced to the beacons TSF and the rx timestamp must be later than that so we can adjust mactime accordingly. also rename the function to ath5k_check_ibss_tsf() and change comments, since "hw merge" is better described as a TSF update. drivers/net/wireless/ath5k/base.c: Changes-licensed-under: 3-Clause-BSD Signed-off-by: Bruno Randolf Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/base.c | 59 +++++++++++++++++++++++++++++---------- 1 file changed, 45 insertions(+), 14 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index 5eacc7cdd9e3..b5c0a0d7a81c 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -1715,8 +1715,10 @@ ath5k_rx_decrypted(struct ath5k_softc *sc, struct ath5k_desc *ds, static void -ath5k_check_ibss_hw_merge(struct ath5k_softc *sc, struct sk_buff *skb) +ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb, + struct ieee80211_rx_status *rxs) { + u64 tsf, bc_tstamp; u32 hw_tu; struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; @@ -1727,16 +1729,45 @@ ath5k_check_ibss_hw_merge(struct ath5k_softc *sc, struct sk_buff *skb) le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS && memcmp(mgmt->bssid, sc->ah->ah_bssid, ETH_ALEN) == 0) { /* - * Received an IBSS beacon with the same BSSID. Hardware might - * have updated the TSF, check if we need to update timers. + * Received an IBSS beacon with the same BSSID. Hardware *must* + * have updated the local TSF. We have to work around various + * hardware bugs, though... */ - hw_tu = TSF_TO_TU(ath5k_hw_get_tsf64(sc->ah)); - if (hw_tu >= sc->nexttbtt) { - ath5k_beacon_update_timers(sc, - le64_to_cpu(mgmt->u.beacon.timestamp)); + tsf = ath5k_hw_get_tsf64(sc->ah); + bc_tstamp = le64_to_cpu(mgmt->u.beacon.timestamp); + hw_tu = TSF_TO_TU(tsf); + + ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, + "beacon %llx mactime %llx (diff %lld) tsf now %llx\n", + bc_tstamp, rxs->mactime, + (rxs->mactime - bc_tstamp), tsf); + + /* + * Sometimes the HW will give us a wrong tstamp in the rx + * status, causing the timestamp extension to go wrong. + * (This seems to happen especially with beacon frames bigger + * than 78 byte (incl. FCS)) + * But we know that the receive timestamp must be later than the + * timestamp of the beacon since HW must have synced to that. + * + * NOTE: here we assume mactime to be after the frame was + * received, not like mac80211 which defines it at the start. + */ + if (bc_tstamp > rxs->mactime) { ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, - "detected HW merge from received beacon\n"); + "fixing mactime from %llx to %llx\n", + rxs->mactime, tsf); + rxs->mactime = tsf; } + + /* + * Local TSF might have moved higher than our beacon timers, + * in that case we have to update them to continue sending + * beacons. This also takes care of synchronizing beacon sending + * times with other stations. + */ + if (hw_tu >= sc->nexttbtt) + ath5k_beacon_update_timers(sc, bc_tstamp); } } @@ -1885,7 +1916,7 @@ accept: /* check beacons in IBSS mode */ if (sc->opmode == IEEE80211_IF_TYPE_IBSS) - ath5k_check_ibss_hw_merge(sc, skb); + ath5k_check_ibss_tsf(sc, skb, &rxs); __ieee80211_rx(sc->hw, skb, &rxs); sc->led_rxrate = rs.rs_rate; @@ -2118,7 +2149,7 @@ ath5k_beacon_send(struct ath5k_softc *sc) * beacon timer registers. * * This is called in a variety of situations, e.g. when a beacon is received, - * when a HW merge has been detected, but also when an new IBSS is created or + * when a TSF update has been detected, but also when an new IBSS is created or * when we otherwise know we have to update the timers, but we keep it in this * function to have it all together in one place. */ @@ -2218,7 +2249,7 @@ ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf) * another AP to associate with. * * In IBSS mode we use a self-linked tx descriptor if possible. We enable SWBA - * interrupts to detect HW merges only. + * interrupts to detect TSF updates only. * * AP mode is missing. */ @@ -2238,7 +2269,7 @@ ath5k_beacon_config(struct ath5k_softc *sc) * hardware send the beacons automatically. We have to load it * only once here. * We use the SWBA interrupt only to keep track of the beacon - * timers in order to detect HW merges (automatic TSF updates). + * timers in order to detect automatic TSF updates. */ ath5k_beaconq_config(sc); @@ -2451,8 +2482,8 @@ ath5k_intr(int irq, void *dev_id) * * In IBSS mode we use this interrupt just to * keep track of the next TBTT (target beacon - * transmission time) in order to detect hardware - * merges (TSF updates). + * transmission time) in order to detect wether + * automatic TSF updates happened. */ if (sc->opmode == IEEE80211_IF_TYPE_IBSS) { /* XXX: only if VEOL suppported */ -- cgit v1.2.1 From f868f4e196177ee96f77304ab707a0ad5ddd6fe4 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Fri, 7 Mar 2008 16:38:43 -0500 Subject: wireless: correct warnings from using '%llx' for type 'u64' drivers/net/wireless/ath5k/debug.c: In function 'read_file_tsf': drivers/net/wireless/ath5k/debug.c:203: warning: format '%016llx' expects type 'long long unsigned int', but argument 4 has type 'u64' drivers/net/wireless/ath5k/debug.c:203: warning: format '%016llx' expects type 'long long unsigned int', but argument 4 has type 'u64' drivers/net/wireless/ath5k/debug.c: In function 'read_file_beacon': drivers/net/wireless/ath5k/debug.c:274: warning: format '%016llx' expects type 'long long unsigned int', but argument 4 has type 'u64' drivers/net/wireless/ath5k/debug.c:274: warning: format '%016llx' expects type 'long long unsigned int', but argument 4 has type 'u64' drivers/net/wireless/iwlwifi/iwl-4965.c: In function 'iwl4965_tx_status_reply_compressed_ba': drivers/net/wireless/iwlwifi/iwl-4965.c:3907: warning: format '%llx' expects type 'long long unsigned int', but argument 4 has type 'u64' drivers/net/wireless/iwlwifi/iwl-4965.c: In function 'iwl4965_rx_reply_compressed_ba': drivers/net/wireless/iwlwifi/iwl-4965.c:4039: warning: format '%llx' expects type 'long long unsigned int', but argument 6 has type '__le64' drivers/net/wireless/iwlwifi/iwl-4965.c:4046: warning: format '%llx' expects type 'long long unsigned int', but argument 5 has type 'u64' drivers/net/wireless/iwlwifi/iwl4965-base.c: In function 'iwl4965_tx_status_reply_tx': drivers/net/wireless/iwlwifi/iwl4965-base.c:3661: warning: format '%llx' expects type 'long long unsigned int', but argument 6 has type 'u64' Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/debug.c | 6 ++++-- drivers/net/wireless/iwlwifi/iwl-4965.c | 6 +++--- 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath5k/debug.c b/drivers/net/wireless/ath5k/debug.c index d3eb9e88c84d..41d5fa34b544 100644 --- a/drivers/net/wireless/ath5k/debug.c +++ b/drivers/net/wireless/ath5k/debug.c @@ -200,7 +200,8 @@ static ssize_t read_file_tsf(struct file *file, char __user *user_buf, { struct ath5k_softc *sc = file->private_data; char buf[100]; - snprintf(buf, sizeof(buf), "0x%016llx\n", ath5k_hw_get_tsf64(sc->ah)); + snprintf(buf, sizeof(buf), "0x%016llx\n", + (unsigned long long)ath5k_hw_get_tsf64(sc->ah)); return simple_read_from_buffer(user_buf, count, ppos, buf, 19); } @@ -271,7 +272,8 @@ static ssize_t read_file_beacon(struct file *file, char __user *user_buf, tsf = ath5k_hw_get_tsf64(sc->ah); len += snprintf(buf+len, sizeof(buf)-len, - "TSF\t\t0x%016llx\tTU: %08x\n", tsf, TSF_TO_TU(tsf)); + "TSF\t\t0x%016llx\tTU: %08x\n", + (unsigned long long)tsf, TSF_TO_TU(tsf)); return simple_read_from_buffer(user_buf, count, ppos, buf, len); } diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 4a7167dbc217..2f01a490c9ee 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -4117,7 +4117,7 @@ static int iwl4965_tx_status_reply_compressed_ba(struct iwl4965_priv *priv, iwl4965_hwrate_to_tx_control(priv, agg->rate_n_flags, &tx_status->control); - IWL_DEBUG_TX_REPLY("Bitmap %llx\n", bitmap); + IWL_DEBUG_TX_REPLY("Bitmap %llx\n", (unsigned long long)bitmap); return 0; } @@ -4262,12 +4262,12 @@ static void iwl4965_rx_reply_compressed_ba(struct iwl4965_priv *priv, "%d, scd_ssn = %d\n", ba_resp->tid, ba_resp->seq_ctl, - ba_resp->bitmap, + (unsigned long long)ba_resp->bitmap, ba_resp->scd_flow, ba_resp->scd_ssn); IWL_DEBUG_TX_REPLY("DAT start_idx = %d, bitmap = 0x%llx \n", agg->start_idx, - agg->bitmap); + (unsigned long long)agg->bitmap); /* Update driver's record of ACK vs. not for each frame in window */ iwl4965_tx_status_reply_compressed_ba(priv, agg, ba_resp); -- cgit v1.2.1 From deedf504302ff747985db081352e045ff7087a11 Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Fri, 7 Mar 2008 13:47:20 -0800 Subject: iwlwifi: fix potential lock inversion deadlock This is a change to a previous patch ("iwlwifi: 3945 split tx_complete to command and packet function") to ensure we do not have hardirq safe locks (priv->lock in this case) depend on hardirq unsafe locks. We only call iwl3945_tx_queue_reclaim while in a tasklet so we have to use the irqsafe version of the function. Signed-off-by: Reinette Chatre Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index dc3d695bf096..50a641c0c5b7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -283,8 +283,8 @@ static void iwl3945_tx_queue_reclaim(struct iwl3945_priv *priv, q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { tx_info = &txq->txb[txq->q.read_ptr]; - ieee80211_tx_status(priv->hw, tx_info->skb[0], - &tx_info->status); + ieee80211_tx_status_irqsafe(priv->hw, tx_info->skb[0], + &tx_info->status); tx_info->skb[0] = NULL; iwl3945_hw_txq_free_tfd(priv, txq); } -- cgit v1.2.1 From affe0a02189eeec43757993b1ccb65f24e39afa5 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Tue, 4 Mar 2008 15:26:06 -0800 Subject: make b43_mac_{enable,suspend}() static b43_mac_{enable,suspend}() can now become static. Signed-off-by: Adrian Bunk Acked-by: Michael Buesch Signed-off-by: Andrew Morton Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 4 ++-- drivers/net/wireless/b43/main.h | 3 --- 2 files changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 694e29570e5d..6c58f8b5dcf5 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -2154,7 +2154,7 @@ static void b43_gpio_cleanup(struct b43_wldev *dev) } /* http://bcm-specs.sipsolutions.net/EnableMac */ -void b43_mac_enable(struct b43_wldev *dev) +static void b43_mac_enable(struct b43_wldev *dev) { dev->mac_suspended--; B43_WARN_ON(dev->mac_suspended < 0); @@ -2178,7 +2178,7 @@ void b43_mac_enable(struct b43_wldev *dev) } /* http://bcm-specs.sipsolutions.net/SuspendMAC */ -void b43_mac_suspend(struct b43_wldev *dev) +static void b43_mac_suspend(struct b43_wldev *dev) { int i; u32 tmp; diff --git a/drivers/net/wireless/b43/main.h b/drivers/net/wireless/b43/main.h index 1197975f9207..5230aeca78bf 100644 --- a/drivers/net/wireless/b43/main.h +++ b/drivers/net/wireless/b43/main.h @@ -106,9 +106,6 @@ void b43_dummy_transmission(struct b43_wldev *dev); void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags); -void b43_mac_suspend(struct b43_wldev *dev); -void b43_mac_enable(struct b43_wldev *dev); - void b43_controller_restart(struct b43_wldev *dev, const char *reason); #define B43_PS_ENABLED (1 << 0) /* Force enable hardware power saving */ -- cgit v1.2.1 From 2079fcdc06ea01c084044c348dbcd7b3e335ad49 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Tue, 4 Mar 2008 15:26:12 -0800 Subject: the scheduled bcm43xx removal Signed-off-by: Adrian Bunk Cc: Cc: Signed-off-by: Andrew Morton Signed-off-by: John W. Linville --- drivers/net/wireless/Kconfig | 1 - drivers/net/wireless/Makefile | 1 - drivers/net/wireless/bcm43xx/Kconfig | 70 - drivers/net/wireless/bcm43xx/Makefile | 12 - drivers/net/wireless/bcm43xx/bcm43xx.h | 997 ------ drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c | 556 --- drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h | 118 - drivers/net/wireless/bcm43xx/bcm43xx_dma.c | 1263 ------- drivers/net/wireless/bcm43xx/bcm43xx_dma.h | 386 --- drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c | 50 - drivers/net/wireless/bcm43xx/bcm43xx_ethtool.h | 8 - drivers/net/wireless/bcm43xx/bcm43xx_ilt.c | 352 -- drivers/net/wireless/bcm43xx/bcm43xx_ilt.h | 33 - drivers/net/wireless/bcm43xx/bcm43xx_leds.c | 307 -- drivers/net/wireless/bcm43xx/bcm43xx_leds.h | 62 - drivers/net/wireless/bcm43xx/bcm43xx_main.c | 4281 ------------------------ drivers/net/wireless/bcm43xx/bcm43xx_main.h | 133 - drivers/net/wireless/bcm43xx/bcm43xx_phy.c | 2346 ------------- drivers/net/wireless/bcm43xx/bcm43xx_phy.h | 78 - drivers/net/wireless/bcm43xx/bcm43xx_pio.c | 674 ---- drivers/net/wireless/bcm43xx/bcm43xx_pio.h | 163 - drivers/net/wireless/bcm43xx/bcm43xx_power.c | 393 --- drivers/net/wireless/bcm43xx/bcm43xx_power.h | 56 - drivers/net/wireless/bcm43xx/bcm43xx_radio.c | 2170 ------------ drivers/net/wireless/bcm43xx/bcm43xx_radio.h | 115 - drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c | 471 --- drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h | 9 - drivers/net/wireless/bcm43xx/bcm43xx_wx.c | 1035 ------ drivers/net/wireless/bcm43xx/bcm43xx_wx.h | 36 - drivers/net/wireless/bcm43xx/bcm43xx_xmit.c | 565 ---- drivers/net/wireless/bcm43xx/bcm43xx_xmit.h | 150 - 31 files changed, 16891 deletions(-) delete mode 100644 drivers/net/wireless/bcm43xx/Kconfig delete mode 100644 drivers/net/wireless/bcm43xx/Makefile delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx.h delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_dma.c delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_dma.h delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_ethtool.h delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_ilt.c delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_ilt.h delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_leds.c delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_leds.h delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_main.c delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_main.h delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_phy.c delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_phy.h delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_pio.c delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_pio.h delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_power.c delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_power.h delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_radio.c delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_radio.h delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_wx.c delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_wx.h delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_xmit.c delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_xmit.h (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 3c3ef966c95b..f4ca6fd4a29f 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -741,7 +741,6 @@ config P54_PCI source "drivers/net/wireless/ath5k/Kconfig" source "drivers/net/wireless/iwlwifi/Kconfig" source "drivers/net/wireless/hostap/Kconfig" -source "drivers/net/wireless/bcm43xx/Kconfig" source "drivers/net/wireless/b43/Kconfig" source "drivers/net/wireless/b43legacy/Kconfig" source "drivers/net/wireless/zd1211rw/Kconfig" diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile index 091dfe2e574e..dd3899747b5c 100644 --- a/drivers/net/wireless/Makefile +++ b/drivers/net/wireless/Makefile @@ -35,7 +35,6 @@ obj-$(CONFIG_PCMCIA_ATMEL) += atmel_cs.o obj-$(CONFIG_PRISM54) += prism54/ obj-$(CONFIG_HOSTAP) += hostap/ -obj-$(CONFIG_BCM43XX) += bcm43xx/ obj-$(CONFIG_B43) += b43/ obj-$(CONFIG_B43LEGACY) += b43legacy/ obj-$(CONFIG_ZD1211RW) += zd1211rw/ diff --git a/drivers/net/wireless/bcm43xx/Kconfig b/drivers/net/wireless/bcm43xx/Kconfig deleted file mode 100644 index afb8f4305c24..000000000000 --- a/drivers/net/wireless/bcm43xx/Kconfig +++ /dev/null @@ -1,70 +0,0 @@ -config BCM43XX - tristate "Broadcom BCM43xx wireless support (DEPRECATED)" - depends on PCI && IEEE80211 && IEEE80211_SOFTMAC && WLAN_80211 && (!SSB_B43_PCI_BRIDGE || SSB != y) && EXPERIMENTAL - select WIRELESS_EXT - select FW_LOADER - select HW_RANDOM - ---help--- - This is an experimental driver for the Broadcom 43xx wireless - chip, found in the Apple Airport Extreme and various other - devices. This driver is deprecated and will be removed - from the kernel in the near future. It has been replaced - by the b43 and b43legacy drivers. - -config BCM43XX_DEBUG - bool "Broadcom BCM43xx debugging (RECOMMENDED)" - depends on BCM43XX - default y - ---help--- - Broadcom 43xx debugging messages. - Say Y, because the driver is still very experimental and - this will help you get it running. - -config BCM43XX_DMA - bool - depends on BCM43XX - -config BCM43XX_PIO - bool - depends on BCM43XX - -choice - prompt "BCM43xx data transfer mode" - depends on BCM43XX - default BCM43XX_DMA_AND_PIO_MODE - -config BCM43XX_DMA_AND_PIO_MODE - bool "DMA + PIO" - select BCM43XX_DMA - select BCM43XX_PIO - ---help--- - Include both, Direct Memory Access (DMA) and Programmed I/O (PIO) - data transfer modes. - The actually used mode is selectable through the module - parameter "pio". If the module parameter is pio=0, DMA is used. - Otherwise PIO is used. DMA is default. - - If unsure, choose this option. - -config BCM43XX_DMA_MODE - bool "DMA (Direct Memory Access) only" - select BCM43XX_DMA - ---help--- - Only include Direct Memory Access (DMA). - This reduces the size of the driver module, by omitting the PIO code. - -config BCM43XX_PIO_MODE - bool "PIO (Programmed I/O) only" - select BCM43XX_PIO - ---help--- - Only include Programmed I/O (PIO). - This reduces the size of the driver module, by omitting the DMA code. - Please note that PIO transfers are slow (compared to DMA). - - Also note that not all devices of the 43xx series support PIO. - The 4306 (Apple Airport Extreme and others) supports PIO, while - the 4318 is known to _not_ support PIO. - - Only use PIO, if DMA does not work for you. - -endchoice diff --git a/drivers/net/wireless/bcm43xx/Makefile b/drivers/net/wireless/bcm43xx/Makefile deleted file mode 100644 index bb5220c629d2..000000000000 --- a/drivers/net/wireless/bcm43xx/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -obj-$(CONFIG_BCM43XX) += bcm43xx.o -bcm43xx-obj-$(CONFIG_BCM43XX_DEBUG) += bcm43xx_debugfs.o - -bcm43xx-obj-$(CONFIG_BCM43XX_DMA) += bcm43xx_dma.o -bcm43xx-obj-$(CONFIG_BCM43XX_PIO) += bcm43xx_pio.o - -bcm43xx-objs := bcm43xx_main.o bcm43xx_ilt.o \ - bcm43xx_radio.o bcm43xx_phy.o \ - bcm43xx_power.o bcm43xx_wx.o \ - bcm43xx_leds.o bcm43xx_ethtool.o \ - bcm43xx_xmit.o bcm43xx_sysfs.o \ - $(bcm43xx-obj-y) diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h deleted file mode 100644 index 2ebd2edf5862..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx.h +++ /dev/null @@ -1,997 +0,0 @@ -#ifndef BCM43xx_H_ -#define BCM43xx_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#include "bcm43xx_debugfs.h" -#include "bcm43xx_leds.h" - - -#define PFX KBUILD_MODNAME ": " - -#define BCM43xx_SWITCH_CORE_MAX_RETRIES 50 -#define BCM43xx_IRQWAIT_MAX_RETRIES 100 - -#define BCM43xx_IO_SIZE 8192 - -/* Active Core PCI Configuration Register. */ -#define BCM43xx_PCICFG_ACTIVE_CORE 0x80 -/* SPROM control register. */ -#define BCM43xx_PCICFG_SPROMCTL 0x88 -/* Interrupt Control PCI Configuration Register. (Only on PCI cores with rev >= 6) */ -#define BCM43xx_PCICFG_ICR 0x94 - -/* MMIO offsets */ -#define BCM43xx_MMIO_DMA0_REASON 0x20 -#define BCM43xx_MMIO_DMA0_IRQ_MASK 0x24 -#define BCM43xx_MMIO_DMA1_REASON 0x28 -#define BCM43xx_MMIO_DMA1_IRQ_MASK 0x2C -#define BCM43xx_MMIO_DMA2_REASON 0x30 -#define BCM43xx_MMIO_DMA2_IRQ_MASK 0x34 -#define BCM43xx_MMIO_DMA3_REASON 0x38 -#define BCM43xx_MMIO_DMA3_IRQ_MASK 0x3C -#define BCM43xx_MMIO_DMA4_REASON 0x40 -#define BCM43xx_MMIO_DMA4_IRQ_MASK 0x44 -#define BCM43xx_MMIO_DMA5_REASON 0x48 -#define BCM43xx_MMIO_DMA5_IRQ_MASK 0x4C -#define BCM43xx_MMIO_STATUS_BITFIELD 0x120 -#define BCM43xx_MMIO_STATUS2_BITFIELD 0x124 -#define BCM43xx_MMIO_GEN_IRQ_REASON 0x128 -#define BCM43xx_MMIO_GEN_IRQ_MASK 0x12C -#define BCM43xx_MMIO_RAM_CONTROL 0x130 -#define BCM43xx_MMIO_RAM_DATA 0x134 -#define BCM43xx_MMIO_PS_STATUS 0x140 -#define BCM43xx_MMIO_RADIO_HWENABLED_HI 0x158 -#define BCM43xx_MMIO_SHM_CONTROL 0x160 -#define BCM43xx_MMIO_SHM_DATA 0x164 -#define BCM43xx_MMIO_SHM_DATA_UNALIGNED 0x166 -#define BCM43xx_MMIO_XMITSTAT_0 0x170 -#define BCM43xx_MMIO_XMITSTAT_1 0x174 -#define BCM43xx_MMIO_REV3PLUS_TSF_LOW 0x180 /* core rev >= 3 only */ -#define BCM43xx_MMIO_REV3PLUS_TSF_HIGH 0x184 /* core rev >= 3 only */ - -/* 32-bit DMA */ -#define BCM43xx_MMIO_DMA32_BASE0 0x200 -#define BCM43xx_MMIO_DMA32_BASE1 0x220 -#define BCM43xx_MMIO_DMA32_BASE2 0x240 -#define BCM43xx_MMIO_DMA32_BASE3 0x260 -#define BCM43xx_MMIO_DMA32_BASE4 0x280 -#define BCM43xx_MMIO_DMA32_BASE5 0x2A0 -/* 64-bit DMA */ -#define BCM43xx_MMIO_DMA64_BASE0 0x200 -#define BCM43xx_MMIO_DMA64_BASE1 0x240 -#define BCM43xx_MMIO_DMA64_BASE2 0x280 -#define BCM43xx_MMIO_DMA64_BASE3 0x2C0 -#define BCM43xx_MMIO_DMA64_BASE4 0x300 -#define BCM43xx_MMIO_DMA64_BASE5 0x340 -/* PIO */ -#define BCM43xx_MMIO_PIO1_BASE 0x300 -#define BCM43xx_MMIO_PIO2_BASE 0x310 -#define BCM43xx_MMIO_PIO3_BASE 0x320 -#define BCM43xx_MMIO_PIO4_BASE 0x330 - -#define BCM43xx_MMIO_PHY_VER 0x3E0 -#define BCM43xx_MMIO_PHY_RADIO 0x3E2 -#define BCM43xx_MMIO_ANTENNA 0x3E8 -#define BCM43xx_MMIO_CHANNEL 0x3F0 -#define BCM43xx_MMIO_CHANNEL_EXT 0x3F4 -#define BCM43xx_MMIO_RADIO_CONTROL 0x3F6 -#define BCM43xx_MMIO_RADIO_DATA_HIGH 0x3F8 -#define BCM43xx_MMIO_RADIO_DATA_LOW 0x3FA -#define BCM43xx_MMIO_PHY_CONTROL 0x3FC -#define BCM43xx_MMIO_PHY_DATA 0x3FE -#define BCM43xx_MMIO_MACFILTER_CONTROL 0x420 -#define BCM43xx_MMIO_MACFILTER_DATA 0x422 -#define BCM43xx_MMIO_RADIO_HWENABLED_LO 0x49A -#define BCM43xx_MMIO_GPIO_CONTROL 0x49C -#define BCM43xx_MMIO_GPIO_MASK 0x49E -#define BCM43xx_MMIO_TSF_0 0x632 /* core rev < 3 only */ -#define BCM43xx_MMIO_TSF_1 0x634 /* core rev < 3 only */ -#define BCM43xx_MMIO_TSF_2 0x636 /* core rev < 3 only */ -#define BCM43xx_MMIO_TSF_3 0x638 /* core rev < 3 only */ -#define BCM43xx_MMIO_RNG 0x65A -#define BCM43xx_MMIO_POWERUP_DELAY 0x6A8 - -/* SPROM offsets. */ -#define BCM43xx_SPROM_BASE 0x1000 -#define BCM43xx_SPROM_BOARDFLAGS2 0x1c -#define BCM43xx_SPROM_IL0MACADDR 0x24 -#define BCM43xx_SPROM_ET0MACADDR 0x27 -#define BCM43xx_SPROM_ET1MACADDR 0x2a -#define BCM43xx_SPROM_ETHPHY 0x2d -#define BCM43xx_SPROM_BOARDREV 0x2e -#define BCM43xx_SPROM_PA0B0 0x2f -#define BCM43xx_SPROM_PA0B1 0x30 -#define BCM43xx_SPROM_PA0B2 0x31 -#define BCM43xx_SPROM_WL0GPIO0 0x32 -#define BCM43xx_SPROM_WL0GPIO2 0x33 -#define BCM43xx_SPROM_MAXPWR 0x34 -#define BCM43xx_SPROM_PA1B0 0x35 -#define BCM43xx_SPROM_PA1B1 0x36 -#define BCM43xx_SPROM_PA1B2 0x37 -#define BCM43xx_SPROM_IDL_TSSI_TGT 0x38 -#define BCM43xx_SPROM_BOARDFLAGS 0x39 -#define BCM43xx_SPROM_ANTENNA_GAIN 0x3a -#define BCM43xx_SPROM_VERSION 0x3f - -/* BCM43xx_SPROM_BOARDFLAGS values */ -#define BCM43xx_BFL_BTCOEXIST 0x0001 /* implements Bluetooth coexistance */ -#define BCM43xx_BFL_PACTRL 0x0002 /* GPIO 9 controlling the PA */ -#define BCM43xx_BFL_AIRLINEMODE 0x0004 /* implements GPIO 13 radio disable indication */ -#define BCM43xx_BFL_RSSI 0x0008 /* software calculates nrssi slope. */ -#define BCM43xx_BFL_ENETSPI 0x0010 /* has ephy roboswitch spi */ -#define BCM43xx_BFL_XTAL_NOSLOW 0x0020 /* no slow clock available */ -#define BCM43xx_BFL_CCKHIPWR 0x0040 /* can do high power CCK transmission */ -#define BCM43xx_BFL_ENETADM 0x0080 /* has ADMtek switch */ -#define BCM43xx_BFL_ENETVLAN 0x0100 /* can do vlan */ -#define BCM43xx_BFL_AFTERBURNER 0x0200 /* supports Afterburner mode */ -#define BCM43xx_BFL_NOPCI 0x0400 /* leaves PCI floating */ -#define BCM43xx_BFL_FEM 0x0800 /* supports the Front End Module */ -#define BCM43xx_BFL_EXTLNA 0x1000 /* has an external LNA */ -#define BCM43xx_BFL_HGPA 0x2000 /* had high gain PA */ -#define BCM43xx_BFL_BTCMOD 0x4000 /* BFL_BTCOEXIST is given in alternate GPIOs */ -#define BCM43xx_BFL_ALTIQ 0x8000 /* alternate I/Q settings */ - -/* GPIO register offset, in both ChipCommon and PCI core. */ -#define BCM43xx_GPIO_CONTROL 0x6c - -/* SHM Routing */ -#define BCM43xx_SHM_SHARED 0x0001 -#define BCM43xx_SHM_WIRELESS 0x0002 -#define BCM43xx_SHM_PCM 0x0003 -#define BCM43xx_SHM_HWMAC 0x0004 -#define BCM43xx_SHM_UCODE 0x0300 - -/* MacFilter offsets. */ -#define BCM43xx_MACFILTER_SELF 0x0000 -#define BCM43xx_MACFILTER_ASSOC 0x0003 - -/* Chipcommon registers. */ -#define BCM43xx_CHIPCOMMON_CAPABILITIES 0x04 -#define BCM43xx_CHIPCOMMON_CTL 0x28 -#define BCM43xx_CHIPCOMMON_PLLONDELAY 0xB0 -#define BCM43xx_CHIPCOMMON_FREFSELDELAY 0xB4 -#define BCM43xx_CHIPCOMMON_SLOWCLKCTL 0xB8 -#define BCM43xx_CHIPCOMMON_SYSCLKCTL 0xC0 - -/* PCI core specific registers. */ -#define BCM43xx_PCICORE_BCAST_ADDR 0x50 -#define BCM43xx_PCICORE_BCAST_DATA 0x54 -#define BCM43xx_PCICORE_SBTOPCI2 0x108 - -/* SBTOPCI2 values. */ -#define BCM43xx_SBTOPCI2_PREFETCH 0x4 -#define BCM43xx_SBTOPCI2_BURST 0x8 -#define BCM43xx_SBTOPCI2_MEMREAD_MULTI 0x20 - -/* PCI-E core registers. */ -#define BCM43xx_PCIECORE_REG_ADDR 0x0130 -#define BCM43xx_PCIECORE_REG_DATA 0x0134 -#define BCM43xx_PCIECORE_MDIO_CTL 0x0128 -#define BCM43xx_PCIECORE_MDIO_DATA 0x012C - -/* PCI-E registers. */ -#define BCM43xx_PCIE_TLP_WORKAROUND 0x0004 -#define BCM43xx_PCIE_DLLP_LINKCTL 0x0100 - -/* PCI-E MDIO bits. */ -#define BCM43xx_PCIE_MDIO_ST 0x40000000 -#define BCM43xx_PCIE_MDIO_WT 0x10000000 -#define BCM43xx_PCIE_MDIO_DEV 22 -#define BCM43xx_PCIE_MDIO_REG 18 -#define BCM43xx_PCIE_MDIO_TA 0x00020000 -#define BCM43xx_PCIE_MDIO_TC 0x0100 - -/* MDIO devices. */ -#define BCM43xx_MDIO_SERDES_RX 0x1F - -/* SERDES RX registers. */ -#define BCM43xx_SERDES_RXTIMER 0x2 -#define BCM43xx_SERDES_CDR 0x6 -#define BCM43xx_SERDES_CDR_BW 0x7 - -/* Chipcommon capabilities. */ -#define BCM43xx_CAPABILITIES_PCTL 0x00040000 -#define BCM43xx_CAPABILITIES_PLLMASK 0x00030000 -#define BCM43xx_CAPABILITIES_PLLSHIFT 16 -#define BCM43xx_CAPABILITIES_FLASHMASK 0x00000700 -#define BCM43xx_CAPABILITIES_FLASHSHIFT 8 -#define BCM43xx_CAPABILITIES_EXTBUSPRESENT 0x00000040 -#define BCM43xx_CAPABILITIES_UARTGPIO 0x00000020 -#define BCM43xx_CAPABILITIES_UARTCLOCKMASK 0x00000018 -#define BCM43xx_CAPABILITIES_UARTCLOCKSHIFT 3 -#define BCM43xx_CAPABILITIES_MIPSBIGENDIAN 0x00000004 -#define BCM43xx_CAPABILITIES_NRUARTSMASK 0x00000003 - -/* PowerControl */ -#define BCM43xx_PCTL_IN 0xB0 -#define BCM43xx_PCTL_OUT 0xB4 -#define BCM43xx_PCTL_OUTENABLE 0xB8 -#define BCM43xx_PCTL_XTAL_POWERUP 0x40 -#define BCM43xx_PCTL_PLL_POWERDOWN 0x80 - -/* PowerControl Clock Modes */ -#define BCM43xx_PCTL_CLK_FAST 0x00 -#define BCM43xx_PCTL_CLK_SLOW 0x01 -#define BCM43xx_PCTL_CLK_DYNAMIC 0x02 - -#define BCM43xx_PCTL_FORCE_SLOW 0x0800 -#define BCM43xx_PCTL_FORCE_PLL 0x1000 -#define BCM43xx_PCTL_DYN_XTAL 0x2000 - -/* COREIDs */ -#define BCM43xx_COREID_CHIPCOMMON 0x800 -#define BCM43xx_COREID_ILINE20 0x801 -#define BCM43xx_COREID_SDRAM 0x803 -#define BCM43xx_COREID_PCI 0x804 -#define BCM43xx_COREID_MIPS 0x805 -#define BCM43xx_COREID_ETHERNET 0x806 -#define BCM43xx_COREID_V90 0x807 -#define BCM43xx_COREID_USB11_HOSTDEV 0x80a -#define BCM43xx_COREID_IPSEC 0x80b -#define BCM43xx_COREID_PCMCIA 0x80d -#define BCM43xx_COREID_EXT_IF 0x80f -#define BCM43xx_COREID_80211 0x812 -#define BCM43xx_COREID_MIPS_3302 0x816 -#define BCM43xx_COREID_USB11_HOST 0x817 -#define BCM43xx_COREID_USB11_DEV 0x818 -#define BCM43xx_COREID_USB20_HOST 0x819 -#define BCM43xx_COREID_USB20_DEV 0x81a -#define BCM43xx_COREID_SDIO_HOST 0x81b -#define BCM43xx_COREID_PCIE 0x820 - -/* Core Information Registers */ -#define BCM43xx_CIR_BASE 0xf00 -#define BCM43xx_CIR_SBTPSFLAG (BCM43xx_CIR_BASE + 0x18) -#define BCM43xx_CIR_SBIMSTATE (BCM43xx_CIR_BASE + 0x90) -#define BCM43xx_CIR_SBINTVEC (BCM43xx_CIR_BASE + 0x94) -#define BCM43xx_CIR_SBTMSTATELOW (BCM43xx_CIR_BASE + 0x98) -#define BCM43xx_CIR_SBTMSTATEHIGH (BCM43xx_CIR_BASE + 0x9c) -#define BCM43xx_CIR_SBIMCONFIGLOW (BCM43xx_CIR_BASE + 0xa8) -#define BCM43xx_CIR_SB_ID_HI (BCM43xx_CIR_BASE + 0xfc) - -/* Mask to get the Backplane Flag Number from SBTPSFLAG. */ -#define BCM43xx_BACKPLANE_FLAG_NR_MASK 0x3f - -/* SBIMCONFIGLOW values/masks. */ -#define BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK 0x00000007 -#define BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_SHIFT 0 -#define BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK 0x00000070 -#define BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_SHIFT 4 -#define BCM43xx_SBIMCONFIGLOW_CONNID_MASK 0x00ff0000 -#define BCM43xx_SBIMCONFIGLOW_CONNID_SHIFT 16 - -/* sbtmstatelow state flags */ -#define BCM43xx_SBTMSTATELOW_RESET 0x01 -#define BCM43xx_SBTMSTATELOW_REJECT 0x02 -#define BCM43xx_SBTMSTATELOW_CLOCK 0x10000 -#define BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK 0x20000 -#define BCM43xx_SBTMSTATELOW_G_MODE_ENABLE 0x20000000 - -/* sbtmstatehigh state flags */ -#define BCM43xx_SBTMSTATEHIGH_SERROR 0x00000001 -#define BCM43xx_SBTMSTATEHIGH_BUSY 0x00000004 -#define BCM43xx_SBTMSTATEHIGH_TIMEOUT 0x00000020 -#define BCM43xx_SBTMSTATEHIGH_G_PHY_AVAIL 0x00010000 -#define BCM43xx_SBTMSTATEHIGH_A_PHY_AVAIL 0x00020000 -#define BCM43xx_SBTMSTATEHIGH_COREFLAGS 0x1FFF0000 -#define BCM43xx_SBTMSTATEHIGH_DMA64BIT 0x10000000 -#define BCM43xx_SBTMSTATEHIGH_GATEDCLK 0x20000000 -#define BCM43xx_SBTMSTATEHIGH_BISTFAILED 0x40000000 -#define BCM43xx_SBTMSTATEHIGH_BISTCOMPLETE 0x80000000 - -/* sbimstate flags */ -#define BCM43xx_SBIMSTATE_IB_ERROR 0x20000 -#define BCM43xx_SBIMSTATE_TIMEOUT 0x40000 - -/* PHYVersioning */ -#define BCM43xx_PHYTYPE_A 0x00 -#define BCM43xx_PHYTYPE_B 0x01 -#define BCM43xx_PHYTYPE_G 0x02 - -/* PHYRegisters */ -#define BCM43xx_PHY_ILT_A_CTRL 0x0072 -#define BCM43xx_PHY_ILT_A_DATA1 0x0073 -#define BCM43xx_PHY_ILT_A_DATA2 0x0074 -#define BCM43xx_PHY_G_LO_CONTROL 0x0810 -#define BCM43xx_PHY_ILT_G_CTRL 0x0472 -#define BCM43xx_PHY_ILT_G_DATA1 0x0473 -#define BCM43xx_PHY_ILT_G_DATA2 0x0474 -#define BCM43xx_PHY_A_PCTL 0x007B -#define BCM43xx_PHY_G_PCTL 0x0029 -#define BCM43xx_PHY_A_CRS 0x0029 -#define BCM43xx_PHY_RADIO_BITFIELD 0x0401 -#define BCM43xx_PHY_G_CRS 0x0429 -#define BCM43xx_PHY_NRSSILT_CTRL 0x0803 -#define BCM43xx_PHY_NRSSILT_DATA 0x0804 - -/* RadioRegisters */ -#define BCM43xx_RADIOCTL_ID 0x01 - -/* StatusBitField */ -#define BCM43xx_SBF_MAC_ENABLED 0x00000001 -#define BCM43xx_SBF_2 0x00000002 /*FIXME: fix name*/ -#define BCM43xx_SBF_CORE_READY 0x00000004 -#define BCM43xx_SBF_400 0x00000400 /*FIXME: fix name*/ -#define BCM43xx_SBF_4000 0x00004000 /*FIXME: fix name*/ -#define BCM43xx_SBF_8000 0x00008000 /*FIXME: fix name*/ -#define BCM43xx_SBF_XFER_REG_BYTESWAP 0x00010000 -#define BCM43xx_SBF_MODE_NOTADHOC 0x00020000 -#define BCM43xx_SBF_MODE_AP 0x00040000 -#define BCM43xx_SBF_RADIOREG_LOCK 0x00080000 -#define BCM43xx_SBF_MODE_MONITOR 0x00400000 -#define BCM43xx_SBF_MODE_PROMISC 0x01000000 -#define BCM43xx_SBF_PS1 0x02000000 -#define BCM43xx_SBF_PS2 0x04000000 -#define BCM43xx_SBF_NO_SSID_BCAST 0x08000000 -#define BCM43xx_SBF_TIME_UPDATE 0x10000000 -#define BCM43xx_SBF_MODE_G 0x80000000 - -/* Microcode */ -#define BCM43xx_UCODE_REVISION 0x0000 -#define BCM43xx_UCODE_PATCHLEVEL 0x0002 -#define BCM43xx_UCODE_DATE 0x0004 -#define BCM43xx_UCODE_TIME 0x0006 -#define BCM43xx_UCODE_STATUS 0x0040 - -/* MicrocodeFlagsBitfield (addr + lo-word values?)*/ -#define BCM43xx_UCODEFLAGS_OFFSET 0x005E - -#define BCM43xx_UCODEFLAG_AUTODIV 0x0001 -#define BCM43xx_UCODEFLAG_UNKBGPHY 0x0002 -#define BCM43xx_UCODEFLAG_UNKBPHY 0x0004 -#define BCM43xx_UCODEFLAG_UNKGPHY 0x0020 -#define BCM43xx_UCODEFLAG_UNKPACTRL 0x0040 -#define BCM43xx_UCODEFLAG_JAPAN 0x0080 - -/* Hardware Radio Enable masks */ -#define BCM43xx_MMIO_RADIO_HWENABLED_HI_MASK (1 << 16) -#define BCM43xx_MMIO_RADIO_HWENABLED_LO_MASK (1 << 4) - -/* Generic-Interrupt reasons. */ -#define BCM43xx_IRQ_READY (1 << 0) -#define BCM43xx_IRQ_BEACON (1 << 1) -#define BCM43xx_IRQ_PS (1 << 2) -#define BCM43xx_IRQ_REG124 (1 << 5) -#define BCM43xx_IRQ_PMQ (1 << 6) -#define BCM43xx_IRQ_PIO_WORKAROUND (1 << 8) -#define BCM43xx_IRQ_XMIT_ERROR (1 << 11) -#define BCM43xx_IRQ_RX (1 << 15) -#define BCM43xx_IRQ_SCAN (1 << 16) -#define BCM43xx_IRQ_NOISE (1 << 18) -#define BCM43xx_IRQ_XMIT_STATUS (1 << 29) - -#define BCM43xx_IRQ_ALL 0xffffffff -#define BCM43xx_IRQ_INITIAL (BCM43xx_IRQ_PS | \ - BCM43xx_IRQ_REG124 | \ - BCM43xx_IRQ_PMQ | \ - BCM43xx_IRQ_XMIT_ERROR | \ - BCM43xx_IRQ_RX | \ - BCM43xx_IRQ_SCAN | \ - BCM43xx_IRQ_NOISE | \ - BCM43xx_IRQ_XMIT_STATUS) - - -/* Initial default iw_mode */ -#define BCM43xx_INITIAL_IWMODE IW_MODE_INFRA - -/* Bus type PCI. */ -#define BCM43xx_BUSTYPE_PCI 0 -/* Bus type Silicone Backplane Bus. */ -#define BCM43xx_BUSTYPE_SB 1 -/* Bus type PCMCIA. */ -#define BCM43xx_BUSTYPE_PCMCIA 2 - -/* Threshold values. */ -#define BCM43xx_MIN_RTS_THRESHOLD 1U -#define BCM43xx_MAX_RTS_THRESHOLD 2304U -#define BCM43xx_DEFAULT_RTS_THRESHOLD BCM43xx_MAX_RTS_THRESHOLD - -#define BCM43xx_DEFAULT_SHORT_RETRY_LIMIT 7 -#define BCM43xx_DEFAULT_LONG_RETRY_LIMIT 4 - -/* FIXME: the next line is a guess as to what the maximum RSSI value might be */ -#define RX_RSSI_MAX 60 - -/* Max size of a security key */ -#define BCM43xx_SEC_KEYSIZE 16 -/* Security algorithms. */ -enum { - BCM43xx_SEC_ALGO_NONE = 0, /* unencrypted, as of TX header. */ - BCM43xx_SEC_ALGO_WEP, - BCM43xx_SEC_ALGO_UNKNOWN, - BCM43xx_SEC_ALGO_AES, - BCM43xx_SEC_ALGO_WEP104, - BCM43xx_SEC_ALGO_TKIP, -}; - -#ifdef assert -# undef assert -#endif -#ifdef CONFIG_BCM43XX_DEBUG -#define assert(expr) \ - do { \ - if (unlikely(!(expr))) { \ - printk(KERN_ERR PFX "ASSERTION FAILED (%s) at: %s:%d:%s()\n", \ - #expr, __FILE__, __LINE__, __FUNCTION__); \ - } \ - } while (0) -#else -#define assert(expr) do { /* nothing */ } while (0) -#endif - -/* rate limited printk(). */ -#ifdef printkl -# undef printkl -#endif -#define printkl(f, x...) do { if (printk_ratelimit()) printk(f ,##x); } while (0) -/* rate limited printk() for debugging */ -#ifdef dprintkl -# undef dprintkl -#endif -#ifdef CONFIG_BCM43XX_DEBUG -# define dprintkl printkl -#else -# define dprintkl(f, x...) do { /* nothing */ } while (0) -#endif - -/* Helper macro for if branches. - * An if branch marked with this macro is only taken in DEBUG mode. - * Example: - * if (DEBUG_ONLY(foo == bar)) { - * do something - * } - * In DEBUG mode, the branch will be taken if (foo == bar). - * In non-DEBUG mode, the branch will never be taken. - */ -#ifdef DEBUG_ONLY -# undef DEBUG_ONLY -#endif -#ifdef CONFIG_BCM43XX_DEBUG -# define DEBUG_ONLY(x) (x) -#else -# define DEBUG_ONLY(x) 0 -#endif - -/* debugging printk() */ -#ifdef dprintk -# undef dprintk -#endif -#ifdef CONFIG_BCM43XX_DEBUG -# define dprintk(f, x...) do { printk(f ,##x); } while (0) -#else -# define dprintk(f, x...) do { /* nothing */ } while (0) -#endif - - -struct net_device; -struct pci_dev; -struct bcm43xx_dmaring; -struct bcm43xx_pioqueue; - -struct bcm43xx_initval { - __be16 offset; - __be16 size; - __be32 value; -} __attribute__((__packed__)); - -/* Values for bcm430x_sprominfo.locale */ -enum { - BCM43xx_LOCALE_WORLD = 0, - BCM43xx_LOCALE_THAILAND, - BCM43xx_LOCALE_ISRAEL, - BCM43xx_LOCALE_JORDAN, - BCM43xx_LOCALE_CHINA, - BCM43xx_LOCALE_JAPAN, - BCM43xx_LOCALE_USA_CANADA_ANZ, - BCM43xx_LOCALE_EUROPE, - BCM43xx_LOCALE_USA_LOW, - BCM43xx_LOCALE_JAPAN_HIGH, - BCM43xx_LOCALE_ALL, - BCM43xx_LOCALE_NONE, -}; - -#define BCM43xx_SPROM_SIZE 64 /* in 16-bit words. */ -struct bcm43xx_sprominfo { - u16 boardflags2; - u8 il0macaddr[6]; - u8 et0macaddr[6]; - u8 et1macaddr[6]; - u8 et0phyaddr:5; - u8 et1phyaddr:5; - u8 boardrev; - u8 locale:4; - u8 antennas_aphy:2; - u8 antennas_bgphy:2; - u16 pa0b0; - u16 pa0b1; - u16 pa0b2; - u8 wl0gpio0; - u8 wl0gpio1; - u8 wl0gpio2; - u8 wl0gpio3; - u8 maxpower_aphy; - u8 maxpower_bgphy; - u16 pa1b0; - u16 pa1b1; - u16 pa1b2; - u8 idle_tssi_tgt_aphy; - u8 idle_tssi_tgt_bgphy; - u16 boardflags; - u16 antennagain_aphy; - u16 antennagain_bgphy; -}; - -/* Value pair to measure the LocalOscillator. */ -struct bcm43xx_lopair { - s8 low; - s8 high; - u8 used:1; -}; -#define BCM43xx_LO_COUNT (14*4) - -struct bcm43xx_phyinfo { - /* Hardware Data */ - u8 analog; - u8 type; - u8 rev; - u16 antenna_diversity; - u16 savedpctlreg; - u16 minlowsig[2]; - u16 minlowsigpos[2]; - u8 connected:1, - calibrated:1, - is_locked:1, /* used in bcm43xx_phy_{un}lock() */ - dyn_tssi_tbl:1; /* used in bcm43xx_phy_init_tssi2dbm_table() */ - /* LO Measurement Data. - * Use bcm43xx_get_lopair() to get a value. - */ - struct bcm43xx_lopair *_lo_pairs; - - /* TSSI to dBm table in use */ - const s8 *tssi2dbm; - /* idle TSSI value */ - s8 idle_tssi; - - /* Values from bcm43xx_calc_loopback_gain() */ - u16 loopback_gain[2]; - - /* PHY lock for core.rev < 3 - * This lock is only used by bcm43xx_phy_{un}lock() - */ - spinlock_t lock; - - /* Firmware. */ - const struct firmware *ucode; - const struct firmware *pcm; - const struct firmware *initvals0; - const struct firmware *initvals1; -}; - - -struct bcm43xx_radioinfo { - u16 manufact; - u16 version; - u8 revision; - - /* Desired TX power in dBm Q5.2 */ - u16 txpower_desired; - /* TX Power control values. */ - union { - /* B/G PHY */ - struct { - u16 baseband_atten; - u16 radio_atten; - u16 txctl1; - u16 txctl2; - }; - /* A PHY */ - struct { - u16 txpwr_offset; - }; - }; - - /* Current Interference Mitigation mode */ - int interfmode; - /* Stack of saved values from the Interference Mitigation code. - * Each value in the stack is layed out as follows: - * bit 0-11: offset - * bit 12-15: register ID - * bit 16-32: value - * register ID is: 0x1 PHY, 0x2 Radio, 0x3 ILT - */ -#define BCM43xx_INTERFSTACK_SIZE 26 - u32 interfstack[BCM43xx_INTERFSTACK_SIZE]; - - /* Saved values from the NRSSI Slope calculation */ - s16 nrssi[2]; - s32 nrssislope; - /* In memory nrssi lookup table. */ - s8 nrssi_lt[64]; - - /* current channel */ - u8 channel; - u8 initial_channel; - - u16 lofcal; - - u16 initval; - - u8 enabled:1; - /* ACI (adjacent channel interference) flags. */ - u8 aci_enable:1, - aci_wlan_automatic:1, - aci_hw_rssi:1; -}; - -/* Data structures for DMA transmission, per 80211 core. */ -struct bcm43xx_dma { - struct bcm43xx_dmaring *tx_ring0; - struct bcm43xx_dmaring *tx_ring1; - struct bcm43xx_dmaring *tx_ring2; - struct bcm43xx_dmaring *tx_ring3; - struct bcm43xx_dmaring *tx_ring4; - struct bcm43xx_dmaring *tx_ring5; - - struct bcm43xx_dmaring *rx_ring0; - struct bcm43xx_dmaring *rx_ring3; /* only available on core.rev < 5 */ -}; - -/* Data structures for PIO transmission, per 80211 core. */ -struct bcm43xx_pio { - struct bcm43xx_pioqueue *queue0; - struct bcm43xx_pioqueue *queue1; - struct bcm43xx_pioqueue *queue2; - struct bcm43xx_pioqueue *queue3; -}; - -#define BCM43xx_MAX_80211_CORES 2 - -/* Generic information about a core. */ -struct bcm43xx_coreinfo { - u8 available:1, - enabled:1, - initialized:1; - /** core_rev revision number */ - u8 rev; - /** Index number for _switch_core() */ - u8 index; - /** core_id ID number */ - u16 id; - /** Core-specific data. */ - void *priv; -}; - -/* Additional information for each 80211 core. */ -struct bcm43xx_coreinfo_80211 { - /* PHY device. */ - struct bcm43xx_phyinfo phy; - /* Radio device. */ - struct bcm43xx_radioinfo radio; - union { - /* DMA context. */ - struct bcm43xx_dma dma; - /* PIO context. */ - struct bcm43xx_pio pio; - }; -}; - -/* Context information for a noise calculation (Link Quality). */ -struct bcm43xx_noise_calculation { - struct bcm43xx_coreinfo *core_at_start; - u8 channel_at_start; - u8 calculation_running:1; - u8 nr_samples; - s8 samples[8][4]; -}; - -struct bcm43xx_stats { - u8 noise; - struct iw_statistics wstats; - /* Store the last TX/RX times here for updating the leds. */ - unsigned long last_tx; - unsigned long last_rx; -}; - -struct bcm43xx_key { - u8 enabled:1; - u8 algorithm; -}; - -/* Driver initialization status. */ -enum { - BCM43xx_STAT_UNINIT, /* Uninitialized. */ - BCM43xx_STAT_INITIALIZING, /* init_board() in progress. */ - BCM43xx_STAT_INITIALIZED, /* Fully operational. */ - BCM43xx_STAT_SHUTTINGDOWN, /* free_board() in progress. */ - BCM43xx_STAT_RESTARTING, /* controller_restart() called. */ -}; -#define bcm43xx_status(bcm) atomic_read(&(bcm)->init_status) -#define bcm43xx_set_status(bcm, stat) do { \ - atomic_set(&(bcm)->init_status, (stat)); \ - smp_wmb(); \ - } while (0) - -/* *** THEORY OF LOCKING *** - * - * We have two different locks in the bcm43xx driver. - * => bcm->mutex: General sleeping mutex. Protects struct bcm43xx_private - * and the device registers. This mutex does _not_ protect - * against concurrency from the IRQ handler. - * => bcm->irq_lock: IRQ spinlock. Protects against IRQ handler concurrency. - * - * Please note that, if you only take the irq_lock, you are not protected - * against concurrency from the periodic work handlers. - * Most times you want to take _both_ locks. - */ - -struct bcm43xx_private { - struct ieee80211_device *ieee; - struct ieee80211softmac_device *softmac; - - struct net_device *net_dev; - struct pci_dev *pci_dev; - unsigned int irq; - - void __iomem *mmio_addr; - - spinlock_t irq_lock; - struct mutex mutex; - - /* Driver initialization status BCM43xx_STAT_*** */ - atomic_t init_status; - - u16 was_initialized:1, /* for PCI suspend/resume. */ - __using_pio:1, /* Internal, use bcm43xx_using_pio(). */ - bad_frames_preempt:1, /* Use "Bad Frames Preemption" (default off) */ - reg124_set_0x4:1, /* Some variable to keep track of IRQ stuff. */ - short_preamble:1, /* TRUE, if short preamble is enabled. */ - firmware_norelease:1, /* Do not release the firmware. Used on suspend. */ - radio_hw_enable:1; /* TRUE if radio is hardware enabled */ - - struct bcm43xx_stats stats; - - /* Bus type we are connected to. - * This is currently always BCM43xx_BUSTYPE_PCI - */ - u8 bustype; - u64 dma_mask; - - u16 board_vendor; - u16 board_type; - u16 board_revision; - - u16 chip_id; - u8 chip_rev; - u8 chip_package; - - struct bcm43xx_sprominfo sprom; -#define BCM43xx_NR_LEDS 4 - struct bcm43xx_led leds[BCM43xx_NR_LEDS]; - spinlock_t leds_lock; - - /* The currently active core. */ - struct bcm43xx_coreinfo *current_core; - struct bcm43xx_coreinfo *active_80211_core; - /* coreinfo structs for all possible cores follow. - * Note that a core might not exist. - * So check the coreinfo flags before using it. - */ - struct bcm43xx_coreinfo core_chipcommon; - struct bcm43xx_coreinfo core_pci; - struct bcm43xx_coreinfo core_80211[ BCM43xx_MAX_80211_CORES ]; - /* Additional information, specific to the 80211 cores. */ - struct bcm43xx_coreinfo_80211 core_80211_ext[ BCM43xx_MAX_80211_CORES ]; - /* Number of available 80211 cores. */ - int nr_80211_available; - - u32 chipcommon_capabilities; - - /* Reason code of the last interrupt. */ - u32 irq_reason; - u32 dma_reason[6]; - /* saved irq enable/disable state bitfield. */ - u32 irq_savedstate; - /* Link Quality calculation context. */ - struct bcm43xx_noise_calculation noisecalc; - /* if > 0 MAC is suspended. if == 0 MAC is enabled. */ - int mac_suspended; - - /* Threshold values. */ - //TODO: The RTS thr has to be _used_. Currently, it is only set via WX. - u32 rts_threshold; - - /* Interrupt Service Routine tasklet (bottom-half) */ - struct tasklet_struct isr_tasklet; - - /* Periodic tasks */ - struct delayed_work periodic_work; - unsigned int periodic_state; - - struct work_struct restart_work; - - /* Informational stuff. */ - char nick[IW_ESSID_MAX_SIZE + 1]; - - /* encryption/decryption */ - u16 security_offset; - struct bcm43xx_key key[54]; - u8 default_key_idx; - - /* Random Number Generator. */ - struct hwrng rng; - char rng_name[20 + 1]; - - /* Debugging stuff follows. */ -#ifdef CONFIG_BCM43XX_DEBUG - struct bcm43xx_dfsentry *dfsentry; -#endif -}; - - -static inline -struct bcm43xx_private * bcm43xx_priv(struct net_device *dev) -{ - return ieee80211softmac_priv(dev); -} - -struct device; - -static inline -struct bcm43xx_private * dev_to_bcm(struct device *dev) -{ - struct net_device *net_dev; - struct bcm43xx_private *bcm; - - net_dev = dev_get_drvdata(dev); - bcm = bcm43xx_priv(net_dev); - - return bcm; -} - - -/* Helper function, which returns a boolean. - * TRUE, if PIO is used; FALSE, if DMA is used. - */ -#if defined(CONFIG_BCM43XX_DMA) && defined(CONFIG_BCM43XX_PIO) -static inline -int bcm43xx_using_pio(struct bcm43xx_private *bcm) -{ - return bcm->__using_pio; -} -#elif defined(CONFIG_BCM43XX_DMA) -static inline -int bcm43xx_using_pio(struct bcm43xx_private *bcm) -{ - return 0; -} -#elif defined(CONFIG_BCM43XX_PIO) -static inline -int bcm43xx_using_pio(struct bcm43xx_private *bcm) -{ - return 1; -} -#else -# error "Using neither DMA nor PIO? Confused..." -#endif - -/* Helper functions to access data structures private to the 80211 cores. - * Note that we _must_ have an 80211 core mapped when calling - * any of these functions. - */ -static inline -struct bcm43xx_coreinfo_80211 * -bcm43xx_current_80211_priv(struct bcm43xx_private *bcm) -{ - assert(bcm->current_core->id == BCM43xx_COREID_80211); - return bcm->current_core->priv; -} -static inline -struct bcm43xx_pio * bcm43xx_current_pio(struct bcm43xx_private *bcm) -{ - assert(bcm43xx_using_pio(bcm)); - return &(bcm43xx_current_80211_priv(bcm)->pio); -} -static inline -struct bcm43xx_dma * bcm43xx_current_dma(struct bcm43xx_private *bcm) -{ - assert(!bcm43xx_using_pio(bcm)); - return &(bcm43xx_current_80211_priv(bcm)->dma); -} -static inline -struct bcm43xx_phyinfo * bcm43xx_current_phy(struct bcm43xx_private *bcm) -{ - return &(bcm43xx_current_80211_priv(bcm)->phy); -} -static inline -struct bcm43xx_radioinfo * bcm43xx_current_radio(struct bcm43xx_private *bcm) -{ - return &(bcm43xx_current_80211_priv(bcm)->radio); -} - - -static inline -struct bcm43xx_lopair * bcm43xx_get_lopair(struct bcm43xx_phyinfo *phy, - u16 radio_attenuation, - u16 baseband_attenuation) -{ - return phy->_lo_pairs + (radio_attenuation + 14 * (baseband_attenuation / 2)); -} - - -static inline -u16 bcm43xx_read16(struct bcm43xx_private *bcm, u16 offset) -{ - return ioread16(bcm->mmio_addr + offset); -} - -static inline -void bcm43xx_write16(struct bcm43xx_private *bcm, u16 offset, u16 value) -{ - iowrite16(value, bcm->mmio_addr + offset); -} - -static inline -u32 bcm43xx_read32(struct bcm43xx_private *bcm, u16 offset) -{ - return ioread32(bcm->mmio_addr + offset); -} - -static inline -void bcm43xx_write32(struct bcm43xx_private *bcm, u16 offset, u32 value) -{ - iowrite32(value, bcm->mmio_addr + offset); -} - -static inline -int bcm43xx_pci_read_config16(struct bcm43xx_private *bcm, int offset, u16 *value) -{ - return pci_read_config_word(bcm->pci_dev, offset, value); -} - -static inline -int bcm43xx_pci_read_config32(struct bcm43xx_private *bcm, int offset, u32 *value) -{ - return pci_read_config_dword(bcm->pci_dev, offset, value); -} - -static inline -int bcm43xx_pci_write_config16(struct bcm43xx_private *bcm, int offset, u16 value) -{ - return pci_write_config_word(bcm->pci_dev, offset, value); -} - -static inline -int bcm43xx_pci_write_config32(struct bcm43xx_private *bcm, int offset, u32 value) -{ - return pci_write_config_dword(bcm->pci_dev, offset, value); -} - -/** Limit a value between two limits */ -#ifdef limit_value -# undef limit_value -#endif -#define limit_value(value, min, max) \ - ({ \ - typeof(value) __value = (value); \ - typeof(value) __min = (min); \ - typeof(value) __max = (max); \ - if (__value < __min) \ - __value = __min; \ - else if (__value > __max) \ - __value = __max; \ - __value; \ - }) - -#endif /* BCM43xx_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c deleted file mode 100644 index 76e9dd843faa..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c +++ /dev/null @@ -1,556 +0,0 @@ -/* - - Broadcom BCM43xx wireless driver - - debugfs driver debugging code - - Copyright (c) 2005 Michael Buesch - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - - - -#include -#include -#include -#include -#include -#include - -#include "bcm43xx.h" -#include "bcm43xx_main.h" -#include "bcm43xx_debugfs.h" -#include "bcm43xx_dma.h" -#include "bcm43xx_pio.h" -#include "bcm43xx_xmit.h" - -#define REALLY_BIG_BUFFER_SIZE (1024*256) - -static struct bcm43xx_debugfs fs; -static char really_big_buffer[REALLY_BIG_BUFFER_SIZE]; -static DECLARE_MUTEX(big_buffer_sem); - - -static ssize_t write_file_dummy(struct file *file, const char __user *buf, - size_t count, loff_t *ppos) -{ - return count; -} - -static int open_file_generic(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - -#define fappend(fmt, x...) pos += snprintf(buf + pos, len - pos, fmt , ##x) - -static ssize_t devinfo_read_file(struct file *file, char __user *userbuf, - size_t count, loff_t *ppos) -{ - const size_t len = REALLY_BIG_BUFFER_SIZE; - - struct bcm43xx_private *bcm = file->private_data; - char *buf = really_big_buffer; - size_t pos = 0; - ssize_t res; - struct net_device *net_dev; - struct pci_dev *pci_dev; - unsigned long flags; - u16 tmp16; - int i; - - down(&big_buffer_sem); - - mutex_lock(&bcm->mutex); - spin_lock_irqsave(&bcm->irq_lock, flags); - if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) { - fappend("Board not initialized.\n"); - goto out; - } - net_dev = bcm->net_dev; - pci_dev = bcm->pci_dev; - - /* This is where the information is written to the "devinfo" file */ - fappend("*** %s devinfo ***\n", net_dev->name); - fappend("vendor: 0x%04x device: 0x%04x\n", - pci_dev->vendor, pci_dev->device); - fappend("subsystem_vendor: 0x%04x subsystem_device: 0x%04x\n", - pci_dev->subsystem_vendor, pci_dev->subsystem_device); - fappend("IRQ: %d\n", bcm->irq); - fappend("mmio_addr: 0x%p\n", bcm->mmio_addr); - fappend("chip_id: 0x%04x chip_rev: 0x%02x\n", bcm->chip_id, bcm->chip_rev); - if ((bcm->core_80211[0].rev >= 3) && (bcm43xx_read32(bcm, 0x0158) & (1 << 16))) - fappend("Radio disabled by hardware!\n"); - if ((bcm->core_80211[0].rev < 3) && !(bcm43xx_read16(bcm, 0x049A) & (1 << 4))) - fappend("Radio disabled by hardware!\n"); - fappend("board_vendor: 0x%04x board_type: 0x%04x\n", bcm->board_vendor, - bcm->board_type); - - fappend("\nCores:\n"); -#define fappend_core(name, info) fappend("core \"" name "\" %s, %s, id: 0x%04x, " \ - "rev: 0x%02x, index: 0x%02x\n", \ - (info).available \ - ? "available" : "nonavailable", \ - (info).enabled \ - ? "enabled" : "disabled", \ - (info).id, (info).rev, (info).index) - fappend_core("CHIPCOMMON", bcm->core_chipcommon); - fappend_core("PCI", bcm->core_pci); - fappend_core("first 80211", bcm->core_80211[0]); - fappend_core("second 80211", bcm->core_80211[1]); -#undef fappend_core - tmp16 = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL); - fappend("LEDs: "); - for (i = 0; i < BCM43xx_NR_LEDS; i++) - fappend("%d ", !!(tmp16 & (1 << i))); - fappend("\n"); - -out: - spin_unlock_irqrestore(&bcm->irq_lock, flags); - mutex_unlock(&bcm->mutex); - res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); - up(&big_buffer_sem); - return res; -} - -static ssize_t drvinfo_read_file(struct file *file, char __user *userbuf, - size_t count, loff_t *ppos) -{ - const size_t len = REALLY_BIG_BUFFER_SIZE; - - char *buf = really_big_buffer; - size_t pos = 0; - ssize_t res; - - down(&big_buffer_sem); - - /* This is where the information is written to the "driver" file */ - fappend(KBUILD_MODNAME " driver\n"); - fappend("Compiled at: %s %s\n", __DATE__, __TIME__); - - res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); - up(&big_buffer_sem); - return res; -} - -static ssize_t spromdump_read_file(struct file *file, char __user *userbuf, - size_t count, loff_t *ppos) -{ - const size_t len = REALLY_BIG_BUFFER_SIZE; - - struct bcm43xx_private *bcm = file->private_data; - char *buf = really_big_buffer; - size_t pos = 0; - ssize_t res; - unsigned long flags; - - down(&big_buffer_sem); - mutex_lock(&bcm->mutex); - spin_lock_irqsave(&bcm->irq_lock, flags); - if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) { - fappend("Board not initialized.\n"); - goto out; - } - - /* This is where the information is written to the "sprom_dump" file */ - fappend("boardflags: 0x%04x\n", bcm->sprom.boardflags); - -out: - spin_unlock_irqrestore(&bcm->irq_lock, flags); - mutex_unlock(&bcm->mutex); - res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); - up(&big_buffer_sem); - return res; -} - -static ssize_t tsf_read_file(struct file *file, char __user *userbuf, - size_t count, loff_t *ppos) -{ - const size_t len = REALLY_BIG_BUFFER_SIZE; - - struct bcm43xx_private *bcm = file->private_data; - char *buf = really_big_buffer; - size_t pos = 0; - ssize_t res; - unsigned long flags; - u64 tsf; - - down(&big_buffer_sem); - mutex_lock(&bcm->mutex); - spin_lock_irqsave(&bcm->irq_lock, flags); - if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) { - fappend("Board not initialized.\n"); - goto out; - } - bcm43xx_tsf_read(bcm, &tsf); - fappend("0x%08x%08x\n", - (unsigned int)((tsf & 0xFFFFFFFF00000000ULL) >> 32), - (unsigned int)(tsf & 0xFFFFFFFFULL)); - -out: - spin_unlock_irqrestore(&bcm->irq_lock, flags); - mutex_unlock(&bcm->mutex); - res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); - up(&big_buffer_sem); - return res; -} - -static ssize_t tsf_write_file(struct file *file, const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct bcm43xx_private *bcm = file->private_data; - char *buf = really_big_buffer; - ssize_t buf_size; - ssize_t res; - unsigned long flags; - unsigned long long tsf; - - buf_size = min(count, sizeof (really_big_buffer) - 1); - down(&big_buffer_sem); - if (copy_from_user(buf, user_buf, buf_size)) { - res = -EFAULT; - goto out_up; - } - mutex_lock(&bcm->mutex); - spin_lock_irqsave(&bcm->irq_lock, flags); - if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) { - printk(KERN_INFO PFX "debugfs: Board not initialized.\n"); - res = -EFAULT; - goto out_unlock; - } - if (sscanf(buf, "%lli", &tsf) != 1) { - printk(KERN_INFO PFX "debugfs: invalid values for \"tsf\"\n"); - res = -EINVAL; - goto out_unlock; - } - bcm43xx_tsf_write(bcm, tsf); - mmiowb(); - res = buf_size; - -out_unlock: - spin_unlock_irqrestore(&bcm->irq_lock, flags); - mutex_unlock(&bcm->mutex); -out_up: - up(&big_buffer_sem); - return res; -} - -static ssize_t txstat_read_file(struct file *file, char __user *userbuf, - size_t count, loff_t *ppos) -{ - const size_t len = REALLY_BIG_BUFFER_SIZE; - - struct bcm43xx_private *bcm = file->private_data; - char *buf = really_big_buffer; - size_t pos = 0; - ssize_t res; - unsigned long flags; - struct bcm43xx_dfsentry *e; - struct bcm43xx_xmitstatus *status; - int i, cnt, j = 0; - - down(&big_buffer_sem); - mutex_lock(&bcm->mutex); - spin_lock_irqsave(&bcm->irq_lock, flags); - - fappend("Last %d logged xmitstatus blobs (Latest first):\n\n", - BCM43xx_NR_LOGGED_XMITSTATUS); - e = bcm->dfsentry; - if (e->xmitstatus_printing == 0) { - /* At the beginning, make a copy of all data to avoid - * concurrency, as this function is called multiple - * times for big logs. Without copying, the data might - * change between reads. This would result in total trash. - */ - e->xmitstatus_printing = 1; - e->saved_xmitstatus_ptr = e->xmitstatus_ptr; - e->saved_xmitstatus_cnt = e->xmitstatus_cnt; - memcpy(e->xmitstatus_print_buffer, e->xmitstatus_buffer, - BCM43xx_NR_LOGGED_XMITSTATUS * sizeof(*(e->xmitstatus_buffer))); - } - i = e->saved_xmitstatus_ptr - 1; - if (i < 0) - i = BCM43xx_NR_LOGGED_XMITSTATUS - 1; - cnt = e->saved_xmitstatus_cnt; - while (cnt) { - status = e->xmitstatus_print_buffer + i; - fappend("0x%02x: cookie: 0x%04x, flags: 0x%02x, " - "cnt1: 0x%02x, cnt2: 0x%02x, seq: 0x%04x, " - "unk: 0x%04x\n", j, - status->cookie, status->flags, - status->cnt1, status->cnt2, status->seq, - status->unknown); - j++; - cnt--; - i--; - if (i < 0) - i = BCM43xx_NR_LOGGED_XMITSTATUS - 1; - } - - spin_unlock_irqrestore(&bcm->irq_lock, flags); - res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); - spin_lock_irqsave(&bcm->irq_lock, flags); - if (*ppos == pos) { - /* Done. Drop the copied data. */ - e->xmitstatus_printing = 0; - } - spin_unlock_irqrestore(&bcm->irq_lock, flags); - mutex_unlock(&bcm->mutex); - up(&big_buffer_sem); - return res; -} - -static ssize_t restart_write_file(struct file *file, const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct bcm43xx_private *bcm = file->private_data; - char *buf = really_big_buffer; - ssize_t buf_size; - ssize_t res; - unsigned long flags; - - buf_size = min(count, sizeof (really_big_buffer) - 1); - down(&big_buffer_sem); - if (copy_from_user(buf, user_buf, buf_size)) { - res = -EFAULT; - goto out_up; - } - mutex_lock(&(bcm)->mutex); - spin_lock_irqsave(&(bcm)->irq_lock, flags); - if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) { - printk(KERN_INFO PFX "debugfs: Board not initialized.\n"); - res = -EFAULT; - goto out_unlock; - } - if (count > 0 && buf[0] == '1') { - bcm43xx_controller_restart(bcm, "manually restarted"); - res = count; - } else - res = -EINVAL; - -out_unlock: - spin_unlock_irqrestore(&(bcm)->irq_lock, flags); - mutex_unlock(&(bcm)->mutex); -out_up: - up(&big_buffer_sem); - return res; -} - -#undef fappend - - -static const struct file_operations devinfo_fops = { - .read = devinfo_read_file, - .write = write_file_dummy, - .open = open_file_generic, -}; - -static const struct file_operations spromdump_fops = { - .read = spromdump_read_file, - .write = write_file_dummy, - .open = open_file_generic, -}; - -static const struct file_operations drvinfo_fops = { - .read = drvinfo_read_file, - .write = write_file_dummy, - .open = open_file_generic, -}; - -static const struct file_operations tsf_fops = { - .read = tsf_read_file, - .write = tsf_write_file, - .open = open_file_generic, -}; - -static const struct file_operations txstat_fops = { - .read = txstat_read_file, - .write = write_file_dummy, - .open = open_file_generic, -}; - -static const struct file_operations restart_fops = { - .write = restart_write_file, - .open = open_file_generic, -}; - - -void bcm43xx_debugfs_add_device(struct bcm43xx_private *bcm) -{ - struct bcm43xx_dfsentry *e; - char devdir[IFNAMSIZ]; - - assert(bcm); - e = kzalloc(sizeof(*e), GFP_KERNEL); - if (!e) { - printk(KERN_ERR PFX "out of memory\n"); - return; - } - e->bcm = bcm; - e->xmitstatus_buffer = kzalloc(BCM43xx_NR_LOGGED_XMITSTATUS - * sizeof(*(e->xmitstatus_buffer)), - GFP_KERNEL); - if (!e->xmitstatus_buffer) { - printk(KERN_ERR PFX "out of memory\n"); - kfree(e); - return; - } - e->xmitstatus_print_buffer = kzalloc(BCM43xx_NR_LOGGED_XMITSTATUS - * sizeof(*(e->xmitstatus_buffer)), - GFP_KERNEL); - if (!e->xmitstatus_print_buffer) { - printk(KERN_ERR PFX "out of memory\n"); - kfree(e); - return; - } - - - bcm->dfsentry = e; - - strncpy(devdir, bcm->net_dev->name, ARRAY_SIZE(devdir)); - e->subdir = debugfs_create_dir(devdir, fs.root); - e->dentry_devinfo = debugfs_create_file("devinfo", 0444, e->subdir, - bcm, &devinfo_fops); - if (!e->dentry_devinfo) - printk(KERN_ERR PFX "debugfs: creating \"devinfo\" for \"%s\" failed!\n", devdir); - e->dentry_spromdump = debugfs_create_file("sprom_dump", 0444, e->subdir, - bcm, &spromdump_fops); - if (!e->dentry_spromdump) - printk(KERN_ERR PFX "debugfs: creating \"sprom_dump\" for \"%s\" failed!\n", devdir); - e->dentry_tsf = debugfs_create_file("tsf", 0666, e->subdir, - bcm, &tsf_fops); - if (!e->dentry_tsf) - printk(KERN_ERR PFX "debugfs: creating \"tsf\" for \"%s\" failed!\n", devdir); - e->dentry_txstat = debugfs_create_file("tx_status", 0444, e->subdir, - bcm, &txstat_fops); - if (!e->dentry_txstat) - printk(KERN_ERR PFX "debugfs: creating \"tx_status\" for \"%s\" failed!\n", devdir); - e->dentry_restart = debugfs_create_file("restart", 0222, e->subdir, - bcm, &restart_fops); - if (!e->dentry_restart) - printk(KERN_ERR PFX "debugfs: creating \"restart\" for \"%s\" failed!\n", devdir); -} - -void bcm43xx_debugfs_remove_device(struct bcm43xx_private *bcm) -{ - struct bcm43xx_dfsentry *e; - - if (!bcm) - return; - - e = bcm->dfsentry; - assert(e); - debugfs_remove(e->dentry_spromdump); - debugfs_remove(e->dentry_devinfo); - debugfs_remove(e->dentry_tsf); - debugfs_remove(e->dentry_txstat); - debugfs_remove(e->dentry_restart); - debugfs_remove(e->subdir); - kfree(e->xmitstatus_buffer); - kfree(e->xmitstatus_print_buffer); - kfree(e); -} - -void bcm43xx_debugfs_log_txstat(struct bcm43xx_private *bcm, - struct bcm43xx_xmitstatus *status) -{ - struct bcm43xx_dfsentry *e; - struct bcm43xx_xmitstatus *savedstatus; - - /* This is protected by bcm->_lock */ - e = bcm->dfsentry; - assert(e); - savedstatus = e->xmitstatus_buffer + e->xmitstatus_ptr; - memcpy(savedstatus, status, sizeof(*status)); - e->xmitstatus_ptr++; - if (e->xmitstatus_ptr >= BCM43xx_NR_LOGGED_XMITSTATUS) - e->xmitstatus_ptr = 0; - if (e->xmitstatus_cnt < BCM43xx_NR_LOGGED_XMITSTATUS) - e->xmitstatus_cnt++; -} - -void bcm43xx_debugfs_init(void) -{ - memset(&fs, 0, sizeof(fs)); - fs.root = debugfs_create_dir(KBUILD_MODNAME, NULL); - if (!fs.root) - printk(KERN_ERR PFX "debugfs: creating \"" KBUILD_MODNAME "\" subdir failed!\n"); - fs.dentry_driverinfo = debugfs_create_file("driver", 0444, fs.root, NULL, &drvinfo_fops); - if (!fs.dentry_driverinfo) - printk(KERN_ERR PFX "debugfs: creating \"" KBUILD_MODNAME "/driver\" failed!\n"); -} - -void bcm43xx_debugfs_exit(void) -{ - debugfs_remove(fs.dentry_driverinfo); - debugfs_remove(fs.root); -} - -void bcm43xx_printk_dump(const char *data, - size_t size, - const char *description) -{ - size_t i; - char c; - - printk(KERN_INFO PFX "Data dump (%s, %zd bytes):", - description, size); - for (i = 0; i < size; i++) { - c = data[i]; - if (i % 8 == 0) - printk("\n" KERN_INFO PFX "0x%08zx: 0x%02x, ", i, c & 0xff); - else - printk("0x%02x, ", c & 0xff); - } - printk("\n"); -} - -void bcm43xx_printk_bitdump(const unsigned char *data, - size_t bytes, int msb_to_lsb, - const char *description) -{ - size_t i; - int j; - const unsigned char *d; - - printk(KERN_INFO PFX "*** Bitdump (%s, %zd bytes, %s) ***", - description, bytes, msb_to_lsb ? "MSB to LSB" : "LSB to MSB"); - for (i = 0; i < bytes; i++) { - d = data + i; - if (i % 8 == 0) - printk("\n" KERN_INFO PFX "0x%08zx: ", i); - if (msb_to_lsb) { - for (j = 7; j >= 0; j--) { - if (*d & (1 << j)) - printk("1"); - else - printk("0"); - } - } else { - for (j = 0; j < 8; j++) { - if (*d & (1 << j)) - printk("1"); - else - printk("0"); - } - } - printk(" "); - } - printk("\n"); -} diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h deleted file mode 100644 index a40d1af35545..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h +++ /dev/null @@ -1,118 +0,0 @@ -#ifndef BCM43xx_DEBUGFS_H_ -#define BCM43xx_DEBUGFS_H_ - -struct bcm43xx_private; -struct bcm43xx_xmitstatus; - -#ifdef CONFIG_BCM43XX_DEBUG - -#include -#include - -struct dentry; - -/* limited by the size of the "really_big_buffer" */ -#define BCM43xx_NR_LOGGED_XMITSTATUS 100 - -struct bcm43xx_dfsentry { - struct dentry *subdir; - struct dentry *dentry_devinfo; - struct dentry *dentry_spromdump; - struct dentry *dentry_tsf; - struct dentry *dentry_txstat; - struct dentry *dentry_restart; - - struct bcm43xx_private *bcm; - - /* saved xmitstatus. */ - struct bcm43xx_xmitstatus *xmitstatus_buffer; - int xmitstatus_ptr; - int xmitstatus_cnt; - /* We need a seperate buffer while printing to avoid - * concurrency issues. (New xmitstatus can arrive - * while we are printing). - */ - struct bcm43xx_xmitstatus *xmitstatus_print_buffer; - int saved_xmitstatus_ptr; - int saved_xmitstatus_cnt; - int xmitstatus_printing; -}; - -struct bcm43xx_debugfs { - struct dentry *root; - struct dentry *dentry_driverinfo; -}; - -void bcm43xx_debugfs_init(void); -void bcm43xx_debugfs_exit(void); -void bcm43xx_debugfs_add_device(struct bcm43xx_private *bcm); -void bcm43xx_debugfs_remove_device(struct bcm43xx_private *bcm); -void bcm43xx_debugfs_log_txstat(struct bcm43xx_private *bcm, - struct bcm43xx_xmitstatus *status); - -/* Debug helper: Dump binary data through printk. */ -void bcm43xx_printk_dump(const char *data, - size_t size, - const char *description); -/* Debug helper: Dump bitwise binary data through printk. */ -void bcm43xx_printk_bitdump(const unsigned char *data, - size_t bytes, int msb_to_lsb, - const char *description); -#define bcm43xx_printk_bitdumpt(pointer, msb_to_lsb, description) \ - do { \ - bcm43xx_printk_bitdump((const unsigned char *)(pointer), \ - sizeof(*(pointer)), \ - (msb_to_lsb), \ - (description)); \ - } while (0) - -#else /* CONFIG_BCM43XX_DEBUG*/ - -static inline -void bcm43xx_debugfs_init(void) { } -static inline -void bcm43xx_debugfs_exit(void) { } -static inline -void bcm43xx_debugfs_add_device(struct bcm43xx_private *bcm) { } -static inline -void bcm43xx_debugfs_remove_device(struct bcm43xx_private *bcm) { } -static inline -void bcm43xx_debugfs_log_txstat(struct bcm43xx_private *bcm, - struct bcm43xx_xmitstatus *status) { } - -static inline -void bcm43xx_printk_dump(const char *data, - size_t size, - const char *description) -{ -} -static inline -void bcm43xx_printk_bitdump(const unsigned char *data, - size_t bytes, int msb_to_lsb, - const char *description) -{ -} -#define bcm43xx_printk_bitdumpt(pointer, msb_to_lsb, description) do { /* nothing */ } while (0) - -#endif /* CONFIG_BCM43XX_DEBUG*/ - -/* Ugly helper macros to make incomplete code more verbose on runtime */ -#ifdef TODO -# undef TODO -#endif -#define TODO() \ - do { \ - printk(KERN_INFO PFX "TODO: Incomplete code in %s() at %s:%d\n", \ - __FUNCTION__, __FILE__, __LINE__); \ - } while (0) - -#ifdef FIXME -# undef FIXME -#endif -#define FIXME() \ - do { \ - printk(KERN_INFO PFX "FIXME: Possibly broken code in %s() at %s:%d\n", \ - __FUNCTION__, __FILE__, __LINE__); \ - } while (0) - -#endif /* BCM43xx_DEBUGFS_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c deleted file mode 100644 index 1f7731fcfbd5..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c +++ /dev/null @@ -1,1263 +0,0 @@ -/* - - Broadcom BCM43xx wireless driver - - DMA ringbuffer and descriptor allocation/management - - Copyright (c) 2005, 2006 Michael Buesch - - Some code in this file is derived from the b44.c driver - Copyright (C) 2002 David S. Miller - Copyright (C) Pekka Pietikainen - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include "bcm43xx.h" -#include "bcm43xx_dma.h" -#include "bcm43xx_main.h" -#include "bcm43xx_debugfs.h" -#include "bcm43xx_power.h" -#include "bcm43xx_xmit.h" - -#include -#include -#include -#include - - -static inline int free_slots(struct bcm43xx_dmaring *ring) -{ - return (ring->nr_slots - ring->used_slots); -} - -static inline int next_slot(struct bcm43xx_dmaring *ring, int slot) -{ - assert(slot >= -1 && slot <= ring->nr_slots - 1); - if (slot == ring->nr_slots - 1) - return 0; - return slot + 1; -} - -static inline int prev_slot(struct bcm43xx_dmaring *ring, int slot) -{ - assert(slot >= 0 && slot <= ring->nr_slots - 1); - if (slot == 0) - return ring->nr_slots - 1; - return slot - 1; -} - -/* Request a slot for usage. */ -static inline -int request_slot(struct bcm43xx_dmaring *ring) -{ - int slot; - - assert(ring->tx); - assert(!ring->suspended); - assert(free_slots(ring) != 0); - - slot = next_slot(ring, ring->current_slot); - ring->current_slot = slot; - ring->used_slots++; - - /* Check the number of available slots and suspend TX, - * if we are running low on free slots. - */ - if (unlikely(free_slots(ring) < ring->suspend_mark)) { - netif_stop_queue(ring->bcm->net_dev); - ring->suspended = 1; - } -#ifdef CONFIG_BCM43XX_DEBUG - if (ring->used_slots > ring->max_used_slots) - ring->max_used_slots = ring->used_slots; -#endif /* CONFIG_BCM43XX_DEBUG*/ - - return slot; -} - -/* Return a slot to the free slots. */ -static inline -void return_slot(struct bcm43xx_dmaring *ring, int slot) -{ - assert(ring->tx); - - ring->used_slots--; - - /* Check if TX is suspended and check if we have - * enough free slots to resume it again. - */ - if (unlikely(ring->suspended)) { - if (free_slots(ring) >= ring->resume_mark) { - ring->suspended = 0; - netif_wake_queue(ring->bcm->net_dev); - } - } -} - -u16 bcm43xx_dmacontroller_base(int dma64bit, int controller_idx) -{ - static const u16 map64[] = { - BCM43xx_MMIO_DMA64_BASE0, - BCM43xx_MMIO_DMA64_BASE1, - BCM43xx_MMIO_DMA64_BASE2, - BCM43xx_MMIO_DMA64_BASE3, - BCM43xx_MMIO_DMA64_BASE4, - BCM43xx_MMIO_DMA64_BASE5, - }; - static const u16 map32[] = { - BCM43xx_MMIO_DMA32_BASE0, - BCM43xx_MMIO_DMA32_BASE1, - BCM43xx_MMIO_DMA32_BASE2, - BCM43xx_MMIO_DMA32_BASE3, - BCM43xx_MMIO_DMA32_BASE4, - BCM43xx_MMIO_DMA32_BASE5, - }; - - if (dma64bit) { - assert(controller_idx >= 0 && - controller_idx < ARRAY_SIZE(map64)); - return map64[controller_idx]; - } - assert(controller_idx >= 0 && - controller_idx < ARRAY_SIZE(map32)); - return map32[controller_idx]; -} - -static inline -dma_addr_t map_descbuffer(struct bcm43xx_dmaring *ring, - unsigned char *buf, - size_t len, - int tx) -{ - dma_addr_t dmaaddr; - int direction = PCI_DMA_FROMDEVICE; - - if (tx) - direction = PCI_DMA_TODEVICE; - - dmaaddr = pci_map_single(ring->bcm->pci_dev, - buf, len, - direction); - - return dmaaddr; -} - -static inline -void unmap_descbuffer(struct bcm43xx_dmaring *ring, - dma_addr_t addr, - size_t len, - int tx) -{ - if (tx) { - pci_unmap_single(ring->bcm->pci_dev, - addr, len, - PCI_DMA_TODEVICE); - } else { - pci_unmap_single(ring->bcm->pci_dev, - addr, len, - PCI_DMA_FROMDEVICE); - } -} - -static inline -void sync_descbuffer_for_cpu(struct bcm43xx_dmaring *ring, - dma_addr_t addr, - size_t len) -{ - assert(!ring->tx); - - pci_dma_sync_single_for_cpu(ring->bcm->pci_dev, - addr, len, PCI_DMA_FROMDEVICE); -} - -static inline -void sync_descbuffer_for_device(struct bcm43xx_dmaring *ring, - dma_addr_t addr, - size_t len) -{ - assert(!ring->tx); - - pci_dma_sync_single_for_cpu(ring->bcm->pci_dev, - addr, len, PCI_DMA_TODEVICE); -} - -/* Unmap and free a descriptor buffer. */ -static inline -void free_descriptor_buffer(struct bcm43xx_dmaring *ring, - struct bcm43xx_dmadesc_meta *meta, - int irq_context) -{ - assert(meta->skb); - if (irq_context) - dev_kfree_skb_irq(meta->skb); - else - dev_kfree_skb(meta->skb); - meta->skb = NULL; -} - -static int alloc_ringmemory(struct bcm43xx_dmaring *ring) -{ - ring->descbase = pci_alloc_consistent(ring->bcm->pci_dev, BCM43xx_DMA_RINGMEMSIZE, - &(ring->dmabase)); - if (!ring->descbase) { - /* Allocation may have failed due to pci_alloc_consistent - insisting on use of GFP_DMA, which is more restrictive - than necessary... */ - struct dma_desc *rx_ring; - dma_addr_t rx_ring_dma; - - rx_ring = kzalloc(BCM43xx_DMA_RINGMEMSIZE, GFP_KERNEL); - if (!rx_ring) - goto out_err; - - rx_ring_dma = pci_map_single(ring->bcm->pci_dev, rx_ring, - BCM43xx_DMA_RINGMEMSIZE, - PCI_DMA_BIDIRECTIONAL); - - if (pci_dma_mapping_error(rx_ring_dma) || - rx_ring_dma + BCM43xx_DMA_RINGMEMSIZE > ring->bcm->dma_mask) { - /* Sigh... */ - if (!pci_dma_mapping_error(rx_ring_dma)) - pci_unmap_single(ring->bcm->pci_dev, - rx_ring_dma, BCM43xx_DMA_RINGMEMSIZE, - PCI_DMA_BIDIRECTIONAL); - rx_ring_dma = pci_map_single(ring->bcm->pci_dev, - rx_ring, BCM43xx_DMA_RINGMEMSIZE, - PCI_DMA_BIDIRECTIONAL); - if (pci_dma_mapping_error(rx_ring_dma) || - rx_ring_dma + BCM43xx_DMA_RINGMEMSIZE > ring->bcm->dma_mask) { - assert(0); - if (!pci_dma_mapping_error(rx_ring_dma)) - pci_unmap_single(ring->bcm->pci_dev, - rx_ring_dma, BCM43xx_DMA_RINGMEMSIZE, - PCI_DMA_BIDIRECTIONAL); - goto out_err; - } - } - - ring->descbase = rx_ring; - ring->dmabase = rx_ring_dma; - } - memset(ring->descbase, 0, BCM43xx_DMA_RINGMEMSIZE); - - return 0; -out_err: - printk(KERN_ERR PFX "DMA ringmemory allocation failed\n"); - return -ENOMEM; -} - -static void free_ringmemory(struct bcm43xx_dmaring *ring) -{ - struct device *dev = &(ring->bcm->pci_dev->dev); - - dma_free_coherent(dev, BCM43xx_DMA_RINGMEMSIZE, - ring->descbase, ring->dmabase); -} - -/* Reset the RX DMA channel */ -int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm, - u16 mmio_base, int dma64) -{ - int i; - u32 value; - u16 offset; - - offset = dma64 ? BCM43xx_DMA64_RXCTL : BCM43xx_DMA32_RXCTL; - bcm43xx_write32(bcm, mmio_base + offset, 0); - for (i = 0; i < 1000; i++) { - offset = dma64 ? BCM43xx_DMA64_RXSTATUS : BCM43xx_DMA32_RXSTATUS; - value = bcm43xx_read32(bcm, mmio_base + offset); - if (dma64) { - value &= BCM43xx_DMA64_RXSTAT; - if (value == BCM43xx_DMA64_RXSTAT_DISABLED) { - i = -1; - break; - } - } else { - value &= BCM43xx_DMA32_RXSTATE; - if (value == BCM43xx_DMA32_RXSTAT_DISABLED) { - i = -1; - break; - } - } - udelay(10); - } - if (i != -1) { - printk(KERN_ERR PFX "Error: Wait on DMA RX status timed out.\n"); - return -ENODEV; - } - - return 0; -} - -/* Reset the RX DMA channel */ -int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm, - u16 mmio_base, int dma64) -{ - int i; - u32 value; - u16 offset; - - for (i = 0; i < 1000; i++) { - offset = dma64 ? BCM43xx_DMA64_TXSTATUS : BCM43xx_DMA32_TXSTATUS; - value = bcm43xx_read32(bcm, mmio_base + offset); - if (dma64) { - value &= BCM43xx_DMA64_TXSTAT; - if (value == BCM43xx_DMA64_TXSTAT_DISABLED || - value == BCM43xx_DMA64_TXSTAT_IDLEWAIT || - value == BCM43xx_DMA64_TXSTAT_STOPPED) - break; - } else { - value &= BCM43xx_DMA32_TXSTATE; - if (value == BCM43xx_DMA32_TXSTAT_DISABLED || - value == BCM43xx_DMA32_TXSTAT_IDLEWAIT || - value == BCM43xx_DMA32_TXSTAT_STOPPED) - break; - } - udelay(10); - } - offset = dma64 ? BCM43xx_DMA64_TXCTL : BCM43xx_DMA32_TXCTL; - bcm43xx_write32(bcm, mmio_base + offset, 0); - for (i = 0; i < 1000; i++) { - offset = dma64 ? BCM43xx_DMA64_TXSTATUS : BCM43xx_DMA32_TXSTATUS; - value = bcm43xx_read32(bcm, mmio_base + offset); - if (dma64) { - value &= BCM43xx_DMA64_TXSTAT; - if (value == BCM43xx_DMA64_TXSTAT_DISABLED) { - i = -1; - break; - } - } else { - value &= BCM43xx_DMA32_TXSTATE; - if (value == BCM43xx_DMA32_TXSTAT_DISABLED) { - i = -1; - break; - } - } - udelay(10); - } - if (i != -1) { - printk(KERN_ERR PFX "Error: Wait on DMA TX status timed out.\n"); - return -ENODEV; - } - /* ensure the reset is completed. */ - udelay(300); - - return 0; -} - -static void fill_descriptor(struct bcm43xx_dmaring *ring, - struct bcm43xx_dmadesc_generic *desc, - dma_addr_t dmaaddr, - u16 bufsize, - int start, int end, int irq) -{ - int slot; - - slot = bcm43xx_dma_desc2idx(ring, desc); - assert(slot >= 0 && slot < ring->nr_slots); - - if (ring->dma64) { - u32 ctl0 = 0, ctl1 = 0; - u32 addrlo, addrhi; - u32 addrext; - - addrlo = (u32)(dmaaddr & 0xFFFFFFFF); - addrhi = (((u64)dmaaddr >> 32) & ~BCM43xx_DMA64_ROUTING); - addrext = (((u64)dmaaddr >> 32) >> BCM43xx_DMA64_ROUTING_SHIFT); - addrhi |= ring->routing; - if (slot == ring->nr_slots - 1) - ctl0 |= BCM43xx_DMA64_DCTL0_DTABLEEND; - if (start) - ctl0 |= BCM43xx_DMA64_DCTL0_FRAMESTART; - if (end) - ctl0 |= BCM43xx_DMA64_DCTL0_FRAMEEND; - if (irq) - ctl0 |= BCM43xx_DMA64_DCTL0_IRQ; - ctl1 |= (bufsize - ring->frameoffset) - & BCM43xx_DMA64_DCTL1_BYTECNT; - ctl1 |= (addrext << BCM43xx_DMA64_DCTL1_ADDREXT_SHIFT) - & BCM43xx_DMA64_DCTL1_ADDREXT_MASK; - - desc->dma64.control0 = cpu_to_le32(ctl0); - desc->dma64.control1 = cpu_to_le32(ctl1); - desc->dma64.address_low = cpu_to_le32(addrlo); - desc->dma64.address_high = cpu_to_le32(addrhi); - } else { - u32 ctl; - u32 addr; - u32 addrext; - - addr = (u32)(dmaaddr & ~BCM43xx_DMA32_ROUTING); - addrext = (u32)(dmaaddr & BCM43xx_DMA32_ROUTING) - >> BCM43xx_DMA32_ROUTING_SHIFT; - addr |= ring->routing; - ctl = (bufsize - ring->frameoffset) - & BCM43xx_DMA32_DCTL_BYTECNT; - if (slot == ring->nr_slots - 1) - ctl |= BCM43xx_DMA32_DCTL_DTABLEEND; - if (start) - ctl |= BCM43xx_DMA32_DCTL_FRAMESTART; - if (end) - ctl |= BCM43xx_DMA32_DCTL_FRAMEEND; - if (irq) - ctl |= BCM43xx_DMA32_DCTL_IRQ; - ctl |= (addrext << BCM43xx_DMA32_DCTL_ADDREXT_SHIFT) - & BCM43xx_DMA32_DCTL_ADDREXT_MASK; - - desc->dma32.control = cpu_to_le32(ctl); - desc->dma32.address = cpu_to_le32(addr); - } -} - -static int setup_rx_descbuffer(struct bcm43xx_dmaring *ring, - struct bcm43xx_dmadesc_generic *desc, - struct bcm43xx_dmadesc_meta *meta, - gfp_t gfp_flags) -{ - struct bcm43xx_rxhdr *rxhdr; - struct bcm43xx_hwxmitstatus *xmitstat; - dma_addr_t dmaaddr; - struct sk_buff *skb; - - assert(!ring->tx); - - skb = __dev_alloc_skb(ring->rx_buffersize, gfp_flags); - if (unlikely(!skb)) - return -ENOMEM; - dmaaddr = map_descbuffer(ring, skb->data, ring->rx_buffersize, 0); - /* This hardware bug work-around adapted from the b44 driver. - The chip may be unable to do PCI DMA to/from anything above 1GB */ - if (pci_dma_mapping_error(dmaaddr) || - dmaaddr + ring->rx_buffersize > ring->bcm->dma_mask) { - /* This one has 30-bit addressing... */ - if (!pci_dma_mapping_error(dmaaddr)) - pci_unmap_single(ring->bcm->pci_dev, - dmaaddr, ring->rx_buffersize, - PCI_DMA_FROMDEVICE); - dev_kfree_skb_any(skb); - skb = __dev_alloc_skb(ring->rx_buffersize,GFP_DMA); - if (skb == NULL) - return -ENOMEM; - dmaaddr = pci_map_single(ring->bcm->pci_dev, - skb->data, ring->rx_buffersize, - PCI_DMA_FROMDEVICE); - if (pci_dma_mapping_error(dmaaddr) || - dmaaddr + ring->rx_buffersize > ring->bcm->dma_mask) { - assert(0); - dev_kfree_skb_any(skb); - return -ENOMEM; - } - } - meta->skb = skb; - meta->dmaaddr = dmaaddr; - skb->dev = ring->bcm->net_dev; - - fill_descriptor(ring, desc, dmaaddr, - ring->rx_buffersize, 0, 0, 0); - - rxhdr = (struct bcm43xx_rxhdr *)(skb->data); - rxhdr->frame_length = 0; - rxhdr->flags1 = 0; - xmitstat = (struct bcm43xx_hwxmitstatus *)(skb->data); - xmitstat->cookie = 0; - - return 0; -} - -/* Allocate the initial descbuffers. - * This is used for an RX ring only. - */ -static int alloc_initial_descbuffers(struct bcm43xx_dmaring *ring) -{ - int i, err = -ENOMEM; - struct bcm43xx_dmadesc_generic *desc; - struct bcm43xx_dmadesc_meta *meta; - - for (i = 0; i < ring->nr_slots; i++) { - desc = bcm43xx_dma_idx2desc(ring, i, &meta); - - err = setup_rx_descbuffer(ring, desc, meta, GFP_KERNEL); - if (err) - goto err_unwind; - } - mb(); - ring->used_slots = ring->nr_slots; - err = 0; -out: - return err; - -err_unwind: - for (i--; i >= 0; i--) { - desc = bcm43xx_dma_idx2desc(ring, i, &meta); - - unmap_descbuffer(ring, meta->dmaaddr, ring->rx_buffersize, 0); - dev_kfree_skb(meta->skb); - } - goto out; -} - -/* Do initial setup of the DMA controller. - * Reset the controller, write the ring busaddress - * and switch the "enable" bit on. - */ -static int dmacontroller_setup(struct bcm43xx_dmaring *ring) -{ - int err = 0; - u32 value; - u32 addrext; - - if (ring->tx) { - if (ring->dma64) { - u64 ringbase = (u64)(ring->dmabase); - - addrext = ((ringbase >> 32) >> BCM43xx_DMA64_ROUTING_SHIFT); - value = BCM43xx_DMA64_TXENABLE; - value |= (addrext << BCM43xx_DMA64_TXADDREXT_SHIFT) - & BCM43xx_DMA64_TXADDREXT_MASK; - bcm43xx_dma_write(ring, BCM43xx_DMA64_TXCTL, value); - bcm43xx_dma_write(ring, BCM43xx_DMA64_TXRINGLO, - (ringbase & 0xFFFFFFFF)); - bcm43xx_dma_write(ring, BCM43xx_DMA64_TXRINGHI, - ((ringbase >> 32) & ~BCM43xx_DMA64_ROUTING) - | ring->routing); - } else { - u32 ringbase = (u32)(ring->dmabase); - - addrext = (ringbase >> BCM43xx_DMA32_ROUTING_SHIFT); - value = BCM43xx_DMA32_TXENABLE; - value |= (addrext << BCM43xx_DMA32_TXADDREXT_SHIFT) - & BCM43xx_DMA32_TXADDREXT_MASK; - bcm43xx_dma_write(ring, BCM43xx_DMA32_TXCTL, value); - bcm43xx_dma_write(ring, BCM43xx_DMA32_TXRING, - (ringbase & ~BCM43xx_DMA32_ROUTING) - | ring->routing); - } - } else { - err = alloc_initial_descbuffers(ring); - if (err) - goto out; - if (ring->dma64) { - u64 ringbase = (u64)(ring->dmabase); - - addrext = ((ringbase >> 32) >> BCM43xx_DMA64_ROUTING_SHIFT); - value = (ring->frameoffset << BCM43xx_DMA64_RXFROFF_SHIFT); - value |= BCM43xx_DMA64_RXENABLE; - value |= (addrext << BCM43xx_DMA64_RXADDREXT_SHIFT) - & BCM43xx_DMA64_RXADDREXT_MASK; - bcm43xx_dma_write(ring, BCM43xx_DMA64_RXCTL, value); - bcm43xx_dma_write(ring, BCM43xx_DMA64_RXRINGLO, - (ringbase & 0xFFFFFFFF)); - bcm43xx_dma_write(ring, BCM43xx_DMA64_RXRINGHI, - ((ringbase >> 32) & ~BCM43xx_DMA64_ROUTING) - | ring->routing); - bcm43xx_dma_write(ring, BCM43xx_DMA64_RXINDEX, 200); - } else { - u32 ringbase = (u32)(ring->dmabase); - - addrext = (ringbase >> BCM43xx_DMA32_ROUTING_SHIFT); - value = (ring->frameoffset << BCM43xx_DMA32_RXFROFF_SHIFT); - value |= BCM43xx_DMA32_RXENABLE; - value |= (addrext << BCM43xx_DMA32_RXADDREXT_SHIFT) - & BCM43xx_DMA32_RXADDREXT_MASK; - bcm43xx_dma_write(ring, BCM43xx_DMA32_RXCTL, value); - bcm43xx_dma_write(ring, BCM43xx_DMA32_RXRING, - (ringbase & ~BCM43xx_DMA32_ROUTING) - | ring->routing); - bcm43xx_dma_write(ring, BCM43xx_DMA32_RXINDEX, 200); - } - } - -out: - return err; -} - -/* Shutdown the DMA controller. */ -static void dmacontroller_cleanup(struct bcm43xx_dmaring *ring) -{ - if (ring->tx) { - bcm43xx_dmacontroller_tx_reset(ring->bcm, ring->mmio_base, ring->dma64); - if (ring->dma64) { - bcm43xx_dma_write(ring, BCM43xx_DMA64_TXRINGLO, 0); - bcm43xx_dma_write(ring, BCM43xx_DMA64_TXRINGHI, 0); - } else - bcm43xx_dma_write(ring, BCM43xx_DMA32_TXRING, 0); - } else { - bcm43xx_dmacontroller_rx_reset(ring->bcm, ring->mmio_base, ring->dma64); - if (ring->dma64) { - bcm43xx_dma_write(ring, BCM43xx_DMA64_RXRINGLO, 0); - bcm43xx_dma_write(ring, BCM43xx_DMA64_RXRINGHI, 0); - } else - bcm43xx_dma_write(ring, BCM43xx_DMA32_RXRING, 0); - } -} - -static void free_all_descbuffers(struct bcm43xx_dmaring *ring) -{ - struct bcm43xx_dmadesc_generic *desc; - struct bcm43xx_dmadesc_meta *meta; - int i; - - if (!ring->used_slots) - return; - for (i = 0; i < ring->nr_slots; i++) { - desc = bcm43xx_dma_idx2desc(ring, i, &meta); - - if (!meta->skb) { - assert(ring->tx); - continue; - } - if (ring->tx) { - unmap_descbuffer(ring, meta->dmaaddr, - meta->skb->len, 1); - } else { - unmap_descbuffer(ring, meta->dmaaddr, - ring->rx_buffersize, 0); - } - free_descriptor_buffer(ring, meta, 0); - } -} - -/* Main initialization function. */ -static -struct bcm43xx_dmaring * bcm43xx_setup_dmaring(struct bcm43xx_private *bcm, - int controller_index, - int for_tx, - int dma64) -{ - struct bcm43xx_dmaring *ring; - int err; - int nr_slots; - - ring = kzalloc(sizeof(*ring), GFP_KERNEL); - if (!ring) - goto out; - - nr_slots = BCM43xx_RXRING_SLOTS; - if (for_tx) - nr_slots = BCM43xx_TXRING_SLOTS; - - ring->meta = kcalloc(nr_slots, sizeof(struct bcm43xx_dmadesc_meta), - GFP_KERNEL); - if (!ring->meta) - goto err_kfree_ring; - - ring->routing = BCM43xx_DMA32_CLIENTTRANS; - if (dma64) - ring->routing = BCM43xx_DMA64_CLIENTTRANS; - - ring->bcm = bcm; - ring->nr_slots = nr_slots; - ring->suspend_mark = ring->nr_slots * BCM43xx_TXSUSPEND_PERCENT / 100; - ring->resume_mark = ring->nr_slots * BCM43xx_TXRESUME_PERCENT / 100; - assert(ring->suspend_mark < ring->resume_mark); - ring->mmio_base = bcm43xx_dmacontroller_base(dma64, controller_index); - ring->index = controller_index; - ring->dma64 = !!dma64; - if (for_tx) { - ring->tx = 1; - ring->current_slot = -1; - } else { - if (ring->index == 0) { - ring->rx_buffersize = BCM43xx_DMA0_RX_BUFFERSIZE; - ring->frameoffset = BCM43xx_DMA0_RX_FRAMEOFFSET; - } else if (ring->index == 3) { - ring->rx_buffersize = BCM43xx_DMA3_RX_BUFFERSIZE; - ring->frameoffset = BCM43xx_DMA3_RX_FRAMEOFFSET; - } else - assert(0); - } - - err = alloc_ringmemory(ring); - if (err) - goto err_kfree_meta; - err = dmacontroller_setup(ring); - if (err) - goto err_free_ringmemory; - return ring; - -out: - printk(KERN_ERR PFX "Error in bcm43xx_setup_dmaring\n"); - return ring; - -err_free_ringmemory: - free_ringmemory(ring); -err_kfree_meta: - kfree(ring->meta); -err_kfree_ring: - kfree(ring); - ring = NULL; - goto out; -} - -/* Main cleanup function. */ -static void bcm43xx_destroy_dmaring(struct bcm43xx_dmaring *ring) -{ - if (!ring) - return; - - dprintk(KERN_INFO PFX "DMA-%s 0x%04X (%s) max used slots: %d/%d\n", - (ring->dma64) ? "64" : "32", - ring->mmio_base, - (ring->tx) ? "TX" : "RX", - ring->max_used_slots, ring->nr_slots); - /* Device IRQs are disabled prior entering this function, - * so no need to take care of concurrency with rx handler stuff. - */ - dmacontroller_cleanup(ring); - free_all_descbuffers(ring); - free_ringmemory(ring); - - kfree(ring->meta); - kfree(ring); -} - -void bcm43xx_dma_free(struct bcm43xx_private *bcm) -{ - struct bcm43xx_dma *dma; - - if (bcm43xx_using_pio(bcm)) - return; - dma = bcm43xx_current_dma(bcm); - - bcm43xx_destroy_dmaring(dma->rx_ring3); - dma->rx_ring3 = NULL; - bcm43xx_destroy_dmaring(dma->rx_ring0); - dma->rx_ring0 = NULL; - - bcm43xx_destroy_dmaring(dma->tx_ring5); - dma->tx_ring5 = NULL; - bcm43xx_destroy_dmaring(dma->tx_ring4); - dma->tx_ring4 = NULL; - bcm43xx_destroy_dmaring(dma->tx_ring3); - dma->tx_ring3 = NULL; - bcm43xx_destroy_dmaring(dma->tx_ring2); - dma->tx_ring2 = NULL; - bcm43xx_destroy_dmaring(dma->tx_ring1); - dma->tx_ring1 = NULL; - bcm43xx_destroy_dmaring(dma->tx_ring0); - dma->tx_ring0 = NULL; -} - -int bcm43xx_dma_init(struct bcm43xx_private *bcm) -{ - struct bcm43xx_dma *dma = bcm43xx_current_dma(bcm); - struct bcm43xx_dmaring *ring; - int err = -ENOMEM; - int dma64 = 0; - - bcm->dma_mask = bcm43xx_get_supported_dma_mask(bcm); - if (bcm->dma_mask == DMA_64BIT_MASK) - dma64 = 1; - err = pci_set_dma_mask(bcm->pci_dev, bcm->dma_mask); - if (err) - goto no_dma; - err = pci_set_consistent_dma_mask(bcm->pci_dev, bcm->dma_mask); - if (err) - goto no_dma; - - /* setup TX DMA channels. */ - ring = bcm43xx_setup_dmaring(bcm, 0, 1, dma64); - if (!ring) - goto out; - dma->tx_ring0 = ring; - - ring = bcm43xx_setup_dmaring(bcm, 1, 1, dma64); - if (!ring) - goto err_destroy_tx0; - dma->tx_ring1 = ring; - - ring = bcm43xx_setup_dmaring(bcm, 2, 1, dma64); - if (!ring) - goto err_destroy_tx1; - dma->tx_ring2 = ring; - - ring = bcm43xx_setup_dmaring(bcm, 3, 1, dma64); - if (!ring) - goto err_destroy_tx2; - dma->tx_ring3 = ring; - - ring = bcm43xx_setup_dmaring(bcm, 4, 1, dma64); - if (!ring) - goto err_destroy_tx3; - dma->tx_ring4 = ring; - - ring = bcm43xx_setup_dmaring(bcm, 5, 1, dma64); - if (!ring) - goto err_destroy_tx4; - dma->tx_ring5 = ring; - - /* setup RX DMA channels. */ - ring = bcm43xx_setup_dmaring(bcm, 0, 0, dma64); - if (!ring) - goto err_destroy_tx5; - dma->rx_ring0 = ring; - - if (bcm->current_core->rev < 5) { - ring = bcm43xx_setup_dmaring(bcm, 3, 0, dma64); - if (!ring) - goto err_destroy_rx0; - dma->rx_ring3 = ring; - } - - dprintk(KERN_INFO PFX "%d-bit DMA initialized\n", - (bcm->dma_mask == DMA_64BIT_MASK) ? 64 : - (bcm->dma_mask == DMA_32BIT_MASK) ? 32 : 30); - err = 0; -out: - return err; - -err_destroy_rx0: - bcm43xx_destroy_dmaring(dma->rx_ring0); - dma->rx_ring0 = NULL; -err_destroy_tx5: - bcm43xx_destroy_dmaring(dma->tx_ring5); - dma->tx_ring5 = NULL; -err_destroy_tx4: - bcm43xx_destroy_dmaring(dma->tx_ring4); - dma->tx_ring4 = NULL; -err_destroy_tx3: - bcm43xx_destroy_dmaring(dma->tx_ring3); - dma->tx_ring3 = NULL; -err_destroy_tx2: - bcm43xx_destroy_dmaring(dma->tx_ring2); - dma->tx_ring2 = NULL; -err_destroy_tx1: - bcm43xx_destroy_dmaring(dma->tx_ring1); - dma->tx_ring1 = NULL; -err_destroy_tx0: - bcm43xx_destroy_dmaring(dma->tx_ring0); - dma->tx_ring0 = NULL; -no_dma: -#ifdef CONFIG_BCM43XX_PIO - printk(KERN_WARNING PFX "DMA not supported on this device." - " Falling back to PIO.\n"); - bcm->__using_pio = 1; - return -ENOSYS; -#else - printk(KERN_ERR PFX "FATAL: DMA not supported and PIO not configured. " - "Please recompile the driver with PIO support.\n"); - return -ENODEV; -#endif /* CONFIG_BCM43XX_PIO */ -} - -/* Generate a cookie for the TX header. */ -static u16 generate_cookie(struct bcm43xx_dmaring *ring, - int slot) -{ - u16 cookie = 0x1000; - - /* Use the upper 4 bits of the cookie as - * DMA controller ID and store the slot number - * in the lower 12 bits. - * Note that the cookie must never be 0, as this - * is a special value used in RX path. - */ - switch (ring->index) { - case 0: - cookie = 0xA000; - break; - case 1: - cookie = 0xB000; - break; - case 2: - cookie = 0xC000; - break; - case 3: - cookie = 0xD000; - break; - case 4: - cookie = 0xE000; - break; - case 5: - cookie = 0xF000; - break; - } - assert(((u16)slot & 0xF000) == 0x0000); - cookie |= (u16)slot; - - return cookie; -} - -/* Inspect a cookie and find out to which controller/slot it belongs. */ -static -struct bcm43xx_dmaring * parse_cookie(struct bcm43xx_private *bcm, - u16 cookie, int *slot) -{ - struct bcm43xx_dma *dma = bcm43xx_current_dma(bcm); - struct bcm43xx_dmaring *ring = NULL; - - switch (cookie & 0xF000) { - case 0xA000: - ring = dma->tx_ring0; - break; - case 0xB000: - ring = dma->tx_ring1; - break; - case 0xC000: - ring = dma->tx_ring2; - break; - case 0xD000: - ring = dma->tx_ring3; - break; - case 0xE000: - ring = dma->tx_ring4; - break; - case 0xF000: - ring = dma->tx_ring5; - break; - default: - assert(0); - } - *slot = (cookie & 0x0FFF); - assert(*slot >= 0 && *slot < ring->nr_slots); - - return ring; -} - -static void dmacontroller_poke_tx(struct bcm43xx_dmaring *ring, - int slot) -{ - u16 offset; - int descsize; - - /* Everything is ready to start. Buffers are DMA mapped and - * associated with slots. - * "slot" is the last slot of the new frame we want to transmit. - * Close your seat belts now, please. - */ - wmb(); - slot = next_slot(ring, slot); - offset = (ring->dma64) ? BCM43xx_DMA64_TXINDEX : BCM43xx_DMA32_TXINDEX; - descsize = (ring->dma64) ? sizeof(struct bcm43xx_dmadesc64) - : sizeof(struct bcm43xx_dmadesc32); - bcm43xx_dma_write(ring, offset, - (u32)(slot * descsize)); -} - -static void dma_tx_fragment(struct bcm43xx_dmaring *ring, - struct sk_buff *skb, - u8 cur_frag) -{ - int slot; - struct bcm43xx_dmadesc_generic *desc; - struct bcm43xx_dmadesc_meta *meta; - dma_addr_t dmaaddr; - struct sk_buff *bounce_skb; - - assert(skb_shinfo(skb)->nr_frags == 0); - - slot = request_slot(ring); - desc = bcm43xx_dma_idx2desc(ring, slot, &meta); - - /* Add a device specific TX header. */ - assert(skb_headroom(skb) >= sizeof(struct bcm43xx_txhdr)); - /* Reserve enough headroom for the device tx header. */ - __skb_push(skb, sizeof(struct bcm43xx_txhdr)); - /* Now calculate and add the tx header. - * The tx header includes the PLCP header. - */ - bcm43xx_generate_txhdr(ring->bcm, - (struct bcm43xx_txhdr *)skb->data, - skb->data + sizeof(struct bcm43xx_txhdr), - skb->len - sizeof(struct bcm43xx_txhdr), - (cur_frag == 0), - generate_cookie(ring, slot)); - dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); - if (dma_mapping_error(dmaaddr) || dmaaddr + skb->len > ring->bcm->dma_mask) { - /* chip cannot handle DMA to/from > 1GB, use bounce buffer (copied from b44 driver) */ - if (!dma_mapping_error(dmaaddr)) - unmap_descbuffer(ring, dmaaddr, skb->len, 1); - bounce_skb = __dev_alloc_skb(skb->len, GFP_ATOMIC|GFP_DMA); - if (!bounce_skb) - return; - dmaaddr = map_descbuffer(ring, bounce_skb->data, bounce_skb->len, 1); - if (dma_mapping_error(dmaaddr) || dmaaddr + skb->len > ring->bcm->dma_mask) { - if (!dma_mapping_error(dmaaddr)) - unmap_descbuffer(ring, dmaaddr, skb->len, 1); - dev_kfree_skb_any(bounce_skb); - assert(0); - return; - } - skb_copy_from_linear_data(skb, skb_put(bounce_skb, skb->len), - skb->len); - dev_kfree_skb_any(skb); - skb = bounce_skb; - } - - meta->skb = skb; - meta->dmaaddr = dmaaddr; - - fill_descriptor(ring, desc, dmaaddr, - skb->len, 1, 1, 1); - - /* Now transfer the whole frame. */ - dmacontroller_poke_tx(ring, slot); -} - -int bcm43xx_dma_tx(struct bcm43xx_private *bcm, - struct ieee80211_txb *txb) -{ - /* We just received a packet from the kernel network subsystem. - * Add headers and DMA map the memory. Poke - * the device to send the stuff. - * Note that this is called from atomic context. - */ - struct bcm43xx_dmaring *ring = bcm43xx_current_dma(bcm)->tx_ring1; - u8 i; - struct sk_buff *skb; - - assert(ring->tx); - if (unlikely(free_slots(ring) < txb->nr_frags)) { - /* The queue should be stopped, - * if we are low on free slots. - * If this ever triggers, we have to lower the suspend_mark. - */ - dprintkl(KERN_ERR PFX "Out of DMA descriptor slots!\n"); - return -ENOMEM; - } - - for (i = 0; i < txb->nr_frags; i++) { - skb = txb->fragments[i]; - /* Take skb from ieee80211_txb_free */ - txb->fragments[i] = NULL; - dma_tx_fragment(ring, skb, i); - } - ieee80211_txb_free(txb); - - return 0; -} - -void bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm, - struct bcm43xx_xmitstatus *status) -{ - struct bcm43xx_dmaring *ring; - struct bcm43xx_dmadesc_generic *desc; - struct bcm43xx_dmadesc_meta *meta; - int is_last_fragment; - int slot; - u32 tmp; - - ring = parse_cookie(bcm, status->cookie, &slot); - assert(ring); - assert(ring->tx); - while (1) { - assert(slot >= 0 && slot < ring->nr_slots); - desc = bcm43xx_dma_idx2desc(ring, slot, &meta); - - if (ring->dma64) { - tmp = le32_to_cpu(desc->dma64.control0); - is_last_fragment = !!(tmp & BCM43xx_DMA64_DCTL0_FRAMEEND); - } else { - tmp = le32_to_cpu(desc->dma32.control); - is_last_fragment = !!(tmp & BCM43xx_DMA32_DCTL_FRAMEEND); - } - unmap_descbuffer(ring, meta->dmaaddr, meta->skb->len, 1); - free_descriptor_buffer(ring, meta, 1); - /* Everything belonging to the slot is unmapped - * and freed, so we can return it. - */ - return_slot(ring, slot); - - if (is_last_fragment) - break; - slot = next_slot(ring, slot); - } - bcm->stats.last_tx = jiffies; -} - -static void dma_rx(struct bcm43xx_dmaring *ring, - int *slot) -{ - struct bcm43xx_dmadesc_generic *desc; - struct bcm43xx_dmadesc_meta *meta; - struct bcm43xx_rxhdr *rxhdr; - struct sk_buff *skb; - u16 len; - int err; - dma_addr_t dmaaddr; - - desc = bcm43xx_dma_idx2desc(ring, *slot, &meta); - - sync_descbuffer_for_cpu(ring, meta->dmaaddr, ring->rx_buffersize); - skb = meta->skb; - - if (ring->index == 3) { - /* We received an xmit status. */ - struct bcm43xx_hwxmitstatus *hw = (struct bcm43xx_hwxmitstatus *)skb->data; - struct bcm43xx_xmitstatus stat; - int i = 0; - - stat.cookie = le16_to_cpu(hw->cookie); - while (stat.cookie == 0) { - if (unlikely(++i >= 10000)) { - assert(0); - break; - } - udelay(2); - barrier(); - stat.cookie = le16_to_cpu(hw->cookie); - } - stat.flags = hw->flags; - stat.cnt1 = hw->cnt1; - stat.cnt2 = hw->cnt2; - stat.seq = le16_to_cpu(hw->seq); - stat.unknown = le16_to_cpu(hw->unknown); - - bcm43xx_debugfs_log_txstat(ring->bcm, &stat); - bcm43xx_dma_handle_xmitstatus(ring->bcm, &stat); - /* recycle the descriptor buffer. */ - sync_descbuffer_for_device(ring, meta->dmaaddr, ring->rx_buffersize); - - return; - } - rxhdr = (struct bcm43xx_rxhdr *)skb->data; - len = le16_to_cpu(rxhdr->frame_length); - if (len == 0) { - int i = 0; - - do { - udelay(2); - barrier(); - len = le16_to_cpu(rxhdr->frame_length); - } while (len == 0 && i++ < 5); - if (unlikely(len == 0)) { - /* recycle the descriptor buffer. */ - sync_descbuffer_for_device(ring, meta->dmaaddr, - ring->rx_buffersize); - goto drop; - } - } - if (unlikely(len > ring->rx_buffersize)) { - /* The data did not fit into one descriptor buffer - * and is split over multiple buffers. - * This should never happen, as we try to allocate buffers - * big enough. So simply ignore this packet. - */ - int cnt = 0; - s32 tmp = len; - - while (1) { - desc = bcm43xx_dma_idx2desc(ring, *slot, &meta); - /* recycle the descriptor buffer. */ - sync_descbuffer_for_device(ring, meta->dmaaddr, - ring->rx_buffersize); - *slot = next_slot(ring, *slot); - cnt++; - tmp -= ring->rx_buffersize; - if (tmp <= 0) - break; - } - printkl(KERN_ERR PFX "DMA RX buffer too small " - "(len: %u, buffer: %u, nr-dropped: %d)\n", - len, ring->rx_buffersize, cnt); - goto drop; - } - len -= IEEE80211_FCS_LEN; - - dmaaddr = meta->dmaaddr; - err = setup_rx_descbuffer(ring, desc, meta, GFP_ATOMIC); - if (unlikely(err)) { - dprintkl(KERN_ERR PFX "DMA RX: setup_rx_descbuffer() failed\n"); - sync_descbuffer_for_device(ring, dmaaddr, - ring->rx_buffersize); - goto drop; - } - - unmap_descbuffer(ring, dmaaddr, ring->rx_buffersize, 0); - skb_put(skb, len + ring->frameoffset); - skb_pull(skb, ring->frameoffset); - - err = bcm43xx_rx(ring->bcm, skb, rxhdr); - if (err) { - dev_kfree_skb_irq(skb); - goto drop; - } - -drop: - return; -} - -void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring) -{ - u32 status; - u16 descptr; - int slot, current_slot; -#ifdef CONFIG_BCM43XX_DEBUG - int used_slots = 0; -#endif - - assert(!ring->tx); - if (ring->dma64) { - status = bcm43xx_dma_read(ring, BCM43xx_DMA64_RXSTATUS); - descptr = (status & BCM43xx_DMA64_RXSTATDPTR); - current_slot = descptr / sizeof(struct bcm43xx_dmadesc64); - } else { - status = bcm43xx_dma_read(ring, BCM43xx_DMA32_RXSTATUS); - descptr = (status & BCM43xx_DMA32_RXDPTR); - current_slot = descptr / sizeof(struct bcm43xx_dmadesc32); - } - assert(current_slot >= 0 && current_slot < ring->nr_slots); - - slot = ring->current_slot; - for ( ; slot != current_slot; slot = next_slot(ring, slot)) { - dma_rx(ring, &slot); -#ifdef CONFIG_BCM43XX_DEBUG - if (++used_slots > ring->max_used_slots) - ring->max_used_slots = used_slots; -#endif - } - if (ring->dma64) { - bcm43xx_dma_write(ring, BCM43xx_DMA64_RXINDEX, - (u32)(slot * sizeof(struct bcm43xx_dmadesc64))); - } else { - bcm43xx_dma_write(ring, BCM43xx_DMA32_RXINDEX, - (u32)(slot * sizeof(struct bcm43xx_dmadesc32))); - } - ring->current_slot = slot; -} - -void bcm43xx_dma_tx_suspend(struct bcm43xx_dmaring *ring) -{ - assert(ring->tx); - bcm43xx_power_saving_ctl_bits(ring->bcm, -1, 1); - if (ring->dma64) { - bcm43xx_dma_write(ring, BCM43xx_DMA64_TXCTL, - bcm43xx_dma_read(ring, BCM43xx_DMA64_TXCTL) - | BCM43xx_DMA64_TXSUSPEND); - } else { - bcm43xx_dma_write(ring, BCM43xx_DMA32_TXCTL, - bcm43xx_dma_read(ring, BCM43xx_DMA32_TXCTL) - | BCM43xx_DMA32_TXSUSPEND); - } -} - -void bcm43xx_dma_tx_resume(struct bcm43xx_dmaring *ring) -{ - assert(ring->tx); - if (ring->dma64) { - bcm43xx_dma_write(ring, BCM43xx_DMA64_TXCTL, - bcm43xx_dma_read(ring, BCM43xx_DMA64_TXCTL) - & ~BCM43xx_DMA64_TXSUSPEND); - } else { - bcm43xx_dma_write(ring, BCM43xx_DMA32_TXCTL, - bcm43xx_dma_read(ring, BCM43xx_DMA32_TXCTL) - & ~BCM43xx_DMA32_TXSUSPEND); - } - bcm43xx_power_saving_ctl_bits(ring->bcm, -1, -1); -} diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h deleted file mode 100644 index d1105e569a41..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h +++ /dev/null @@ -1,386 +0,0 @@ -#ifndef BCM43xx_DMA_H_ -#define BCM43xx_DMA_H_ - -#include -#include -#include -#include -#include -#include - - -/* DMA-Interrupt reasons. */ -#define BCM43xx_DMAIRQ_FATALMASK ((1 << 10) | (1 << 11) | (1 << 12) \ - | (1 << 14) | (1 << 15)) -#define BCM43xx_DMAIRQ_NONFATALMASK (1 << 13) -#define BCM43xx_DMAIRQ_RX_DONE (1 << 16) - - -/*** 32-bit DMA Engine. ***/ - -/* 32-bit DMA controller registers. */ -#define BCM43xx_DMA32_TXCTL 0x00 -#define BCM43xx_DMA32_TXENABLE 0x00000001 -#define BCM43xx_DMA32_TXSUSPEND 0x00000002 -#define BCM43xx_DMA32_TXLOOPBACK 0x00000004 -#define BCM43xx_DMA32_TXFLUSH 0x00000010 -#define BCM43xx_DMA32_TXADDREXT_MASK 0x00030000 -#define BCM43xx_DMA32_TXADDREXT_SHIFT 16 -#define BCM43xx_DMA32_TXRING 0x04 -#define BCM43xx_DMA32_TXINDEX 0x08 -#define BCM43xx_DMA32_TXSTATUS 0x0C -#define BCM43xx_DMA32_TXDPTR 0x00000FFF -#define BCM43xx_DMA32_TXSTATE 0x0000F000 -#define BCM43xx_DMA32_TXSTAT_DISABLED 0x00000000 -#define BCM43xx_DMA32_TXSTAT_ACTIVE 0x00001000 -#define BCM43xx_DMA32_TXSTAT_IDLEWAIT 0x00002000 -#define BCM43xx_DMA32_TXSTAT_STOPPED 0x00003000 -#define BCM43xx_DMA32_TXSTAT_SUSP 0x00004000 -#define BCM43xx_DMA32_TXERROR 0x000F0000 -#define BCM43xx_DMA32_TXERR_NOERR 0x00000000 -#define BCM43xx_DMA32_TXERR_PROT 0x00010000 -#define BCM43xx_DMA32_TXERR_UNDERRUN 0x00020000 -#define BCM43xx_DMA32_TXERR_BUFREAD 0x00030000 -#define BCM43xx_DMA32_TXERR_DESCREAD 0x00040000 -#define BCM43xx_DMA32_TXACTIVE 0xFFF00000 -#define BCM43xx_DMA32_RXCTL 0x10 -#define BCM43xx_DMA32_RXENABLE 0x00000001 -#define BCM43xx_DMA32_RXFROFF_MASK 0x000000FE -#define BCM43xx_DMA32_RXFROFF_SHIFT 1 -#define BCM43xx_DMA32_RXDIRECTFIFO 0x00000100 -#define BCM43xx_DMA32_RXADDREXT_MASK 0x00030000 -#define BCM43xx_DMA32_RXADDREXT_SHIFT 16 -#define BCM43xx_DMA32_RXRING 0x14 -#define BCM43xx_DMA32_RXINDEX 0x18 -#define BCM43xx_DMA32_RXSTATUS 0x1C -#define BCM43xx_DMA32_RXDPTR 0x00000FFF -#define BCM43xx_DMA32_RXSTATE 0x0000F000 -#define BCM43xx_DMA32_RXSTAT_DISABLED 0x00000000 -#define BCM43xx_DMA32_RXSTAT_ACTIVE 0x00001000 -#define BCM43xx_DMA32_RXSTAT_IDLEWAIT 0x00002000 -#define BCM43xx_DMA32_RXSTAT_STOPPED 0x00003000 -#define BCM43xx_DMA32_RXERROR 0x000F0000 -#define BCM43xx_DMA32_RXERR_NOERR 0x00000000 -#define BCM43xx_DMA32_RXERR_PROT 0x00010000 -#define BCM43xx_DMA32_RXERR_OVERFLOW 0x00020000 -#define BCM43xx_DMA32_RXERR_BUFWRITE 0x00030000 -#define BCM43xx_DMA32_RXERR_DESCREAD 0x00040000 -#define BCM43xx_DMA32_RXACTIVE 0xFFF00000 - -/* 32-bit DMA descriptor. */ -struct bcm43xx_dmadesc32 { - __le32 control; - __le32 address; -} __attribute__((__packed__)); -#define BCM43xx_DMA32_DCTL_BYTECNT 0x00001FFF -#define BCM43xx_DMA32_DCTL_ADDREXT_MASK 0x00030000 -#define BCM43xx_DMA32_DCTL_ADDREXT_SHIFT 16 -#define BCM43xx_DMA32_DCTL_DTABLEEND 0x10000000 -#define BCM43xx_DMA32_DCTL_IRQ 0x20000000 -#define BCM43xx_DMA32_DCTL_FRAMEEND 0x40000000 -#define BCM43xx_DMA32_DCTL_FRAMESTART 0x80000000 - -/* Address field Routing value. */ -#define BCM43xx_DMA32_ROUTING 0xC0000000 -#define BCM43xx_DMA32_ROUTING_SHIFT 30 -#define BCM43xx_DMA32_NOTRANS 0x00000000 -#define BCM43xx_DMA32_CLIENTTRANS 0x40000000 - - - -/*** 64-bit DMA Engine. ***/ - -/* 64-bit DMA controller registers. */ -#define BCM43xx_DMA64_TXCTL 0x00 -#define BCM43xx_DMA64_TXENABLE 0x00000001 -#define BCM43xx_DMA64_TXSUSPEND 0x00000002 -#define BCM43xx_DMA64_TXLOOPBACK 0x00000004 -#define BCM43xx_DMA64_TXFLUSH 0x00000010 -#define BCM43xx_DMA64_TXADDREXT_MASK 0x00030000 -#define BCM43xx_DMA64_TXADDREXT_SHIFT 16 -#define BCM43xx_DMA64_TXINDEX 0x04 -#define BCM43xx_DMA64_TXRINGLO 0x08 -#define BCM43xx_DMA64_TXRINGHI 0x0C -#define BCM43xx_DMA64_TXSTATUS 0x10 -#define BCM43xx_DMA64_TXSTATDPTR 0x00001FFF -#define BCM43xx_DMA64_TXSTAT 0xF0000000 -#define BCM43xx_DMA64_TXSTAT_DISABLED 0x00000000 -#define BCM43xx_DMA64_TXSTAT_ACTIVE 0x10000000 -#define BCM43xx_DMA64_TXSTAT_IDLEWAIT 0x20000000 -#define BCM43xx_DMA64_TXSTAT_STOPPED 0x30000000 -#define BCM43xx_DMA64_TXSTAT_SUSP 0x40000000 -#define BCM43xx_DMA64_TXERROR 0x14 -#define BCM43xx_DMA64_TXERRDPTR 0x0001FFFF -#define BCM43xx_DMA64_TXERR 0xF0000000 -#define BCM43xx_DMA64_TXERR_NOERR 0x00000000 -#define BCM43xx_DMA64_TXERR_PROT 0x10000000 -#define BCM43xx_DMA64_TXERR_UNDERRUN 0x20000000 -#define BCM43xx_DMA64_TXERR_TRANSFER 0x30000000 -#define BCM43xx_DMA64_TXERR_DESCREAD 0x40000000 -#define BCM43xx_DMA64_TXERR_CORE 0x50000000 -#define BCM43xx_DMA64_RXCTL 0x20 -#define BCM43xx_DMA64_RXENABLE 0x00000001 -#define BCM43xx_DMA64_RXFROFF_MASK 0x000000FE -#define BCM43xx_DMA64_RXFROFF_SHIFT 1 -#define BCM43xx_DMA64_RXDIRECTFIFO 0x00000100 -#define BCM43xx_DMA64_RXADDREXT_MASK 0x00030000 -#define BCM43xx_DMA64_RXADDREXT_SHIFT 16 -#define BCM43xx_DMA64_RXINDEX 0x24 -#define BCM43xx_DMA64_RXRINGLO 0x28 -#define BCM43xx_DMA64_RXRINGHI 0x2C -#define BCM43xx_DMA64_RXSTATUS 0x30 -#define BCM43xx_DMA64_RXSTATDPTR 0x00001FFF -#define BCM43xx_DMA64_RXSTAT 0xF0000000 -#define BCM43xx_DMA64_RXSTAT_DISABLED 0x00000000 -#define BCM43xx_DMA64_RXSTAT_ACTIVE 0x10000000 -#define BCM43xx_DMA64_RXSTAT_IDLEWAIT 0x20000000 -#define BCM43xx_DMA64_RXSTAT_STOPPED 0x30000000 -#define BCM43xx_DMA64_RXSTAT_SUSP 0x40000000 -#define BCM43xx_DMA64_RXERROR 0x34 -#define BCM43xx_DMA64_RXERRDPTR 0x0001FFFF -#define BCM43xx_DMA64_RXERR 0xF0000000 -#define BCM43xx_DMA64_RXERR_NOERR 0x00000000 -#define BCM43xx_DMA64_RXERR_PROT 0x10000000 -#define BCM43xx_DMA64_RXERR_UNDERRUN 0x20000000 -#define BCM43xx_DMA64_RXERR_TRANSFER 0x30000000 -#define BCM43xx_DMA64_RXERR_DESCREAD 0x40000000 -#define BCM43xx_DMA64_RXERR_CORE 0x50000000 - -/* 64-bit DMA descriptor. */ -struct bcm43xx_dmadesc64 { - __le32 control0; - __le32 control1; - __le32 address_low; - __le32 address_high; -} __attribute__((__packed__)); -#define BCM43xx_DMA64_DCTL0_DTABLEEND 0x10000000 -#define BCM43xx_DMA64_DCTL0_IRQ 0x20000000 -#define BCM43xx_DMA64_DCTL0_FRAMEEND 0x40000000 -#define BCM43xx_DMA64_DCTL0_FRAMESTART 0x80000000 -#define BCM43xx_DMA64_DCTL1_BYTECNT 0x00001FFF -#define BCM43xx_DMA64_DCTL1_ADDREXT_MASK 0x00030000 -#define BCM43xx_DMA64_DCTL1_ADDREXT_SHIFT 16 - -/* Address field Routing value. */ -#define BCM43xx_DMA64_ROUTING 0xC0000000 -#define BCM43xx_DMA64_ROUTING_SHIFT 30 -#define BCM43xx_DMA64_NOTRANS 0x00000000 -#define BCM43xx_DMA64_CLIENTTRANS 0x80000000 - - - -struct bcm43xx_dmadesc_generic { - union { - struct bcm43xx_dmadesc32 dma32; - struct bcm43xx_dmadesc64 dma64; - } __attribute__((__packed__)); -} __attribute__((__packed__)); - - -/* Misc DMA constants */ -#define BCM43xx_DMA_RINGMEMSIZE PAGE_SIZE -#define BCM43xx_DMA0_RX_FRAMEOFFSET 30 -#define BCM43xx_DMA3_RX_FRAMEOFFSET 0 - - -/* DMA engine tuning knobs */ -#define BCM43xx_TXRING_SLOTS 512 -#define BCM43xx_RXRING_SLOTS 64 -#define BCM43xx_DMA0_RX_BUFFERSIZE (2304 + 100) -#define BCM43xx_DMA3_RX_BUFFERSIZE 16 -/* Suspend the tx queue, if less than this percent slots are free. */ -#define BCM43xx_TXSUSPEND_PERCENT 20 -/* Resume the tx queue, if more than this percent slots are free. */ -#define BCM43xx_TXRESUME_PERCENT 50 - - - -#ifdef CONFIG_BCM43XX_DMA - - -struct sk_buff; -struct bcm43xx_private; -struct bcm43xx_xmitstatus; - - -struct bcm43xx_dmadesc_meta { - /* The kernel DMA-able buffer. */ - struct sk_buff *skb; - /* DMA base bus-address of the descriptor buffer. */ - dma_addr_t dmaaddr; -}; - -struct bcm43xx_dmaring { - /* Kernel virtual base address of the ring memory. */ - void *descbase; - /* Meta data about all descriptors. */ - struct bcm43xx_dmadesc_meta *meta; - /* DMA Routing value. */ - u32 routing; - /* (Unadjusted) DMA base bus-address of the ring memory. */ - dma_addr_t dmabase; - /* Number of descriptor slots in the ring. */ - int nr_slots; - /* Number of used descriptor slots. */ - int used_slots; - /* Currently used slot in the ring. */ - int current_slot; - /* Marks to suspend/resume the queue. */ - int suspend_mark; - int resume_mark; - /* Frameoffset in octets. */ - u32 frameoffset; - /* Descriptor buffer size. */ - u16 rx_buffersize; - /* The MMIO base register of the DMA controller. */ - u16 mmio_base; - /* DMA controller index number (0-5). */ - int index; - /* Boolean. Is this a TX ring? */ - u8 tx; - /* Boolean. 64bit DMA if true, 32bit DMA otherwise. */ - u8 dma64; - /* Boolean. Are transfers suspended on this ring? */ - u8 suspended; - struct bcm43xx_private *bcm; -#ifdef CONFIG_BCM43XX_DEBUG - /* Maximum number of used slots. */ - int max_used_slots; -#endif /* CONFIG_BCM43XX_DEBUG*/ -}; - - -static inline -int bcm43xx_dma_desc2idx(struct bcm43xx_dmaring *ring, - struct bcm43xx_dmadesc_generic *desc) -{ - if (ring->dma64) { - struct bcm43xx_dmadesc64 *dd64 = ring->descbase; - return (int)(&(desc->dma64) - dd64); - } else { - struct bcm43xx_dmadesc32 *dd32 = ring->descbase; - return (int)(&(desc->dma32) - dd32); - } -} - -static inline -struct bcm43xx_dmadesc_generic * bcm43xx_dma_idx2desc(struct bcm43xx_dmaring *ring, - int slot, - struct bcm43xx_dmadesc_meta **meta) -{ - *meta = &(ring->meta[slot]); - if (ring->dma64) { - struct bcm43xx_dmadesc64 *dd64 = ring->descbase; - return (struct bcm43xx_dmadesc_generic *)(&(dd64[slot])); - } else { - struct bcm43xx_dmadesc32 *dd32 = ring->descbase; - return (struct bcm43xx_dmadesc_generic *)(&(dd32[slot])); - } -} - -static inline -u32 bcm43xx_dma_read(struct bcm43xx_dmaring *ring, - u16 offset) -{ - return bcm43xx_read32(ring->bcm, ring->mmio_base + offset); -} - -static inline -void bcm43xx_dma_write(struct bcm43xx_dmaring *ring, - u16 offset, u32 value) -{ - bcm43xx_write32(ring->bcm, ring->mmio_base + offset, value); -} - - -int bcm43xx_dma_init(struct bcm43xx_private *bcm); -void bcm43xx_dma_free(struct bcm43xx_private *bcm); - -int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm, - u16 dmacontroller_mmio_base, - int dma64); -int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm, - u16 dmacontroller_mmio_base, - int dma64); - -u16 bcm43xx_dmacontroller_base(int dma64bit, int dmacontroller_idx); - -void bcm43xx_dma_tx_suspend(struct bcm43xx_dmaring *ring); -void bcm43xx_dma_tx_resume(struct bcm43xx_dmaring *ring); - -void bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm, - struct bcm43xx_xmitstatus *status); - -int bcm43xx_dma_tx(struct bcm43xx_private *bcm, - struct ieee80211_txb *txb); -void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring); - -/* Helper function that returns the dma mask for this device. */ -static inline -u64 bcm43xx_get_supported_dma_mask(struct bcm43xx_private *bcm) -{ - int dma64 = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH) & - BCM43xx_SBTMSTATEHIGH_DMA64BIT; - u16 mmio_base = bcm43xx_dmacontroller_base(dma64, 0); - u32 mask = BCM43xx_DMA32_TXADDREXT_MASK; - - if (dma64) - return DMA_64BIT_MASK; - bcm43xx_write32(bcm, mmio_base + BCM43xx_DMA32_TXCTL, mask); - if (bcm43xx_read32(bcm, mmio_base + BCM43xx_DMA32_TXCTL) & mask) - return DMA_32BIT_MASK; - return DMA_30BIT_MASK; -} - -#else /* CONFIG_BCM43XX_DMA */ - - -static inline -int bcm43xx_dma_init(struct bcm43xx_private *bcm) -{ - return 0; -} -static inline -void bcm43xx_dma_free(struct bcm43xx_private *bcm) -{ -} -static inline -int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm, - u16 dmacontroller_mmio_base, - int dma64) -{ - return 0; -} -static inline -int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm, - u16 dmacontroller_mmio_base, - int dma64) -{ - return 0; -} -static inline -int bcm43xx_dma_tx(struct bcm43xx_private *bcm, - struct ieee80211_txb *txb) -{ - return 0; -} -static inline -void bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm, - struct bcm43xx_xmitstatus *status) -{ -} -static inline -void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring) -{ -} -static inline -void bcm43xx_dma_tx_suspend(struct bcm43xx_dmaring *ring) -{ -} -static inline -void bcm43xx_dma_tx_resume(struct bcm43xx_dmaring *ring) -{ -} - -#endif /* CONFIG_BCM43XX_DMA */ -#endif /* BCM43xx_DMA_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c b/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c deleted file mode 100644 index d2df6a0100a1..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c +++ /dev/null @@ -1,50 +0,0 @@ -/* - - Broadcom BCM43xx wireless driver - - ethtool support - - Copyright (c) 2006 Jason Lunz - - Some code in this file is derived from the 8139too.c driver - Copyright (C) 2002 Jeff Garzik - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include "bcm43xx.h" -#include "bcm43xx_ethtool.h" - -#include -#include -#include -#include - - -static void bcm43xx_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(dev); - - strncpy(info->driver, KBUILD_MODNAME, sizeof(info->driver)); - strncpy(info->version, utsname()->release, sizeof(info->version)); - strncpy(info->bus_info, pci_name(bcm->pci_dev), ETHTOOL_BUSINFO_LEN); -} - -const struct ethtool_ops bcm43xx_ethtool_ops = { - .get_drvinfo = bcm43xx_get_drvinfo, - .get_link = ethtool_op_get_link, -}; diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.h b/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.h deleted file mode 100644 index 6f8d42d3cdf5..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef BCM43xx_ETHTOOL_H_ -#define BCM43xx_ETHTOOL_H_ - -#include - -extern const struct ethtool_ops bcm43xx_ethtool_ops; - -#endif /* BCM43xx_ETHTOOL_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c b/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c deleted file mode 100644 index f2b8dbac55a4..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c +++ /dev/null @@ -1,352 +0,0 @@ -/* - - Broadcom BCM43xx wireless driver - - Copyright (c) 2005 Martin Langer , - Stefano Brivio - Michael Buesch - Danny van Dyk - Andreas Jaggi - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include "bcm43xx.h" -#include "bcm43xx_ilt.h" -#include "bcm43xx_phy.h" - - -/**** Initial Internal Lookup Tables ****/ - -const u32 bcm43xx_ilt_rotor[BCM43xx_ILT_ROTOR_SIZE] = { - 0xFEB93FFD, 0xFEC63FFD, /* 0 */ - 0xFED23FFD, 0xFEDF3FFD, - 0xFEEC3FFE, 0xFEF83FFE, - 0xFF053FFE, 0xFF113FFE, - 0xFF1E3FFE, 0xFF2A3FFF, /* 8 */ - 0xFF373FFF, 0xFF443FFF, - 0xFF503FFF, 0xFF5D3FFF, - 0xFF693FFF, 0xFF763FFF, - 0xFF824000, 0xFF8F4000, /* 16 */ - 0xFF9B4000, 0xFFA84000, - 0xFFB54000, 0xFFC14000, - 0xFFCE4000, 0xFFDA4000, - 0xFFE74000, 0xFFF34000, /* 24 */ - 0x00004000, 0x000D4000, - 0x00194000, 0x00264000, - 0x00324000, 0x003F4000, - 0x004B4000, 0x00584000, /* 32 */ - 0x00654000, 0x00714000, - 0x007E4000, 0x008A3FFF, - 0x00973FFF, 0x00A33FFF, - 0x00B03FFF, 0x00BC3FFF, /* 40 */ - 0x00C93FFF, 0x00D63FFF, - 0x00E23FFE, 0x00EF3FFE, - 0x00FB3FFE, 0x01083FFE, - 0x01143FFE, 0x01213FFD, /* 48 */ - 0x012E3FFD, 0x013A3FFD, - 0x01473FFD, -}; - -const u32 bcm43xx_ilt_retard[BCM43xx_ILT_RETARD_SIZE] = { - 0xDB93CB87, 0xD666CF64, /* 0 */ - 0xD1FDD358, 0xCDA6D826, - 0xCA38DD9F, 0xC729E2B4, - 0xC469E88E, 0xC26AEE2B, - 0xC0DEF46C, 0xC073FA62, /* 8 */ - 0xC01D00D5, 0xC0760743, - 0xC1560D1E, 0xC2E51369, - 0xC4ED18FF, 0xC7AC1ED7, - 0xCB2823B2, 0xCEFA28D9, /* 16 */ - 0xD2F62D3F, 0xD7BB3197, - 0xDCE53568, 0xE1FE3875, - 0xE7D13B35, 0xED663D35, - 0xF39B3EC4, 0xF98E3FA7, /* 24 */ - 0x00004000, 0x06723FA7, - 0x0C653EC4, 0x129A3D35, - 0x182F3B35, 0x1E023875, - 0x231B3568, 0x28453197, /* 32 */ - 0x2D0A2D3F, 0x310628D9, - 0x34D823B2, 0x38541ED7, - 0x3B1318FF, 0x3D1B1369, - 0x3EAA0D1E, 0x3F8A0743, /* 40 */ - 0x3FE300D5, 0x3F8DFA62, - 0x3F22F46C, 0x3D96EE2B, - 0x3B97E88E, 0x38D7E2B4, - 0x35C8DD9F, 0x325AD826, /* 48 */ - 0x2E03D358, 0x299ACF64, - 0x246DCB87, -}; - -const u16 bcm43xx_ilt_finefreqa[BCM43xx_ILT_FINEFREQA_SIZE] = { - 0x0082, 0x0082, 0x0102, 0x0182, /* 0 */ - 0x0202, 0x0282, 0x0302, 0x0382, - 0x0402, 0x0482, 0x0502, 0x0582, - 0x05E2, 0x0662, 0x06E2, 0x0762, - 0x07E2, 0x0842, 0x08C2, 0x0942, /* 16 */ - 0x09C2, 0x0A22, 0x0AA2, 0x0B02, - 0x0B82, 0x0BE2, 0x0C62, 0x0CC2, - 0x0D42, 0x0DA2, 0x0E02, 0x0E62, - 0x0EE2, 0x0F42, 0x0FA2, 0x1002, /* 32 */ - 0x1062, 0x10C2, 0x1122, 0x1182, - 0x11E2, 0x1242, 0x12A2, 0x12E2, - 0x1342, 0x13A2, 0x1402, 0x1442, - 0x14A2, 0x14E2, 0x1542, 0x1582, /* 48 */ - 0x15E2, 0x1622, 0x1662, 0x16C1, - 0x1701, 0x1741, 0x1781, 0x17E1, - 0x1821, 0x1861, 0x18A1, 0x18E1, - 0x1921, 0x1961, 0x19A1, 0x19E1, /* 64 */ - 0x1A21, 0x1A61, 0x1AA1, 0x1AC1, - 0x1B01, 0x1B41, 0x1B81, 0x1BA1, - 0x1BE1, 0x1C21, 0x1C41, 0x1C81, - 0x1CA1, 0x1CE1, 0x1D01, 0x1D41, /* 80 */ - 0x1D61, 0x1DA1, 0x1DC1, 0x1E01, - 0x1E21, 0x1E61, 0x1E81, 0x1EA1, - 0x1EE1, 0x1F01, 0x1F21, 0x1F41, - 0x1F81, 0x1FA1, 0x1FC1, 0x1FE1, /* 96 */ - 0x2001, 0x2041, 0x2061, 0x2081, - 0x20A1, 0x20C1, 0x20E1, 0x2101, - 0x2121, 0x2141, 0x2161, 0x2181, - 0x21A1, 0x21C1, 0x21E1, 0x2201, /* 112 */ - 0x2221, 0x2241, 0x2261, 0x2281, - 0x22A1, 0x22C1, 0x22C1, 0x22E1, - 0x2301, 0x2321, 0x2341, 0x2361, - 0x2361, 0x2381, 0x23A1, 0x23C1, /* 128 */ - 0x23E1, 0x23E1, 0x2401, 0x2421, - 0x2441, 0x2441, 0x2461, 0x2481, - 0x2481, 0x24A1, 0x24C1, 0x24C1, - 0x24E1, 0x2501, 0x2501, 0x2521, /* 144 */ - 0x2541, 0x2541, 0x2561, 0x2561, - 0x2581, 0x25A1, 0x25A1, 0x25C1, - 0x25C1, 0x25E1, 0x2601, 0x2601, - 0x2621, 0x2621, 0x2641, 0x2641, /* 160 */ - 0x2661, 0x2661, 0x2681, 0x2681, - 0x26A1, 0x26A1, 0x26C1, 0x26C1, - 0x26E1, 0x26E1, 0x2701, 0x2701, - 0x2721, 0x2721, 0x2740, 0x2740, /* 176 */ - 0x2760, 0x2760, 0x2780, 0x2780, - 0x2780, 0x27A0, 0x27A0, 0x27C0, - 0x27C0, 0x27E0, 0x27E0, 0x27E0, - 0x2800, 0x2800, 0x2820, 0x2820, /* 192 */ - 0x2820, 0x2840, 0x2840, 0x2840, - 0x2860, 0x2860, 0x2880, 0x2880, - 0x2880, 0x28A0, 0x28A0, 0x28A0, - 0x28C0, 0x28C0, 0x28C0, 0x28E0, /* 208 */ - 0x28E0, 0x28E0, 0x2900, 0x2900, - 0x2900, 0x2920, 0x2920, 0x2920, - 0x2940, 0x2940, 0x2940, 0x2960, - 0x2960, 0x2960, 0x2960, 0x2980, /* 224 */ - 0x2980, 0x2980, 0x29A0, 0x29A0, - 0x29A0, 0x29A0, 0x29C0, 0x29C0, - 0x29C0, 0x29E0, 0x29E0, 0x29E0, - 0x29E0, 0x2A00, 0x2A00, 0x2A00, /* 240 */ - 0x2A00, 0x2A20, 0x2A20, 0x2A20, - 0x2A20, 0x2A40, 0x2A40, 0x2A40, - 0x2A40, 0x2A60, 0x2A60, 0x2A60, -}; - -const u16 bcm43xx_ilt_finefreqg[BCM43xx_ILT_FINEFREQG_SIZE] = { - 0x0089, 0x02E9, 0x0409, 0x04E9, /* 0 */ - 0x05A9, 0x0669, 0x0709, 0x0789, - 0x0829, 0x08A9, 0x0929, 0x0989, - 0x0A09, 0x0A69, 0x0AC9, 0x0B29, - 0x0BA9, 0x0BE9, 0x0C49, 0x0CA9, /* 16 */ - 0x0D09, 0x0D69, 0x0DA9, 0x0E09, - 0x0E69, 0x0EA9, 0x0F09, 0x0F49, - 0x0FA9, 0x0FE9, 0x1029, 0x1089, - 0x10C9, 0x1109, 0x1169, 0x11A9, /* 32 */ - 0x11E9, 0x1229, 0x1289, 0x12C9, - 0x1309, 0x1349, 0x1389, 0x13C9, - 0x1409, 0x1449, 0x14A9, 0x14E9, - 0x1529, 0x1569, 0x15A9, 0x15E9, /* 48 */ - 0x1629, 0x1669, 0x16A9, 0x16E8, - 0x1728, 0x1768, 0x17A8, 0x17E8, - 0x1828, 0x1868, 0x18A8, 0x18E8, - 0x1928, 0x1968, 0x19A8, 0x19E8, /* 64 */ - 0x1A28, 0x1A68, 0x1AA8, 0x1AE8, - 0x1B28, 0x1B68, 0x1BA8, 0x1BE8, - 0x1C28, 0x1C68, 0x1CA8, 0x1CE8, - 0x1D28, 0x1D68, 0x1DC8, 0x1E08, /* 80 */ - 0x1E48, 0x1E88, 0x1EC8, 0x1F08, - 0x1F48, 0x1F88, 0x1FE8, 0x2028, - 0x2068, 0x20A8, 0x2108, 0x2148, - 0x2188, 0x21C8, 0x2228, 0x2268, /* 96 */ - 0x22C8, 0x2308, 0x2348, 0x23A8, - 0x23E8, 0x2448, 0x24A8, 0x24E8, - 0x2548, 0x25A8, 0x2608, 0x2668, - 0x26C8, 0x2728, 0x2787, 0x27E7, /* 112 */ - 0x2847, 0x28C7, 0x2947, 0x29A7, - 0x2A27, 0x2AC7, 0x2B47, 0x2BE7, - 0x2CA7, 0x2D67, 0x2E47, 0x2F67, - 0x3247, 0x3526, 0x3646, 0x3726, /* 128 */ - 0x3806, 0x38A6, 0x3946, 0x39E6, - 0x3A66, 0x3AE6, 0x3B66, 0x3BC6, - 0x3C45, 0x3CA5, 0x3D05, 0x3D85, - 0x3DE5, 0x3E45, 0x3EA5, 0x3EE5, /* 144 */ - 0x3F45, 0x3FA5, 0x4005, 0x4045, - 0x40A5, 0x40E5, 0x4145, 0x4185, - 0x41E5, 0x4225, 0x4265, 0x42C5, - 0x4305, 0x4345, 0x43A5, 0x43E5, /* 160 */ - 0x4424, 0x4464, 0x44C4, 0x4504, - 0x4544, 0x4584, 0x45C4, 0x4604, - 0x4644, 0x46A4, 0x46E4, 0x4724, - 0x4764, 0x47A4, 0x47E4, 0x4824, /* 176 */ - 0x4864, 0x48A4, 0x48E4, 0x4924, - 0x4964, 0x49A4, 0x49E4, 0x4A24, - 0x4A64, 0x4AA4, 0x4AE4, 0x4B23, - 0x4B63, 0x4BA3, 0x4BE3, 0x4C23, /* 192 */ - 0x4C63, 0x4CA3, 0x4CE3, 0x4D23, - 0x4D63, 0x4DA3, 0x4DE3, 0x4E23, - 0x4E63, 0x4EA3, 0x4EE3, 0x4F23, - 0x4F63, 0x4FC3, 0x5003, 0x5043, /* 208 */ - 0x5083, 0x50C3, 0x5103, 0x5143, - 0x5183, 0x51E2, 0x5222, 0x5262, - 0x52A2, 0x52E2, 0x5342, 0x5382, - 0x53C2, 0x5402, 0x5462, 0x54A2, /* 224 */ - 0x5502, 0x5542, 0x55A2, 0x55E2, - 0x5642, 0x5682, 0x56E2, 0x5722, - 0x5782, 0x57E1, 0x5841, 0x58A1, - 0x5901, 0x5961, 0x59C1, 0x5A21, /* 240 */ - 0x5AA1, 0x5B01, 0x5B81, 0x5BE1, - 0x5C61, 0x5D01, 0x5D80, 0x5E20, - 0x5EE0, 0x5FA0, 0x6080, 0x61C0, -}; - -const u16 bcm43xx_ilt_noisea2[BCM43xx_ILT_NOISEA2_SIZE] = { - 0x0001, 0x0001, 0x0001, 0xFFFE, - 0xFFFE, 0x3FFF, 0x1000, 0x0393, -}; - -const u16 bcm43xx_ilt_noisea3[BCM43xx_ILT_NOISEA3_SIZE] = { - 0x4C4C, 0x4C4C, 0x4C4C, 0x2D36, - 0x4C4C, 0x4C4C, 0x4C4C, 0x2D36, -}; - -const u16 bcm43xx_ilt_noiseg1[BCM43xx_ILT_NOISEG1_SIZE] = { - 0x013C, 0x01F5, 0x031A, 0x0631, - 0x0001, 0x0001, 0x0001, 0x0001, -}; - -const u16 bcm43xx_ilt_noiseg2[BCM43xx_ILT_NOISEG2_SIZE] = { - 0x5484, 0x3C40, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, -}; - -const u16 bcm43xx_ilt_noisescaleg1[BCM43xx_ILT_NOISESCALEG_SIZE] = { - 0x6C77, 0x5162, 0x3B40, 0x3335, /* 0 */ - 0x2F2D, 0x2A2A, 0x2527, 0x1F21, - 0x1A1D, 0x1719, 0x1616, 0x1414, - 0x1414, 0x1400, 0x1414, 0x1614, - 0x1716, 0x1A19, 0x1F1D, 0x2521, /* 16 */ - 0x2A27, 0x2F2A, 0x332D, 0x3B35, - 0x5140, 0x6C62, 0x0077, -}; - -const u16 bcm43xx_ilt_noisescaleg2[BCM43xx_ILT_NOISESCALEG_SIZE] = { - 0xD8DD, 0xCBD4, 0xBCC0, 0XB6B7, /* 0 */ - 0xB2B0, 0xADAD, 0xA7A9, 0x9FA1, - 0x969B, 0x9195, 0x8F8F, 0x8A8A, - 0x8A8A, 0x8A00, 0x8A8A, 0x8F8A, - 0x918F, 0x9695, 0x9F9B, 0xA7A1, /* 16 */ - 0xADA9, 0xB2AD, 0xB6B0, 0xBCB7, - 0xCBC0, 0xD8D4, 0x00DD, -}; - -const u16 bcm43xx_ilt_noisescaleg3[BCM43xx_ILT_NOISESCALEG_SIZE] = { - 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, /* 0 */ - 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, - 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, - 0xA4A4, 0xA400, 0xA4A4, 0xA4A4, - 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, /* 16 */ - 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, - 0xA4A4, 0xA4A4, 0x00A4, -}; - -const u16 bcm43xx_ilt_sigmasqr1[BCM43xx_ILT_SIGMASQR_SIZE] = { - 0x007A, 0x0075, 0x0071, 0x006C, /* 0 */ - 0x0067, 0x0063, 0x005E, 0x0059, - 0x0054, 0x0050, 0x004B, 0x0046, - 0x0042, 0x003D, 0x003D, 0x003D, - 0x003D, 0x003D, 0x003D, 0x003D, /* 16 */ - 0x003D, 0x003D, 0x003D, 0x003D, - 0x003D, 0x003D, 0x0000, 0x003D, - 0x003D, 0x003D, 0x003D, 0x003D, - 0x003D, 0x003D, 0x003D, 0x003D, /* 32 */ - 0x003D, 0x003D, 0x003D, 0x003D, - 0x0042, 0x0046, 0x004B, 0x0050, - 0x0054, 0x0059, 0x005E, 0x0063, - 0x0067, 0x006C, 0x0071, 0x0075, /* 48 */ - 0x007A, -}; - -const u16 bcm43xx_ilt_sigmasqr2[BCM43xx_ILT_SIGMASQR_SIZE] = { - 0x00DE, 0x00DC, 0x00DA, 0x00D8, /* 0 */ - 0x00D6, 0x00D4, 0x00D2, 0x00CF, - 0x00CD, 0x00CA, 0x00C7, 0x00C4, - 0x00C1, 0x00BE, 0x00BE, 0x00BE, - 0x00BE, 0x00BE, 0x00BE, 0x00BE, /* 16 */ - 0x00BE, 0x00BE, 0x00BE, 0x00BE, - 0x00BE, 0x00BE, 0x0000, 0x00BE, - 0x00BE, 0x00BE, 0x00BE, 0x00BE, - 0x00BE, 0x00BE, 0x00BE, 0x00BE, /* 32 */ - 0x00BE, 0x00BE, 0x00BE, 0x00BE, - 0x00C1, 0x00C4, 0x00C7, 0x00CA, - 0x00CD, 0x00CF, 0x00D2, 0x00D4, - 0x00D6, 0x00D8, 0x00DA, 0x00DC, /* 48 */ - 0x00DE, -}; - -/**** Helper functions to access the device Internal Lookup Tables ****/ - -void bcm43xx_ilt_write(struct bcm43xx_private *bcm, u16 offset, u16 val) -{ - if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A) { - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, offset); - mmiowb(); - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, val); - } else { - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_CTRL, offset); - mmiowb(); - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_DATA1, val); - } -} - -void bcm43xx_ilt_write32(struct bcm43xx_private *bcm, u16 offset, u32 val) -{ - if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A) { - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, offset); - mmiowb(); - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA2, (val & 0xFFFF0000) >> 16); - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, val & 0x0000FFFF); - } else { - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_CTRL, offset); - mmiowb(); - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_DATA2, (val & 0xFFFF0000) >> 16); - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_DATA1, val & 0x0000FFFF); - } -} - -u16 bcm43xx_ilt_read(struct bcm43xx_private *bcm, u16 offset) -{ - if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A) { - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, offset); - return bcm43xx_phy_read(bcm, BCM43xx_PHY_ILT_A_DATA1); - } else { - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_CTRL, offset); - return bcm43xx_phy_read(bcm, BCM43xx_PHY_ILT_G_DATA1); - } -} diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h b/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h deleted file mode 100644 index d7eaf5f25b7f..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef BCM43xx_ILT_H_ -#define BCM43xx_ILT_H_ - -#define BCM43xx_ILT_ROTOR_SIZE 53 -extern const u32 bcm43xx_ilt_rotor[BCM43xx_ILT_ROTOR_SIZE]; -#define BCM43xx_ILT_RETARD_SIZE 53 -extern const u32 bcm43xx_ilt_retard[BCM43xx_ILT_RETARD_SIZE]; -#define BCM43xx_ILT_FINEFREQA_SIZE 256 -extern const u16 bcm43xx_ilt_finefreqa[BCM43xx_ILT_FINEFREQA_SIZE]; -#define BCM43xx_ILT_FINEFREQG_SIZE 256 -extern const u16 bcm43xx_ilt_finefreqg[BCM43xx_ILT_FINEFREQG_SIZE]; -#define BCM43xx_ILT_NOISEA2_SIZE 8 -extern const u16 bcm43xx_ilt_noisea2[BCM43xx_ILT_NOISEA2_SIZE]; -#define BCM43xx_ILT_NOISEA3_SIZE 8 -extern const u16 bcm43xx_ilt_noisea3[BCM43xx_ILT_NOISEA3_SIZE]; -#define BCM43xx_ILT_NOISEG1_SIZE 8 -extern const u16 bcm43xx_ilt_noiseg1[BCM43xx_ILT_NOISEG1_SIZE]; -#define BCM43xx_ILT_NOISEG2_SIZE 8 -extern const u16 bcm43xx_ilt_noiseg2[BCM43xx_ILT_NOISEG2_SIZE]; -#define BCM43xx_ILT_NOISESCALEG_SIZE 27 -extern const u16 bcm43xx_ilt_noisescaleg1[BCM43xx_ILT_NOISESCALEG_SIZE]; -extern const u16 bcm43xx_ilt_noisescaleg2[BCM43xx_ILT_NOISESCALEG_SIZE]; -extern const u16 bcm43xx_ilt_noisescaleg3[BCM43xx_ILT_NOISESCALEG_SIZE]; -#define BCM43xx_ILT_SIGMASQR_SIZE 53 -extern const u16 bcm43xx_ilt_sigmasqr1[BCM43xx_ILT_SIGMASQR_SIZE]; -extern const u16 bcm43xx_ilt_sigmasqr2[BCM43xx_ILT_SIGMASQR_SIZE]; - - -void bcm43xx_ilt_write(struct bcm43xx_private *bcm, u16 offset, u16 val); -void bcm43xx_ilt_write32(struct bcm43xx_private *bcm, u16 offset, u32 val); -u16 bcm43xx_ilt_read(struct bcm43xx_private *bcm, u16 offset); - -#endif /* BCM43xx_ILT_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c deleted file mode 100644 index cb51dc51cce6..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c +++ /dev/null @@ -1,307 +0,0 @@ -/* - - Broadcom BCM43xx wireless driver - - Copyright (c) 2005 Martin Langer , - Stefano Brivio - Michael Buesch - Danny van Dyk - Andreas Jaggi - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include "bcm43xx_leds.h" -#include "bcm43xx_radio.h" -#include "bcm43xx.h" - -#include - - -static void bcm43xx_led_changestate(struct bcm43xx_led *led) -{ - struct bcm43xx_private *bcm = led->bcm; - const int index = bcm43xx_led_index(led); - const u16 mask = (1 << index); - u16 ledctl; - - assert(index >= 0 && index < BCM43xx_NR_LEDS); - assert(led->blink_interval); - ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL); - ledctl = (ledctl & mask) ? (ledctl & ~mask) : (ledctl | mask); - bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl); -} - -static void bcm43xx_led_blink(unsigned long d) -{ - struct bcm43xx_led *led = (struct bcm43xx_led *)d; - struct bcm43xx_private *bcm = led->bcm; - unsigned long flags; - - spin_lock_irqsave(&bcm->leds_lock, flags); - if (led->blink_interval) { - bcm43xx_led_changestate(led); - mod_timer(&led->blink_timer, jiffies + led->blink_interval); - } - spin_unlock_irqrestore(&bcm->leds_lock, flags); -} - -static void bcm43xx_led_blink_start(struct bcm43xx_led *led, - unsigned long interval) -{ - if (led->blink_interval) - return; - led->blink_interval = interval; - bcm43xx_led_changestate(led); - led->blink_timer.expires = jiffies + interval; - add_timer(&led->blink_timer); -} - -static void bcm43xx_led_blink_stop(struct bcm43xx_led *led, int sync) -{ - struct bcm43xx_private *bcm = led->bcm; - const int index = bcm43xx_led_index(led); - u16 ledctl; - - if (!led->blink_interval) - return; - if (unlikely(sync)) - del_timer_sync(&led->blink_timer); - else - del_timer(&led->blink_timer); - led->blink_interval = 0; - - /* Make sure the LED is turned off. */ - assert(index >= 0 && index < BCM43xx_NR_LEDS); - ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL); - if (led->activelow) - ledctl |= (1 << index); - else - ledctl &= ~(1 << index); - bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl); -} - -static void bcm43xx_led_init_hardcoded(struct bcm43xx_private *bcm, - struct bcm43xx_led *led, - int led_index) -{ - /* This function is called, if the behaviour (and activelow) - * information for a LED is missing in the SPROM. - * We hardcode the behaviour values for various devices here. - * Note that the BCM43xx_LED_TEST_XXX behaviour values can - * be used to figure out which led is mapped to which index. - */ - - switch (led_index) { - case 0: - led->behaviour = BCM43xx_LED_ACTIVITY; - led->activelow = 1; - if (bcm->board_vendor == PCI_VENDOR_ID_COMPAQ) - led->behaviour = BCM43xx_LED_RADIO_ALL; - break; - case 1: - led->behaviour = BCM43xx_LED_RADIO_B; - if (bcm->board_vendor == PCI_VENDOR_ID_ASUSTEK) - led->behaviour = BCM43xx_LED_ASSOC; - break; - case 2: - led->behaviour = BCM43xx_LED_RADIO_A; - break; - case 3: - led->behaviour = BCM43xx_LED_OFF; - break; - default: - assert(0); - } -} - -int bcm43xx_leds_init(struct bcm43xx_private *bcm) -{ - struct bcm43xx_led *led; - u8 sprom[4]; - int i; - - sprom[0] = bcm->sprom.wl0gpio0; - sprom[1] = bcm->sprom.wl0gpio1; - sprom[2] = bcm->sprom.wl0gpio2; - sprom[3] = bcm->sprom.wl0gpio3; - - for (i = 0; i < BCM43xx_NR_LEDS; i++) { - led = &(bcm->leds[i]); - led->bcm = bcm; - setup_timer(&led->blink_timer, - bcm43xx_led_blink, - (unsigned long)led); - - if (sprom[i] == 0xFF) { - bcm43xx_led_init_hardcoded(bcm, led, i); - } else { - led->behaviour = sprom[i] & BCM43xx_LED_BEHAVIOUR; - led->activelow = !!(sprom[i] & BCM43xx_LED_ACTIVELOW); - } - } - - return 0; -} - -void bcm43xx_leds_exit(struct bcm43xx_private *bcm) -{ - struct bcm43xx_led *led; - int i; - - for (i = 0; i < BCM43xx_NR_LEDS; i++) { - led = &(bcm->leds[i]); - bcm43xx_led_blink_stop(led, 1); - } - bcm43xx_leds_switch_all(bcm, 0); -} - -void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity) -{ - struct bcm43xx_led *led; - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - const int transferring = (jiffies - bcm->stats.last_tx) < BCM43xx_LED_XFER_THRES; - int i, turn_on; - unsigned long interval = 0; - u16 ledctl; - unsigned long flags; - - spin_lock_irqsave(&bcm->leds_lock, flags); - ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL); - for (i = 0; i < BCM43xx_NR_LEDS; i++) { - led = &(bcm->leds[i]); - - turn_on = 0; - switch (led->behaviour) { - case BCM43xx_LED_INACTIVE: - continue; - case BCM43xx_LED_OFF: - case BCM43xx_LED_BCM4303_3: - break; - case BCM43xx_LED_ON: - turn_on = 1; - break; - case BCM43xx_LED_ACTIVITY: - case BCM43xx_LED_BCM4303_0: - turn_on = activity; - break; - case BCM43xx_LED_RADIO_ALL: - turn_on = radio->enabled && bcm43xx_is_hw_radio_enabled(bcm); - break; - case BCM43xx_LED_RADIO_A: - case BCM43xx_LED_BCM4303_2: - turn_on = (radio->enabled && bcm43xx_is_hw_radio_enabled(bcm) && - phy->type == BCM43xx_PHYTYPE_A); - break; - case BCM43xx_LED_RADIO_B: - case BCM43xx_LED_BCM4303_1: - turn_on = (radio->enabled && bcm43xx_is_hw_radio_enabled(bcm) && - (phy->type == BCM43xx_PHYTYPE_B || - phy->type == BCM43xx_PHYTYPE_G)); - break; - case BCM43xx_LED_MODE_BG: - if (phy->type == BCM43xx_PHYTYPE_G && bcm43xx_is_hw_radio_enabled(bcm) && - 1/*FIXME: using G rates.*/) - turn_on = 1; - break; - case BCM43xx_LED_TRANSFER: - if (transferring) - bcm43xx_led_blink_start(led, BCM43xx_LEDBLINK_MEDIUM); - else - bcm43xx_led_blink_stop(led, 0); - continue; - case BCM43xx_LED_APTRANSFER: - if (bcm->ieee->iw_mode == IW_MODE_MASTER) { - if (transferring) { - interval = BCM43xx_LEDBLINK_FAST; - turn_on = 1; - } - } else { - turn_on = 1; - if (0/*TODO: not assoc*/) - interval = BCM43xx_LEDBLINK_SLOW; - else if (transferring) - interval = BCM43xx_LEDBLINK_FAST; - else - turn_on = 0; - } - if (turn_on) - bcm43xx_led_blink_start(led, interval); - else - bcm43xx_led_blink_stop(led, 0); - continue; - case BCM43xx_LED_WEIRD: - //TODO - break; - case BCM43xx_LED_ASSOC: - if (bcm->softmac->associnfo.associated) - turn_on = 1; - break; -#ifdef CONFIG_BCM43XX_DEBUG - case BCM43xx_LED_TEST_BLINKSLOW: - bcm43xx_led_blink_start(led, BCM43xx_LEDBLINK_SLOW); - continue; - case BCM43xx_LED_TEST_BLINKMEDIUM: - bcm43xx_led_blink_start(led, BCM43xx_LEDBLINK_MEDIUM); - continue; - case BCM43xx_LED_TEST_BLINKFAST: - bcm43xx_led_blink_start(led, BCM43xx_LEDBLINK_FAST); - continue; -#endif /* CONFIG_BCM43XX_DEBUG */ - default: - dprintkl(KERN_INFO PFX "Bad value in leds_update," - " led->behaviour: 0x%x\n", led->behaviour); - }; - - if (led->activelow) - turn_on = !turn_on; - if (turn_on) - ledctl |= (1 << i); - else - ledctl &= ~(1 << i); - } - bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl); - spin_unlock_irqrestore(&bcm->leds_lock, flags); -} - -void bcm43xx_leds_switch_all(struct bcm43xx_private *bcm, int on) -{ - struct bcm43xx_led *led; - u16 ledctl; - int i; - int bit_on; - unsigned long flags; - - spin_lock_irqsave(&bcm->leds_lock, flags); - ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL); - for (i = 0; i < BCM43xx_NR_LEDS; i++) { - led = &(bcm->leds[i]); - if (led->behaviour == BCM43xx_LED_INACTIVE) - continue; - if (on) - bit_on = led->activelow ? 0 : 1; - else - bit_on = led->activelow ? 1 : 0; - if (bit_on) - ledctl |= (1 << i); - else - ledctl &= ~(1 << i); - } - bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl); - spin_unlock_irqrestore(&bcm->leds_lock, flags); -} diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_leds.h b/drivers/net/wireless/bcm43xx/bcm43xx_leds.h deleted file mode 100644 index 811e14a81198..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx_leds.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef BCM43xx_LEDS_H_ -#define BCM43xx_LEDS_H_ - -#include -#include - - -struct bcm43xx_led { - u8 behaviour:7; - u8 activelow:1; - - struct bcm43xx_private *bcm; - struct timer_list blink_timer; - unsigned long blink_interval; -}; -#define bcm43xx_led_index(led) ((int)((led) - (led)->bcm->leds)) - -/* Delay between state changes when blinking in jiffies */ -#define BCM43xx_LEDBLINK_SLOW (HZ / 1) -#define BCM43xx_LEDBLINK_MEDIUM (HZ / 4) -#define BCM43xx_LEDBLINK_FAST (HZ / 8) - -#define BCM43xx_LED_XFER_THRES (HZ / 100) - -#define BCM43xx_LED_BEHAVIOUR 0x7F -#define BCM43xx_LED_ACTIVELOW 0x80 -enum { /* LED behaviour values */ - BCM43xx_LED_OFF, - BCM43xx_LED_ON, - BCM43xx_LED_ACTIVITY, - BCM43xx_LED_RADIO_ALL, - BCM43xx_LED_RADIO_A, - BCM43xx_LED_RADIO_B, - BCM43xx_LED_MODE_BG, - BCM43xx_LED_TRANSFER, - BCM43xx_LED_APTRANSFER, - BCM43xx_LED_WEIRD,//FIXME - BCM43xx_LED_ASSOC, - BCM43xx_LED_INACTIVE, - - /* Behaviour values for testing. - * With these values it is easier to figure out - * the real behaviour of leds, in case the SPROM - * is missing information. - */ - BCM43xx_LED_TEST_BLINKSLOW, - BCM43xx_LED_TEST_BLINKMEDIUM, - BCM43xx_LED_TEST_BLINKFAST, - - /* Misc values for BCM4303 */ - BCM43xx_LED_BCM4303_0 = 0x2B, - BCM43xx_LED_BCM4303_1 = 0x78, - BCM43xx_LED_BCM4303_2 = 0x2E, - BCM43xx_LED_BCM4303_3 = 0x19, -}; - -int bcm43xx_leds_init(struct bcm43xx_private *bcm); -void bcm43xx_leds_exit(struct bcm43xx_private *bcm); -void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity); -void bcm43xx_leds_switch_all(struct bcm43xx_private *bcm, int on); - -#endif /* BCM43xx_LEDS_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c deleted file mode 100644 index b96a325b6ec8..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ /dev/null @@ -1,4281 +0,0 @@ -/* - - Broadcom BCM43xx wireless driver - - Copyright (c) 2005 Martin Langer , - Stefano Brivio - Michael Buesch - Danny van Dyk - Andreas Jaggi - - Some parts of the code in this file are derived from the ipw2200 - driver Copyright(c) 2003 - 2004 Intel Corporation. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "bcm43xx.h" -#include "bcm43xx_main.h" -#include "bcm43xx_debugfs.h" -#include "bcm43xx_radio.h" -#include "bcm43xx_phy.h" -#include "bcm43xx_dma.h" -#include "bcm43xx_pio.h" -#include "bcm43xx_power.h" -#include "bcm43xx_wx.h" -#include "bcm43xx_ethtool.h" -#include "bcm43xx_xmit.h" -#include "bcm43xx_sysfs.h" - - -MODULE_DESCRIPTION("Broadcom BCM43xx wireless driver"); -MODULE_AUTHOR("Martin Langer"); -MODULE_AUTHOR("Stefano Brivio"); -MODULE_AUTHOR("Michael Buesch"); -MODULE_LICENSE("GPL"); - -#if defined(CONFIG_BCM43XX_DMA) && defined(CONFIG_BCM43XX_PIO) -static int modparam_pio; -module_param_named(pio, modparam_pio, int, 0444); -MODULE_PARM_DESC(pio, "enable(1) / disable(0) PIO mode"); -#elif defined(CONFIG_BCM43XX_DMA) -# define modparam_pio 0 -#elif defined(CONFIG_BCM43XX_PIO) -# define modparam_pio 1 -#endif - -static int modparam_bad_frames_preempt; -module_param_named(bad_frames_preempt, modparam_bad_frames_preempt, int, 0444); -MODULE_PARM_DESC(bad_frames_preempt, "enable(1) / disable(0) Bad Frames Preemption"); - -static int modparam_short_retry = BCM43xx_DEFAULT_SHORT_RETRY_LIMIT; -module_param_named(short_retry, modparam_short_retry, int, 0444); -MODULE_PARM_DESC(short_retry, "Short-Retry-Limit (0 - 15)"); - -static int modparam_long_retry = BCM43xx_DEFAULT_LONG_RETRY_LIMIT; -module_param_named(long_retry, modparam_long_retry, int, 0444); -MODULE_PARM_DESC(long_retry, "Long-Retry-Limit (0 - 15)"); - -static int modparam_locale = -1; -module_param_named(locale, modparam_locale, int, 0444); -MODULE_PARM_DESC(country, "Select LocaleCode 0-11 (For travelers)"); - -static int modparam_noleds; -module_param_named(noleds, modparam_noleds, int, 0444); -MODULE_PARM_DESC(noleds, "Turn off all LED activity"); - -static char modparam_fwpostfix[64]; -module_param_string(fwpostfix, modparam_fwpostfix, 64, 0444); -MODULE_PARM_DESC(fwpostfix, "Postfix for .fw files. Useful for using multiple firmware image versions."); - - -/* If you want to debug with just a single device, enable this, - * where the string is the pci device ID (as given by the kernel's - * pci_name function) of the device to be used. - */ -//#define DEBUG_SINGLE_DEVICE_ONLY "0001:11:00.0" - -/* If you want to enable printing of each MMIO access, enable this. */ -//#define DEBUG_ENABLE_MMIO_PRINT - -/* If you want to enable printing of MMIO access within - * ucode/pcm upload, initvals write, enable this. - */ -//#define DEBUG_ENABLE_UCODE_MMIO_PRINT - -/* If you want to enable printing of PCI Config Space access, enable this */ -//#define DEBUG_ENABLE_PCILOG - - -/* Detailed list maintained at: - * http://openfacts.berlios.de/index-en.phtml?title=Bcm43xxDevices - */ - static struct pci_device_id bcm43xx_pci_tbl[] = { - /* Broadcom 4303 802.11b */ - { PCI_VENDOR_ID_BROADCOM, 0x4301, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - /* Broadcom 4307 802.11b */ - { PCI_VENDOR_ID_BROADCOM, 0x4307, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - /* Broadcom 4311 802.11(a)/b/g */ - { PCI_VENDOR_ID_BROADCOM, 0x4311, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - /* Broadcom 4312 802.11a/b/g */ - { PCI_VENDOR_ID_BROADCOM, 0x4312, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - /* Broadcom 4318 802.11b/g */ - { PCI_VENDOR_ID_BROADCOM, 0x4318, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - /* Broadcom 4319 802.11a/b/g */ - { PCI_VENDOR_ID_BROADCOM, 0x4319, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - /* Broadcom 4306 802.11b/g */ - { PCI_VENDOR_ID_BROADCOM, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - /* Broadcom 4306 802.11a */ -// { PCI_VENDOR_ID_BROADCOM, 0x4321, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - /* Broadcom 4309 802.11a/b/g */ - { PCI_VENDOR_ID_BROADCOM, 0x4324, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - /* Broadcom 43XG 802.11b/g */ - { PCI_VENDOR_ID_BROADCOM, 0x4325, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { 0 }, -}; -MODULE_DEVICE_TABLE(pci, bcm43xx_pci_tbl); - -static void bcm43xx_ram_write(struct bcm43xx_private *bcm, u16 offset, u32 val) -{ - u32 status; - - status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); - if (!(status & BCM43xx_SBF_XFER_REG_BYTESWAP)) - val = swab32(val); - - bcm43xx_write32(bcm, BCM43xx_MMIO_RAM_CONTROL, offset); - mmiowb(); - bcm43xx_write32(bcm, BCM43xx_MMIO_RAM_DATA, val); -} - -static inline -void bcm43xx_shm_control_word(struct bcm43xx_private *bcm, - u16 routing, u16 offset) -{ - u32 control; - - /* "offset" is the WORD offset. */ - - control = routing; - control <<= 16; - control |= offset; - bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_CONTROL, control); -} - -u32 bcm43xx_shm_read32(struct bcm43xx_private *bcm, - u16 routing, u16 offset) -{ - u32 ret; - - if (routing == BCM43xx_SHM_SHARED) { - if (offset & 0x0003) { - /* Unaligned access */ - bcm43xx_shm_control_word(bcm, routing, offset >> 2); - ret = bcm43xx_read16(bcm, BCM43xx_MMIO_SHM_DATA_UNALIGNED); - ret <<= 16; - bcm43xx_shm_control_word(bcm, routing, (offset >> 2) + 1); - ret |= bcm43xx_read16(bcm, BCM43xx_MMIO_SHM_DATA); - - return ret; - } - offset >>= 2; - } - bcm43xx_shm_control_word(bcm, routing, offset); - ret = bcm43xx_read32(bcm, BCM43xx_MMIO_SHM_DATA); - - return ret; -} - -u16 bcm43xx_shm_read16(struct bcm43xx_private *bcm, - u16 routing, u16 offset) -{ - u16 ret; - - if (routing == BCM43xx_SHM_SHARED) { - if (offset & 0x0003) { - /* Unaligned access */ - bcm43xx_shm_control_word(bcm, routing, offset >> 2); - ret = bcm43xx_read16(bcm, BCM43xx_MMIO_SHM_DATA_UNALIGNED); - - return ret; - } - offset >>= 2; - } - bcm43xx_shm_control_word(bcm, routing, offset); - ret = bcm43xx_read16(bcm, BCM43xx_MMIO_SHM_DATA); - - return ret; -} - -void bcm43xx_shm_write32(struct bcm43xx_private *bcm, - u16 routing, u16 offset, - u32 value) -{ - if (routing == BCM43xx_SHM_SHARED) { - if (offset & 0x0003) { - /* Unaligned access */ - bcm43xx_shm_control_word(bcm, routing, offset >> 2); - mmiowb(); - bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA_UNALIGNED, - (value >> 16) & 0xffff); - mmiowb(); - bcm43xx_shm_control_word(bcm, routing, (offset >> 2) + 1); - mmiowb(); - bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA, - value & 0xffff); - return; - } - offset >>= 2; - } - bcm43xx_shm_control_word(bcm, routing, offset); - mmiowb(); - bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA, value); -} - -void bcm43xx_shm_write16(struct bcm43xx_private *bcm, - u16 routing, u16 offset, - u16 value) -{ - if (routing == BCM43xx_SHM_SHARED) { - if (offset & 0x0003) { - /* Unaligned access */ - bcm43xx_shm_control_word(bcm, routing, offset >> 2); - mmiowb(); - bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA_UNALIGNED, - value); - return; - } - offset >>= 2; - } - bcm43xx_shm_control_word(bcm, routing, offset); - mmiowb(); - bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA, value); -} - -void bcm43xx_tsf_read(struct bcm43xx_private *bcm, u64 *tsf) -{ - /* We need to be careful. As we read the TSF from multiple - * registers, we should take care of register overflows. - * In theory, the whole tsf read process should be atomic. - * We try to be atomic here, by restaring the read process, - * if any of the high registers changed (overflew). - */ - if (bcm->current_core->rev >= 3) { - u32 low, high, high2; - - do { - high = bcm43xx_read32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_HIGH); - low = bcm43xx_read32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_LOW); - high2 = bcm43xx_read32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_HIGH); - } while (unlikely(high != high2)); - - *tsf = high; - *tsf <<= 32; - *tsf |= low; - } else { - u64 tmp; - u16 v0, v1, v2, v3; - u16 test1, test2, test3; - - do { - v3 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_3); - v2 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_2); - v1 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_1); - v0 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_0); - - test3 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_3); - test2 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_2); - test1 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_1); - } while (v3 != test3 || v2 != test2 || v1 != test1); - - *tsf = v3; - *tsf <<= 48; - tmp = v2; - tmp <<= 32; - *tsf |= tmp; - tmp = v1; - tmp <<= 16; - *tsf |= tmp; - *tsf |= v0; - } -} - -void bcm43xx_tsf_write(struct bcm43xx_private *bcm, u64 tsf) -{ - u32 status; - - status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); - status |= BCM43xx_SBF_TIME_UPDATE; - bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status); - mmiowb(); - - /* Be careful with the in-progress timer. - * First zero out the low register, so we have a full - * register-overflow duration to complete the operation. - */ - if (bcm->current_core->rev >= 3) { - u32 lo = (tsf & 0x00000000FFFFFFFFULL); - u32 hi = (tsf & 0xFFFFFFFF00000000ULL) >> 32; - - bcm43xx_write32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_LOW, 0); - mmiowb(); - bcm43xx_write32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_HIGH, hi); - mmiowb(); - bcm43xx_write32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_LOW, lo); - } else { - u16 v0 = (tsf & 0x000000000000FFFFULL); - u16 v1 = (tsf & 0x00000000FFFF0000ULL) >> 16; - u16 v2 = (tsf & 0x0000FFFF00000000ULL) >> 32; - u16 v3 = (tsf & 0xFFFF000000000000ULL) >> 48; - - bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_0, 0); - mmiowb(); - bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_3, v3); - mmiowb(); - bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_2, v2); - mmiowb(); - bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_1, v1); - mmiowb(); - bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_0, v0); - } - - status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); - status &= ~BCM43xx_SBF_TIME_UPDATE; - bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status); -} - -static -void bcm43xx_macfilter_set(struct bcm43xx_private *bcm, - u16 offset, - const u8 *mac) -{ - u16 data; - - offset |= 0x0020; - bcm43xx_write16(bcm, BCM43xx_MMIO_MACFILTER_CONTROL, offset); - - data = mac[0]; - data |= mac[1] << 8; - bcm43xx_write16(bcm, BCM43xx_MMIO_MACFILTER_DATA, data); - data = mac[2]; - data |= mac[3] << 8; - bcm43xx_write16(bcm, BCM43xx_MMIO_MACFILTER_DATA, data); - data = mac[4]; - data |= mac[5] << 8; - bcm43xx_write16(bcm, BCM43xx_MMIO_MACFILTER_DATA, data); -} - -static void bcm43xx_macfilter_clear(struct bcm43xx_private *bcm, - u16 offset) -{ - const u8 zero_addr[ETH_ALEN] = { 0 }; - - bcm43xx_macfilter_set(bcm, offset, zero_addr); -} - -static void bcm43xx_write_mac_bssid_templates(struct bcm43xx_private *bcm) -{ - const u8 *mac = (const u8 *)(bcm->net_dev->dev_addr); - const u8 *bssid = (const u8 *)(bcm->ieee->bssid); - u8 mac_bssid[ETH_ALEN * 2]; - int i; - - memcpy(mac_bssid, mac, ETH_ALEN); - memcpy(mac_bssid + ETH_ALEN, bssid, ETH_ALEN); - - /* Write our MAC address and BSSID to template ram */ - for (i = 0; i < ARRAY_SIZE(mac_bssid); i += sizeof(u32)) - bcm43xx_ram_write(bcm, 0x20 + i, *((u32 *)(mac_bssid + i))); - for (i = 0; i < ARRAY_SIZE(mac_bssid); i += sizeof(u32)) - bcm43xx_ram_write(bcm, 0x78 + i, *((u32 *)(mac_bssid + i))); - for (i = 0; i < ARRAY_SIZE(mac_bssid); i += sizeof(u32)) - bcm43xx_ram_write(bcm, 0x478 + i, *((u32 *)(mac_bssid + i))); -} - -//FIXME: Well, we should probably call them from somewhere. -#if 0 -static void bcm43xx_set_slot_time(struct bcm43xx_private *bcm, u16 slot_time) -{ - /* slot_time is in usec. */ - if (bcm43xx_current_phy(bcm)->type != BCM43xx_PHYTYPE_G) - return; - bcm43xx_write16(bcm, 0x684, 510 + slot_time); - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0010, slot_time); -} - -static void bcm43xx_short_slot_timing_enable(struct bcm43xx_private *bcm) -{ - bcm43xx_set_slot_time(bcm, 9); -} - -static void bcm43xx_short_slot_timing_disable(struct bcm43xx_private *bcm) -{ - bcm43xx_set_slot_time(bcm, 20); -} -#endif - -/* FIXME: To get the MAC-filter working, we need to implement the - * following functions (and rename them :) - */ -#if 0 -static void bcm43xx_disassociate(struct bcm43xx_private *bcm) -{ - bcm43xx_mac_suspend(bcm); - bcm43xx_macfilter_clear(bcm, BCM43xx_MACFILTER_ASSOC); - - bcm43xx_ram_write(bcm, 0x0026, 0x0000); - bcm43xx_ram_write(bcm, 0x0028, 0x0000); - bcm43xx_ram_write(bcm, 0x007E, 0x0000); - bcm43xx_ram_write(bcm, 0x0080, 0x0000); - bcm43xx_ram_write(bcm, 0x047E, 0x0000); - bcm43xx_ram_write(bcm, 0x0480, 0x0000); - - if (bcm->current_core->rev < 3) { - bcm43xx_write16(bcm, 0x0610, 0x8000); - bcm43xx_write16(bcm, 0x060E, 0x0000); - } else - bcm43xx_write32(bcm, 0x0188, 0x80000000); - - bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0004, 0x000003ff); - - if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_G && - ieee80211_is_ofdm_rate(bcm->softmac->txrates.default_rate)) - bcm43xx_short_slot_timing_enable(bcm); - - bcm43xx_mac_enable(bcm); -} - -static void bcm43xx_associate(struct bcm43xx_private *bcm, - const u8 *mac) -{ - memcpy(bcm->ieee->bssid, mac, ETH_ALEN); - - bcm43xx_mac_suspend(bcm); - bcm43xx_macfilter_set(bcm, BCM43xx_MACFILTER_ASSOC, mac); - bcm43xx_write_mac_bssid_templates(bcm); - bcm43xx_mac_enable(bcm); -} -#endif - -/* Enable a Generic IRQ. "mask" is the mask of which IRQs to enable. - * Returns the _previously_ enabled IRQ mask. - */ -static inline u32 bcm43xx_interrupt_enable(struct bcm43xx_private *bcm, u32 mask) -{ - u32 old_mask; - - old_mask = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK); - bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK, old_mask | mask); - - return old_mask; -} - -/* Disable a Generic IRQ. "mask" is the mask of which IRQs to disable. - * Returns the _previously_ enabled IRQ mask. - */ -static inline u32 bcm43xx_interrupt_disable(struct bcm43xx_private *bcm, u32 mask) -{ - u32 old_mask; - - old_mask = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK); - bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK, old_mask & ~mask); - - return old_mask; -} - -/* Synchronize IRQ top- and bottom-half. - * IRQs must be masked before calling this. - * This must not be called with the irq_lock held. - */ -static void bcm43xx_synchronize_irq(struct bcm43xx_private *bcm) -{ - synchronize_irq(bcm->irq); - tasklet_disable(&bcm->isr_tasklet); -} - -/* Make sure we don't receive more data from the device. */ -static int bcm43xx_disable_interrupts_sync(struct bcm43xx_private *bcm) -{ - unsigned long flags; - - spin_lock_irqsave(&bcm->irq_lock, flags); - if (unlikely(bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)) { - spin_unlock_irqrestore(&bcm->irq_lock, flags); - return -EBUSY; - } - bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); - bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK); /* flush */ - spin_unlock_irqrestore(&bcm->irq_lock, flags); - bcm43xx_synchronize_irq(bcm); - - return 0; -} - -static int bcm43xx_read_radioinfo(struct bcm43xx_private *bcm) -{ - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - u32 radio_id; - u16 manufact; - u16 version; - u8 revision; - - if (bcm->chip_id == 0x4317) { - if (bcm->chip_rev == 0x00) - radio_id = 0x3205017F; - else if (bcm->chip_rev == 0x01) - radio_id = 0x4205017F; - else - radio_id = 0x5205017F; - } else { - bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_CONTROL, BCM43xx_RADIOCTL_ID); - radio_id = bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_DATA_HIGH); - radio_id <<= 16; - bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_CONTROL, BCM43xx_RADIOCTL_ID); - radio_id |= bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_DATA_LOW); - } - - manufact = (radio_id & 0x00000FFF); - version = (radio_id & 0x0FFFF000) >> 12; - revision = (radio_id & 0xF0000000) >> 28; - - dprintk(KERN_INFO PFX "Detected Radio: ID: %x (Manuf: %x Ver: %x Rev: %x)\n", - radio_id, manufact, version, revision); - - switch (phy->type) { - case BCM43xx_PHYTYPE_A: - if ((version != 0x2060) || (revision != 1) || (manufact != 0x17f)) - goto err_unsupported_radio; - break; - case BCM43xx_PHYTYPE_B: - if ((version & 0xFFF0) != 0x2050) - goto err_unsupported_radio; - break; - case BCM43xx_PHYTYPE_G: - if (version != 0x2050) - goto err_unsupported_radio; - break; - } - - radio->manufact = manufact; - radio->version = version; - radio->revision = revision; - - if (phy->type == BCM43xx_PHYTYPE_A) - radio->txpower_desired = bcm->sprom.maxpower_aphy; - else - radio->txpower_desired = bcm->sprom.maxpower_bgphy; - - return 0; - -err_unsupported_radio: - printk(KERN_ERR PFX "Unsupported Radio connected to the PHY!\n"); - return -ENODEV; -} - -static const char * bcm43xx_locale_iso(u8 locale) -{ - /* ISO 3166-1 country codes. - * Note that there aren't ISO 3166-1 codes for - * all or locales. (Not all locales are countries) - */ - switch (locale) { - case BCM43xx_LOCALE_WORLD: - case BCM43xx_LOCALE_ALL: - return "XX"; - case BCM43xx_LOCALE_THAILAND: - return "TH"; - case BCM43xx_LOCALE_ISRAEL: - return "IL"; - case BCM43xx_LOCALE_JORDAN: - return "JO"; - case BCM43xx_LOCALE_CHINA: - return "CN"; - case BCM43xx_LOCALE_JAPAN: - case BCM43xx_LOCALE_JAPAN_HIGH: - return "JP"; - case BCM43xx_LOCALE_USA_CANADA_ANZ: - case BCM43xx_LOCALE_USA_LOW: - return "US"; - case BCM43xx_LOCALE_EUROPE: - return "EU"; - case BCM43xx_LOCALE_NONE: - return " "; - } - assert(0); - return " "; -} - -static const char * bcm43xx_locale_string(u8 locale) -{ - switch (locale) { - case BCM43xx_LOCALE_WORLD: - return "World"; - case BCM43xx_LOCALE_THAILAND: - return "Thailand"; - case BCM43xx_LOCALE_ISRAEL: - return "Israel"; - case BCM43xx_LOCALE_JORDAN: - return "Jordan"; - case BCM43xx_LOCALE_CHINA: - return "China"; - case BCM43xx_LOCALE_JAPAN: - return "Japan"; - case BCM43xx_LOCALE_USA_CANADA_ANZ: - return "USA/Canada/ANZ"; - case BCM43xx_LOCALE_EUROPE: - return "Europe"; - case BCM43xx_LOCALE_USA_LOW: - return "USAlow"; - case BCM43xx_LOCALE_JAPAN_HIGH: - return "JapanHigh"; - case BCM43xx_LOCALE_ALL: - return "All"; - case BCM43xx_LOCALE_NONE: - return "None"; - } - assert(0); - return ""; -} - -static inline u8 bcm43xx_crc8(u8 crc, u8 data) -{ - static const u8 t[] = { - 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B, - 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21, - 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF, - 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5, - 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14, - 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E, - 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80, - 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA, - 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95, - 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF, - 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01, - 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B, - 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA, - 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0, - 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E, - 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34, - 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0, - 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A, - 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54, - 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E, - 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF, - 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5, - 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B, - 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61, - 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E, - 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74, - 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA, - 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0, - 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41, - 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B, - 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5, - 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F, - }; - return t[crc ^ data]; -} - -static u8 bcm43xx_sprom_crc(const u16 *sprom) -{ - int word; - u8 crc = 0xFF; - - for (word = 0; word < BCM43xx_SPROM_SIZE - 1; word++) { - crc = bcm43xx_crc8(crc, sprom[word] & 0x00FF); - crc = bcm43xx_crc8(crc, (sprom[word] & 0xFF00) >> 8); - } - crc = bcm43xx_crc8(crc, sprom[BCM43xx_SPROM_VERSION] & 0x00FF); - crc ^= 0xFF; - - return crc; -} - -int bcm43xx_sprom_read(struct bcm43xx_private *bcm, u16 *sprom) -{ - int i; - u8 crc, expected_crc; - - for (i = 0; i < BCM43xx_SPROM_SIZE; i++) - sprom[i] = bcm43xx_read16(bcm, BCM43xx_SPROM_BASE + (i * 2)); - /* CRC-8 check. */ - crc = bcm43xx_sprom_crc(sprom); - expected_crc = (sprom[BCM43xx_SPROM_VERSION] & 0xFF00) >> 8; - if (crc != expected_crc) { - printk(KERN_WARNING PFX "WARNING: Invalid SPROM checksum " - "(0x%02X, expected: 0x%02X)\n", - crc, expected_crc); - return -EINVAL; - } - - return 0; -} - -int bcm43xx_sprom_write(struct bcm43xx_private *bcm, const u16 *sprom) -{ - int i, err; - u8 crc, expected_crc; - u32 spromctl; - - /* CRC-8 validation of the input data. */ - crc = bcm43xx_sprom_crc(sprom); - expected_crc = (sprom[BCM43xx_SPROM_VERSION] & 0xFF00) >> 8; - if (crc != expected_crc) { - printk(KERN_ERR PFX "SPROM input data: Invalid CRC\n"); - return -EINVAL; - } - - printk(KERN_INFO PFX "Writing SPROM. Do NOT turn off the power! Please stand by...\n"); - err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCICFG_SPROMCTL, &spromctl); - if (err) - goto err_ctlreg; - spromctl |= 0x10; /* SPROM WRITE enable. */ - err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_SPROMCTL, spromctl); - if (err) - goto err_ctlreg; - /* We must burn lots of CPU cycles here, but that does not - * really matter as one does not write the SPROM every other minute... - */ - printk(KERN_INFO PFX "[ 0%%"); - mdelay(500); - for (i = 0; i < BCM43xx_SPROM_SIZE; i++) { - if (i == 16) - printk("25%%"); - else if (i == 32) - printk("50%%"); - else if (i == 48) - printk("75%%"); - else if (i % 2) - printk("."); - bcm43xx_write16(bcm, BCM43xx_SPROM_BASE + (i * 2), sprom[i]); - mmiowb(); - mdelay(20); - } - spromctl &= ~0x10; /* SPROM WRITE enable. */ - err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_SPROMCTL, spromctl); - if (err) - goto err_ctlreg; - mdelay(500); - printk("100%% ]\n"); - printk(KERN_INFO PFX "SPROM written.\n"); - bcm43xx_controller_restart(bcm, "SPROM update"); - - return 0; -err_ctlreg: - printk(KERN_ERR PFX "Could not access SPROM control register.\n"); - return -ENODEV; -} - -static int bcm43xx_sprom_extract(struct bcm43xx_private *bcm) -{ - u16 value; - u16 *sprom; - - sprom = kzalloc(BCM43xx_SPROM_SIZE * sizeof(u16), - GFP_KERNEL); - if (!sprom) { - printk(KERN_ERR PFX "sprom_extract OOM\n"); - return -ENOMEM; - } - bcm43xx_sprom_read(bcm, sprom); - - /* boardflags2 */ - value = sprom[BCM43xx_SPROM_BOARDFLAGS2]; - bcm->sprom.boardflags2 = value; - - /* il0macaddr */ - value = sprom[BCM43xx_SPROM_IL0MACADDR + 0]; - *(((__be16 *)bcm->sprom.il0macaddr) + 0) = cpu_to_be16(value); - value = sprom[BCM43xx_SPROM_IL0MACADDR + 1]; - *(((__be16 *)bcm->sprom.il0macaddr) + 1) = cpu_to_be16(value); - value = sprom[BCM43xx_SPROM_IL0MACADDR + 2]; - *(((__be16 *)bcm->sprom.il0macaddr) + 2) = cpu_to_be16(value); - - /* et0macaddr */ - value = sprom[BCM43xx_SPROM_ET0MACADDR + 0]; - *(((__be16 *)bcm->sprom.et0macaddr) + 0) = cpu_to_be16(value); - value = sprom[BCM43xx_SPROM_ET0MACADDR + 1]; - *(((__be16 *)bcm->sprom.et0macaddr) + 1) = cpu_to_be16(value); - value = sprom[BCM43xx_SPROM_ET0MACADDR + 2]; - *(((__be16 *)bcm->sprom.et0macaddr) + 2) = cpu_to_be16(value); - - /* et1macaddr */ - value = sprom[BCM43xx_SPROM_ET1MACADDR + 0]; - *(((__be16 *)bcm->sprom.et1macaddr) + 0) = cpu_to_be16(value); - value = sprom[BCM43xx_SPROM_ET1MACADDR + 1]; - *(((__be16 *)bcm->sprom.et1macaddr) + 1) = cpu_to_be16(value); - value = sprom[BCM43xx_SPROM_ET1MACADDR + 2]; - *(((__be16 *)bcm->sprom.et1macaddr) + 2) = cpu_to_be16(value); - - /* ethernet phy settings */ - value = sprom[BCM43xx_SPROM_ETHPHY]; - bcm->sprom.et0phyaddr = (value & 0x001F); - bcm->sprom.et1phyaddr = (value & 0x03E0) >> 5; - - /* boardrev, antennas, locale */ - value = sprom[BCM43xx_SPROM_BOARDREV]; - bcm->sprom.boardrev = (value & 0x00FF); - bcm->sprom.locale = (value & 0x0F00) >> 8; - bcm->sprom.antennas_aphy = (value & 0x3000) >> 12; - bcm->sprom.antennas_bgphy = (value & 0xC000) >> 14; - if (modparam_locale != -1) { - if (modparam_locale >= 0 && modparam_locale <= 11) { - bcm->sprom.locale = modparam_locale; - printk(KERN_WARNING PFX "Operating with modified " - "LocaleCode %u (%s)\n", - bcm->sprom.locale, - bcm43xx_locale_string(bcm->sprom.locale)); - } else { - printk(KERN_WARNING PFX "Module parameter \"locale\" " - "invalid value. (0 - 11)\n"); - } - } - - /* pa0b* */ - value = sprom[BCM43xx_SPROM_PA0B0]; - bcm->sprom.pa0b0 = value; - value = sprom[BCM43xx_SPROM_PA0B1]; - bcm->sprom.pa0b1 = value; - value = sprom[BCM43xx_SPROM_PA0B2]; - bcm->sprom.pa0b2 = value; - - /* wl0gpio* */ - value = sprom[BCM43xx_SPROM_WL0GPIO0]; - if (value == 0x0000) - value = 0xFFFF; - bcm->sprom.wl0gpio0 = value & 0x00FF; - bcm->sprom.wl0gpio1 = (value & 0xFF00) >> 8; - value = sprom[BCM43xx_SPROM_WL0GPIO2]; - if (value == 0x0000) - value = 0xFFFF; - bcm->sprom.wl0gpio2 = value & 0x00FF; - bcm->sprom.wl0gpio3 = (value & 0xFF00) >> 8; - - /* maxpower */ - value = sprom[BCM43xx_SPROM_MAXPWR]; - bcm->sprom.maxpower_aphy = (value & 0xFF00) >> 8; - bcm->sprom.maxpower_bgphy = value & 0x00FF; - - /* pa1b* */ - value = sprom[BCM43xx_SPROM_PA1B0]; - bcm->sprom.pa1b0 = value; - value = sprom[BCM43xx_SPROM_PA1B1]; - bcm->sprom.pa1b1 = value; - value = sprom[BCM43xx_SPROM_PA1B2]; - bcm->sprom.pa1b2 = value; - - /* idle tssi target */ - value = sprom[BCM43xx_SPROM_IDL_TSSI_TGT]; - bcm->sprom.idle_tssi_tgt_aphy = value & 0x00FF; - bcm->sprom.idle_tssi_tgt_bgphy = (value & 0xFF00) >> 8; - - /* boardflags */ - value = sprom[BCM43xx_SPROM_BOARDFLAGS]; - if (value == 0xFFFF) - value = 0x0000; - bcm->sprom.boardflags = value; - /* boardflags workarounds */ - if (bcm->board_vendor == PCI_VENDOR_ID_DELL && - bcm->chip_id == 0x4301 && - bcm->board_revision == 0x74) - bcm->sprom.boardflags |= BCM43xx_BFL_BTCOEXIST; - if (bcm->board_vendor == PCI_VENDOR_ID_APPLE && - bcm->board_type == 0x4E && - bcm->board_revision > 0x40) - bcm->sprom.boardflags |= BCM43xx_BFL_PACTRL; - - /* antenna gain */ - value = sprom[BCM43xx_SPROM_ANTENNA_GAIN]; - if (value == 0x0000 || value == 0xFFFF) - value = 0x0202; - /* convert values to Q5.2 */ - bcm->sprom.antennagain_aphy = ((value & 0xFF00) >> 8) * 4; - bcm->sprom.antennagain_bgphy = (value & 0x00FF) * 4; - - kfree(sprom); - - return 0; -} - -static int bcm43xx_geo_init(struct bcm43xx_private *bcm) -{ - struct ieee80211_geo *geo; - struct ieee80211_channel *chan; - int have_a = 0, have_bg = 0; - int i; - u8 channel; - struct bcm43xx_phyinfo *phy; - const char *iso_country; - u8 max_bg_channel; - - geo = kzalloc(sizeof(*geo), GFP_KERNEL); - if (!geo) - return -ENOMEM; - - for (i = 0; i < bcm->nr_80211_available; i++) { - phy = &(bcm->core_80211_ext[i].phy); - switch (phy->type) { - case BCM43xx_PHYTYPE_B: - case BCM43xx_PHYTYPE_G: - have_bg = 1; - break; - case BCM43xx_PHYTYPE_A: - have_a = 1; - break; - default: - assert(0); - } - } - iso_country = bcm43xx_locale_iso(bcm->sprom.locale); - -/* set the maximum channel based on locale set in sprom or witle locale option */ - switch (bcm->sprom.locale) { - case BCM43xx_LOCALE_THAILAND: - case BCM43xx_LOCALE_ISRAEL: - case BCM43xx_LOCALE_JORDAN: - case BCM43xx_LOCALE_USA_CANADA_ANZ: - case BCM43xx_LOCALE_USA_LOW: - max_bg_channel = 11; - break; - case BCM43xx_LOCALE_JAPAN: - case BCM43xx_LOCALE_JAPAN_HIGH: - max_bg_channel = 14; - break; - default: - max_bg_channel = 13; - } - - if (have_a) { - for (i = 0, channel = IEEE80211_52GHZ_MIN_CHANNEL; - channel <= IEEE80211_52GHZ_MAX_CHANNEL; channel++) { - chan = &geo->a[i++]; - chan->freq = bcm43xx_channel_to_freq_a(channel); - chan->channel = channel; - } - geo->a_channels = i; - } - if (have_bg) { - for (i = 0, channel = IEEE80211_24GHZ_MIN_CHANNEL; - channel <= max_bg_channel; channel++) { - chan = &geo->bg[i++]; - chan->freq = bcm43xx_channel_to_freq_bg(channel); - chan->channel = channel; - } - geo->bg_channels = i; - } - memcpy(geo->name, iso_country, 2); - if (0 /*TODO: Outdoor use only */) - geo->name[2] = 'O'; - else if (0 /*TODO: Indoor use only */) - geo->name[2] = 'I'; - else - geo->name[2] = ' '; - geo->name[3] = '\0'; - - ieee80211_set_geo(bcm->ieee, geo); - kfree(geo); - - return 0; -} - -/* DummyTransmission function, as documented on - * http://bcm-specs.sipsolutions.net/DummyTransmission - */ -void bcm43xx_dummy_transmission(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - unsigned int i, max_loop; - u16 value = 0; - u32 buffer[5] = { - 0x00000000, - 0x0000D400, - 0x00000000, - 0x00000001, - 0x00000000, - }; - - switch (phy->type) { - case BCM43xx_PHYTYPE_A: - max_loop = 0x1E; - buffer[0] = 0xCC010200; - break; - case BCM43xx_PHYTYPE_B: - case BCM43xx_PHYTYPE_G: - max_loop = 0xFA; - buffer[0] = 0x6E840B00; - break; - default: - assert(0); - return; - } - - for (i = 0; i < 5; i++) - bcm43xx_ram_write(bcm, i * 4, buffer[i]); - - bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */ - - bcm43xx_write16(bcm, 0x0568, 0x0000); - bcm43xx_write16(bcm, 0x07C0, 0x0000); - bcm43xx_write16(bcm, 0x050C, ((phy->type == BCM43xx_PHYTYPE_A) ? 1 : 0)); - bcm43xx_write16(bcm, 0x0508, 0x0000); - bcm43xx_write16(bcm, 0x050A, 0x0000); - bcm43xx_write16(bcm, 0x054C, 0x0000); - bcm43xx_write16(bcm, 0x056A, 0x0014); - bcm43xx_write16(bcm, 0x0568, 0x0826); - bcm43xx_write16(bcm, 0x0500, 0x0000); - bcm43xx_write16(bcm, 0x0502, 0x0030); - - if (radio->version == 0x2050 && radio->revision <= 0x5) - bcm43xx_radio_write16(bcm, 0x0051, 0x0017); - for (i = 0x00; i < max_loop; i++) { - value = bcm43xx_read16(bcm, 0x050E); - if (value & 0x0080) - break; - udelay(10); - } - for (i = 0x00; i < 0x0A; i++) { - value = bcm43xx_read16(bcm, 0x050E); - if (value & 0x0400) - break; - udelay(10); - } - for (i = 0x00; i < 0x0A; i++) { - value = bcm43xx_read16(bcm, 0x0690); - if (!(value & 0x0100)) - break; - udelay(10); - } - if (radio->version == 0x2050 && radio->revision <= 0x5) - bcm43xx_radio_write16(bcm, 0x0051, 0x0037); -} - -static void key_write(struct bcm43xx_private *bcm, - u8 index, u8 algorithm, const __le16 *key) -{ - unsigned int i, basic_wep = 0; - u32 offset; - u16 value; - - /* Write associated key information */ - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x100 + (index * 2), - ((index << 4) | (algorithm & 0x0F))); - - /* The first 4 WEP keys need extra love */ - if (((algorithm == BCM43xx_SEC_ALGO_WEP) || - (algorithm == BCM43xx_SEC_ALGO_WEP104)) && (index < 4)) - basic_wep = 1; - - /* Write key payload, 8 little endian words */ - offset = bcm->security_offset + (index * BCM43xx_SEC_KEYSIZE); - for (i = 0; i < (BCM43xx_SEC_KEYSIZE / sizeof(u16)); i++) { - value = le16_to_cpu(key[i]); - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, - offset + (i * 2), value); - - if (!basic_wep) - continue; - - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, - offset + (i * 2) + 4 * BCM43xx_SEC_KEYSIZE, - value); - } -} - -static void keymac_write(struct bcm43xx_private *bcm, - u8 index, const __be32 *addr) -{ - /* for keys 0-3 there is no associated mac address */ - if (index < 4) - return; - - index -= 4; - if (bcm->current_core->rev >= 5) { - bcm43xx_shm_write32(bcm, - BCM43xx_SHM_HWMAC, - index * 2, - be32_to_cpu(*addr)); - bcm43xx_shm_write16(bcm, - BCM43xx_SHM_HWMAC, - (index * 2) + 1, - be16_to_cpu(*((__be16 *)(addr + 1)))); - } else { - if (index < 8) { - TODO(); /* Put them in the macaddress filter */ - } else { - TODO(); - /* Put them BCM43xx_SHM_SHARED, stating index 0x0120. - Keep in mind to update the count of keymacs in 0x003E as well! */ - } - } -} - -static int bcm43xx_key_write(struct bcm43xx_private *bcm, - u8 index, u8 algorithm, - const u8 *_key, int key_len, - const u8 *mac_addr) -{ - u8 key[BCM43xx_SEC_KEYSIZE] = { 0 }; - - if (index >= ARRAY_SIZE(bcm->key)) - return -EINVAL; - if (key_len > ARRAY_SIZE(key)) - return -EINVAL; - if (algorithm < 1 || algorithm > 5) - return -EINVAL; - - memcpy(key, _key, key_len); - key_write(bcm, index, algorithm, (const __le16 *)key); - keymac_write(bcm, index, (const __be32 *)mac_addr); - - bcm->key[index].algorithm = algorithm; - - return 0; -} - -static void bcm43xx_clear_keys(struct bcm43xx_private *bcm) -{ - static const __be32 zero_mac[2] = { 0 }; - unsigned int i,j, nr_keys = 54; - u16 offset; - - if (bcm->current_core->rev < 5) - nr_keys = 16; - assert(nr_keys <= ARRAY_SIZE(bcm->key)); - - for (i = 0; i < nr_keys; i++) { - bcm->key[i].enabled = 0; - /* returns for i < 4 immediately */ - keymac_write(bcm, i, zero_mac); - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, - 0x100 + (i * 2), 0x0000); - for (j = 0; j < 8; j++) { - offset = bcm->security_offset + (j * 4) + (i * BCM43xx_SEC_KEYSIZE); - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, - offset, 0x0000); - } - } - dprintk(KERN_INFO PFX "Keys cleared\n"); -} - -/* Lowlevel core-switch function. This is only to be used in - * bcm43xx_switch_core() and bcm43xx_probe_cores() - */ -static int _switch_core(struct bcm43xx_private *bcm, int core) -{ - int err; - int attempts = 0; - u32 current_core; - - assert(core >= 0); - while (1) { - err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_ACTIVE_CORE, - (core * 0x1000) + 0x18000000); - if (unlikely(err)) - goto error; - err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCICFG_ACTIVE_CORE, - ¤t_core); - if (unlikely(err)) - goto error; - current_core = (current_core - 0x18000000) / 0x1000; - if (current_core == core) - break; - - if (unlikely(attempts++ > BCM43xx_SWITCH_CORE_MAX_RETRIES)) - goto error; - udelay(10); - } - - return 0; -error: - printk(KERN_ERR PFX "Failed to switch to core %d\n", core); - return -ENODEV; -} - -int bcm43xx_switch_core(struct bcm43xx_private *bcm, struct bcm43xx_coreinfo *new_core) -{ - int err; - - if (unlikely(!new_core)) - return 0; - if (!new_core->available) - return -ENODEV; - if (bcm->current_core == new_core) - return 0; - err = _switch_core(bcm, new_core->index); - if (unlikely(err)) - goto out; - - bcm->current_core = new_core; -out: - return err; -} - -static int bcm43xx_core_enabled(struct bcm43xx_private *bcm) -{ - u32 value; - - value = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); - value &= BCM43xx_SBTMSTATELOW_CLOCK | BCM43xx_SBTMSTATELOW_RESET - | BCM43xx_SBTMSTATELOW_REJECT; - - return (value == BCM43xx_SBTMSTATELOW_CLOCK); -} - -/* disable current core */ -static int bcm43xx_core_disable(struct bcm43xx_private *bcm, u32 core_flags) -{ - u32 sbtmstatelow; - u32 sbtmstatehigh; - int i; - - /* fetch sbtmstatelow from core information registers */ - sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); - - /* core is already in reset */ - if (sbtmstatelow & BCM43xx_SBTMSTATELOW_RESET) - goto out; - - if (sbtmstatelow & BCM43xx_SBTMSTATELOW_CLOCK) { - sbtmstatelow = BCM43xx_SBTMSTATELOW_CLOCK | - BCM43xx_SBTMSTATELOW_REJECT; - bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); - - for (i = 0; i < 1000; i++) { - sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); - if (sbtmstatelow & BCM43xx_SBTMSTATELOW_REJECT) { - i = -1; - break; - } - udelay(10); - } - if (i != -1) { - printk(KERN_ERR PFX "Error: core_disable() REJECT timeout!\n"); - return -EBUSY; - } - - for (i = 0; i < 1000; i++) { - sbtmstatehigh = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH); - if (!(sbtmstatehigh & BCM43xx_SBTMSTATEHIGH_BUSY)) { - i = -1; - break; - } - udelay(10); - } - if (i != -1) { - printk(KERN_ERR PFX "Error: core_disable() BUSY timeout!\n"); - return -EBUSY; - } - - sbtmstatelow = BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK | - BCM43xx_SBTMSTATELOW_REJECT | - BCM43xx_SBTMSTATELOW_RESET | - BCM43xx_SBTMSTATELOW_CLOCK | - core_flags; - bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); - udelay(10); - } - - sbtmstatelow = BCM43xx_SBTMSTATELOW_RESET | - BCM43xx_SBTMSTATELOW_REJECT | - core_flags; - bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); - -out: - bcm->current_core->enabled = 0; - - return 0; -} - -/* enable (reset) current core */ -static int bcm43xx_core_enable(struct bcm43xx_private *bcm, u32 core_flags) -{ - u32 sbtmstatelow; - u32 sbtmstatehigh; - u32 sbimstate; - int err; - - err = bcm43xx_core_disable(bcm, core_flags); - if (err) - goto out; - - sbtmstatelow = BCM43xx_SBTMSTATELOW_CLOCK | - BCM43xx_SBTMSTATELOW_RESET | - BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK | - core_flags; - bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); - udelay(1); - - sbtmstatehigh = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH); - if (sbtmstatehigh & BCM43xx_SBTMSTATEHIGH_SERROR) { - sbtmstatehigh = 0x00000000; - bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATEHIGH, sbtmstatehigh); - } - - sbimstate = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMSTATE); - if (sbimstate & (BCM43xx_SBIMSTATE_IB_ERROR | BCM43xx_SBIMSTATE_TIMEOUT)) { - sbimstate &= ~(BCM43xx_SBIMSTATE_IB_ERROR | BCM43xx_SBIMSTATE_TIMEOUT); - bcm43xx_write32(bcm, BCM43xx_CIR_SBIMSTATE, sbimstate); - } - - sbtmstatelow = BCM43xx_SBTMSTATELOW_CLOCK | - BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK | - core_flags; - bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); - udelay(1); - - sbtmstatelow = BCM43xx_SBTMSTATELOW_CLOCK | core_flags; - bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); - udelay(1); - - bcm->current_core->enabled = 1; - assert(err == 0); -out: - return err; -} - -/* http://bcm-specs.sipsolutions.net/80211CoreReset */ -void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy) -{ - u32 flags = 0x00040000; - - if ((bcm43xx_core_enabled(bcm)) && - !bcm43xx_using_pio(bcm)) { - } - if (bcm43xx_status(bcm) == BCM43xx_STAT_SHUTTINGDOWN) { - bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, - bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) - & ~(BCM43xx_SBF_MAC_ENABLED | 0x00000002)); - } else { - if (connect_phy) - flags |= BCM43xx_SBTMSTATELOW_G_MODE_ENABLE; - bcm43xx_phy_connect(bcm, connect_phy); - bcm43xx_core_enable(bcm, flags); - bcm43xx_write16(bcm, 0x03E6, 0x0000); - bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, - bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) - | BCM43xx_SBF_400); - } -} - -static void bcm43xx_wireless_core_disable(struct bcm43xx_private *bcm) -{ - bcm43xx_radio_turn_off(bcm); - bcm43xx_write16(bcm, 0x03E6, 0x00F4); - bcm43xx_core_disable(bcm, 0); -} - -/* Mark the current 80211 core inactive. */ -static void bcm43xx_wireless_core_mark_inactive(struct bcm43xx_private *bcm) -{ - u32 sbtmstatelow; - - bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); - bcm43xx_radio_turn_off(bcm); - sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); - sbtmstatelow &= 0xDFF5FFFF; - sbtmstatelow |= 0x000A0000; - bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); - udelay(1); - sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); - sbtmstatelow &= 0xFFF5FFFF; - sbtmstatelow |= 0x00080000; - bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); - udelay(1); -} - -static void handle_irq_transmit_status(struct bcm43xx_private *bcm) -{ - u32 v0, v1; - u16 tmp; - struct bcm43xx_xmitstatus stat; - - while (1) { - v0 = bcm43xx_read32(bcm, BCM43xx_MMIO_XMITSTAT_0); - if (!v0) - break; - v1 = bcm43xx_read32(bcm, BCM43xx_MMIO_XMITSTAT_1); - - stat.cookie = (v0 >> 16) & 0x0000FFFF; - tmp = (u16)((v0 & 0xFFF0) | ((v0 & 0xF) >> 1)); - stat.flags = tmp & 0xFF; - stat.cnt1 = (tmp & 0x0F00) >> 8; - stat.cnt2 = (tmp & 0xF000) >> 12; - stat.seq = (u16)(v1 & 0xFFFF); - stat.unknown = (u16)((v1 >> 16) & 0xFF); - - bcm43xx_debugfs_log_txstat(bcm, &stat); - - if (stat.flags & BCM43xx_TXSTAT_FLAG_AMPDU) - continue; - if (stat.flags & BCM43xx_TXSTAT_FLAG_INTER) - continue; - - if (bcm43xx_using_pio(bcm)) - bcm43xx_pio_handle_xmitstatus(bcm, &stat); - else - bcm43xx_dma_handle_xmitstatus(bcm, &stat); - } -} - -static void drain_txstatus_queue(struct bcm43xx_private *bcm) -{ - u32 dummy; - - if (bcm->current_core->rev < 5) - return; - /* Read all entries from the microcode TXstatus FIFO - * and throw them away. - */ - while (1) { - dummy = bcm43xx_read32(bcm, BCM43xx_MMIO_XMITSTAT_0); - if (!dummy) - break; - dummy = bcm43xx_read32(bcm, BCM43xx_MMIO_XMITSTAT_1); - } -} - -static void bcm43xx_generate_noise_sample(struct bcm43xx_private *bcm) -{ - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x408, 0x7F7F); - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x40A, 0x7F7F); - bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD, - bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD) | (1 << 4)); - assert(bcm->noisecalc.core_at_start == bcm->current_core); - assert(bcm->noisecalc.channel_at_start == bcm43xx_current_radio(bcm)->channel); -} - -static void bcm43xx_calculate_link_quality(struct bcm43xx_private *bcm) -{ - /* Top half of Link Quality calculation. */ - - if (bcm->noisecalc.calculation_running) - return; - bcm->noisecalc.core_at_start = bcm->current_core; - bcm->noisecalc.channel_at_start = bcm43xx_current_radio(bcm)->channel; - bcm->noisecalc.calculation_running = 1; - bcm->noisecalc.nr_samples = 0; - - bcm43xx_generate_noise_sample(bcm); -} - -static void handle_irq_noise(struct bcm43xx_private *bcm) -{ - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - u16 tmp; - u8 noise[4]; - u8 i, j; - s32 average; - - /* Bottom half of Link Quality calculation. */ - - assert(bcm->noisecalc.calculation_running); - if (bcm->noisecalc.core_at_start != bcm->current_core || - bcm->noisecalc.channel_at_start != radio->channel) - goto drop_calculation; - tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x408); - noise[0] = (tmp & 0x00FF); - noise[1] = (tmp & 0xFF00) >> 8; - tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x40A); - noise[2] = (tmp & 0x00FF); - noise[3] = (tmp & 0xFF00) >> 8; - if (noise[0] == 0x7F || noise[1] == 0x7F || - noise[2] == 0x7F || noise[3] == 0x7F) - goto generate_new; - - /* Get the noise samples. */ - assert(bcm->noisecalc.nr_samples < 8); - i = bcm->noisecalc.nr_samples; - noise[0] = limit_value(noise[0], 0, ARRAY_SIZE(radio->nrssi_lt) - 1); - noise[1] = limit_value(noise[1], 0, ARRAY_SIZE(radio->nrssi_lt) - 1); - noise[2] = limit_value(noise[2], 0, ARRAY_SIZE(radio->nrssi_lt) - 1); - noise[3] = limit_value(noise[3], 0, ARRAY_SIZE(radio->nrssi_lt) - 1); - bcm->noisecalc.samples[i][0] = radio->nrssi_lt[noise[0]]; - bcm->noisecalc.samples[i][1] = radio->nrssi_lt[noise[1]]; - bcm->noisecalc.samples[i][2] = radio->nrssi_lt[noise[2]]; - bcm->noisecalc.samples[i][3] = radio->nrssi_lt[noise[3]]; - bcm->noisecalc.nr_samples++; - if (bcm->noisecalc.nr_samples == 8) { - /* Calculate the Link Quality by the noise samples. */ - average = 0; - for (i = 0; i < 8; i++) { - for (j = 0; j < 4; j++) - average += bcm->noisecalc.samples[i][j]; - } - average /= (8 * 4); - average *= 125; - average += 64; - average /= 128; - - tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x40C); - tmp = (tmp / 128) & 0x1F; - if (tmp >= 8) - average += 2; - else - average -= 25; - if (tmp == 8) - average -= 72; - else - average -= 48; - - bcm->stats.noise = average; -drop_calculation: - bcm->noisecalc.calculation_running = 0; - return; - } -generate_new: - bcm43xx_generate_noise_sample(bcm); -} - -static void handle_irq_ps(struct bcm43xx_private *bcm) -{ - if (bcm->ieee->iw_mode == IW_MODE_MASTER) { - ///TODO: PS TBTT - } else { - if (1/*FIXME: the last PSpoll frame was sent successfully */) - bcm43xx_power_saving_ctl_bits(bcm, -1, -1); - } - if (bcm->ieee->iw_mode == IW_MODE_ADHOC) - bcm->reg124_set_0x4 = 1; - //FIXME else set to false? -} - -static void handle_irq_reg124(struct bcm43xx_private *bcm) -{ - if (!bcm->reg124_set_0x4) - return; - bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD, - bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD) - | 0x4); - //FIXME: reset reg124_set_0x4 to false? -} - -static void handle_irq_pmq(struct bcm43xx_private *bcm) -{ - u32 tmp; - - //TODO: AP mode. - - while (1) { - tmp = bcm43xx_read32(bcm, BCM43xx_MMIO_PS_STATUS); - if (!(tmp & 0x00000008)) - break; - } - /* 16bit write is odd, but correct. */ - bcm43xx_write16(bcm, BCM43xx_MMIO_PS_STATUS, 0x0002); -} - -static void bcm43xx_generate_beacon_template(struct bcm43xx_private *bcm, - u16 ram_offset, u16 shm_size_offset) -{ - u32 value; - u16 size = 0; - - /* Timestamp. */ - //FIXME: assumption: The chip sets the timestamp - value = 0; - bcm43xx_ram_write(bcm, ram_offset++, value); - bcm43xx_ram_write(bcm, ram_offset++, value); - size += 8; - - /* Beacon Interval / Capability Information */ - value = 0x0000;//FIXME: Which interval? - value |= (1 << 0) << 16; /* ESS */ - value |= (1 << 2) << 16; /* CF Pollable */ //FIXME? - value |= (1 << 3) << 16; /* CF Poll Request */ //FIXME? - if (!bcm->ieee->open_wep) - value |= (1 << 4) << 16; /* Privacy */ - bcm43xx_ram_write(bcm, ram_offset++, value); - size += 4; - - /* SSID */ - //TODO - - /* FH Parameter Set */ - //TODO - - /* DS Parameter Set */ - //TODO - - /* CF Parameter Set */ - //TODO - - /* TIM */ - //TODO - - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, shm_size_offset, size); -} - -static void handle_irq_beacon(struct bcm43xx_private *bcm) -{ - u32 status; - - bcm->irq_savedstate &= ~BCM43xx_IRQ_BEACON; - status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD); - - if ((status & 0x1) && (status & 0x2)) { - /* ACK beacon IRQ. */ - bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, - BCM43xx_IRQ_BEACON); - bcm->irq_savedstate |= BCM43xx_IRQ_BEACON; - return; - } - if (!(status & 0x1)) { - bcm43xx_generate_beacon_template(bcm, 0x68, 0x18); - status |= 0x1; - bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD, status); - } - if (!(status & 0x2)) { - bcm43xx_generate_beacon_template(bcm, 0x468, 0x1A); - status |= 0x2; - bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD, status); - } -} - -/* Interrupt handler bottom-half */ -static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm) -{ - u32 reason; - u32 dma_reason[6]; - u32 merged_dma_reason = 0; - int i, activity = 0; - unsigned long flags; - -#ifdef CONFIG_BCM43XX_DEBUG - u32 _handled = 0x00000000; -# define bcmirq_handled(irq) do { _handled |= (irq); } while (0) -#else -# define bcmirq_handled(irq) do { /* nothing */ } while (0) -#endif /* CONFIG_BCM43XX_DEBUG*/ - - spin_lock_irqsave(&bcm->irq_lock, flags); - reason = bcm->irq_reason; - for (i = 5; i >= 0; i--) { - dma_reason[i] = bcm->dma_reason[i]; - merged_dma_reason |= dma_reason[i]; - } - - if (unlikely(reason & BCM43xx_IRQ_XMIT_ERROR)) { - /* TX error. We get this when Template Ram is written in wrong endianess - * in dummy_tx(). We also get this if something is wrong with the TX header - * on DMA or PIO queues. - * Maybe we get this in other error conditions, too. - */ - printkl(KERN_ERR PFX "FATAL ERROR: BCM43xx_IRQ_XMIT_ERROR\n"); - bcmirq_handled(BCM43xx_IRQ_XMIT_ERROR); - } - if (unlikely(merged_dma_reason & BCM43xx_DMAIRQ_FATALMASK)) { - printkl(KERN_ERR PFX "FATAL ERROR: Fatal DMA error: " - "0x%08X, 0x%08X, 0x%08X, " - "0x%08X, 0x%08X, 0x%08X\n", - dma_reason[0], dma_reason[1], - dma_reason[2], dma_reason[3], - dma_reason[4], dma_reason[5]); - bcm43xx_controller_restart(bcm, "DMA error"); - mmiowb(); - spin_unlock_irqrestore(&bcm->irq_lock, flags); - return; - } - if (unlikely(merged_dma_reason & BCM43xx_DMAIRQ_NONFATALMASK)) { - printkl(KERN_ERR PFX "DMA error: " - "0x%08X, 0x%08X, 0x%08X, " - "0x%08X, 0x%08X, 0x%08X\n", - dma_reason[0], dma_reason[1], - dma_reason[2], dma_reason[3], - dma_reason[4], dma_reason[5]); - } - - if (reason & BCM43xx_IRQ_PS) { - handle_irq_ps(bcm); - bcmirq_handled(BCM43xx_IRQ_PS); - } - - if (reason & BCM43xx_IRQ_REG124) { - handle_irq_reg124(bcm); - bcmirq_handled(BCM43xx_IRQ_REG124); - } - - if (reason & BCM43xx_IRQ_BEACON) { - if (bcm->ieee->iw_mode == IW_MODE_MASTER) - handle_irq_beacon(bcm); - bcmirq_handled(BCM43xx_IRQ_BEACON); - } - - if (reason & BCM43xx_IRQ_PMQ) { - handle_irq_pmq(bcm); - bcmirq_handled(BCM43xx_IRQ_PMQ); - } - - if (reason & BCM43xx_IRQ_SCAN) { - /*TODO*/ - //bcmirq_handled(BCM43xx_IRQ_SCAN); - } - - if (reason & BCM43xx_IRQ_NOISE) { - handle_irq_noise(bcm); - bcmirq_handled(BCM43xx_IRQ_NOISE); - } - - /* Check the DMA reason registers for received data. */ - if (dma_reason[0] & BCM43xx_DMAIRQ_RX_DONE) { - if (bcm43xx_using_pio(bcm)) - bcm43xx_pio_rx(bcm43xx_current_pio(bcm)->queue0); - else - bcm43xx_dma_rx(bcm43xx_current_dma(bcm)->rx_ring0); - /* We intentionally don't set "activity" to 1, here. */ - } - assert(!(dma_reason[1] & BCM43xx_DMAIRQ_RX_DONE)); - assert(!(dma_reason[2] & BCM43xx_DMAIRQ_RX_DONE)); - if (dma_reason[3] & BCM43xx_DMAIRQ_RX_DONE) { - if (bcm43xx_using_pio(bcm)) - bcm43xx_pio_rx(bcm43xx_current_pio(bcm)->queue3); - else - bcm43xx_dma_rx(bcm43xx_current_dma(bcm)->rx_ring3); - activity = 1; - } - assert(!(dma_reason[4] & BCM43xx_DMAIRQ_RX_DONE)); - assert(!(dma_reason[5] & BCM43xx_DMAIRQ_RX_DONE)); - bcmirq_handled(BCM43xx_IRQ_RX); - - if (reason & BCM43xx_IRQ_XMIT_STATUS) { - handle_irq_transmit_status(bcm); - activity = 1; - //TODO: In AP mode, this also causes sending of powersave responses. - bcmirq_handled(BCM43xx_IRQ_XMIT_STATUS); - } - - /* IRQ_PIO_WORKAROUND is handled in the top-half. */ - bcmirq_handled(BCM43xx_IRQ_PIO_WORKAROUND); -#ifdef CONFIG_BCM43XX_DEBUG - if (unlikely(reason & ~_handled)) { - printkl(KERN_WARNING PFX - "Unhandled IRQ! Reason: 0x%08x, Unhandled: 0x%08x, " - "DMA: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n", - reason, (reason & ~_handled), - dma_reason[0], dma_reason[1], - dma_reason[2], dma_reason[3]); - } -#endif -#undef bcmirq_handled - - if (!modparam_noleds) - bcm43xx_leds_update(bcm, activity); - bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate); - mmiowb(); - spin_unlock_irqrestore(&bcm->irq_lock, flags); -} - -static void pio_irq_workaround(struct bcm43xx_private *bcm, - u16 base, int queueidx) -{ - u16 rxctl; - - rxctl = bcm43xx_read16(bcm, base + BCM43xx_PIO_RXCTL); - if (rxctl & BCM43xx_PIO_RXCTL_DATAAVAILABLE) - bcm->dma_reason[queueidx] |= BCM43xx_DMAIRQ_RX_DONE; - else - bcm->dma_reason[queueidx] &= ~BCM43xx_DMAIRQ_RX_DONE; -} - -static void bcm43xx_interrupt_ack(struct bcm43xx_private *bcm, u32 reason) -{ - if (bcm43xx_using_pio(bcm) && - (bcm->current_core->rev < 3) && - (!(reason & BCM43xx_IRQ_PIO_WORKAROUND))) { - /* Apply a PIO specific workaround to the dma_reasons */ - pio_irq_workaround(bcm, BCM43xx_MMIO_PIO1_BASE, 0); - pio_irq_workaround(bcm, BCM43xx_MMIO_PIO2_BASE, 1); - pio_irq_workaround(bcm, BCM43xx_MMIO_PIO3_BASE, 2); - pio_irq_workaround(bcm, BCM43xx_MMIO_PIO4_BASE, 3); - } - - bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, reason); - - bcm43xx_write32(bcm, BCM43xx_MMIO_DMA0_REASON, - bcm->dma_reason[0]); - bcm43xx_write32(bcm, BCM43xx_MMIO_DMA1_REASON, - bcm->dma_reason[1]); - bcm43xx_write32(bcm, BCM43xx_MMIO_DMA2_REASON, - bcm->dma_reason[2]); - bcm43xx_write32(bcm, BCM43xx_MMIO_DMA3_REASON, - bcm->dma_reason[3]); - bcm43xx_write32(bcm, BCM43xx_MMIO_DMA4_REASON, - bcm->dma_reason[4]); - bcm43xx_write32(bcm, BCM43xx_MMIO_DMA5_REASON, - bcm->dma_reason[5]); -} - -/* Interrupt handler top-half */ -static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id) -{ - irqreturn_t ret = IRQ_HANDLED; - struct bcm43xx_private *bcm = dev_id; - u32 reason; - - if (!bcm) - return IRQ_NONE; - - spin_lock(&bcm->irq_lock); - - reason = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); - if (reason == 0xffffffff) { - /* irq not for us (shared irq) */ - ret = IRQ_NONE; - goto out; - } - reason &= bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK); - if (!reason) - goto out; - - assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED); - assert(bcm->current_core->id == BCM43xx_COREID_80211); - - bcm->dma_reason[0] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA0_REASON) - & 0x0001DC00; - bcm->dma_reason[1] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA1_REASON) - & 0x0000DC00; - bcm->dma_reason[2] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA2_REASON) - & 0x0000DC00; - bcm->dma_reason[3] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA3_REASON) - & 0x0001DC00; - bcm->dma_reason[4] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA4_REASON) - & 0x0000DC00; - bcm->dma_reason[5] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA5_REASON) - & 0x0000DC00; - - bcm43xx_interrupt_ack(bcm, reason); - - /* disable all IRQs. They are enabled again in the bottom half. */ - bcm->irq_savedstate = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); - /* save the reason code and call our bottom half. */ - bcm->irq_reason = reason; - tasklet_schedule(&bcm->isr_tasklet); - -out: - mmiowb(); - spin_unlock(&bcm->irq_lock); - - return ret; -} - -static void bcm43xx_release_firmware(struct bcm43xx_private *bcm, int force) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - - if (bcm->firmware_norelease && !force) - return; /* Suspending or controller reset. */ - release_firmware(phy->ucode); - phy->ucode = NULL; - release_firmware(phy->pcm); - phy->pcm = NULL; - release_firmware(phy->initvals0); - phy->initvals0 = NULL; - release_firmware(phy->initvals1); - phy->initvals1 = NULL; -} - -static int bcm43xx_request_firmware(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - u8 rev = bcm->current_core->rev; - int err = 0; - int nr; - char buf[22 + sizeof(modparam_fwpostfix) - 1] = { 0 }; - - if (!phy->ucode) { - snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_microcode%d%s.fw", - (rev >= 5 ? 5 : rev), - modparam_fwpostfix); - err = request_firmware(&phy->ucode, buf, &bcm->pci_dev->dev); - if (err) { - printk(KERN_ERR PFX - "Error: Microcode \"%s\" not available or load failed.\n", - buf); - goto error; - } - } - - if (!phy->pcm) { - snprintf(buf, ARRAY_SIZE(buf), - "bcm43xx_pcm%d%s.fw", - (rev < 5 ? 4 : 5), - modparam_fwpostfix); - err = request_firmware(&phy->pcm, buf, &bcm->pci_dev->dev); - if (err) { - printk(KERN_ERR PFX - "Error: PCM \"%s\" not available or load failed.\n", - buf); - goto error; - } - } - - if (!phy->initvals0) { - if (rev == 2 || rev == 4) { - switch (phy->type) { - case BCM43xx_PHYTYPE_A: - nr = 3; - break; - case BCM43xx_PHYTYPE_B: - case BCM43xx_PHYTYPE_G: - nr = 1; - break; - default: - goto err_noinitval; - } - - } else if (rev >= 5) { - switch (phy->type) { - case BCM43xx_PHYTYPE_A: - nr = 7; - break; - case BCM43xx_PHYTYPE_B: - case BCM43xx_PHYTYPE_G: - nr = 5; - break; - default: - goto err_noinitval; - } - } else - goto err_noinitval; - snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_initval%02d%s.fw", - nr, modparam_fwpostfix); - - err = request_firmware(&phy->initvals0, buf, &bcm->pci_dev->dev); - if (err) { - printk(KERN_ERR PFX - "Error: InitVals \"%s\" not available or load failed.\n", - buf); - goto error; - } - if (phy->initvals0->size % sizeof(struct bcm43xx_initval)) { - printk(KERN_ERR PFX "InitVals fileformat error.\n"); - goto error; - } - } - - if (!phy->initvals1) { - if (rev >= 5) { - u32 sbtmstatehigh; - - switch (phy->type) { - case BCM43xx_PHYTYPE_A: - sbtmstatehigh = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH); - if (sbtmstatehigh & 0x00010000) - nr = 9; - else - nr = 10; - break; - case BCM43xx_PHYTYPE_B: - case BCM43xx_PHYTYPE_G: - nr = 6; - break; - default: - goto err_noinitval; - } - snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_initval%02d%s.fw", - nr, modparam_fwpostfix); - - err = request_firmware(&phy->initvals1, buf, &bcm->pci_dev->dev); - if (err) { - printk(KERN_ERR PFX - "Error: InitVals \"%s\" not available or load failed.\n", - buf); - goto error; - } - if (phy->initvals1->size % sizeof(struct bcm43xx_initval)) { - printk(KERN_ERR PFX "InitVals fileformat error.\n"); - goto error; - } - } - } - -out: - return err; -error: - bcm43xx_release_firmware(bcm, 1); - goto out; -err_noinitval: - printk(KERN_ERR PFX "Error: No InitVals available!\n"); - err = -ENOENT; - goto error; -} - -static void bcm43xx_upload_microcode(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - const __be32 *data; - unsigned int i, len; - - /* Upload Microcode. */ - data = (__be32 *)(phy->ucode->data); - len = phy->ucode->size / sizeof(u32); - bcm43xx_shm_control_word(bcm, BCM43xx_SHM_UCODE, 0x0000); - for (i = 0; i < len; i++) { - bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA, - be32_to_cpu(data[i])); - udelay(10); - } - - /* Upload PCM data. */ - data = (__be32 *)(phy->pcm->data); - len = phy->pcm->size / sizeof(u32); - bcm43xx_shm_control_word(bcm, BCM43xx_SHM_PCM, 0x01ea); - bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA, 0x00004000); - bcm43xx_shm_control_word(bcm, BCM43xx_SHM_PCM, 0x01eb); - for (i = 0; i < len; i++) { - bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA, - be32_to_cpu(data[i])); - udelay(10); - } -} - -static int bcm43xx_write_initvals(struct bcm43xx_private *bcm, - const struct bcm43xx_initval *data, - const unsigned int len) -{ - u16 offset, size; - u32 value; - unsigned int i; - - for (i = 0; i < len; i++) { - offset = be16_to_cpu(data[i].offset); - size = be16_to_cpu(data[i].size); - value = be32_to_cpu(data[i].value); - - if (unlikely(offset >= 0x1000)) - goto err_format; - if (size == 2) { - if (unlikely(value & 0xFFFF0000)) - goto err_format; - bcm43xx_write16(bcm, offset, (u16)value); - } else if (size == 4) { - bcm43xx_write32(bcm, offset, value); - } else - goto err_format; - } - - return 0; - -err_format: - printk(KERN_ERR PFX "InitVals (bcm43xx_initvalXX.fw) file-format error. " - "Please fix your bcm43xx firmware files.\n"); - return -EPROTO; -} - -static int bcm43xx_upload_initvals(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - int err; - - err = bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)phy->initvals0->data, - phy->initvals0->size / sizeof(struct bcm43xx_initval)); - if (err) - goto out; - if (phy->initvals1) { - err = bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)phy->initvals1->data, - phy->initvals1->size / sizeof(struct bcm43xx_initval)); - if (err) - goto out; - } -out: - return err; -} - -static int bcm43xx_initialize_irq(struct bcm43xx_private *bcm) -{ - int err; - - bcm->irq = bcm->pci_dev->irq; - err = request_irq(bcm->irq, bcm43xx_interrupt_handler, - IRQF_SHARED, KBUILD_MODNAME, bcm); - if (err) - printk(KERN_ERR PFX "Cannot register IRQ%d\n", bcm->irq); - - return err; -} - -/* Switch to the core used to write the GPIO register. - * This is either the ChipCommon, or the PCI core. - */ -static int switch_to_gpio_core(struct bcm43xx_private *bcm) -{ - int err; - - /* Where to find the GPIO register depends on the chipset. - * If it has a ChipCommon, its register at offset 0x6c is the GPIO - * control register. Otherwise the register at offset 0x6c in the - * PCI core is the GPIO control register. - */ - err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon); - if (err == -ENODEV) { - err = bcm43xx_switch_core(bcm, &bcm->core_pci); - if (unlikely(err == -ENODEV)) { - printk(KERN_ERR PFX "gpio error: " - "Neither ChipCommon nor PCI core available!\n"); - } - } - - return err; -} - -/* Initialize the GPIOs - * http://bcm-specs.sipsolutions.net/GPIO - */ -static int bcm43xx_gpio_init(struct bcm43xx_private *bcm) -{ - struct bcm43xx_coreinfo *old_core; - int err; - u32 mask, set; - - bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, - bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) - & 0xFFFF3FFF); - - bcm43xx_leds_switch_all(bcm, 0); - bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_MASK, - bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_MASK) | 0x000F); - - mask = 0x0000001F; - set = 0x0000000F; - if (bcm->chip_id == 0x4301) { - mask |= 0x0060; - set |= 0x0060; - } - if (0 /* FIXME: conditional unknown */) { - bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_MASK, - bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_MASK) - | 0x0100); - mask |= 0x0180; - set |= 0x0180; - } - if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) { - bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_MASK, - bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_MASK) - | 0x0200); - mask |= 0x0200; - set |= 0x0200; - } - if (bcm->current_core->rev >= 2) - mask |= 0x0010; /* FIXME: This is redundant. */ - - old_core = bcm->current_core; - err = switch_to_gpio_core(bcm); - if (err) - goto out; - bcm43xx_write32(bcm, BCM43xx_GPIO_CONTROL, - (bcm43xx_read32(bcm, BCM43xx_GPIO_CONTROL) & mask) | set); - err = bcm43xx_switch_core(bcm, old_core); -out: - return err; -} - -/* Turn off all GPIO stuff. Call this on module unload, for example. */ -static int bcm43xx_gpio_cleanup(struct bcm43xx_private *bcm) -{ - struct bcm43xx_coreinfo *old_core; - int err; - - old_core = bcm->current_core; - err = switch_to_gpio_core(bcm); - if (err) - return err; - bcm43xx_write32(bcm, BCM43xx_GPIO_CONTROL, 0x00000000); - err = bcm43xx_switch_core(bcm, old_core); - assert(err == 0); - - return 0; -} - -/* http://bcm-specs.sipsolutions.net/EnableMac */ -void bcm43xx_mac_enable(struct bcm43xx_private *bcm) -{ - bcm->mac_suspended--; - assert(bcm->mac_suspended >= 0); - if (bcm->mac_suspended == 0) { - bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, - bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) - | BCM43xx_SBF_MAC_ENABLED); - bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, BCM43xx_IRQ_READY); - bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */ - bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */ - bcm43xx_power_saving_ctl_bits(bcm, -1, -1); - } -} - -/* http://bcm-specs.sipsolutions.net/SuspendMAC */ -void bcm43xx_mac_suspend(struct bcm43xx_private *bcm) -{ - int i; - u32 tmp; - - assert(bcm->mac_suspended >= 0); - if (bcm->mac_suspended == 0) { - bcm43xx_power_saving_ctl_bits(bcm, -1, 1); - bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, - bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) - & ~BCM43xx_SBF_MAC_ENABLED); - bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */ - for (i = 10000; i; i--) { - tmp = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); - if (tmp & BCM43xx_IRQ_READY) - goto out; - udelay(1); - } - printkl(KERN_ERR PFX "MAC suspend failed\n"); - } -out: - bcm->mac_suspended++; -} - -void bcm43xx_set_iwmode(struct bcm43xx_private *bcm, - int iw_mode) -{ - unsigned long flags; - struct net_device *net_dev = bcm->net_dev; - u32 status; - u16 value; - - spin_lock_irqsave(&bcm->ieee->lock, flags); - bcm->ieee->iw_mode = iw_mode; - spin_unlock_irqrestore(&bcm->ieee->lock, flags); - if (iw_mode == IW_MODE_MONITOR) - net_dev->type = ARPHRD_IEEE80211; - else - net_dev->type = ARPHRD_ETHER; - - status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); - /* Reset status to infrastructured mode */ - status &= ~(BCM43xx_SBF_MODE_AP | BCM43xx_SBF_MODE_MONITOR); - status &= ~BCM43xx_SBF_MODE_PROMISC; - status |= BCM43xx_SBF_MODE_NOTADHOC; - -/* FIXME: Always enable promisc mode, until we get the MAC filters working correctly. */ -status |= BCM43xx_SBF_MODE_PROMISC; - - switch (iw_mode) { - case IW_MODE_MONITOR: - status |= BCM43xx_SBF_MODE_MONITOR; - status |= BCM43xx_SBF_MODE_PROMISC; - break; - case IW_MODE_ADHOC: - status &= ~BCM43xx_SBF_MODE_NOTADHOC; - break; - case IW_MODE_MASTER: - status |= BCM43xx_SBF_MODE_AP; - break; - case IW_MODE_SECOND: - case IW_MODE_REPEAT: - TODO(); /* TODO */ - break; - case IW_MODE_INFRA: - /* nothing to be done here... */ - break; - default: - dprintk(KERN_ERR PFX "Unknown mode in set_iwmode: %d\n", iw_mode); - } - if (net_dev->flags & IFF_PROMISC) - status |= BCM43xx_SBF_MODE_PROMISC; - bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status); - - value = 0x0002; - if (iw_mode != IW_MODE_ADHOC && iw_mode != IW_MODE_MASTER) { - if (bcm->chip_id == 0x4306 && bcm->chip_rev == 3) - value = 0x0064; - else - value = 0x0032; - } - bcm43xx_write16(bcm, 0x0612, value); -} - -/* This is the opposite of bcm43xx_chip_init() */ -static void bcm43xx_chip_cleanup(struct bcm43xx_private *bcm) -{ - bcm43xx_radio_turn_off(bcm); - if (!modparam_noleds) - bcm43xx_leds_exit(bcm); - bcm43xx_gpio_cleanup(bcm); - bcm43xx_release_firmware(bcm, 0); -} - -/* Initialize the chip - * http://bcm-specs.sipsolutions.net/ChipInit - */ -static int bcm43xx_chip_init(struct bcm43xx_private *bcm) -{ - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - int err; - int i, tmp; - u32 value32; - u16 value16; - - bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, - BCM43xx_SBF_CORE_READY - | BCM43xx_SBF_400); - - err = bcm43xx_request_firmware(bcm); - if (err) - goto out; - bcm43xx_upload_microcode(bcm); - - bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, 0xFFFFFFFF); - bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, 0x00020402); - i = 0; - while (1) { - value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); - if (value32 == BCM43xx_IRQ_READY) - break; - i++; - if (i >= BCM43xx_IRQWAIT_MAX_RETRIES) { - printk(KERN_ERR PFX "IRQ_READY timeout\n"); - err = -ENODEV; - goto err_release_fw; - } - udelay(10); - } - bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */ - - value16 = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, - BCM43xx_UCODE_REVISION); - - dprintk(KERN_INFO PFX "Microcode rev 0x%x, pl 0x%x " - "(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n", value16, - bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, - BCM43xx_UCODE_PATCHLEVEL), - (bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, - BCM43xx_UCODE_DATE) >> 12) & 0xf, - (bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, - BCM43xx_UCODE_DATE) >> 8) & 0xf, - bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, - BCM43xx_UCODE_DATE) & 0xff, - (bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, - BCM43xx_UCODE_TIME) >> 11) & 0x1f, - (bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, - BCM43xx_UCODE_TIME) >> 5) & 0x3f, - bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, - BCM43xx_UCODE_TIME) & 0x1f); - - if ( value16 > 0x128 ) { - printk(KERN_ERR PFX - "Firmware: no support for microcode extracted " - "from version 4.x binary drivers.\n"); - err = -EOPNOTSUPP; - goto err_release_fw; - } - - err = bcm43xx_gpio_init(bcm); - if (err) - goto err_release_fw; - - err = bcm43xx_upload_initvals(bcm); - if (err) - goto err_gpio_cleanup; - bcm43xx_radio_turn_on(bcm); - bcm->radio_hw_enable = bcm43xx_is_hw_radio_enabled(bcm); - printk(KERN_INFO PFX "Radio %s by hardware\n", - (bcm->radio_hw_enable == 0) ? "disabled" : "enabled"); - - bcm43xx_write16(bcm, 0x03E6, 0x0000); - err = bcm43xx_phy_init(bcm); - if (err) - goto err_radio_off; - - /* Select initial Interference Mitigation. */ - tmp = radio->interfmode; - radio->interfmode = BCM43xx_RADIO_INTERFMODE_NONE; - bcm43xx_radio_set_interference_mitigation(bcm, tmp); - - bcm43xx_phy_set_antenna_diversity(bcm); - bcm43xx_radio_set_txantenna(bcm, BCM43xx_RADIO_TXANTENNA_DEFAULT); - if (phy->type == BCM43xx_PHYTYPE_B) { - value16 = bcm43xx_read16(bcm, 0x005E); - value16 |= 0x0004; - bcm43xx_write16(bcm, 0x005E, value16); - } - bcm43xx_write32(bcm, 0x0100, 0x01000000); - if (bcm->current_core->rev < 5) - bcm43xx_write32(bcm, 0x010C, 0x01000000); - - value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); - value32 &= ~ BCM43xx_SBF_MODE_NOTADHOC; - bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32); - value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); - value32 |= BCM43xx_SBF_MODE_NOTADHOC; - bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32); - - value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); - value32 |= 0x100000; - bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32); - - if (bcm43xx_using_pio(bcm)) { - bcm43xx_write32(bcm, 0x0210, 0x00000100); - bcm43xx_write32(bcm, 0x0230, 0x00000100); - bcm43xx_write32(bcm, 0x0250, 0x00000100); - bcm43xx_write32(bcm, 0x0270, 0x00000100); - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0034, 0x0000); - } - - /* Probe Response Timeout value */ - /* FIXME: Default to 0, has to be set by ioctl probably... :-/ */ - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0074, 0x0000); - - /* Initially set the wireless operation mode. */ - bcm43xx_set_iwmode(bcm, bcm->ieee->iw_mode); - - if (bcm->current_core->rev < 3) { - bcm43xx_write16(bcm, 0x060E, 0x0000); - bcm43xx_write16(bcm, 0x0610, 0x8000); - bcm43xx_write16(bcm, 0x0604, 0x0000); - bcm43xx_write16(bcm, 0x0606, 0x0200); - } else { - bcm43xx_write32(bcm, 0x0188, 0x80000000); - bcm43xx_write32(bcm, 0x018C, 0x02000000); - } - bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, 0x00004000); - bcm43xx_write32(bcm, BCM43xx_MMIO_DMA0_IRQ_MASK, 0x0001DC00); - bcm43xx_write32(bcm, BCM43xx_MMIO_DMA1_IRQ_MASK, 0x0000DC00); - bcm43xx_write32(bcm, BCM43xx_MMIO_DMA2_IRQ_MASK, 0x0000DC00); - bcm43xx_write32(bcm, BCM43xx_MMIO_DMA3_IRQ_MASK, 0x0001DC00); - bcm43xx_write32(bcm, BCM43xx_MMIO_DMA4_IRQ_MASK, 0x0000DC00); - bcm43xx_write32(bcm, BCM43xx_MMIO_DMA5_IRQ_MASK, 0x0000DC00); - - value32 = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); - value32 |= 0x00100000; - bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, value32); - - bcm43xx_write16(bcm, BCM43xx_MMIO_POWERUP_DELAY, bcm43xx_pctl_powerup_delay(bcm)); - - assert(err == 0); - dprintk(KERN_INFO PFX "Chip initialized\n"); -out: - return err; - -err_radio_off: - bcm43xx_radio_turn_off(bcm); -err_gpio_cleanup: - bcm43xx_gpio_cleanup(bcm); -err_release_fw: - bcm43xx_release_firmware(bcm, 1); - goto out; -} - -/* Validate chip access - * http://bcm-specs.sipsolutions.net/ValidateChipAccess */ -static int bcm43xx_validate_chip(struct bcm43xx_private *bcm) -{ - u32 value; - u32 shm_backup; - - shm_backup = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0000); - bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, 0x0000, 0xAA5555AA); - if (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0000) != 0xAA5555AA) - goto error; - bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, 0x0000, 0x55AAAA55); - if (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0000) != 0x55AAAA55) - goto error; - bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, 0x0000, shm_backup); - - value = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); - if ((value | 0x80000000) != 0x80000400) - goto error; - - value = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); - if (value != 0x00000000) - goto error; - - return 0; -error: - printk(KERN_ERR PFX "Failed to validate the chipaccess\n"); - return -ENODEV; -} - -static void bcm43xx_init_struct_phyinfo(struct bcm43xx_phyinfo *phy) -{ - /* Initialize a "phyinfo" structure. The structure is already - * zeroed out. - * This is called on insmod time to initialize members. - */ - phy->savedpctlreg = 0xFFFF; - spin_lock_init(&phy->lock); -} - -static void bcm43xx_init_struct_radioinfo(struct bcm43xx_radioinfo *radio) -{ - /* Initialize a "radioinfo" structure. The structure is already - * zeroed out. - * This is called on insmod time to initialize members. - */ - radio->interfmode = BCM43xx_RADIO_INTERFMODE_NONE; - radio->channel = 0xFF; - radio->initial_channel = 0xFF; -} - -static int bcm43xx_probe_cores(struct bcm43xx_private *bcm) -{ - int err, i; - int current_core; - u32 core_vendor, core_id, core_rev; - u32 sb_id_hi, chip_id_32 = 0; - u16 pci_device, chip_id_16; - u8 core_count; - - memset(&bcm->core_chipcommon, 0, sizeof(struct bcm43xx_coreinfo)); - memset(&bcm->core_pci, 0, sizeof(struct bcm43xx_coreinfo)); - memset(&bcm->core_80211, 0, sizeof(struct bcm43xx_coreinfo) - * BCM43xx_MAX_80211_CORES); - memset(&bcm->core_80211_ext, 0, sizeof(struct bcm43xx_coreinfo_80211) - * BCM43xx_MAX_80211_CORES); - bcm->nr_80211_available = 0; - bcm->current_core = NULL; - bcm->active_80211_core = NULL; - - /* map core 0 */ - err = _switch_core(bcm, 0); - if (err) - goto out; - - /* fetch sb_id_hi from core information registers */ - sb_id_hi = bcm43xx_read32(bcm, BCM43xx_CIR_SB_ID_HI); - - core_id = (sb_id_hi & 0x8FF0) >> 4; - core_rev = (sb_id_hi & 0x7000) >> 8; - core_rev |= (sb_id_hi & 0xF); - core_vendor = (sb_id_hi & 0xFFFF0000) >> 16; - - /* if present, chipcommon is always core 0; read the chipid from it */ - if (core_id == BCM43xx_COREID_CHIPCOMMON) { - chip_id_32 = bcm43xx_read32(bcm, 0); - chip_id_16 = chip_id_32 & 0xFFFF; - bcm->core_chipcommon.available = 1; - bcm->core_chipcommon.id = core_id; - bcm->core_chipcommon.rev = core_rev; - bcm->core_chipcommon.index = 0; - /* While we are at it, also read the capabilities. */ - bcm->chipcommon_capabilities = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_CAPABILITIES); - } else { - /* without a chipCommon, use a hard coded table. */ - pci_device = bcm->pci_dev->device; - if (pci_device == 0x4301) - chip_id_16 = 0x4301; - else if ((pci_device >= 0x4305) && (pci_device <= 0x4307)) - chip_id_16 = 0x4307; - else if ((pci_device >= 0x4402) && (pci_device <= 0x4403)) - chip_id_16 = 0x4402; - else if ((pci_device >= 0x4610) && (pci_device <= 0x4615)) - chip_id_16 = 0x4610; - else if ((pci_device >= 0x4710) && (pci_device <= 0x4715)) - chip_id_16 = 0x4710; - else { - printk(KERN_ERR PFX "Could not determine Chip ID\n"); - return -ENODEV; - } - } - - /* ChipCommon with Core Rev >=4 encodes number of cores, - * otherwise consult hardcoded table */ - if ((core_id == BCM43xx_COREID_CHIPCOMMON) && (core_rev >= 4)) { - core_count = (chip_id_32 & 0x0F000000) >> 24; - } else { - switch (chip_id_16) { - case 0x4610: - case 0x4704: - case 0x4710: - core_count = 9; - break; - case 0x4310: - core_count = 8; - break; - case 0x5365: - core_count = 7; - break; - case 0x4306: - core_count = 6; - break; - case 0x4301: - case 0x4307: - core_count = 5; - break; - case 0x4402: - core_count = 3; - break; - default: - /* SOL if we get here */ - assert(0); - core_count = 1; - } - } - - bcm->chip_id = chip_id_16; - bcm->chip_rev = (chip_id_32 & 0x000F0000) >> 16; - bcm->chip_package = (chip_id_32 & 0x00F00000) >> 20; - - dprintk(KERN_INFO PFX "Chip ID 0x%x, rev 0x%x\n", - bcm->chip_id, bcm->chip_rev); - dprintk(KERN_INFO PFX "Number of cores: %d\n", core_count); - if (bcm->core_chipcommon.available) { - dprintk(KERN_INFO PFX "Core 0: ID 0x%x, rev 0x%x, vendor 0x%x\n", - core_id, core_rev, core_vendor); - current_core = 1; - } else - current_core = 0; - for ( ; current_core < core_count; current_core++) { - struct bcm43xx_coreinfo *core; - struct bcm43xx_coreinfo_80211 *ext_80211; - - err = _switch_core(bcm, current_core); - if (err) - goto out; - /* Gather information */ - /* fetch sb_id_hi from core information registers */ - sb_id_hi = bcm43xx_read32(bcm, BCM43xx_CIR_SB_ID_HI); - - /* extract core_id, core_rev, core_vendor */ - core_id = (sb_id_hi & 0x8FF0) >> 4; - core_rev = ((sb_id_hi & 0xF) | ((sb_id_hi & 0x7000) >> 8)); - core_vendor = (sb_id_hi & 0xFFFF0000) >> 16; - - dprintk(KERN_INFO PFX "Core %d: ID 0x%x, rev 0x%x, vendor 0x%x\n", - current_core, core_id, core_rev, core_vendor); - - core = NULL; - switch (core_id) { - case BCM43xx_COREID_PCI: - case BCM43xx_COREID_PCIE: - core = &bcm->core_pci; - if (core->available) { - printk(KERN_WARNING PFX "Multiple PCI cores found.\n"); - continue; - } - break; - case BCM43xx_COREID_80211: - for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) { - core = &(bcm->core_80211[i]); - ext_80211 = &(bcm->core_80211_ext[i]); - if (!core->available) - break; - core = NULL; - } - if (!core) { - printk(KERN_WARNING PFX "More than %d cores of type 802.11 found.\n", - BCM43xx_MAX_80211_CORES); - continue; - } - if (i != 0) { - /* More than one 80211 core is only supported - * by special chips. - * There are chips with two 80211 cores, but with - * dangling pins on the second core. Be careful - * and ignore these cores here. - */ - if (1 /*bcm->pci_dev->device != 0x4324*/ ) { - /* TODO: A PHY */ - dprintk(KERN_INFO PFX "Ignoring additional 802.11a core.\n"); - continue; - } - } - switch (core_rev) { - case 2: - case 4: - case 5: - case 6: - case 7: - case 9: - case 10: - break; - default: - printk(KERN_WARNING PFX - "Unsupported 80211 core revision %u\n", - core_rev); - } - bcm->nr_80211_available++; - core->priv = ext_80211; - bcm43xx_init_struct_phyinfo(&ext_80211->phy); - bcm43xx_init_struct_radioinfo(&ext_80211->radio); - break; - case BCM43xx_COREID_CHIPCOMMON: - printk(KERN_WARNING PFX "Multiple CHIPCOMMON cores found.\n"); - break; - } - if (core) { - core->available = 1; - core->id = core_id; - core->rev = core_rev; - core->index = current_core; - } - } - - if (!bcm->core_80211[0].available) { - printk(KERN_ERR PFX "Error: No 80211 core found!\n"); - err = -ENODEV; - goto out; - } - - err = bcm43xx_switch_core(bcm, &bcm->core_80211[0]); - - assert(err == 0); -out: - return err; -} - -static void bcm43xx_gen_bssid(struct bcm43xx_private *bcm) -{ - const u8 *mac = (const u8*)(bcm->net_dev->dev_addr); - u8 *bssid = bcm->ieee->bssid; - - switch (bcm->ieee->iw_mode) { - case IW_MODE_ADHOC: - random_ether_addr(bssid); - break; - case IW_MODE_MASTER: - case IW_MODE_INFRA: - case IW_MODE_REPEAT: - case IW_MODE_SECOND: - case IW_MODE_MONITOR: - memcpy(bssid, mac, ETH_ALEN); - break; - default: - assert(0); - } -} - -static void bcm43xx_rate_memory_write(struct bcm43xx_private *bcm, - u16 rate, - int is_ofdm) -{ - u16 offset; - - if (is_ofdm) { - offset = 0x480; - offset += (bcm43xx_plcp_get_ratecode_ofdm(rate) & 0x000F) * 2; - } - else { - offset = 0x4C0; - offset += (bcm43xx_plcp_get_ratecode_cck(rate) & 0x000F) * 2; - } - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, offset + 0x20, - bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, offset)); -} - -static void bcm43xx_rate_memory_init(struct bcm43xx_private *bcm) -{ - switch (bcm43xx_current_phy(bcm)->type) { - case BCM43xx_PHYTYPE_A: - case BCM43xx_PHYTYPE_G: - bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_6MB, 1); - bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_12MB, 1); - bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_18MB, 1); - bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_24MB, 1); - bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_36MB, 1); - bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_48MB, 1); - bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_54MB, 1); - case BCM43xx_PHYTYPE_B: - bcm43xx_rate_memory_write(bcm, IEEE80211_CCK_RATE_1MB, 0); - bcm43xx_rate_memory_write(bcm, IEEE80211_CCK_RATE_2MB, 0); - bcm43xx_rate_memory_write(bcm, IEEE80211_CCK_RATE_5MB, 0); - bcm43xx_rate_memory_write(bcm, IEEE80211_CCK_RATE_11MB, 0); - break; - default: - assert(0); - } -} - -static void bcm43xx_wireless_core_cleanup(struct bcm43xx_private *bcm) -{ - bcm43xx_chip_cleanup(bcm); - bcm43xx_pio_free(bcm); - bcm43xx_dma_free(bcm); - - bcm->current_core->initialized = 0; -} - -/* http://bcm-specs.sipsolutions.net/80211Init */ -static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm, - int active_wlcore) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - u32 ucodeflags; - int err; - u32 sbimconfiglow; - u8 limit; - - if (bcm->core_pci.rev <= 5 && bcm->core_pci.id != BCM43xx_COREID_PCIE) { - sbimconfiglow = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMCONFIGLOW); - sbimconfiglow &= ~ BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK; - sbimconfiglow &= ~ BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK; - if (bcm->bustype == BCM43xx_BUSTYPE_PCI) - sbimconfiglow |= 0x32; - else - sbimconfiglow |= 0x53; - bcm43xx_write32(bcm, BCM43xx_CIR_SBIMCONFIGLOW, sbimconfiglow); - } - - bcm43xx_phy_calibrate(bcm); - err = bcm43xx_chip_init(bcm); - if (err) - goto out; - - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0016, bcm->current_core->rev); - ucodeflags = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, BCM43xx_UCODEFLAGS_OFFSET); - - if (0 /*FIXME: which condition has to be used here? */) - ucodeflags |= 0x00000010; - - /* HW decryption needs to be set now */ - ucodeflags |= 0x40000000; - - if (phy->type == BCM43xx_PHYTYPE_G) { - ucodeflags |= BCM43xx_UCODEFLAG_UNKBGPHY; - if (phy->rev == 1) - ucodeflags |= BCM43xx_UCODEFLAG_UNKGPHY; - if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) - ucodeflags |= BCM43xx_UCODEFLAG_UNKPACTRL; - } else if (phy->type == BCM43xx_PHYTYPE_B) { - ucodeflags |= BCM43xx_UCODEFLAG_UNKBGPHY; - if (phy->rev >= 2 && radio->version == 0x2050) - ucodeflags &= ~BCM43xx_UCODEFLAG_UNKGPHY; - } - - if (ucodeflags != bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, - BCM43xx_UCODEFLAGS_OFFSET)) { - bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, - BCM43xx_UCODEFLAGS_OFFSET, ucodeflags); - } - - /* Short/Long Retry Limit. - * The retry-limit is a 4-bit counter. Enforce this to avoid overflowing - * the chip-internal counter. - */ - limit = limit_value(modparam_short_retry, 0, 0xF); - bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0006, limit); - limit = limit_value(modparam_long_retry, 0, 0xF); - bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0007, limit); - - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0044, 3); - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0046, 2); - - bcm43xx_rate_memory_init(bcm); - - /* Minimum Contention Window */ - if (phy->type == BCM43xx_PHYTYPE_B) - bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0003, 0x0000001f); - else - bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0003, 0x0000000f); - /* Maximum Contention Window */ - bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0004, 0x000003ff); - - bcm43xx_gen_bssid(bcm); - bcm43xx_write_mac_bssid_templates(bcm); - - if (bcm->current_core->rev >= 5) - bcm43xx_write16(bcm, 0x043C, 0x000C); - - if (active_wlcore) { - if (bcm43xx_using_pio(bcm)) { - err = bcm43xx_pio_init(bcm); - } else { - err = bcm43xx_dma_init(bcm); - if (err == -ENOSYS) - err = bcm43xx_pio_init(bcm); - } - if (err) - goto err_chip_cleanup; - } - bcm43xx_write16(bcm, 0x0612, 0x0050); - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0416, 0x0050); - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0414, 0x01F4); - - if (active_wlcore) { - if (radio->initial_channel != 0xFF) - bcm43xx_radio_selectchannel(bcm, radio->initial_channel, 0); - } - - /* Don't enable MAC/IRQ here, as it will race with the IRQ handler. - * We enable it later. - */ - bcm->current_core->initialized = 1; -out: - return err; - -err_chip_cleanup: - bcm43xx_chip_cleanup(bcm); - goto out; -} - -static int bcm43xx_chipset_attach(struct bcm43xx_private *bcm) -{ - int err; - u16 pci_status; - - err = bcm43xx_pctl_set_crystal(bcm, 1); - if (err) - goto out; - err = bcm43xx_pci_read_config16(bcm, PCI_STATUS, &pci_status); - if (err) - goto out; - err = bcm43xx_pci_write_config16(bcm, PCI_STATUS, pci_status & ~PCI_STATUS_SIG_TARGET_ABORT); - -out: - return err; -} - -static void bcm43xx_chipset_detach(struct bcm43xx_private *bcm) -{ - bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_SLOW); - bcm43xx_pctl_set_crystal(bcm, 0); -} - -static void bcm43xx_pcicore_broadcast_value(struct bcm43xx_private *bcm, - u32 address, - u32 data) -{ - bcm43xx_write32(bcm, BCM43xx_PCICORE_BCAST_ADDR, address); - bcm43xx_write32(bcm, BCM43xx_PCICORE_BCAST_DATA, data); -} - -static int bcm43xx_pcicore_commit_settings(struct bcm43xx_private *bcm) -{ - int err = 0; - - bcm->irq_savedstate = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); - - if (bcm->core_chipcommon.available) { - err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon); - if (err) - goto out; - - bcm43xx_pcicore_broadcast_value(bcm, 0xfd8, 0x00000000); - - /* this function is always called when a PCI core is mapped */ - err = bcm43xx_switch_core(bcm, &bcm->core_pci); - if (err) - goto out; - } else - bcm43xx_pcicore_broadcast_value(bcm, 0xfd8, 0x00000000); - - bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate); - -out: - return err; -} - -static u32 bcm43xx_pcie_reg_read(struct bcm43xx_private *bcm, u32 address) -{ - bcm43xx_write32(bcm, BCM43xx_PCIECORE_REG_ADDR, address); - return bcm43xx_read32(bcm, BCM43xx_PCIECORE_REG_DATA); -} - -static void bcm43xx_pcie_reg_write(struct bcm43xx_private *bcm, u32 address, - u32 data) -{ - bcm43xx_write32(bcm, BCM43xx_PCIECORE_REG_ADDR, address); - bcm43xx_write32(bcm, BCM43xx_PCIECORE_REG_DATA, data); -} - -static void bcm43xx_pcie_mdio_write(struct bcm43xx_private *bcm, u8 dev, u8 reg, - u16 data) -{ - int i; - - bcm43xx_write32(bcm, BCM43xx_PCIECORE_MDIO_CTL, 0x0082); - bcm43xx_write32(bcm, BCM43xx_PCIECORE_MDIO_DATA, BCM43xx_PCIE_MDIO_ST | - BCM43xx_PCIE_MDIO_WT | (dev << BCM43xx_PCIE_MDIO_DEV) | - (reg << BCM43xx_PCIE_MDIO_REG) | BCM43xx_PCIE_MDIO_TA | - data); - udelay(10); - - for (i = 0; i < 10; i++) { - if (bcm43xx_read32(bcm, BCM43xx_PCIECORE_MDIO_CTL) & - BCM43xx_PCIE_MDIO_TC) - break; - msleep(1); - } - bcm43xx_write32(bcm, BCM43xx_PCIECORE_MDIO_CTL, 0); -} - -/* Make an I/O Core usable. "core_mask" is the bitmask of the cores to enable. - * To enable core 0, pass a core_mask of 1<<0 - */ -static int bcm43xx_setup_backplane_pci_connection(struct bcm43xx_private *bcm, - u32 core_mask) -{ - u32 backplane_flag_nr; - u32 value; - struct bcm43xx_coreinfo *old_core; - int err = 0; - - value = bcm43xx_read32(bcm, BCM43xx_CIR_SBTPSFLAG); - backplane_flag_nr = value & BCM43xx_BACKPLANE_FLAG_NR_MASK; - - old_core = bcm->current_core; - err = bcm43xx_switch_core(bcm, &bcm->core_pci); - if (err) - goto out; - - if (bcm->current_core->rev < 6 && - bcm->current_core->id == BCM43xx_COREID_PCI) { - value = bcm43xx_read32(bcm, BCM43xx_CIR_SBINTVEC); - value |= (1 << backplane_flag_nr); - bcm43xx_write32(bcm, BCM43xx_CIR_SBINTVEC, value); - } else { - err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCICFG_ICR, &value); - if (err) { - printk(KERN_ERR PFX "Error: ICR setup failure!\n"); - goto out_switch_back; - } - value |= core_mask << 8; - err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_ICR, value); - if (err) { - printk(KERN_ERR PFX "Error: ICR setup failure!\n"); - goto out_switch_back; - } - } - - if (bcm->current_core->id == BCM43xx_COREID_PCI) { - value = bcm43xx_read32(bcm, BCM43xx_PCICORE_SBTOPCI2); - value |= BCM43xx_SBTOPCI2_PREFETCH | BCM43xx_SBTOPCI2_BURST; - bcm43xx_write32(bcm, BCM43xx_PCICORE_SBTOPCI2, value); - - if (bcm->current_core->rev < 5) { - value = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMCONFIGLOW); - value |= (2 << BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_SHIFT) - & BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK; - value |= (3 << BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_SHIFT) - & BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK; - bcm43xx_write32(bcm, BCM43xx_CIR_SBIMCONFIGLOW, value); - err = bcm43xx_pcicore_commit_settings(bcm); - assert(err == 0); - } else if (bcm->current_core->rev >= 11) { - value = bcm43xx_read32(bcm, BCM43xx_PCICORE_SBTOPCI2); - value |= BCM43xx_SBTOPCI2_MEMREAD_MULTI; - bcm43xx_write32(bcm, BCM43xx_PCICORE_SBTOPCI2, value); - } - } else { - if (bcm->current_core->rev == 0 || bcm->current_core->rev == 1) { - value = bcm43xx_pcie_reg_read(bcm, BCM43xx_PCIE_TLP_WORKAROUND); - value |= 0x8; - bcm43xx_pcie_reg_write(bcm, BCM43xx_PCIE_TLP_WORKAROUND, - value); - } - if (bcm->current_core->rev == 0) { - bcm43xx_pcie_mdio_write(bcm, BCM43xx_MDIO_SERDES_RX, - BCM43xx_SERDES_RXTIMER, 0x8128); - bcm43xx_pcie_mdio_write(bcm, BCM43xx_MDIO_SERDES_RX, - BCM43xx_SERDES_CDR, 0x0100); - bcm43xx_pcie_mdio_write(bcm, BCM43xx_MDIO_SERDES_RX, - BCM43xx_SERDES_CDR_BW, 0x1466); - } else if (bcm->current_core->rev == 1) { - value = bcm43xx_pcie_reg_read(bcm, BCM43xx_PCIE_DLLP_LINKCTL); - value |= 0x40; - bcm43xx_pcie_reg_write(bcm, BCM43xx_PCIE_DLLP_LINKCTL, - value); - } - } -out_switch_back: - err = bcm43xx_switch_core(bcm, old_core); -out: - return err; -} - -static void bcm43xx_periodic_every120sec(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - - if (phy->type != BCM43xx_PHYTYPE_G || phy->rev < 2) - return; - - bcm43xx_mac_suspend(bcm); - bcm43xx_phy_lo_g_measure(bcm); - bcm43xx_mac_enable(bcm); -} - -static void bcm43xx_periodic_every60sec(struct bcm43xx_private *bcm) -{ - bcm43xx_phy_lo_mark_all_unused(bcm); - if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) { - bcm43xx_mac_suspend(bcm); - bcm43xx_calc_nrssi_slope(bcm); - bcm43xx_mac_enable(bcm); - } -} - -static void bcm43xx_periodic_every30sec(struct bcm43xx_private *bcm) -{ - /* Update device statistics. */ - bcm43xx_calculate_link_quality(bcm); -} - -static void bcm43xx_periodic_every15sec(struct bcm43xx_private *bcm) -{ - bcm43xx_phy_xmitpower(bcm); //FIXME: unless scanning? - //TODO for APHY (temperature?) -} - -static void bcm43xx_periodic_every1sec(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - int radio_hw_enable; - - /* check if radio hardware enabled status changed */ - radio_hw_enable = bcm43xx_is_hw_radio_enabled(bcm); - if (unlikely(bcm->radio_hw_enable != radio_hw_enable)) { - bcm->radio_hw_enable = radio_hw_enable; - printk(KERN_INFO PFX "Radio hardware status changed to %s\n", - (radio_hw_enable == 0) ? "disabled" : "enabled"); - bcm43xx_leds_update(bcm, 0); - } - if (phy->type == BCM43xx_PHYTYPE_G) { - //TODO: update_aci_moving_average - if (radio->aci_enable && radio->aci_wlan_automatic) { - bcm43xx_mac_suspend(bcm); - if (!radio->aci_enable && 1 /*TODO: not scanning? */) { - if (0 /*TODO: bunch of conditions*/) { - bcm43xx_radio_set_interference_mitigation(bcm, - BCM43xx_RADIO_INTERFMODE_MANUALWLAN); - } - } else if (1/*TODO*/) { - /* - if ((aci_average > 1000) && !(bcm43xx_radio_aci_scan(bcm))) { - bcm43xx_radio_set_interference_mitigation(bcm, - BCM43xx_RADIO_INTERFMODE_NONE); - } - */ - } - bcm43xx_mac_enable(bcm); - } else if (radio->interfmode == BCM43xx_RADIO_INTERFMODE_NONWLAN && - phy->rev == 1) { - //TODO: implement rev1 workaround - } - } -} - -static void do_periodic_work(struct bcm43xx_private *bcm) -{ - if (bcm->periodic_state % 120 == 0) - bcm43xx_periodic_every120sec(bcm); - if (bcm->periodic_state % 60 == 0) - bcm43xx_periodic_every60sec(bcm); - if (bcm->periodic_state % 30 == 0) - bcm43xx_periodic_every30sec(bcm); - if (bcm->periodic_state % 15 == 0) - bcm43xx_periodic_every15sec(bcm); - bcm43xx_periodic_every1sec(bcm); - - schedule_delayed_work(&bcm->periodic_work, HZ); -} - -static void bcm43xx_periodic_work_handler(struct work_struct *work) -{ - struct bcm43xx_private *bcm = - container_of(work, struct bcm43xx_private, periodic_work.work); - struct net_device *net_dev = bcm->net_dev; - unsigned long flags; - u32 savedirqs = 0; - unsigned long orig_trans_start = 0; - - mutex_lock(&bcm->mutex); - /* keep from doing and rearming periodic work if shutting down */ - if (bcm43xx_status(bcm) == BCM43xx_STAT_UNINIT) - goto unlock_mutex; - if (unlikely(bcm->periodic_state % 60 == 0)) { - /* Periodic work will take a long time, so we want it to - * be preemtible. - */ - - netif_tx_lock_bh(net_dev); - /* We must fake a started transmission here, as we are going to - * disable TX. If we wouldn't fake a TX, it would be possible to - * trigger the netdev watchdog, if the last real TX is already - * some time on the past (slightly less than 5secs) - */ - orig_trans_start = net_dev->trans_start; - net_dev->trans_start = jiffies; - netif_stop_queue(net_dev); - netif_tx_unlock_bh(net_dev); - - spin_lock_irqsave(&bcm->irq_lock, flags); - bcm43xx_mac_suspend(bcm); - if (bcm43xx_using_pio(bcm)) - bcm43xx_pio_freeze_txqueues(bcm); - savedirqs = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); - spin_unlock_irqrestore(&bcm->irq_lock, flags); - bcm43xx_synchronize_irq(bcm); - } else { - /* Periodic work should take short time, so we want low - * locking overhead. - */ - spin_lock_irqsave(&bcm->irq_lock, flags); - } - - do_periodic_work(bcm); - - if (unlikely(bcm->periodic_state % 60 == 0)) { - spin_lock_irqsave(&bcm->irq_lock, flags); - tasklet_enable(&bcm->isr_tasklet); - bcm43xx_interrupt_enable(bcm, savedirqs); - if (bcm43xx_using_pio(bcm)) - bcm43xx_pio_thaw_txqueues(bcm); - bcm43xx_mac_enable(bcm); - netif_wake_queue(bcm->net_dev); - net_dev->trans_start = orig_trans_start; - } - mmiowb(); - bcm->periodic_state++; - spin_unlock_irqrestore(&bcm->irq_lock, flags); -unlock_mutex: - mutex_unlock(&bcm->mutex); -} - -void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm) -{ - struct delayed_work *work = &bcm->periodic_work; - - assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED); - INIT_DELAYED_WORK(work, bcm43xx_periodic_work_handler); - schedule_delayed_work(work, 0); -} - -static void bcm43xx_security_init(struct bcm43xx_private *bcm) -{ - bcm->security_offset = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, - 0x0056) * 2; - bcm43xx_clear_keys(bcm); -} - -static int bcm43xx_rng_read(struct hwrng *rng, u32 *data) -{ - struct bcm43xx_private *bcm = (struct bcm43xx_private *)rng->priv; - unsigned long flags; - - spin_lock_irqsave(&(bcm)->irq_lock, flags); - *data = bcm43xx_read16(bcm, BCM43xx_MMIO_RNG); - spin_unlock_irqrestore(&(bcm)->irq_lock, flags); - - return (sizeof(u16)); -} - -static void bcm43xx_rng_exit(struct bcm43xx_private *bcm) -{ - hwrng_unregister(&bcm->rng); -} - -static int bcm43xx_rng_init(struct bcm43xx_private *bcm) -{ - int err; - - snprintf(bcm->rng_name, ARRAY_SIZE(bcm->rng_name), - "%s_%s", KBUILD_MODNAME, bcm->net_dev->name); - bcm->rng.name = bcm->rng_name; - bcm->rng.data_read = bcm43xx_rng_read; - bcm->rng.priv = (unsigned long)bcm; - err = hwrng_register(&bcm->rng); - if (err) - printk(KERN_ERR PFX "RNG init failed (%d)\n", err); - - return err; -} - -void bcm43xx_cancel_work(struct bcm43xx_private *bcm) -{ - /* The system must be unlocked when this routine is entered. - * If not, the next 2 steps may deadlock */ - cancel_work_sync(&bcm->restart_work); - cancel_delayed_work_sync(&bcm->periodic_work); -} - -static int bcm43xx_shutdown_all_wireless_cores(struct bcm43xx_private *bcm) -{ - int ret = 0; - int i, err; - struct bcm43xx_coreinfo *core; - - bcm43xx_set_status(bcm, BCM43xx_STAT_SHUTTINGDOWN); - for (i = 0; i < bcm->nr_80211_available; i++) { - core = &(bcm->core_80211[i]); - assert(core->available); - if (!core->initialized) - continue; - err = bcm43xx_switch_core(bcm, core); - if (err) { - dprintk(KERN_ERR PFX "shutdown_all_wireless_cores " - "switch_core failed (%d)\n", err); - ret = err; - continue; - } - bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); - bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */ - bcm43xx_wireless_core_cleanup(bcm); - if (core == bcm->active_80211_core) - bcm->active_80211_core = NULL; - } - free_irq(bcm->irq, bcm); - bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT); - - return ret; -} - -/* This is the opposite of bcm43xx_init_board() */ -static void bcm43xx_free_board(struct bcm43xx_private *bcm) -{ - bcm43xx_rng_exit(bcm); - bcm43xx_sysfs_unregister(bcm); - - mutex_lock(&(bcm)->mutex); - bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT); - mutex_unlock(&(bcm)->mutex); - - bcm43xx_cancel_work(bcm); - - mutex_lock(&(bcm)->mutex); - bcm43xx_shutdown_all_wireless_cores(bcm); - bcm43xx_pctl_set_crystal(bcm, 0); - mutex_unlock(&(bcm)->mutex); -} - -static void prepare_phydata_for_init(struct bcm43xx_phyinfo *phy) -{ - phy->antenna_diversity = 0xFFFF; - memset(phy->minlowsig, 0xFF, sizeof(phy->minlowsig)); - memset(phy->minlowsigpos, 0, sizeof(phy->minlowsigpos)); - - /* Flags */ - phy->calibrated = 0; - phy->is_locked = 0; - - if (phy->_lo_pairs) { - memset(phy->_lo_pairs, 0, - sizeof(struct bcm43xx_lopair) * BCM43xx_LO_COUNT); - } - memset(phy->loopback_gain, 0, sizeof(phy->loopback_gain)); -} - -static void prepare_radiodata_for_init(struct bcm43xx_private *bcm, - struct bcm43xx_radioinfo *radio) -{ - int i; - - /* Set default attenuation values. */ - radio->baseband_atten = bcm43xx_default_baseband_attenuation(bcm); - radio->radio_atten = bcm43xx_default_radio_attenuation(bcm); - radio->txctl1 = bcm43xx_default_txctl1(bcm); - radio->txctl2 = 0xFFFF; - radio->txpwr_offset = 0; - - /* NRSSI */ - radio->nrssislope = 0; - for (i = 0; i < ARRAY_SIZE(radio->nrssi); i++) - radio->nrssi[i] = -1000; - for (i = 0; i < ARRAY_SIZE(radio->nrssi_lt); i++) - radio->nrssi_lt[i] = i; - - radio->lofcal = 0xFFFF; - radio->initval = 0xFFFF; - - radio->aci_enable = 0; - radio->aci_wlan_automatic = 0; - radio->aci_hw_rssi = 0; -} - -static void prepare_priv_for_init(struct bcm43xx_private *bcm) -{ - int i; - struct bcm43xx_coreinfo *core; - struct bcm43xx_coreinfo_80211 *wlext; - - assert(!bcm->active_80211_core); - - bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZING); - - /* Flags */ - bcm->was_initialized = 0; - bcm->reg124_set_0x4 = 0; - - /* Stats */ - memset(&bcm->stats, 0, sizeof(bcm->stats)); - - /* Wireless core data */ - for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) { - core = &(bcm->core_80211[i]); - wlext = core->priv; - - if (!core->available) - continue; - assert(wlext == &(bcm->core_80211_ext[i])); - - prepare_phydata_for_init(&wlext->phy); - prepare_radiodata_for_init(bcm, &wlext->radio); - } - - /* IRQ related flags */ - bcm->irq_reason = 0; - memset(bcm->dma_reason, 0, sizeof(bcm->dma_reason)); - bcm->irq_savedstate = BCM43xx_IRQ_INITIAL; - - bcm->mac_suspended = 1; - - /* Noise calculation context */ - memset(&bcm->noisecalc, 0, sizeof(bcm->noisecalc)); - - /* Periodic work context */ - bcm->periodic_state = 0; -} - -static int wireless_core_up(struct bcm43xx_private *bcm, - int active_wlcore) -{ - int err; - - if (!bcm43xx_core_enabled(bcm)) - bcm43xx_wireless_core_reset(bcm, 1); - if (!active_wlcore) - bcm43xx_wireless_core_mark_inactive(bcm); - err = bcm43xx_wireless_core_init(bcm, active_wlcore); - if (err) - goto out; - if (!active_wlcore) - bcm43xx_radio_turn_off(bcm); -out: - return err; -} - -/* Select and enable the "to be used" wireless core. - * Locking: bcm->mutex must be aquired before calling this. - * bcm->irq_lock must not be aquired. - */ -int bcm43xx_select_wireless_core(struct bcm43xx_private *bcm, - int phytype) -{ - int i, err; - struct bcm43xx_coreinfo *active_core = NULL; - struct bcm43xx_coreinfo_80211 *active_wlext = NULL; - struct bcm43xx_coreinfo *core; - struct bcm43xx_coreinfo_80211 *wlext; - int adjust_active_sbtmstatelow = 0; - - might_sleep(); - - if (phytype < 0) { - /* If no phytype is requested, select the first core. */ - assert(bcm->core_80211[0].available); - wlext = bcm->core_80211[0].priv; - phytype = wlext->phy.type; - } - /* Find the requested core. */ - for (i = 0; i < bcm->nr_80211_available; i++) { - core = &(bcm->core_80211[i]); - wlext = core->priv; - if (wlext->phy.type == phytype) { - active_core = core; - active_wlext = wlext; - break; - } - } - if (!active_core) - return -ESRCH; /* No such PHYTYPE on this board. */ - - if (bcm->active_80211_core) { - /* We already selected a wl core in the past. - * So first clean up everything. - */ - dprintk(KERN_INFO PFX "select_wireless_core: cleanup\n"); - ieee80211softmac_stop(bcm->net_dev); - bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZED); - err = bcm43xx_disable_interrupts_sync(bcm); - assert(!err); - tasklet_enable(&bcm->isr_tasklet); - err = bcm43xx_shutdown_all_wireless_cores(bcm); - if (err) - goto error; - /* Ok, everything down, continue to re-initialize. */ - bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZING); - } - - /* Reset all data structures. */ - prepare_priv_for_init(bcm); - - err = bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_FAST); - if (err) - goto error; - - /* Mark all unused cores "inactive". */ - for (i = 0; i < bcm->nr_80211_available; i++) { - core = &(bcm->core_80211[i]); - wlext = core->priv; - - if (core == active_core) - continue; - err = bcm43xx_switch_core(bcm, core); - if (err) { - dprintk(KERN_ERR PFX "Could not switch to inactive " - "802.11 core (%d)\n", err); - goto error; - } - err = wireless_core_up(bcm, 0); - if (err) { - dprintk(KERN_ERR PFX "core_up for inactive 802.11 core " - "failed (%d)\n", err); - goto error; - } - adjust_active_sbtmstatelow = 1; - } - - /* Now initialize the active 802.11 core. */ - err = bcm43xx_switch_core(bcm, active_core); - if (err) { - dprintk(KERN_ERR PFX "Could not switch to active " - "802.11 core (%d)\n", err); - goto error; - } - if (adjust_active_sbtmstatelow && - active_wlext->phy.type == BCM43xx_PHYTYPE_G) { - u32 sbtmstatelow; - - sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); - sbtmstatelow |= BCM43xx_SBTMSTATELOW_G_MODE_ENABLE; - bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); - } - err = wireless_core_up(bcm, 1); - if (err) { - dprintk(KERN_ERR PFX "core_up for active 802.11 core " - "failed (%d)\n", err); - goto error; - } - err = bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_DYNAMIC); - if (err) - goto error; - bcm->active_80211_core = active_core; - - bcm43xx_macfilter_clear(bcm, BCM43xx_MACFILTER_ASSOC); - bcm43xx_macfilter_set(bcm, BCM43xx_MACFILTER_SELF, (u8 *)(bcm->net_dev->dev_addr)); - bcm43xx_security_init(bcm); - drain_txstatus_queue(bcm); - ieee80211softmac_start(bcm->net_dev); - - /* Let's go! Be careful after enabling the IRQs. - * Don't switch cores, for example. - */ - bcm43xx_mac_enable(bcm); - bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZED); - err = bcm43xx_initialize_irq(bcm); - if (err) - goto error; - bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate); - - dprintk(KERN_INFO PFX "Selected 802.11 core (phytype %d)\n", - active_wlext->phy.type); - - return 0; - -error: - bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT); - bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_SLOW); - return err; -} - -static int bcm43xx_init_board(struct bcm43xx_private *bcm) -{ - int err; - - mutex_lock(&(bcm)->mutex); - - tasklet_enable(&bcm->isr_tasklet); - err = bcm43xx_pctl_set_crystal(bcm, 1); - if (err) - goto err_tasklet; - err = bcm43xx_pctl_init(bcm); - if (err) - goto err_crystal_off; - err = bcm43xx_select_wireless_core(bcm, -1); - if (err) - goto err_crystal_off; - err = bcm43xx_sysfs_register(bcm); - if (err) - goto err_wlshutdown; - err = bcm43xx_rng_init(bcm); - if (err) - goto err_sysfs_unreg; - bcm43xx_periodic_tasks_setup(bcm); - - /*FIXME: This should be handled by softmac instead. */ - schedule_delayed_work(&bcm->softmac->associnfo.work, 0); - -out: - mutex_unlock(&(bcm)->mutex); - - return err; - -err_sysfs_unreg: - bcm43xx_sysfs_unregister(bcm); -err_wlshutdown: - bcm43xx_shutdown_all_wireless_cores(bcm); -err_crystal_off: - bcm43xx_pctl_set_crystal(bcm, 0); -err_tasklet: - tasklet_disable(&bcm->isr_tasklet); - goto out; -} - -static void bcm43xx_detach_board(struct bcm43xx_private *bcm) -{ - struct pci_dev *pci_dev = bcm->pci_dev; - int i; - - bcm43xx_chipset_detach(bcm); - /* Do _not_ access the chip, after it is detached. */ - pci_iounmap(pci_dev, bcm->mmio_addr); - pci_release_regions(pci_dev); - pci_disable_device(pci_dev); - - /* Free allocated structures/fields */ - for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) { - kfree(bcm->core_80211_ext[i].phy._lo_pairs); - if (bcm->core_80211_ext[i].phy.dyn_tssi_tbl) - kfree(bcm->core_80211_ext[i].phy.tssi2dbm); - } -} - -static int bcm43xx_read_phyinfo(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - u16 value; - u8 phy_analog; - u8 phy_type; - u8 phy_rev; - int phy_rev_ok = 1; - void *p; - - value = bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_VER); - - phy_analog = (value & 0xF000) >> 12; - phy_type = (value & 0x0F00) >> 8; - phy_rev = (value & 0x000F); - - dprintk(KERN_INFO PFX "Detected PHY: Analog: %x, Type %x, Revision %x\n", - phy_analog, phy_type, phy_rev); - - switch (phy_type) { - case BCM43xx_PHYTYPE_A: - if (phy_rev >= 4) - phy_rev_ok = 0; - /*FIXME: We need to switch the ieee->modulation, etc.. flags, - * if we switch 80211 cores after init is done. - * As we do not implement on the fly switching between - * wireless cores, I will leave this as a future task. - */ - bcm->ieee->modulation = IEEE80211_OFDM_MODULATION; - bcm->ieee->mode = IEEE_A; - bcm->ieee->freq_band = IEEE80211_52GHZ_BAND | - IEEE80211_24GHZ_BAND; - break; - case BCM43xx_PHYTYPE_B: - if (phy_rev != 2 && phy_rev != 4 && phy_rev != 6 && phy_rev != 7) - phy_rev_ok = 0; - bcm->ieee->modulation = IEEE80211_CCK_MODULATION; - bcm->ieee->mode = IEEE_B; - bcm->ieee->freq_band = IEEE80211_24GHZ_BAND; - break; - case BCM43xx_PHYTYPE_G: - if (phy_rev > 8) - phy_rev_ok = 0; - bcm->ieee->modulation = IEEE80211_OFDM_MODULATION | - IEEE80211_CCK_MODULATION; - bcm->ieee->mode = IEEE_G; - bcm->ieee->freq_band = IEEE80211_24GHZ_BAND; - break; - default: - printk(KERN_ERR PFX "Error: Unknown PHY Type %x\n", - phy_type); - return -ENODEV; - }; - bcm->ieee->perfect_rssi = RX_RSSI_MAX; - bcm->ieee->worst_rssi = 0; - if (!phy_rev_ok) { - printk(KERN_WARNING PFX "Invalid PHY Revision %x\n", - phy_rev); - } - - phy->analog = phy_analog; - phy->type = phy_type; - phy->rev = phy_rev; - if ((phy_type == BCM43xx_PHYTYPE_B) || (phy_type == BCM43xx_PHYTYPE_G)) { - p = kzalloc(sizeof(struct bcm43xx_lopair) * BCM43xx_LO_COUNT, - GFP_KERNEL); - if (!p) - return -ENOMEM; - phy->_lo_pairs = p; - } - - return 0; -} - -static int bcm43xx_attach_board(struct bcm43xx_private *bcm) -{ - struct pci_dev *pci_dev = bcm->pci_dev; - struct net_device *net_dev = bcm->net_dev; - int err; - int i; - u32 coremask; - - err = pci_enable_device(pci_dev); - if (err) { - printk(KERN_ERR PFX "pci_enable_device() failed\n"); - goto out; - } - err = pci_request_regions(pci_dev, KBUILD_MODNAME); - if (err) { - printk(KERN_ERR PFX "pci_request_regions() failed\n"); - goto err_pci_disable; - } - /* enable PCI bus-mastering */ - pci_set_master(pci_dev); - bcm->mmio_addr = pci_iomap(pci_dev, 0, ~0UL); - if (!bcm->mmio_addr) { - printk(KERN_ERR PFX "pci_iomap() failed\n"); - err = -EIO; - goto err_pci_release; - } - net_dev->base_addr = (unsigned long)bcm->mmio_addr; - - err = bcm43xx_pci_read_config16(bcm, PCI_SUBSYSTEM_VENDOR_ID, - &bcm->board_vendor); - if (err) - goto err_iounmap; - err = bcm43xx_pci_read_config16(bcm, PCI_SUBSYSTEM_ID, - &bcm->board_type); - if (err) - goto err_iounmap; - - bcm->board_revision = bcm->pci_dev->revision; - - err = bcm43xx_chipset_attach(bcm); - if (err) - goto err_iounmap; - err = bcm43xx_pctl_init(bcm); - if (err) - goto err_chipset_detach; - err = bcm43xx_probe_cores(bcm); - if (err) - goto err_chipset_detach; - - /* Attach all IO cores to the backplane. */ - coremask = 0; - for (i = 0; i < bcm->nr_80211_available; i++) - coremask |= (1 << bcm->core_80211[i].index); - //FIXME: Also attach some non80211 cores? - err = bcm43xx_setup_backplane_pci_connection(bcm, coremask); - if (err) { - printk(KERN_ERR PFX "Backplane->PCI connection failed!\n"); - goto err_chipset_detach; - } - - err = bcm43xx_sprom_extract(bcm); - if (err) - goto err_chipset_detach; - err = bcm43xx_leds_init(bcm); - if (err) - goto err_chipset_detach; - - for (i = 0; i < bcm->nr_80211_available; i++) { - err = bcm43xx_switch_core(bcm, &bcm->core_80211[i]); - assert(err != -ENODEV); - if (err) - goto err_80211_unwind; - - /* Enable the selected wireless core. - * Connect PHY only on the first core. - */ - bcm43xx_wireless_core_reset(bcm, (i == 0)); - - err = bcm43xx_read_phyinfo(bcm); - if (err && (i == 0)) - goto err_80211_unwind; - - err = bcm43xx_read_radioinfo(bcm); - if (err && (i == 0)) - goto err_80211_unwind; - - err = bcm43xx_validate_chip(bcm); - if (err && (i == 0)) - goto err_80211_unwind; - - bcm43xx_radio_turn_off(bcm); - err = bcm43xx_phy_init_tssi2dbm_table(bcm); - if (err) - goto err_80211_unwind; - bcm43xx_wireless_core_disable(bcm); - } - err = bcm43xx_geo_init(bcm); - if (err) - goto err_80211_unwind; - bcm43xx_pctl_set_crystal(bcm, 0); - - /* Set the MAC address in the networking subsystem */ - if (is_valid_ether_addr(bcm->sprom.et1macaddr)) - memcpy(bcm->net_dev->dev_addr, bcm->sprom.et1macaddr, 6); - else - memcpy(bcm->net_dev->dev_addr, bcm->sprom.il0macaddr, 6); - - snprintf(bcm->nick, IW_ESSID_MAX_SIZE, - "Broadcom %04X", bcm->chip_id); - - assert(err == 0); -out: - return err; - -err_80211_unwind: - for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) { - kfree(bcm->core_80211_ext[i].phy._lo_pairs); - if (bcm->core_80211_ext[i].phy.dyn_tssi_tbl) - kfree(bcm->core_80211_ext[i].phy.tssi2dbm); - } -err_chipset_detach: - bcm43xx_chipset_detach(bcm); -err_iounmap: - pci_iounmap(pci_dev, bcm->mmio_addr); -err_pci_release: - pci_release_regions(pci_dev); -err_pci_disable: - pci_disable_device(pci_dev); - printk(KERN_ERR PFX "Unable to attach board\n"); - goto out; -} - -/* Do the Hardware IO operations to send the txb */ -static inline int bcm43xx_tx(struct bcm43xx_private *bcm, - struct ieee80211_txb *txb) -{ - int err = -ENODEV; - - if (bcm43xx_using_pio(bcm)) - err = bcm43xx_pio_tx(bcm, txb); - else - err = bcm43xx_dma_tx(bcm, txb); - bcm->net_dev->trans_start = jiffies; - - return err; -} - -static void bcm43xx_ieee80211_set_chan(struct net_device *net_dev, - u8 channel) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - struct bcm43xx_radioinfo *radio; - unsigned long flags; - - mutex_lock(&bcm->mutex); - spin_lock_irqsave(&bcm->irq_lock, flags); - if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) { - bcm43xx_mac_suspend(bcm); - bcm43xx_radio_selectchannel(bcm, channel, 0); - bcm43xx_mac_enable(bcm); - } else { - radio = bcm43xx_current_radio(bcm); - radio->initial_channel = channel; - } - spin_unlock_irqrestore(&bcm->irq_lock, flags); - mutex_unlock(&bcm->mutex); -} - -/* set_security() callback in struct ieee80211_device */ -static void bcm43xx_ieee80211_set_security(struct net_device *net_dev, - struct ieee80211_security *sec) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - struct ieee80211_security *secinfo = &bcm->ieee->sec; - unsigned long flags; - int keyidx; - - dprintk(KERN_INFO PFX "set security called"); - - mutex_lock(&bcm->mutex); - spin_lock_irqsave(&bcm->irq_lock, flags); - - for (keyidx = 0; keyidxflags & (1<encode_alg[keyidx] = sec->encode_alg[keyidx]; - secinfo->key_sizes[keyidx] = sec->key_sizes[keyidx]; - memcpy(secinfo->keys[keyidx], sec->keys[keyidx], SCM_KEY_LEN); - } - - if (sec->flags & SEC_ACTIVE_KEY) { - secinfo->active_key = sec->active_key; - dprintk(", .active_key = %d", sec->active_key); - } - if (sec->flags & SEC_UNICAST_GROUP) { - secinfo->unicast_uses_group = sec->unicast_uses_group; - dprintk(", .unicast_uses_group = %d", sec->unicast_uses_group); - } - if (sec->flags & SEC_LEVEL) { - secinfo->level = sec->level; - dprintk(", .level = %d", sec->level); - } - if (sec->flags & SEC_ENABLED) { - secinfo->enabled = sec->enabled; - dprintk(", .enabled = %d", sec->enabled); - } - if (sec->flags & SEC_ENCRYPT) { - secinfo->encrypt = sec->encrypt; - dprintk(", .encrypt = %d", sec->encrypt); - } - if (sec->flags & SEC_AUTH_MODE) { - secinfo->auth_mode = sec->auth_mode; - dprintk(", .auth_mode = %d", sec->auth_mode); - } - dprintk("\n"); - if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED && - !bcm->ieee->host_encrypt) { - if (secinfo->enabled) { - /* upload WEP keys to hardware */ - char null_address[6] = { 0 }; - u8 algorithm = 0; - for (keyidx = 0; keyidxflags & (1<encode_alg[keyidx]) { - case SEC_ALG_NONE: algorithm = BCM43xx_SEC_ALGO_NONE; break; - case SEC_ALG_WEP: - algorithm = BCM43xx_SEC_ALGO_WEP; - if (secinfo->key_sizes[keyidx] == 13) - algorithm = BCM43xx_SEC_ALGO_WEP104; - break; - case SEC_ALG_TKIP: - FIXME(); - algorithm = BCM43xx_SEC_ALGO_TKIP; - break; - case SEC_ALG_CCMP: - FIXME(); - algorithm = BCM43xx_SEC_ALGO_AES; - break; - default: - assert(0); - break; - } - bcm43xx_key_write(bcm, keyidx, algorithm, sec->keys[keyidx], secinfo->key_sizes[keyidx], &null_address[0]); - bcm->key[keyidx].enabled = 1; - bcm->key[keyidx].algorithm = algorithm; - } - } else - bcm43xx_clear_keys(bcm); - } - spin_unlock_irqrestore(&bcm->irq_lock, flags); - mutex_unlock(&bcm->mutex); -} - -/* hard_start_xmit() callback in struct ieee80211_device */ -static int bcm43xx_ieee80211_hard_start_xmit(struct ieee80211_txb *txb, - struct net_device *net_dev, - int pri) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - int err = -ENODEV; - unsigned long flags; - - spin_lock_irqsave(&bcm->irq_lock, flags); - if (likely(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)) - err = bcm43xx_tx(bcm, txb); - spin_unlock_irqrestore(&bcm->irq_lock, flags); - - if (unlikely(err)) - return NETDEV_TX_BUSY; - return NETDEV_TX_OK; -} - -static void bcm43xx_net_tx_timeout(struct net_device *net_dev) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - unsigned long flags; - - spin_lock_irqsave(&bcm->irq_lock, flags); - bcm43xx_controller_restart(bcm, "TX timeout"); - spin_unlock_irqrestore(&bcm->irq_lock, flags); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -static void bcm43xx_net_poll_controller(struct net_device *net_dev) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - unsigned long flags; - - local_irq_save(flags); - if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) - bcm43xx_interrupt_handler(bcm->irq, bcm); - local_irq_restore(flags); -} -#endif /* CONFIG_NET_POLL_CONTROLLER */ - -static int bcm43xx_net_open(struct net_device *net_dev) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - - return bcm43xx_init_board(bcm); -} - -static int bcm43xx_net_stop(struct net_device *net_dev) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - int err; - - ieee80211softmac_stop(net_dev); - err = bcm43xx_disable_interrupts_sync(bcm); - assert(!err); - bcm43xx_free_board(bcm); - bcm43xx_cancel_work(bcm); - - return 0; -} - -static int bcm43xx_init_private(struct bcm43xx_private *bcm, - struct net_device *net_dev, - struct pci_dev *pci_dev) -{ - bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT); - bcm->ieee = netdev_priv(net_dev); - bcm->softmac = ieee80211_priv(net_dev); - bcm->softmac->set_channel = bcm43xx_ieee80211_set_chan; - - bcm->irq_savedstate = BCM43xx_IRQ_INITIAL; - bcm->mac_suspended = 1; - bcm->pci_dev = pci_dev; - bcm->net_dev = net_dev; - bcm->bad_frames_preempt = modparam_bad_frames_preempt; - spin_lock_init(&bcm->irq_lock); - spin_lock_init(&bcm->leds_lock); - mutex_init(&bcm->mutex); - tasklet_init(&bcm->isr_tasklet, - (void (*)(unsigned long))bcm43xx_interrupt_tasklet, - (unsigned long)bcm); - tasklet_disable_nosync(&bcm->isr_tasklet); - if (modparam_pio) - bcm->__using_pio = 1; - bcm->rts_threshold = BCM43xx_DEFAULT_RTS_THRESHOLD; - - /* default to sw encryption for now */ - bcm->ieee->host_build_iv = 0; - bcm->ieee->host_encrypt = 1; - bcm->ieee->host_decrypt = 1; - - bcm->ieee->iw_mode = BCM43xx_INITIAL_IWMODE; - bcm->ieee->tx_headroom = sizeof(struct bcm43xx_txhdr); - bcm->ieee->set_security = bcm43xx_ieee80211_set_security; - bcm->ieee->hard_start_xmit = bcm43xx_ieee80211_hard_start_xmit; - - return 0; -} - -static int __devinit bcm43xx_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *net_dev; - struct bcm43xx_private *bcm; - int err; - -#ifdef DEBUG_SINGLE_DEVICE_ONLY - if (strcmp(pci_name(pdev), DEBUG_SINGLE_DEVICE_ONLY)) - return -ENODEV; -#endif - - net_dev = alloc_ieee80211softmac(sizeof(*bcm)); - if (!net_dev) { - printk(KERN_ERR PFX - "could not allocate ieee80211 device %s\n", - pci_name(pdev)); - err = -ENOMEM; - goto out; - } - /* initialize the net_device struct */ - SET_NETDEV_DEV(net_dev, &pdev->dev); - - net_dev->open = bcm43xx_net_open; - net_dev->stop = bcm43xx_net_stop; - net_dev->tx_timeout = bcm43xx_net_tx_timeout; -#ifdef CONFIG_NET_POLL_CONTROLLER - net_dev->poll_controller = bcm43xx_net_poll_controller; -#endif - net_dev->wireless_handlers = &bcm43xx_wx_handlers_def; - net_dev->irq = pdev->irq; - SET_ETHTOOL_OPS(net_dev, &bcm43xx_ethtool_ops); - - /* initialize the bcm43xx_private struct */ - bcm = bcm43xx_priv(net_dev); - memset(bcm, 0, sizeof(*bcm)); - err = bcm43xx_init_private(bcm, net_dev, pdev); - if (err) - goto err_free_netdev; - - pci_set_drvdata(pdev, net_dev); - - err = bcm43xx_attach_board(bcm); - if (err) - goto err_free_netdev; - - err = register_netdev(net_dev); - if (err) { - printk(KERN_ERR PFX "Cannot register net device, " - "aborting.\n"); - err = -ENOMEM; - goto err_detach_board; - } - - bcm43xx_debugfs_add_device(bcm); - - assert(err == 0); -out: - return err; - -err_detach_board: - bcm43xx_detach_board(bcm); -err_free_netdev: - free_ieee80211softmac(net_dev); - goto out; -} - -static void __devexit bcm43xx_remove_one(struct pci_dev *pdev) -{ - struct net_device *net_dev = pci_get_drvdata(pdev); - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - - bcm43xx_debugfs_remove_device(bcm); - unregister_netdev(net_dev); - bcm43xx_detach_board(bcm); - free_ieee80211softmac(net_dev); -} - -/* Hard-reset the chip. Do not call this directly. - * Use bcm43xx_controller_restart() - */ -static void bcm43xx_chip_reset(struct work_struct *work) -{ - struct bcm43xx_private *bcm = - container_of(work, struct bcm43xx_private, restart_work); - struct bcm43xx_phyinfo *phy; - int err = -ENODEV; - - bcm43xx_cancel_work(bcm); - mutex_lock(&(bcm)->mutex); - if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) { - phy = bcm43xx_current_phy(bcm); - err = bcm43xx_select_wireless_core(bcm, phy->type); - if (!err) - bcm43xx_periodic_tasks_setup(bcm); - } - mutex_unlock(&(bcm)->mutex); - - printk(KERN_ERR PFX "Controller restart%s\n", - (err == 0) ? "ed" : " failed"); -} - -/* Hard-reset the chip. - * This can be called from interrupt or process context. - * bcm->irq_lock must be locked. - */ -void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason) -{ - if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) - return; - printk(KERN_ERR PFX "Controller RESET (%s) ...\n", reason); - INIT_WORK(&bcm->restart_work, bcm43xx_chip_reset); - schedule_work(&bcm->restart_work); -} - -#ifdef CONFIG_PM - -static int bcm43xx_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *net_dev = pci_get_drvdata(pdev); - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - int err; - - dprintk(KERN_INFO PFX "Suspending...\n"); - - netif_device_detach(net_dev); - bcm->was_initialized = 0; - if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) { - bcm->was_initialized = 1; - ieee80211softmac_stop(net_dev); - err = bcm43xx_disable_interrupts_sync(bcm); - if (unlikely(err)) { - dprintk(KERN_ERR PFX "Suspend failed.\n"); - return -EAGAIN; - } - bcm->firmware_norelease = 1; - bcm43xx_free_board(bcm); - bcm->firmware_norelease = 0; - } - bcm43xx_chipset_detach(bcm); - - pci_save_state(pdev); - pci_disable_device(pdev); - pci_set_power_state(pdev, pci_choose_state(pdev, state)); - - dprintk(KERN_INFO PFX "Device suspended.\n"); - - return 0; -} - -static int bcm43xx_resume(struct pci_dev *pdev) -{ - struct net_device *net_dev = pci_get_drvdata(pdev); - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - int err = 0; - - dprintk(KERN_INFO PFX "Resuming...\n"); - - pci_set_power_state(pdev, 0); - err = pci_enable_device(pdev); - if (err) { - printk(KERN_ERR PFX "Failure with pci_enable_device!\n"); - return err; - } - pci_restore_state(pdev); - - bcm43xx_chipset_attach(bcm); - if (bcm->was_initialized) - err = bcm43xx_init_board(bcm); - if (err) { - printk(KERN_ERR PFX "Resume failed!\n"); - return err; - } - netif_device_attach(net_dev); - - dprintk(KERN_INFO PFX "Device resumed.\n"); - - return 0; -} - -#endif /* CONFIG_PM */ - -static struct pci_driver bcm43xx_pci_driver = { - .name = KBUILD_MODNAME, - .id_table = bcm43xx_pci_tbl, - .probe = bcm43xx_init_one, - .remove = __devexit_p(bcm43xx_remove_one), -#ifdef CONFIG_PM - .suspend = bcm43xx_suspend, - .resume = bcm43xx_resume, -#endif /* CONFIG_PM */ -}; - -static int __init bcm43xx_init(void) -{ - printk(KERN_INFO KBUILD_MODNAME " driver\n"); - bcm43xx_debugfs_init(); - return pci_register_driver(&bcm43xx_pci_driver); -} - -static void __exit bcm43xx_exit(void) -{ - pci_unregister_driver(&bcm43xx_pci_driver); - bcm43xx_debugfs_exit(); -} - -module_init(bcm43xx_init) -module_exit(bcm43xx_exit) diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.h b/drivers/net/wireless/bcm43xx/bcm43xx_main.h deleted file mode 100644 index 14cfbeb582ef..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.h +++ /dev/null @@ -1,133 +0,0 @@ -/* - - Broadcom BCM43xx wireless driver - - Copyright (c) 2005 Martin Langer , - Stefano Brivio - Michael Buesch - Danny van Dyk - Andreas Jaggi - - Some parts of the code in this file are derived from the ipw2200 - driver Copyright(c) 2003 - 2004 Intel Corporation. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#ifndef BCM43xx_MAIN_H_ -#define BCM43xx_MAIN_H_ - -#include "bcm43xx.h" - -#define P4D_BYT3S(magic, nr_bytes) u8 __p4dding##magic[nr_bytes] -#define P4D_BYTES(line, nr_bytes) P4D_BYT3S(line, nr_bytes) -/* Magic helper macro to pad structures. Ignore those above. It's magic. */ -#define PAD_BYTES(nr_bytes) P4D_BYTES( __LINE__ , (nr_bytes)) - - -/* Lightweight function to convert a frequency (in Mhz) to a channel number. */ -static inline -u8 bcm43xx_freq_to_channel_a(int freq) -{ - return ((freq - 5000) / 5); -} -static inline -u8 bcm43xx_freq_to_channel_bg(int freq) -{ - u8 channel; - - if (freq == 2484) - channel = 14; - else - channel = (freq - 2407) / 5; - - return channel; -} -static inline -u8 bcm43xx_freq_to_channel(struct bcm43xx_private *bcm, - int freq) -{ - if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A) - return bcm43xx_freq_to_channel_a(freq); - return bcm43xx_freq_to_channel_bg(freq); -} - -/* Lightweight function to convert a channel number to a frequency (in Mhz). */ -static inline -int bcm43xx_channel_to_freq_a(u8 channel) -{ - return (5000 + (5 * channel)); -} -static inline -int bcm43xx_channel_to_freq_bg(u8 channel) -{ - int freq; - - if (channel == 14) - freq = 2484; - else - freq = 2407 + (5 * channel); - - return freq; -} -static inline -int bcm43xx_channel_to_freq(struct bcm43xx_private *bcm, - u8 channel) -{ - if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A) - return bcm43xx_channel_to_freq_a(channel); - return bcm43xx_channel_to_freq_bg(channel); -} - -void bcm43xx_tsf_read(struct bcm43xx_private *bcm, u64 *tsf); -void bcm43xx_tsf_write(struct bcm43xx_private *bcm, u64 tsf); - -void bcm43xx_set_iwmode(struct bcm43xx_private *bcm, - int iw_mode); - -u32 bcm43xx_shm_read32(struct bcm43xx_private *bcm, - u16 routing, u16 offset); -u16 bcm43xx_shm_read16(struct bcm43xx_private *bcm, - u16 routing, u16 offset); -void bcm43xx_shm_write32(struct bcm43xx_private *bcm, - u16 routing, u16 offset, - u32 value); -void bcm43xx_shm_write16(struct bcm43xx_private *bcm, - u16 routing, u16 offset, - u16 value); - -void bcm43xx_dummy_transmission(struct bcm43xx_private *bcm); - -int bcm43xx_switch_core(struct bcm43xx_private *bcm, struct bcm43xx_coreinfo *new_core); - -int bcm43xx_select_wireless_core(struct bcm43xx_private *bcm, - int phytype); - -void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy); - -void bcm43xx_mac_suspend(struct bcm43xx_private *bcm); -void bcm43xx_mac_enable(struct bcm43xx_private *bcm); - -void bcm43xx_cancel_work(struct bcm43xx_private *bcm); -void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm); - -void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason); - -int bcm43xx_sprom_read(struct bcm43xx_private *bcm, u16 *sprom); -int bcm43xx_sprom_write(struct bcm43xx_private *bcm, const u16 *sprom); - -#endif /* BCM43xx_MAIN_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c deleted file mode 100644 index af3de3343650..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c +++ /dev/null @@ -1,2346 +0,0 @@ -/* - - Broadcom BCM43xx wireless driver - - Copyright (c) 2005 Martin Langer , - Stefano Brivio - Michael Buesch - Danny van Dyk - Andreas Jaggi - - Some parts of the code in this file are derived from the ipw2200 - driver Copyright(c) 2003 - 2004 Intel Corporation. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include -#include -#include - -#include "bcm43xx.h" -#include "bcm43xx_phy.h" -#include "bcm43xx_main.h" -#include "bcm43xx_radio.h" -#include "bcm43xx_ilt.h" -#include "bcm43xx_power.h" - - -static const s8 bcm43xx_tssi2dbm_b_table[] = { - 0x4D, 0x4C, 0x4B, 0x4A, - 0x4A, 0x49, 0x48, 0x47, - 0x47, 0x46, 0x45, 0x45, - 0x44, 0x43, 0x42, 0x42, - 0x41, 0x40, 0x3F, 0x3E, - 0x3D, 0x3C, 0x3B, 0x3A, - 0x39, 0x38, 0x37, 0x36, - 0x35, 0x34, 0x32, 0x31, - 0x30, 0x2F, 0x2D, 0x2C, - 0x2B, 0x29, 0x28, 0x26, - 0x25, 0x23, 0x21, 0x1F, - 0x1D, 0x1A, 0x17, 0x14, - 0x10, 0x0C, 0x06, 0x00, - -7, -7, -7, -7, - -7, -7, -7, -7, - -7, -7, -7, -7, -}; - -static const s8 bcm43xx_tssi2dbm_g_table[] = { - 77, 77, 77, 76, - 76, 76, 75, 75, - 74, 74, 73, 73, - 73, 72, 72, 71, - 71, 70, 70, 69, - 68, 68, 67, 67, - 66, 65, 65, 64, - 63, 63, 62, 61, - 60, 59, 58, 57, - 56, 55, 54, 53, - 52, 50, 49, 47, - 45, 43, 40, 37, - 33, 28, 22, 14, - 5, -7, -20, -20, - -20, -20, -20, -20, - -20, -20, -20, -20, -}; - -static void bcm43xx_phy_initg(struct bcm43xx_private *bcm); - - -static inline -void bcm43xx_voluntary_preempt(void) -{ - assert(!in_atomic() && !in_irq() && - !in_interrupt() && !irqs_disabled()); -#ifndef CONFIG_PREEMPT - cond_resched(); -#endif /* CONFIG_PREEMPT */ -} - -void bcm43xx_raw_phy_lock(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - - assert(irqs_disabled()); - if (bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) == 0x00000000) { - phy->is_locked = 0; - return; - } - if (bcm->current_core->rev < 3) { - bcm43xx_mac_suspend(bcm); - spin_lock(&phy->lock); - } else { - if (bcm->ieee->iw_mode != IW_MODE_MASTER) - bcm43xx_power_saving_ctl_bits(bcm, -1, 1); - } - phy->is_locked = 1; -} - -void bcm43xx_raw_phy_unlock(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - - assert(irqs_disabled()); - if (bcm->current_core->rev < 3) { - if (phy->is_locked) { - spin_unlock(&phy->lock); - bcm43xx_mac_enable(bcm); - } - } else { - if (bcm->ieee->iw_mode != IW_MODE_MASTER) - bcm43xx_power_saving_ctl_bits(bcm, -1, -1); - } - phy->is_locked = 0; -} - -u16 bcm43xx_phy_read(struct bcm43xx_private *bcm, u16 offset) -{ - bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_CONTROL, offset); - return bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_DATA); -} - -void bcm43xx_phy_write(struct bcm43xx_private *bcm, u16 offset, u16 val) -{ - bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_CONTROL, offset); - mmiowb(); - bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_DATA, val); -} - -void bcm43xx_phy_calibrate(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - - bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* Dummy read. */ - if (phy->calibrated) - return; - if (phy->type == BCM43xx_PHYTYPE_G && phy->rev == 1) { - bcm43xx_wireless_core_reset(bcm, 0); - bcm43xx_phy_initg(bcm); - bcm43xx_wireless_core_reset(bcm, 1); - } - phy->calibrated = 1; -} - -/* Connect the PHY - * http://bcm-specs.sipsolutions.net/SetPHY - */ -int bcm43xx_phy_connect(struct bcm43xx_private *bcm, int connect) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - u32 flags; - - if (bcm->current_core->rev < 5) - goto out; - - flags = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH); - if (connect) { - if (!(flags & BCM43xx_SBTMSTATEHIGH_G_PHY_AVAIL)) - return -ENODEV; - flags = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); - flags |= BCM43xx_SBTMSTATELOW_G_MODE_ENABLE; - bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, flags); - } else { - if (!(flags & BCM43xx_SBTMSTATEHIGH_A_PHY_AVAIL)) - return -ENODEV; - flags = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); - flags &= ~BCM43xx_SBTMSTATELOW_G_MODE_ENABLE; - bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, flags); - } -out: - phy->connected = connect; - if (connect) - dprintk(KERN_INFO PFX "PHY connected\n"); - else - dprintk(KERN_INFO PFX "PHY disconnected\n"); - - return 0; -} - -/* intialize B PHY power control - * as described in http://bcm-specs.sipsolutions.net/InitPowerControl - */ -static void bcm43xx_phy_init_pctl(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - u16 saved_batt = 0, saved_ratt = 0, saved_txctl1 = 0; - int must_reset_txpower = 0; - - assert(phy->type != BCM43xx_PHYTYPE_A); - if ((bcm->board_vendor == PCI_VENDOR_ID_BROADCOM) && - (bcm->board_type == 0x0416)) - return; - - bcm43xx_phy_write(bcm, 0x0028, 0x8018); - bcm43xx_write16(bcm, 0x03E6, bcm43xx_read16(bcm, 0x03E6) & 0xFFDF); - - if (phy->type == BCM43xx_PHYTYPE_G) { - if (!phy->connected) - return; - bcm43xx_phy_write(bcm, 0x047A, 0xC111); - } - if (phy->savedpctlreg != 0xFFFF) - return; - - if (phy->type == BCM43xx_PHYTYPE_B && - phy->rev >= 2 && - radio->version == 0x2050) { - bcm43xx_radio_write16(bcm, 0x0076, - bcm43xx_radio_read16(bcm, 0x0076) | 0x0084); - } else { - saved_batt = radio->baseband_atten; - saved_ratt = radio->radio_atten; - saved_txctl1 = radio->txctl1; - if ((radio->revision >= 6) && (radio->revision <= 8) - && /*FIXME: incomplete specs for 5 < revision < 9 */ 0) - bcm43xx_radio_set_txpower_bg(bcm, 0xB, 0x1F, 0); - else - bcm43xx_radio_set_txpower_bg(bcm, 0xB, 9, 0); - must_reset_txpower = 1; - } - bcm43xx_dummy_transmission(bcm); - - phy->savedpctlreg = bcm43xx_phy_read(bcm, BCM43xx_PHY_G_PCTL); - - if (must_reset_txpower) - bcm43xx_radio_set_txpower_bg(bcm, saved_batt, saved_ratt, saved_txctl1); - else - bcm43xx_radio_write16(bcm, 0x0076, bcm43xx_radio_read16(bcm, 0x0076) & 0xFF7B); - bcm43xx_radio_clear_tssi(bcm); -} - -static void bcm43xx_phy_agcsetup(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - u16 offset = 0x0000; - - if (phy->rev == 1) - offset = 0x4C00; - - bcm43xx_ilt_write(bcm, offset, 0x00FE); - bcm43xx_ilt_write(bcm, offset + 1, 0x000D); - bcm43xx_ilt_write(bcm, offset + 2, 0x0013); - bcm43xx_ilt_write(bcm, offset + 3, 0x0019); - - if (phy->rev == 1) { - bcm43xx_ilt_write(bcm, 0x1800, 0x2710); - bcm43xx_ilt_write(bcm, 0x1801, 0x9B83); - bcm43xx_ilt_write(bcm, 0x1802, 0x9B83); - bcm43xx_ilt_write(bcm, 0x1803, 0x0F8D); - bcm43xx_phy_write(bcm, 0x0455, 0x0004); - } - - bcm43xx_phy_write(bcm, 0x04A5, (bcm43xx_phy_read(bcm, 0x04A5) & 0x00FF) | 0x5700); - bcm43xx_phy_write(bcm, 0x041A, (bcm43xx_phy_read(bcm, 0x041A) & 0xFF80) | 0x000F); - bcm43xx_phy_write(bcm, 0x041A, (bcm43xx_phy_read(bcm, 0x041A) & 0xC07F) | 0x2B80); - bcm43xx_phy_write(bcm, 0x048C, (bcm43xx_phy_read(bcm, 0x048C) & 0xF0FF) | 0x0300); - - bcm43xx_radio_write16(bcm, 0x007A, bcm43xx_radio_read16(bcm, 0x007A) | 0x0008); - - bcm43xx_phy_write(bcm, 0x04A0, (bcm43xx_phy_read(bcm, 0x04A0) & 0xFFF0) | 0x0008); - bcm43xx_phy_write(bcm, 0x04A1, (bcm43xx_phy_read(bcm, 0x04A1) & 0xF0FF) | 0x0600); - bcm43xx_phy_write(bcm, 0x04A2, (bcm43xx_phy_read(bcm, 0x04A2) & 0xF0FF) | 0x0700); - bcm43xx_phy_write(bcm, 0x04A0, (bcm43xx_phy_read(bcm, 0x04A0) & 0xF0FF) | 0x0100); - - if (phy->rev == 1) - bcm43xx_phy_write(bcm, 0x04A2, (bcm43xx_phy_read(bcm, 0x04A2) & 0xFFF0) | 0x0007); - - bcm43xx_phy_write(bcm, 0x0488, (bcm43xx_phy_read(bcm, 0x0488) & 0xFF00) | 0x001C); - bcm43xx_phy_write(bcm, 0x0488, (bcm43xx_phy_read(bcm, 0x0488) & 0xC0FF) | 0x0200); - bcm43xx_phy_write(bcm, 0x0496, (bcm43xx_phy_read(bcm, 0x0496) & 0xFF00) | 0x001C); - bcm43xx_phy_write(bcm, 0x0489, (bcm43xx_phy_read(bcm, 0x0489) & 0xFF00) | 0x0020); - bcm43xx_phy_write(bcm, 0x0489, (bcm43xx_phy_read(bcm, 0x0489) & 0xC0FF) | 0x0200); - bcm43xx_phy_write(bcm, 0x0482, (bcm43xx_phy_read(bcm, 0x0482) & 0xFF00) | 0x002E); - bcm43xx_phy_write(bcm, 0x0496, (bcm43xx_phy_read(bcm, 0x0496) & 0x00FF) | 0x1A00); - bcm43xx_phy_write(bcm, 0x0481, (bcm43xx_phy_read(bcm, 0x0481) & 0xFF00) | 0x0028); - bcm43xx_phy_write(bcm, 0x0481, (bcm43xx_phy_read(bcm, 0x0481) & 0x00FF) | 0x2C00); - - if (phy->rev == 1) { - bcm43xx_phy_write(bcm, 0x0430, 0x092B); - bcm43xx_phy_write(bcm, 0x041B, (bcm43xx_phy_read(bcm, 0x041B) & 0xFFE1) | 0x0002); - } else { - bcm43xx_phy_write(bcm, 0x041B, bcm43xx_phy_read(bcm, 0x041B) & 0xFFE1); - bcm43xx_phy_write(bcm, 0x041F, 0x287A); - bcm43xx_phy_write(bcm, 0x0420, (bcm43xx_phy_read(bcm, 0x0420) & 0xFFF0) | 0x0004); - } - - if (phy->rev > 2) { - bcm43xx_phy_write(bcm, 0x0422, 0x287A); - bcm43xx_phy_write(bcm, 0x0420, (bcm43xx_phy_read(bcm, 0x0420) - & 0x0FFF) | 0x3000); - } - - bcm43xx_phy_write(bcm, 0x04A8, (bcm43xx_phy_read(bcm, 0x04A8) & 0x8080) - | 0x7874); - bcm43xx_phy_write(bcm, 0x048E, 0x1C00); - - if (phy->rev == 1) { - bcm43xx_phy_write(bcm, 0x04AB, (bcm43xx_phy_read(bcm, 0x04AB) - & 0xF0FF) | 0x0600); - bcm43xx_phy_write(bcm, 0x048B, 0x005E); - bcm43xx_phy_write(bcm, 0x048C, (bcm43xx_phy_read(bcm, 0x048C) - & 0xFF00) | 0x001E); - bcm43xx_phy_write(bcm, 0x048D, 0x0002); - } - - bcm43xx_ilt_write(bcm, offset + 0x0800, 0); - bcm43xx_ilt_write(bcm, offset + 0x0801, 7); - bcm43xx_ilt_write(bcm, offset + 0x0802, 16); - bcm43xx_ilt_write(bcm, offset + 0x0803, 28); - - if (phy->rev >= 6) { - bcm43xx_phy_write(bcm, 0x0426, (bcm43xx_phy_read(bcm, 0x0426) - & 0xFFFC)); - bcm43xx_phy_write(bcm, 0x0426, (bcm43xx_phy_read(bcm, 0x0426) - & 0xEFFF)); - } -} - -static void bcm43xx_phy_setupg(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - u16 i; - - assert(phy->type == BCM43xx_PHYTYPE_G); - if (phy->rev == 1) { - bcm43xx_phy_write(bcm, 0x0406, 0x4F19); - bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, - (bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) - & 0xFC3F) | 0x0340); - bcm43xx_phy_write(bcm, 0x042C, 0x005A); - bcm43xx_phy_write(bcm, 0x0427, 0x001A); - - for (i = 0; i < BCM43xx_ILT_FINEFREQG_SIZE; i++) - bcm43xx_ilt_write(bcm, 0x5800 + i, bcm43xx_ilt_finefreqg[i]); - for (i = 0; i < BCM43xx_ILT_NOISEG1_SIZE; i++) - bcm43xx_ilt_write(bcm, 0x1800 + i, bcm43xx_ilt_noiseg1[i]); - for (i = 0; i < BCM43xx_ILT_ROTOR_SIZE; i++) - bcm43xx_ilt_write32(bcm, 0x2000 + i, bcm43xx_ilt_rotor[i]); - } else { - /* nrssi values are signed 6-bit values. Not sure why we write 0x7654 here... */ - bcm43xx_nrssi_hw_write(bcm, 0xBA98, (s16)0x7654); - - if (phy->rev == 2) { - bcm43xx_phy_write(bcm, 0x04C0, 0x1861); - bcm43xx_phy_write(bcm, 0x04C1, 0x0271); - } else if (phy->rev > 2) { - bcm43xx_phy_write(bcm, 0x04C0, 0x0098); - bcm43xx_phy_write(bcm, 0x04C1, 0x0070); - bcm43xx_phy_write(bcm, 0x04C9, 0x0080); - } - bcm43xx_phy_write(bcm, 0x042B, bcm43xx_phy_read(bcm, 0x042B) | 0x800); - - for (i = 0; i < 64; i++) - bcm43xx_ilt_write(bcm, 0x4000 + i, i); - for (i = 0; i < BCM43xx_ILT_NOISEG2_SIZE; i++) - bcm43xx_ilt_write(bcm, 0x1800 + i, bcm43xx_ilt_noiseg2[i]); - } - - if (phy->rev <= 2) - for (i = 0; i < BCM43xx_ILT_NOISESCALEG_SIZE; i++) - bcm43xx_ilt_write(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg1[i]); - else if ((phy->rev >= 7) && (bcm43xx_phy_read(bcm, 0x0449) & 0x0200)) - for (i = 0; i < BCM43xx_ILT_NOISESCALEG_SIZE; i++) - bcm43xx_ilt_write(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg3[i]); - else - for (i = 0; i < BCM43xx_ILT_NOISESCALEG_SIZE; i++) - bcm43xx_ilt_write(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg2[i]); - - if (phy->rev == 2) - for (i = 0; i < BCM43xx_ILT_SIGMASQR_SIZE; i++) - bcm43xx_ilt_write(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr1[i]); - else if ((phy->rev > 2) && (phy->rev <= 8)) - for (i = 0; i < BCM43xx_ILT_SIGMASQR_SIZE; i++) - bcm43xx_ilt_write(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr2[i]); - - if (phy->rev == 1) { - for (i = 0; i < BCM43xx_ILT_RETARD_SIZE; i++) - bcm43xx_ilt_write32(bcm, 0x2400 + i, bcm43xx_ilt_retard[i]); - for (i = 0; i < 4; i++) { - bcm43xx_ilt_write(bcm, 0x5404 + i, 0x0020); - bcm43xx_ilt_write(bcm, 0x5408 + i, 0x0020); - bcm43xx_ilt_write(bcm, 0x540C + i, 0x0020); - bcm43xx_ilt_write(bcm, 0x5410 + i, 0x0020); - } - bcm43xx_phy_agcsetup(bcm); - - if ((bcm->board_vendor == PCI_VENDOR_ID_BROADCOM) && - (bcm->board_type == 0x0416) && - (bcm->board_revision == 0x0017)) - return; - - bcm43xx_ilt_write(bcm, 0x5001, 0x0002); - bcm43xx_ilt_write(bcm, 0x5002, 0x0001); - } else { - for (i = 0; i <= 0x2F; i++) - bcm43xx_ilt_write(bcm, 0x1000 + i, 0x0820); - bcm43xx_phy_agcsetup(bcm); - bcm43xx_phy_read(bcm, 0x0400); /* dummy read */ - bcm43xx_phy_write(bcm, 0x0403, 0x1000); - bcm43xx_ilt_write(bcm, 0x3C02, 0x000F); - bcm43xx_ilt_write(bcm, 0x3C03, 0x0014); - - if ((bcm->board_vendor == PCI_VENDOR_ID_BROADCOM) && - (bcm->board_type == 0x0416) && - (bcm->board_revision == 0x0017)) - return; - - bcm43xx_ilt_write(bcm, 0x0401, 0x0002); - bcm43xx_ilt_write(bcm, 0x0402, 0x0001); - } -} - -/* Initialize the noisescaletable for APHY */ -static void bcm43xx_phy_init_noisescaletbl(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - int i; - - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, 0x1400); - for (i = 0; i < 12; i++) { - if (phy->rev == 2) - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x6767); - else - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x2323); - } - if (phy->rev == 2) - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x6700); - else - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x2300); - for (i = 0; i < 11; i++) { - if (phy->rev == 2) - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x6767); - else - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x2323); - } - if (phy->rev == 2) - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x0067); - else - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x0023); -} - -static void bcm43xx_phy_setupa(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - u16 i; - - assert(phy->type == BCM43xx_PHYTYPE_A); - switch (phy->rev) { - case 2: - bcm43xx_phy_write(bcm, 0x008E, 0x3800); - bcm43xx_phy_write(bcm, 0x0035, 0x03FF); - bcm43xx_phy_write(bcm, 0x0036, 0x0400); - - bcm43xx_ilt_write(bcm, 0x3807, 0x0051); - - bcm43xx_phy_write(bcm, 0x001C, 0x0FF9); - bcm43xx_phy_write(bcm, 0x0020, bcm43xx_phy_read(bcm, 0x0020) & 0xFF0F); - bcm43xx_ilt_write(bcm, 0x3C0C, 0x07BF); - bcm43xx_radio_write16(bcm, 0x0002, 0x07BF); - - bcm43xx_phy_write(bcm, 0x0024, 0x4680); - bcm43xx_phy_write(bcm, 0x0020, 0x0003); - bcm43xx_phy_write(bcm, 0x001D, 0x0F40); - bcm43xx_phy_write(bcm, 0x001F, 0x1C00); - - bcm43xx_phy_write(bcm, 0x002A, (bcm43xx_phy_read(bcm, 0x002A) & 0x00FF) | 0x0400); - bcm43xx_phy_write(bcm, 0x002B, bcm43xx_phy_read(bcm, 0x002B) & 0xFBFF); - bcm43xx_phy_write(bcm, 0x008E, 0x58C1); - - bcm43xx_ilt_write(bcm, 0x0803, 0x000F); - bcm43xx_ilt_write(bcm, 0x0804, 0x001F); - bcm43xx_ilt_write(bcm, 0x0805, 0x002A); - bcm43xx_ilt_write(bcm, 0x0805, 0x0030); - bcm43xx_ilt_write(bcm, 0x0807, 0x003A); - - bcm43xx_ilt_write(bcm, 0x0000, 0x0013); - bcm43xx_ilt_write(bcm, 0x0001, 0x0013); - bcm43xx_ilt_write(bcm, 0x0002, 0x0013); - bcm43xx_ilt_write(bcm, 0x0003, 0x0013); - bcm43xx_ilt_write(bcm, 0x0004, 0x0015); - bcm43xx_ilt_write(bcm, 0x0005, 0x0015); - bcm43xx_ilt_write(bcm, 0x0006, 0x0019); - - bcm43xx_ilt_write(bcm, 0x0404, 0x0003); - bcm43xx_ilt_write(bcm, 0x0405, 0x0003); - bcm43xx_ilt_write(bcm, 0x0406, 0x0007); - - for (i = 0; i < 16; i++) - bcm43xx_ilt_write(bcm, 0x4000 + i, (0x8 + i) & 0x000F); - - bcm43xx_ilt_write(bcm, 0x3003, 0x1044); - bcm43xx_ilt_write(bcm, 0x3004, 0x7201); - bcm43xx_ilt_write(bcm, 0x3006, 0x0040); - bcm43xx_ilt_write(bcm, 0x3001, (bcm43xx_ilt_read(bcm, 0x3001) & 0x0010) | 0x0008); - - for (i = 0; i < BCM43xx_ILT_FINEFREQA_SIZE; i++) - bcm43xx_ilt_write(bcm, 0x5800 + i, bcm43xx_ilt_finefreqa[i]); - for (i = 0; i < BCM43xx_ILT_NOISEA2_SIZE; i++) - bcm43xx_ilt_write(bcm, 0x1800 + i, bcm43xx_ilt_noisea2[i]); - for (i = 0; i < BCM43xx_ILT_ROTOR_SIZE; i++) - bcm43xx_ilt_write32(bcm, 0x2000 + i, bcm43xx_ilt_rotor[i]); - bcm43xx_phy_init_noisescaletbl(bcm); - for (i = 0; i < BCM43xx_ILT_RETARD_SIZE; i++) - bcm43xx_ilt_write32(bcm, 0x2400 + i, bcm43xx_ilt_retard[i]); - break; - case 3: - for (i = 0; i < 64; i++) - bcm43xx_ilt_write(bcm, 0x4000 + i, i); - - bcm43xx_ilt_write(bcm, 0x3807, 0x0051); - - bcm43xx_phy_write(bcm, 0x001C, 0x0FF9); - bcm43xx_phy_write(bcm, 0x0020, bcm43xx_phy_read(bcm, 0x0020) & 0xFF0F); - bcm43xx_radio_write16(bcm, 0x0002, 0x07BF); - - bcm43xx_phy_write(bcm, 0x0024, 0x4680); - bcm43xx_phy_write(bcm, 0x0020, 0x0003); - bcm43xx_phy_write(bcm, 0x001D, 0x0F40); - bcm43xx_phy_write(bcm, 0x001F, 0x1C00); - bcm43xx_phy_write(bcm, 0x002A, (bcm43xx_phy_read(bcm, 0x002A) & 0x00FF) | 0x0400); - - bcm43xx_ilt_write(bcm, 0x3001, (bcm43xx_ilt_read(bcm, 0x3001) & 0x0010) | 0x0008); - for (i = 0; i < BCM43xx_ILT_NOISEA3_SIZE; i++) - bcm43xx_ilt_write(bcm, 0x1800 + i, bcm43xx_ilt_noisea3[i]); - bcm43xx_phy_init_noisescaletbl(bcm); - for (i = 0; i < BCM43xx_ILT_SIGMASQR_SIZE; i++) - bcm43xx_ilt_write(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr1[i]); - - bcm43xx_phy_write(bcm, 0x0003, 0x1808); - - bcm43xx_ilt_write(bcm, 0x0803, 0x000F); - bcm43xx_ilt_write(bcm, 0x0804, 0x001F); - bcm43xx_ilt_write(bcm, 0x0805, 0x002A); - bcm43xx_ilt_write(bcm, 0x0805, 0x0030); - bcm43xx_ilt_write(bcm, 0x0807, 0x003A); - - bcm43xx_ilt_write(bcm, 0x0000, 0x0013); - bcm43xx_ilt_write(bcm, 0x0001, 0x0013); - bcm43xx_ilt_write(bcm, 0x0002, 0x0013); - bcm43xx_ilt_write(bcm, 0x0003, 0x0013); - bcm43xx_ilt_write(bcm, 0x0004, 0x0015); - bcm43xx_ilt_write(bcm, 0x0005, 0x0015); - bcm43xx_ilt_write(bcm, 0x0006, 0x0019); - - bcm43xx_ilt_write(bcm, 0x0404, 0x0003); - bcm43xx_ilt_write(bcm, 0x0405, 0x0003); - bcm43xx_ilt_write(bcm, 0x0406, 0x0007); - - bcm43xx_ilt_write(bcm, 0x3C02, 0x000F); - bcm43xx_ilt_write(bcm, 0x3C03, 0x0014); - break; - default: - assert(0); - } -} - -/* Initialize APHY. This is also called for the GPHY in some cases. */ -static void bcm43xx_phy_inita(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - u16 tval; - - if (phy->type == BCM43xx_PHYTYPE_A) { - bcm43xx_phy_setupa(bcm); - } else { - bcm43xx_phy_setupg(bcm); - if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) - bcm43xx_phy_write(bcm, 0x046E, 0x03CF); - return; - } - - bcm43xx_phy_write(bcm, BCM43xx_PHY_A_CRS, - (bcm43xx_phy_read(bcm, BCM43xx_PHY_A_CRS) & 0xF83C) | 0x0340); - bcm43xx_phy_write(bcm, 0x0034, 0x0001); - - TODO();//TODO: RSSI AGC - bcm43xx_phy_write(bcm, BCM43xx_PHY_A_CRS, - bcm43xx_phy_read(bcm, BCM43xx_PHY_A_CRS) | (1 << 14)); - bcm43xx_radio_init2060(bcm); - - if ((bcm->board_vendor == PCI_VENDOR_ID_BROADCOM) - && ((bcm->board_type == 0x0416) || (bcm->board_type == 0x040A))) { - if (radio->lofcal == 0xFFFF) { - TODO();//TODO: LOF Cal - bcm43xx_radio_set_tx_iq(bcm); - } else - bcm43xx_radio_write16(bcm, 0x001E, radio->lofcal); - } - - bcm43xx_phy_write(bcm, 0x007A, 0xF111); - - if (phy->savedpctlreg == 0xFFFF) { - bcm43xx_radio_write16(bcm, 0x0019, 0x0000); - bcm43xx_radio_write16(bcm, 0x0017, 0x0020); - - tval = bcm43xx_ilt_read(bcm, 0x3001); - if (phy->rev == 1) { - bcm43xx_ilt_write(bcm, 0x3001, - (bcm43xx_ilt_read(bcm, 0x3001) & 0xFF87) - | 0x0058); - } else { - bcm43xx_ilt_write(bcm, 0x3001, - (bcm43xx_ilt_read(bcm, 0x3001) & 0xFFC3) - | 0x002C); - } - bcm43xx_dummy_transmission(bcm); - phy->savedpctlreg = bcm43xx_phy_read(bcm, BCM43xx_PHY_A_PCTL); - bcm43xx_ilt_write(bcm, 0x3001, tval); - - bcm43xx_radio_set_txpower_a(bcm, 0x0018); - } - bcm43xx_radio_clear_tssi(bcm); -} - -static void bcm43xx_phy_initb2(struct bcm43xx_private *bcm) -{ - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - u16 offset, val; - - bcm43xx_write16(bcm, 0x03EC, 0x3F22); - bcm43xx_phy_write(bcm, 0x0020, 0x301C); - bcm43xx_phy_write(bcm, 0x0026, 0x0000); - bcm43xx_phy_write(bcm, 0x0030, 0x00C6); - bcm43xx_phy_write(bcm, 0x0088, 0x3E00); - val = 0x3C3D; - for (offset = 0x0089; offset < 0x00A7; offset++) { - bcm43xx_phy_write(bcm, offset, val); - val -= 0x0202; - } - bcm43xx_phy_write(bcm, 0x03E4, 0x3000); - if (radio->channel == 0xFF) - bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_BG, 0); - else - bcm43xx_radio_selectchannel(bcm, radio->channel, 0); - if (radio->version != 0x2050) { - bcm43xx_radio_write16(bcm, 0x0075, 0x0080); - bcm43xx_radio_write16(bcm, 0x0079, 0x0081); - } - bcm43xx_radio_write16(bcm, 0x0050, 0x0020); - bcm43xx_radio_write16(bcm, 0x0050, 0x0023); - if (radio->version == 0x2050) { - bcm43xx_radio_write16(bcm, 0x0050, 0x0020); - bcm43xx_radio_write16(bcm, 0x005A, 0x0070); - bcm43xx_radio_write16(bcm, 0x005B, 0x007B); - bcm43xx_radio_write16(bcm, 0x005C, 0x00B0); - bcm43xx_radio_write16(bcm, 0x007A, 0x000F); - bcm43xx_phy_write(bcm, 0x0038, 0x0677); - bcm43xx_radio_init2050(bcm); - } - bcm43xx_phy_write(bcm, 0x0014, 0x0080); - bcm43xx_phy_write(bcm, 0x0032, 0x00CA); - bcm43xx_phy_write(bcm, 0x0032, 0x00CC); - bcm43xx_phy_write(bcm, 0x0035, 0x07C2); - bcm43xx_phy_lo_b_measure(bcm); - bcm43xx_phy_write(bcm, 0x0026, 0xCC00); - if (radio->version != 0x2050) - bcm43xx_phy_write(bcm, 0x0026, 0xCE00); - bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, 0x1000); - bcm43xx_phy_write(bcm, 0x002A, 0x88A3); - if (radio->version != 0x2050) - bcm43xx_phy_write(bcm, 0x002A, 0x88C2); - bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF); - bcm43xx_phy_init_pctl(bcm); -} - -static void bcm43xx_phy_initb4(struct bcm43xx_private *bcm) -{ - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - u16 offset, val; - - bcm43xx_write16(bcm, 0x03EC, 0x3F22); - bcm43xx_phy_write(bcm, 0x0020, 0x301C); - bcm43xx_phy_write(bcm, 0x0026, 0x0000); - bcm43xx_phy_write(bcm, 0x0030, 0x00C6); - bcm43xx_phy_write(bcm, 0x0088, 0x3E00); - val = 0x3C3D; - for (offset = 0x0089; offset < 0x00A7; offset++) { - bcm43xx_phy_write(bcm, offset, val); - val -= 0x0202; - } - bcm43xx_phy_write(bcm, 0x03E4, 0x3000); - if (radio->channel == 0xFF) - bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_BG, 0); - else - bcm43xx_radio_selectchannel(bcm, radio->channel, 0); - if (radio->version != 0x2050) { - bcm43xx_radio_write16(bcm, 0x0075, 0x0080); - bcm43xx_radio_write16(bcm, 0x0079, 0x0081); - } - bcm43xx_radio_write16(bcm, 0x0050, 0x0020); - bcm43xx_radio_write16(bcm, 0x0050, 0x0023); - if (radio->version == 0x2050) { - bcm43xx_radio_write16(bcm, 0x0050, 0x0020); - bcm43xx_radio_write16(bcm, 0x005A, 0x0070); - bcm43xx_radio_write16(bcm, 0x005B, 0x007B); - bcm43xx_radio_write16(bcm, 0x005C, 0x00B0); - bcm43xx_radio_write16(bcm, 0x007A, 0x000F); - bcm43xx_phy_write(bcm, 0x0038, 0x0677); - bcm43xx_radio_init2050(bcm); - } - bcm43xx_phy_write(bcm, 0x0014, 0x0080); - bcm43xx_phy_write(bcm, 0x0032, 0x00CA); - if (radio->version == 0x2050) - bcm43xx_phy_write(bcm, 0x0032, 0x00E0); - bcm43xx_phy_write(bcm, 0x0035, 0x07C2); - - bcm43xx_phy_lo_b_measure(bcm); - - bcm43xx_phy_write(bcm, 0x0026, 0xCC00); - if (radio->version == 0x2050) - bcm43xx_phy_write(bcm, 0x0026, 0xCE00); - bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, 0x1100); - bcm43xx_phy_write(bcm, 0x002A, 0x88A3); - if (radio->version == 0x2050) - bcm43xx_phy_write(bcm, 0x002A, 0x88C2); - bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF); - if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) { - bcm43xx_calc_nrssi_slope(bcm); - bcm43xx_calc_nrssi_threshold(bcm); - } - bcm43xx_phy_init_pctl(bcm); -} - -static void bcm43xx_phy_initb5(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - u16 offset; - u16 value; - u8 old_channel; - - if (phy->analog == 1) - bcm43xx_radio_write16(bcm, 0x007A, - bcm43xx_radio_read16(bcm, 0x007A) - | 0x0050); - if ((bcm->board_vendor != PCI_VENDOR_ID_BROADCOM) && - (bcm->board_type != 0x0416)) { - value = 0x2120; - for (offset = 0x00A8 ; offset < 0x00C7; offset++) { - bcm43xx_phy_write(bcm, offset, value); - value += 0x0202; - } - } - bcm43xx_phy_write(bcm, 0x0035, - (bcm43xx_phy_read(bcm, 0x0035) & 0xF0FF) - | 0x0700); - if (radio->version == 0x2050) - bcm43xx_phy_write(bcm, 0x0038, 0x0667); - - if (phy->connected) { - if (radio->version == 0x2050) { - bcm43xx_radio_write16(bcm, 0x007A, - bcm43xx_radio_read16(bcm, 0x007A) - | 0x0020); - bcm43xx_radio_write16(bcm, 0x0051, - bcm43xx_radio_read16(bcm, 0x0051) - | 0x0004); - } - bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_RADIO, 0x0000); - - bcm43xx_phy_write(bcm, 0x0802, bcm43xx_phy_read(bcm, 0x0802) | 0x0100); - bcm43xx_phy_write(bcm, 0x042B, bcm43xx_phy_read(bcm, 0x042B) | 0x2000); - - bcm43xx_phy_write(bcm, 0x001C, 0x186A); - - bcm43xx_phy_write(bcm, 0x0013, (bcm43xx_phy_read(bcm, 0x0013) & 0x00FF) | 0x1900); - bcm43xx_phy_write(bcm, 0x0035, (bcm43xx_phy_read(bcm, 0x0035) & 0xFFC0) | 0x0064); - bcm43xx_phy_write(bcm, 0x005D, (bcm43xx_phy_read(bcm, 0x005D) & 0xFF80) | 0x000A); - } - - if (bcm->bad_frames_preempt) { - bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD, - bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) | (1 << 11)); - } - - if (phy->analog == 1) { - bcm43xx_phy_write(bcm, 0x0026, 0xCE00); - bcm43xx_phy_write(bcm, 0x0021, 0x3763); - bcm43xx_phy_write(bcm, 0x0022, 0x1BC3); - bcm43xx_phy_write(bcm, 0x0023, 0x06F9); - bcm43xx_phy_write(bcm, 0x0024, 0x037E); - } else - bcm43xx_phy_write(bcm, 0x0026, 0xCC00); - bcm43xx_phy_write(bcm, 0x0030, 0x00C6); - bcm43xx_write16(bcm, 0x03EC, 0x3F22); - - if (phy->analog == 1) - bcm43xx_phy_write(bcm, 0x0020, 0x3E1C); - else - bcm43xx_phy_write(bcm, 0x0020, 0x301C); - - if (phy->analog == 0) - bcm43xx_write16(bcm, 0x03E4, 0x3000); - - old_channel = radio->channel; - /* Force to channel 7, even if not supported. */ - bcm43xx_radio_selectchannel(bcm, 7, 0); - - if (radio->version != 0x2050) { - bcm43xx_radio_write16(bcm, 0x0075, 0x0080); - bcm43xx_radio_write16(bcm, 0x0079, 0x0081); - } - - bcm43xx_radio_write16(bcm, 0x0050, 0x0020); - bcm43xx_radio_write16(bcm, 0x0050, 0x0023); - - if (radio->version == 0x2050) { - bcm43xx_radio_write16(bcm, 0x0050, 0x0020); - bcm43xx_radio_write16(bcm, 0x005A, 0x0070); - } - - bcm43xx_radio_write16(bcm, 0x005B, 0x007B); - bcm43xx_radio_write16(bcm, 0x005C, 0x00B0); - - bcm43xx_radio_write16(bcm, 0x007A, bcm43xx_radio_read16(bcm, 0x007A) | 0x0007); - - bcm43xx_radio_selectchannel(bcm, old_channel, 0); - - bcm43xx_phy_write(bcm, 0x0014, 0x0080); - bcm43xx_phy_write(bcm, 0x0032, 0x00CA); - bcm43xx_phy_write(bcm, 0x002A, 0x88A3); - - bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF); - - if (radio->version == 0x2050) - bcm43xx_radio_write16(bcm, 0x005D, 0x000D); - - bcm43xx_write16(bcm, 0x03E4, (bcm43xx_read16(bcm, 0x03E4) & 0xFFC0) | 0x0004); -} - -static void bcm43xx_phy_initb6(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - u16 offset, val; - u8 old_channel; - - bcm43xx_phy_write(bcm, 0x003E, 0x817A); - bcm43xx_radio_write16(bcm, 0x007A, - (bcm43xx_radio_read16(bcm, 0x007A) | 0x0058)); - if (radio->revision == 4 || - radio->revision == 5) { - bcm43xx_radio_write16(bcm, 0x0051, 0x0037); - bcm43xx_radio_write16(bcm, 0x0052, 0x0070); - bcm43xx_radio_write16(bcm, 0x0053, 0x00B3); - bcm43xx_radio_write16(bcm, 0x0054, 0x009B); - bcm43xx_radio_write16(bcm, 0x005A, 0x0088); - bcm43xx_radio_write16(bcm, 0x005B, 0x0088); - bcm43xx_radio_write16(bcm, 0x005D, 0x0088); - bcm43xx_radio_write16(bcm, 0x005E, 0x0088); - bcm43xx_radio_write16(bcm, 0x007D, 0x0088); - bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, - BCM43xx_UCODEFLAGS_OFFSET, - (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, - BCM43xx_UCODEFLAGS_OFFSET) - | 0x00000200)); - } - if (radio->revision == 8) { - bcm43xx_radio_write16(bcm, 0x0051, 0x0000); - bcm43xx_radio_write16(bcm, 0x0052, 0x0040); - bcm43xx_radio_write16(bcm, 0x0053, 0x00B7); - bcm43xx_radio_write16(bcm, 0x0054, 0x0098); - bcm43xx_radio_write16(bcm, 0x005A, 0x0088); - bcm43xx_radio_write16(bcm, 0x005B, 0x006B); - bcm43xx_radio_write16(bcm, 0x005C, 0x000F); - if (bcm->sprom.boardflags & 0x8000) { - bcm43xx_radio_write16(bcm, 0x005D, 0x00FA); - bcm43xx_radio_write16(bcm, 0x005E, 0x00D8); - } else { - bcm43xx_radio_write16(bcm, 0x005D, 0x00F5); - bcm43xx_radio_write16(bcm, 0x005E, 0x00B8); - } - bcm43xx_radio_write16(bcm, 0x0073, 0x0003); - bcm43xx_radio_write16(bcm, 0x007D, 0x00A8); - bcm43xx_radio_write16(bcm, 0x007C, 0x0001); - bcm43xx_radio_write16(bcm, 0x007E, 0x0008); - } - val = 0x1E1F; - for (offset = 0x0088; offset < 0x0098; offset++) { - bcm43xx_phy_write(bcm, offset, val); - val -= 0x0202; - } - val = 0x3E3F; - for (offset = 0x0098; offset < 0x00A8; offset++) { - bcm43xx_phy_write(bcm, offset, val); - val -= 0x0202; - } - val = 0x2120; - for (offset = 0x00A8; offset < 0x00C8; offset++) { - bcm43xx_phy_write(bcm, offset, (val & 0x3F3F)); - val += 0x0202; - } - if (phy->type == BCM43xx_PHYTYPE_G) { - bcm43xx_radio_write16(bcm, 0x007A, - bcm43xx_radio_read16(bcm, 0x007A) | 0x0020); - bcm43xx_radio_write16(bcm, 0x0051, - bcm43xx_radio_read16(bcm, 0x0051) | 0x0004); - bcm43xx_phy_write(bcm, 0x0802, - bcm43xx_phy_read(bcm, 0x0802) | 0x0100); - bcm43xx_phy_write(bcm, 0x042B, - bcm43xx_phy_read(bcm, 0x042B) | 0x2000); - bcm43xx_phy_write(bcm, 0x5B, 0x0000); - bcm43xx_phy_write(bcm, 0x5C, 0x0000); - } - - old_channel = radio->channel; - if (old_channel >= 8) - bcm43xx_radio_selectchannel(bcm, 1, 0); - else - bcm43xx_radio_selectchannel(bcm, 13, 0); - - bcm43xx_radio_write16(bcm, 0x0050, 0x0020); - bcm43xx_radio_write16(bcm, 0x0050, 0x0023); - udelay(40); - if (radio->revision < 6 || radio-> revision == 8) { - bcm43xx_radio_write16(bcm, 0x007C, (bcm43xx_radio_read16(bcm, 0x007C) - | 0x0002)); - bcm43xx_radio_write16(bcm, 0x0050, 0x0020); - } - if (radio->revision <= 2) { - bcm43xx_radio_write16(bcm, 0x007C, 0x0020); - bcm43xx_radio_write16(bcm, 0x005A, 0x0070); - bcm43xx_radio_write16(bcm, 0x005B, 0x007B); - bcm43xx_radio_write16(bcm, 0x005C, 0x00B0); - } - bcm43xx_radio_write16(bcm, 0x007A, - (bcm43xx_radio_read16(bcm, 0x007A) & 0x00F8) | 0x0007); - - bcm43xx_radio_selectchannel(bcm, old_channel, 0); - - bcm43xx_phy_write(bcm, 0x0014, 0x0200); - if (radio->revision >= 6) - bcm43xx_phy_write(bcm, 0x002A, 0x88C2); - else - bcm43xx_phy_write(bcm, 0x002A, 0x8AC0); - bcm43xx_phy_write(bcm, 0x0038, 0x0668); - bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF); - if (radio->revision <= 5) - bcm43xx_phy_write(bcm, 0x005D, (bcm43xx_phy_read(bcm, 0x005D) - & 0xFF80) | 0x0003); - if (radio->revision <= 2) - bcm43xx_radio_write16(bcm, 0x005D, 0x000D); - - if (phy->analog == 4){ - bcm43xx_write16(bcm, 0x03E4, 0x0009); - bcm43xx_phy_write(bcm, 0x61, bcm43xx_phy_read(bcm, 0x61) & 0xFFF); - } else { - bcm43xx_phy_write(bcm, 0x0002, (bcm43xx_phy_read(bcm, 0x0002) & 0xFFC0) | 0x0004); - } - if (phy->type == BCM43xx_PHYTYPE_G) - bcm43xx_write16(bcm, 0x03E6, 0x0); - if (phy->type == BCM43xx_PHYTYPE_B) { - bcm43xx_write16(bcm, 0x03E6, 0x8140); - bcm43xx_phy_write(bcm, 0x0016, 0x0410); - bcm43xx_phy_write(bcm, 0x0017, 0x0820); - bcm43xx_phy_write(bcm, 0x0062, 0x0007); - bcm43xx_radio_init2050(bcm); - bcm43xx_phy_lo_g_measure(bcm); - if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) { - bcm43xx_calc_nrssi_slope(bcm); - bcm43xx_calc_nrssi_threshold(bcm); - } - bcm43xx_phy_init_pctl(bcm); - } -} - -static void bcm43xx_calc_loopback_gain(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - u16 backup_phy[15] = {0}; - u16 backup_radio[3]; - u16 backup_bband; - u16 i; - u16 loop1_cnt, loop1_done, loop1_omitted; - u16 loop2_done; - - backup_phy[0] = bcm43xx_phy_read(bcm, 0x0429); - backup_phy[1] = bcm43xx_phy_read(bcm, 0x0001); - backup_phy[2] = bcm43xx_phy_read(bcm, 0x0811); - backup_phy[3] = bcm43xx_phy_read(bcm, 0x0812); - if (phy->rev != 1) { - backup_phy[4] = bcm43xx_phy_read(bcm, 0x0814); - backup_phy[5] = bcm43xx_phy_read(bcm, 0x0815); - } - backup_phy[6] = bcm43xx_phy_read(bcm, 0x005A); - backup_phy[7] = bcm43xx_phy_read(bcm, 0x0059); - backup_phy[8] = bcm43xx_phy_read(bcm, 0x0058); - backup_phy[9] = bcm43xx_phy_read(bcm, 0x000A); - backup_phy[10] = bcm43xx_phy_read(bcm, 0x0003); - backup_phy[11] = bcm43xx_phy_read(bcm, 0x080F); - backup_phy[12] = bcm43xx_phy_read(bcm, 0x0810); - backup_phy[13] = bcm43xx_phy_read(bcm, 0x002B); - backup_phy[14] = bcm43xx_phy_read(bcm, 0x0015); - bcm43xx_phy_read(bcm, 0x002D); /* dummy read */ - backup_bband = radio->baseband_atten; - backup_radio[0] = bcm43xx_radio_read16(bcm, 0x0052); - backup_radio[1] = bcm43xx_radio_read16(bcm, 0x0043); - backup_radio[2] = bcm43xx_radio_read16(bcm, 0x007A); - - bcm43xx_phy_write(bcm, 0x0429, - bcm43xx_phy_read(bcm, 0x0429) & 0x3FFF); - bcm43xx_phy_write(bcm, 0x0001, - bcm43xx_phy_read(bcm, 0x0001) & 0x8000); - bcm43xx_phy_write(bcm, 0x0811, - bcm43xx_phy_read(bcm, 0x0811) | 0x0002); - bcm43xx_phy_write(bcm, 0x0812, - bcm43xx_phy_read(bcm, 0x0812) & 0xFFFD); - bcm43xx_phy_write(bcm, 0x0811, - bcm43xx_phy_read(bcm, 0x0811) | 0x0001); - bcm43xx_phy_write(bcm, 0x0812, - bcm43xx_phy_read(bcm, 0x0812) & 0xFFFE); - if (phy->rev != 1) { - bcm43xx_phy_write(bcm, 0x0814, - bcm43xx_phy_read(bcm, 0x0814) | 0x0001); - bcm43xx_phy_write(bcm, 0x0815, - bcm43xx_phy_read(bcm, 0x0815) & 0xFFFE); - bcm43xx_phy_write(bcm, 0x0814, - bcm43xx_phy_read(bcm, 0x0814) | 0x0002); - bcm43xx_phy_write(bcm, 0x0815, - bcm43xx_phy_read(bcm, 0x0815) & 0xFFFD); - } - bcm43xx_phy_write(bcm, 0x0811, - bcm43xx_phy_read(bcm, 0x0811) | 0x000C); - bcm43xx_phy_write(bcm, 0x0812, - bcm43xx_phy_read(bcm, 0x0812) | 0x000C); - - bcm43xx_phy_write(bcm, 0x0811, - (bcm43xx_phy_read(bcm, 0x0811) - & 0xFFCF) | 0x0030); - bcm43xx_phy_write(bcm, 0x0812, - (bcm43xx_phy_read(bcm, 0x0812) - & 0xFFCF) | 0x0010); - - bcm43xx_phy_write(bcm, 0x005A, 0x0780); - bcm43xx_phy_write(bcm, 0x0059, 0xC810); - bcm43xx_phy_write(bcm, 0x0058, 0x000D); - if (phy->analog == 0) { - bcm43xx_phy_write(bcm, 0x0003, 0x0122); - } else { - bcm43xx_phy_write(bcm, 0x000A, - bcm43xx_phy_read(bcm, 0x000A) - | 0x2000); - } - if (phy->rev != 1) { - bcm43xx_phy_write(bcm, 0x0814, - bcm43xx_phy_read(bcm, 0x0814) | 0x0004); - bcm43xx_phy_write(bcm, 0x0815, - bcm43xx_phy_read(bcm, 0x0815) & 0xFFFB); - } - bcm43xx_phy_write(bcm, 0x0003, - (bcm43xx_phy_read(bcm, 0x0003) - & 0xFF9F) | 0x0040); - if (radio->version == 0x2050 && radio->revision == 2) { - bcm43xx_radio_write16(bcm, 0x0052, 0x0000); - bcm43xx_radio_write16(bcm, 0x0043, - (bcm43xx_radio_read16(bcm, 0x0043) - & 0xFFF0) | 0x0009); - loop1_cnt = 9; - } else if (radio->revision == 8) { - bcm43xx_radio_write16(bcm, 0x0043, 0x000F); - loop1_cnt = 15; - } else - loop1_cnt = 0; - - bcm43xx_phy_set_baseband_attenuation(bcm, 11); - - if (phy->rev >= 3) - bcm43xx_phy_write(bcm, 0x080F, 0xC020); - else - bcm43xx_phy_write(bcm, 0x080F, 0x8020); - bcm43xx_phy_write(bcm, 0x0810, 0x0000); - - bcm43xx_phy_write(bcm, 0x002B, - (bcm43xx_phy_read(bcm, 0x002B) - & 0xFFC0) | 0x0001); - bcm43xx_phy_write(bcm, 0x002B, - (bcm43xx_phy_read(bcm, 0x002B) - & 0xC0FF) | 0x0800); - bcm43xx_phy_write(bcm, 0x0811, - bcm43xx_phy_read(bcm, 0x0811) | 0x0100); - bcm43xx_phy_write(bcm, 0x0812, - bcm43xx_phy_read(bcm, 0x0812) & 0xCFFF); - if (bcm->sprom.boardflags & BCM43xx_BFL_EXTLNA) { - if (phy->rev >= 7) { - bcm43xx_phy_write(bcm, 0x0811, - bcm43xx_phy_read(bcm, 0x0811) - | 0x0800); - bcm43xx_phy_write(bcm, 0x0812, - bcm43xx_phy_read(bcm, 0x0812) - | 0x8000); - } - } - bcm43xx_radio_write16(bcm, 0x007A, - bcm43xx_radio_read16(bcm, 0x007A) - & 0x00F7); - - for (i = 0; i < loop1_cnt; i++) { - bcm43xx_radio_write16(bcm, 0x0043, loop1_cnt); - bcm43xx_phy_write(bcm, 0x0812, - (bcm43xx_phy_read(bcm, 0x0812) - & 0xF0FF) | (i << 8)); - bcm43xx_phy_write(bcm, 0x0015, - (bcm43xx_phy_read(bcm, 0x0015) - & 0x0FFF) | 0xA000); - bcm43xx_phy_write(bcm, 0x0015, - (bcm43xx_phy_read(bcm, 0x0015) - & 0x0FFF) | 0xF000); - udelay(20); - if (bcm43xx_phy_read(bcm, 0x002D) >= 0x0DFC) - break; - } - loop1_done = i; - loop1_omitted = loop1_cnt - loop1_done; - - loop2_done = 0; - if (loop1_done >= 8) { - bcm43xx_phy_write(bcm, 0x0812, - bcm43xx_phy_read(bcm, 0x0812) - | 0x0030); - for (i = loop1_done - 8; i < 16; i++) { - bcm43xx_phy_write(bcm, 0x0812, - (bcm43xx_phy_read(bcm, 0x0812) - & 0xF0FF) | (i << 8)); - bcm43xx_phy_write(bcm, 0x0015, - (bcm43xx_phy_read(bcm, 0x0015) - & 0x0FFF) | 0xA000); - bcm43xx_phy_write(bcm, 0x0015, - (bcm43xx_phy_read(bcm, 0x0015) - & 0x0FFF) | 0xF000); - udelay(20); - if (bcm43xx_phy_read(bcm, 0x002D) >= 0x0DFC) - break; - } - } - - if (phy->rev != 1) { - bcm43xx_phy_write(bcm, 0x0814, backup_phy[4]); - bcm43xx_phy_write(bcm, 0x0815, backup_phy[5]); - } - bcm43xx_phy_write(bcm, 0x005A, backup_phy[6]); - bcm43xx_phy_write(bcm, 0x0059, backup_phy[7]); - bcm43xx_phy_write(bcm, 0x0058, backup_phy[8]); - bcm43xx_phy_write(bcm, 0x000A, backup_phy[9]); - bcm43xx_phy_write(bcm, 0x0003, backup_phy[10]); - bcm43xx_phy_write(bcm, 0x080F, backup_phy[11]); - bcm43xx_phy_write(bcm, 0x0810, backup_phy[12]); - bcm43xx_phy_write(bcm, 0x002B, backup_phy[13]); - bcm43xx_phy_write(bcm, 0x0015, backup_phy[14]); - - bcm43xx_phy_set_baseband_attenuation(bcm, backup_bband); - - bcm43xx_radio_write16(bcm, 0x0052, backup_radio[0]); - bcm43xx_radio_write16(bcm, 0x0043, backup_radio[1]); - bcm43xx_radio_write16(bcm, 0x007A, backup_radio[2]); - - bcm43xx_phy_write(bcm, 0x0811, backup_phy[2] | 0x0003); - udelay(10); - bcm43xx_phy_write(bcm, 0x0811, backup_phy[2]); - bcm43xx_phy_write(bcm, 0x0812, backup_phy[3]); - bcm43xx_phy_write(bcm, 0x0429, backup_phy[0]); - bcm43xx_phy_write(bcm, 0x0001, backup_phy[1]); - - phy->loopback_gain[0] = ((loop1_done * 6) - (loop1_omitted * 4)) - 11; - phy->loopback_gain[1] = (24 - (3 * loop2_done)) * 2; -} - -static void bcm43xx_phy_initg(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - u16 tmp; - - if (phy->rev == 1) - bcm43xx_phy_initb5(bcm); - else - bcm43xx_phy_initb6(bcm); - if (phy->rev >= 2 || phy->connected) - bcm43xx_phy_inita(bcm); - - if (phy->rev >= 2) { - bcm43xx_phy_write(bcm, 0x0814, 0x0000); - bcm43xx_phy_write(bcm, 0x0815, 0x0000); - } - if (phy->rev == 2) { - bcm43xx_phy_write(bcm, 0x0811, 0x0000); - bcm43xx_phy_write(bcm, 0x0015, 0x00C0); - } - if (phy->rev > 5) { - bcm43xx_phy_write(bcm, 0x0811, 0x0400); - bcm43xx_phy_write(bcm, 0x0015, 0x00C0); - } - if (phy->rev >= 2 && phy->connected) { - tmp = bcm43xx_phy_read(bcm, 0x0400) & 0xFF; - if (tmp ==3 || tmp == 5) { - bcm43xx_phy_write(bcm, 0x04C2, 0x1816); - bcm43xx_phy_write(bcm, 0x04C3, 0x8006); - if (tmp == 5) { - bcm43xx_phy_write(bcm, 0x04CC, - (bcm43xx_phy_read(bcm, 0x04CC) - & 0x00FF) | 0x1F00); - } - } - bcm43xx_phy_write(bcm, 0x047E, 0x0078); - } - if (radio->revision == 8) { - bcm43xx_phy_write(bcm, 0x0801, bcm43xx_phy_read(bcm, 0x0801) | 0x0080); - bcm43xx_phy_write(bcm, 0x043E, bcm43xx_phy_read(bcm, 0x043E) | 0x0004); - } - if (phy->rev >= 2 && phy->connected) - bcm43xx_calc_loopback_gain(bcm); - if (radio->revision != 8) { - if (radio->initval == 0xFFFF) - radio->initval = bcm43xx_radio_init2050(bcm); - else - bcm43xx_radio_write16(bcm, 0x0078, radio->initval); - } - if (radio->txctl2 == 0xFFFF) { - bcm43xx_phy_lo_g_measure(bcm); - } else { - if (radio->version == 0x2050 && radio->revision == 8) { - bcm43xx_radio_write16(bcm, 0x0052, - (radio->txctl1 << 4) | radio->txctl2); - } else { - bcm43xx_radio_write16(bcm, 0x0052, - (bcm43xx_radio_read16(bcm, 0x0052) - & 0xFFF0) | radio->txctl1); - } - if (phy->rev >= 6) { - bcm43xx_phy_write(bcm, 0x0036, - (bcm43xx_phy_read(bcm, 0x0036) - & 0x0FFF) | (radio->txctl2 << 12)); - } - if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) - bcm43xx_phy_write(bcm, 0x002E, 0x8075); - else - bcm43xx_phy_write(bcm, 0x002E, 0x807F); - if (phy->rev < 2) - bcm43xx_phy_write(bcm, 0x002F, 0x0101); - else - bcm43xx_phy_write(bcm, 0x002F, 0x0202); - } - if (phy->connected || phy->rev >= 2) { - bcm43xx_phy_lo_adjust(bcm, 0); - bcm43xx_phy_write(bcm, 0x080F, 0x8078); - } - - if (!(bcm->sprom.boardflags & BCM43xx_BFL_RSSI)) { - /* The specs state to update the NRSSI LT with - * the value 0x7FFFFFFF here. I think that is some weird - * compiler optimization in the original driver. - * Essentially, what we do here is resetting all NRSSI LT - * entries to -32 (see the limit_value() in nrssi_hw_update()) - */ - bcm43xx_nrssi_hw_update(bcm, 0xFFFF); - bcm43xx_calc_nrssi_threshold(bcm); - } else if (phy->connected || phy->rev >= 2) { - if (radio->nrssi[0] == -1000) { - assert(radio->nrssi[1] == -1000); - bcm43xx_calc_nrssi_slope(bcm); - } else { - assert(radio->nrssi[1] != -1000); - bcm43xx_calc_nrssi_threshold(bcm); - } - } - if (radio->revision == 8) - bcm43xx_phy_write(bcm, 0x0805, 0x3230); - bcm43xx_phy_init_pctl(bcm); - if (bcm->chip_id == 0x4306 && bcm->chip_package == 2) { - bcm43xx_phy_write(bcm, 0x0429, - bcm43xx_phy_read(bcm, 0x0429) & 0xBFFF); - bcm43xx_phy_write(bcm, 0x04C3, - bcm43xx_phy_read(bcm, 0x04C3) & 0x7FFF); - } -} - -static u16 bcm43xx_phy_lo_b_r15_loop(struct bcm43xx_private *bcm) -{ - int i; - u16 ret = 0; - unsigned long flags; - - local_irq_save(flags); - for (i = 0; i < 10; i++){ - bcm43xx_phy_write(bcm, 0x0015, 0xAFA0); - udelay(1); - bcm43xx_phy_write(bcm, 0x0015, 0xEFA0); - udelay(10); - bcm43xx_phy_write(bcm, 0x0015, 0xFFA0); - udelay(40); - ret += bcm43xx_phy_read(bcm, 0x002C); - } - local_irq_restore(flags); - bcm43xx_voluntary_preempt(); - - return ret; -} - -void bcm43xx_phy_lo_b_measure(struct bcm43xx_private *bcm) -{ - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - u16 regstack[12] = { 0 }; - u16 mls; - u16 fval; - int i, j; - - regstack[0] = bcm43xx_phy_read(bcm, 0x0015); - regstack[1] = bcm43xx_radio_read16(bcm, 0x0052) & 0xFFF0; - - if (radio->version == 0x2053) { - regstack[2] = bcm43xx_phy_read(bcm, 0x000A); - regstack[3] = bcm43xx_phy_read(bcm, 0x002A); - regstack[4] = bcm43xx_phy_read(bcm, 0x0035); - regstack[5] = bcm43xx_phy_read(bcm, 0x0003); - regstack[6] = bcm43xx_phy_read(bcm, 0x0001); - regstack[7] = bcm43xx_phy_read(bcm, 0x0030); - - regstack[8] = bcm43xx_radio_read16(bcm, 0x0043); - regstack[9] = bcm43xx_radio_read16(bcm, 0x007A); - regstack[10] = bcm43xx_read16(bcm, 0x03EC); - regstack[11] = bcm43xx_radio_read16(bcm, 0x0052) & 0x00F0; - - bcm43xx_phy_write(bcm, 0x0030, 0x00FF); - bcm43xx_write16(bcm, 0x03EC, 0x3F3F); - bcm43xx_phy_write(bcm, 0x0035, regstack[4] & 0xFF7F); - bcm43xx_radio_write16(bcm, 0x007A, regstack[9] & 0xFFF0); - } - bcm43xx_phy_write(bcm, 0x0015, 0xB000); - bcm43xx_phy_write(bcm, 0x002B, 0x0004); - - if (radio->version == 0x2053) { - bcm43xx_phy_write(bcm, 0x002B, 0x0203); - bcm43xx_phy_write(bcm, 0x002A, 0x08A3); - } - - phy->minlowsig[0] = 0xFFFF; - - for (i = 0; i < 4; i++) { - bcm43xx_radio_write16(bcm, 0x0052, regstack[1] | i); - bcm43xx_phy_lo_b_r15_loop(bcm); - } - for (i = 0; i < 10; i++) { - bcm43xx_radio_write16(bcm, 0x0052, regstack[1] | i); - mls = bcm43xx_phy_lo_b_r15_loop(bcm) / 10; - if (mls < phy->minlowsig[0]) { - phy->minlowsig[0] = mls; - phy->minlowsigpos[0] = i; - } - } - bcm43xx_radio_write16(bcm, 0x0052, regstack[1] | phy->minlowsigpos[0]); - - phy->minlowsig[1] = 0xFFFF; - - for (i = -4; i < 5; i += 2) { - for (j = -4; j < 5; j += 2) { - if (j < 0) - fval = (0x0100 * i) + j + 0x0100; - else - fval = (0x0100 * i) + j; - bcm43xx_phy_write(bcm, 0x002F, fval); - mls = bcm43xx_phy_lo_b_r15_loop(bcm) / 10; - if (mls < phy->minlowsig[1]) { - phy->minlowsig[1] = mls; - phy->minlowsigpos[1] = fval; - } - } - } - phy->minlowsigpos[1] += 0x0101; - - bcm43xx_phy_write(bcm, 0x002F, phy->minlowsigpos[1]); - if (radio->version == 0x2053) { - bcm43xx_phy_write(bcm, 0x000A, regstack[2]); - bcm43xx_phy_write(bcm, 0x002A, regstack[3]); - bcm43xx_phy_write(bcm, 0x0035, regstack[4]); - bcm43xx_phy_write(bcm, 0x0003, regstack[5]); - bcm43xx_phy_write(bcm, 0x0001, regstack[6]); - bcm43xx_phy_write(bcm, 0x0030, regstack[7]); - - bcm43xx_radio_write16(bcm, 0x0043, regstack[8]); - bcm43xx_radio_write16(bcm, 0x007A, regstack[9]); - - bcm43xx_radio_write16(bcm, 0x0052, - (bcm43xx_radio_read16(bcm, 0x0052) & 0x000F) - | regstack[11]); - - bcm43xx_write16(bcm, 0x03EC, regstack[10]); - } - bcm43xx_phy_write(bcm, 0x0015, regstack[0]); -} - -static inline -u16 bcm43xx_phy_lo_g_deviation_subval(struct bcm43xx_private *bcm, u16 control) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - u16 ret; - unsigned long flags; - - local_irq_save(flags); - if (phy->connected) { - bcm43xx_phy_write(bcm, 0x15, 0xE300); - control <<= 8; - bcm43xx_phy_write(bcm, 0x0812, control | 0x00B0); - udelay(5); - bcm43xx_phy_write(bcm, 0x0812, control | 0x00B2); - udelay(2); - bcm43xx_phy_write(bcm, 0x0812, control | 0x00B3); - udelay(4); - bcm43xx_phy_write(bcm, 0x0015, 0xF300); - udelay(8); - } else { - bcm43xx_phy_write(bcm, 0x0015, control | 0xEFA0); - udelay(2); - bcm43xx_phy_write(bcm, 0x0015, control | 0xEFE0); - udelay(4); - bcm43xx_phy_write(bcm, 0x0015, control | 0xFFE0); - udelay(8); - } - ret = bcm43xx_phy_read(bcm, 0x002D); - local_irq_restore(flags); - bcm43xx_voluntary_preempt(); - - return ret; -} - -static u32 bcm43xx_phy_lo_g_singledeviation(struct bcm43xx_private *bcm, u16 control) -{ - int i; - u32 ret = 0; - - for (i = 0; i < 8; i++) - ret += bcm43xx_phy_lo_g_deviation_subval(bcm, control); - - return ret; -} - -/* Write the LocalOscillator CONTROL */ -static inline -void bcm43xx_lo_write(struct bcm43xx_private *bcm, - struct bcm43xx_lopair *pair) -{ - u16 value; - - value = (u8)(pair->low); - value |= ((u8)(pair->high)) << 8; - -#ifdef CONFIG_BCM43XX_DEBUG - /* Sanity check. */ - if (pair->low < -8 || pair->low > 8 || - pair->high < -8 || pair->high > 8) { - printk(KERN_WARNING PFX - "WARNING: Writing invalid LOpair " - "(low: %d, high: %d, index: %lu)\n", - pair->low, pair->high, - (unsigned long)(pair - bcm43xx_current_phy(bcm)->_lo_pairs)); - dump_stack(); - } -#endif - - bcm43xx_phy_write(bcm, BCM43xx_PHY_G_LO_CONTROL, value); -} - -static inline -struct bcm43xx_lopair * bcm43xx_find_lopair(struct bcm43xx_private *bcm, - u16 baseband_attenuation, - u16 radio_attenuation, - u16 tx) -{ - static const u8 dict[10] = { 11, 10, 11, 12, 13, 12, 13, 12, 13, 12 }; - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - - if (baseband_attenuation > 6) - baseband_attenuation = 6; - assert(radio_attenuation < 10); - - if (tx == 3) { - return bcm43xx_get_lopair(phy, - radio_attenuation, - baseband_attenuation); - } - return bcm43xx_get_lopair(phy, dict[radio_attenuation], baseband_attenuation); -} - -static inline -struct bcm43xx_lopair * bcm43xx_current_lopair(struct bcm43xx_private *bcm) -{ - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - - return bcm43xx_find_lopair(bcm, - radio->baseband_atten, - radio->radio_atten, - radio->txctl1); -} - -/* Adjust B/G LO */ -void bcm43xx_phy_lo_adjust(struct bcm43xx_private *bcm, int fixed) -{ - struct bcm43xx_lopair *pair; - - if (fixed) { - /* Use fixed values. Only for initialization. */ - pair = bcm43xx_find_lopair(bcm, 2, 3, 0); - } else - pair = bcm43xx_current_lopair(bcm); - bcm43xx_lo_write(bcm, pair); -} - -static void bcm43xx_phy_lo_g_measure_txctl2(struct bcm43xx_private *bcm) -{ - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - u16 txctl2 = 0, i; - u32 smallest, tmp; - - bcm43xx_radio_write16(bcm, 0x0052, 0x0000); - udelay(10); - smallest = bcm43xx_phy_lo_g_singledeviation(bcm, 0); - for (i = 0; i < 16; i++) { - bcm43xx_radio_write16(bcm, 0x0052, i); - udelay(10); - tmp = bcm43xx_phy_lo_g_singledeviation(bcm, 0); - if (tmp < smallest) { - smallest = tmp; - txctl2 = i; - } - } - radio->txctl2 = txctl2; -} - -static -void bcm43xx_phy_lo_g_state(struct bcm43xx_private *bcm, - const struct bcm43xx_lopair *in_pair, - struct bcm43xx_lopair *out_pair, - u16 r27) -{ - static const struct bcm43xx_lopair transitions[8] = { - { .high = 1, .low = 1, }, - { .high = 1, .low = 0, }, - { .high = 1, .low = -1, }, - { .high = 0, .low = -1, }, - { .high = -1, .low = -1, }, - { .high = -1, .low = 0, }, - { .high = -1, .low = 1, }, - { .high = 0, .low = 1, }, - }; - struct bcm43xx_lopair lowest_transition = { - .high = in_pair->high, - .low = in_pair->low, - }; - struct bcm43xx_lopair tmp_pair; - struct bcm43xx_lopair transition; - int i = 12; - int state = 0; - int found_lower; - int j, begin, end; - u32 lowest_deviation; - u32 tmp; - - /* Note that in_pair and out_pair can point to the same pair. Be careful. */ - - bcm43xx_lo_write(bcm, &lowest_transition); - lowest_deviation = bcm43xx_phy_lo_g_singledeviation(bcm, r27); - do { - found_lower = 0; - assert(state >= 0 && state <= 8); - if (state == 0) { - begin = 1; - end = 8; - } else if (state % 2 == 0) { - begin = state - 1; - end = state + 1; - } else { - begin = state - 2; - end = state + 2; - } - if (begin < 1) - begin += 8; - if (end > 8) - end -= 8; - - j = begin; - tmp_pair.high = lowest_transition.high; - tmp_pair.low = lowest_transition.low; - while (1) { - assert(j >= 1 && j <= 8); - transition.high = tmp_pair.high + transitions[j - 1].high; - transition.low = tmp_pair.low + transitions[j - 1].low; - if ((abs(transition.low) < 9) && (abs(transition.high) < 9)) { - bcm43xx_lo_write(bcm, &transition); - tmp = bcm43xx_phy_lo_g_singledeviation(bcm, r27); - if (tmp < lowest_deviation) { - lowest_deviation = tmp; - state = j; - found_lower = 1; - - lowest_transition.high = transition.high; - lowest_transition.low = transition.low; - } - } - if (j == end) - break; - if (j == 8) - j = 1; - else - j++; - } - } while (i-- && found_lower); - - out_pair->high = lowest_transition.high; - out_pair->low = lowest_transition.low; -} - -/* Set the baseband attenuation value on chip. */ -void bcm43xx_phy_set_baseband_attenuation(struct bcm43xx_private *bcm, - u16 baseband_attenuation) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - u16 value; - - if (phy->analog == 0) { - value = (bcm43xx_read16(bcm, 0x03E6) & 0xFFF0); - value |= (baseband_attenuation & 0x000F); - bcm43xx_write16(bcm, 0x03E6, value); - return; - } - - if (phy->analog > 1) { - value = bcm43xx_phy_read(bcm, 0x0060) & ~0x003C; - value |= (baseband_attenuation << 2) & 0x003C; - } else { - value = bcm43xx_phy_read(bcm, 0x0060) & ~0x0078; - value |= (baseband_attenuation << 3) & 0x0078; - } - bcm43xx_phy_write(bcm, 0x0060, value); -} - -/* http://bcm-specs.sipsolutions.net/LocalOscillator/Measure */ -void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm) -{ - static const u8 pairorder[10] = { 3, 1, 5, 7, 9, 2, 0, 4, 6, 8 }; - const int is_initializing = (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZING); - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - u16 h, i, oldi = 0, j; - struct bcm43xx_lopair control; - struct bcm43xx_lopair *tmp_control; - u16 tmp; - u16 regstack[16] = { 0 }; - u8 oldchannel; - - //XXX: What are these? - u8 r27 = 0, r31; - - oldchannel = radio->channel; - /* Setup */ - if (phy->connected) { - regstack[0] = bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS); - regstack[1] = bcm43xx_phy_read(bcm, 0x0802); - bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, regstack[0] & 0x7FFF); - bcm43xx_phy_write(bcm, 0x0802, regstack[1] & 0xFFFC); - } - regstack[3] = bcm43xx_read16(bcm, 0x03E2); - bcm43xx_write16(bcm, 0x03E2, regstack[3] | 0x8000); - regstack[4] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT); - regstack[5] = bcm43xx_phy_read(bcm, 0x15); - regstack[6] = bcm43xx_phy_read(bcm, 0x2A); - regstack[7] = bcm43xx_phy_read(bcm, 0x35); - regstack[8] = bcm43xx_phy_read(bcm, 0x60); - regstack[9] = bcm43xx_radio_read16(bcm, 0x43); - regstack[10] = bcm43xx_radio_read16(bcm, 0x7A); - regstack[11] = bcm43xx_radio_read16(bcm, 0x52); - if (phy->connected) { - regstack[12] = bcm43xx_phy_read(bcm, 0x0811); - regstack[13] = bcm43xx_phy_read(bcm, 0x0812); - regstack[14] = bcm43xx_phy_read(bcm, 0x0814); - regstack[15] = bcm43xx_phy_read(bcm, 0x0815); - } - bcm43xx_radio_selectchannel(bcm, 6, 0); - if (phy->connected) { - bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, regstack[0] & 0x7FFF); - bcm43xx_phy_write(bcm, 0x0802, regstack[1] & 0xFFFC); - bcm43xx_dummy_transmission(bcm); - } - bcm43xx_radio_write16(bcm, 0x0043, 0x0006); - - bcm43xx_phy_set_baseband_attenuation(bcm, 2); - - bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, 0x0000); - bcm43xx_phy_write(bcm, 0x002E, 0x007F); - bcm43xx_phy_write(bcm, 0x080F, 0x0078); - bcm43xx_phy_write(bcm, 0x0035, regstack[7] & ~(1 << 7)); - bcm43xx_radio_write16(bcm, 0x007A, regstack[10] & 0xFFF0); - bcm43xx_phy_write(bcm, 0x002B, 0x0203); - bcm43xx_phy_write(bcm, 0x002A, 0x08A3); - if (phy->connected) { - bcm43xx_phy_write(bcm, 0x0814, regstack[14] | 0x0003); - bcm43xx_phy_write(bcm, 0x0815, regstack[15] & 0xFFFC); - bcm43xx_phy_write(bcm, 0x0811, 0x01B3); - bcm43xx_phy_write(bcm, 0x0812, 0x00B2); - } - if (is_initializing) - bcm43xx_phy_lo_g_measure_txctl2(bcm); - bcm43xx_phy_write(bcm, 0x080F, 0x8078); - - /* Measure */ - control.low = 0; - control.high = 0; - for (h = 0; h < 10; h++) { - /* Loop over each possible RadioAttenuation (0-9) */ - i = pairorder[h]; - if (is_initializing) { - if (i == 3) { - control.low = 0; - control.high = 0; - } else if (((i % 2 == 1) && (oldi % 2 == 1)) || - ((i % 2 == 0) && (oldi % 2 == 0))) { - tmp_control = bcm43xx_get_lopair(phy, oldi, 0); - memcpy(&control, tmp_control, sizeof(control)); - } else { - tmp_control = bcm43xx_get_lopair(phy, 3, 0); - memcpy(&control, tmp_control, sizeof(control)); - } - } - /* Loop over each possible BasebandAttenuation/2 */ - for (j = 0; j < 4; j++) { - if (is_initializing) { - tmp = i * 2 + j; - r27 = 0; - r31 = 0; - if (tmp > 14) { - r31 = 1; - if (tmp > 17) - r27 = 1; - if (tmp > 19) - r27 = 2; - } - } else { - tmp_control = bcm43xx_get_lopair(phy, i, j * 2); - if (!tmp_control->used) - continue; - memcpy(&control, tmp_control, sizeof(control)); - r27 = 3; - r31 = 0; - } - bcm43xx_radio_write16(bcm, 0x43, i); - bcm43xx_radio_write16(bcm, 0x52, radio->txctl2); - udelay(10); - bcm43xx_voluntary_preempt(); - - bcm43xx_phy_set_baseband_attenuation(bcm, j * 2); - - tmp = (regstack[10] & 0xFFF0); - if (r31) - tmp |= 0x0008; - bcm43xx_radio_write16(bcm, 0x007A, tmp); - - tmp_control = bcm43xx_get_lopair(phy, i, j * 2); - bcm43xx_phy_lo_g_state(bcm, &control, tmp_control, r27); - } - oldi = i; - } - /* Loop over each possible RadioAttenuation (10-13) */ - for (i = 10; i < 14; i++) { - /* Loop over each possible BasebandAttenuation/2 */ - for (j = 0; j < 4; j++) { - if (is_initializing) { - tmp_control = bcm43xx_get_lopair(phy, i - 9, j * 2); - memcpy(&control, tmp_control, sizeof(control)); - tmp = (i - 9) * 2 + j - 5;//FIXME: This is wrong, as the following if statement can never trigger. - r27 = 0; - r31 = 0; - if (tmp > 14) { - r31 = 1; - if (tmp > 17) - r27 = 1; - if (tmp > 19) - r27 = 2; - } - } else { - tmp_control = bcm43xx_get_lopair(phy, i - 9, j * 2); - if (!tmp_control->used) - continue; - memcpy(&control, tmp_control, sizeof(control)); - r27 = 3; - r31 = 0; - } - bcm43xx_radio_write16(bcm, 0x43, i - 9); - bcm43xx_radio_write16(bcm, 0x52, - radio->txctl2 - | (3/*txctl1*/ << 4));//FIXME: shouldn't txctl1 be zero here and 3 in the loop above? - udelay(10); - bcm43xx_voluntary_preempt(); - - bcm43xx_phy_set_baseband_attenuation(bcm, j * 2); - - tmp = (regstack[10] & 0xFFF0); - if (r31) - tmp |= 0x0008; - bcm43xx_radio_write16(bcm, 0x7A, tmp); - - tmp_control = bcm43xx_get_lopair(phy, i, j * 2); - bcm43xx_phy_lo_g_state(bcm, &control, tmp_control, r27); - } - } - - /* Restoration */ - if (phy->connected) { - bcm43xx_phy_write(bcm, 0x0015, 0xE300); - bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA0); - udelay(5); - bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA2); - udelay(2); - bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA3); - bcm43xx_voluntary_preempt(); - } else - bcm43xx_phy_write(bcm, 0x0015, r27 | 0xEFA0); - bcm43xx_phy_lo_adjust(bcm, is_initializing); - bcm43xx_phy_write(bcm, 0x002E, 0x807F); - if (phy->connected) - bcm43xx_phy_write(bcm, 0x002F, 0x0202); - else - bcm43xx_phy_write(bcm, 0x002F, 0x0101); - bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, regstack[4]); - bcm43xx_phy_write(bcm, 0x0015, regstack[5]); - bcm43xx_phy_write(bcm, 0x002A, regstack[6]); - bcm43xx_phy_write(bcm, 0x0035, regstack[7]); - bcm43xx_phy_write(bcm, 0x0060, regstack[8]); - bcm43xx_radio_write16(bcm, 0x0043, regstack[9]); - bcm43xx_radio_write16(bcm, 0x007A, regstack[10]); - regstack[11] &= 0x00F0; - regstack[11] |= (bcm43xx_radio_read16(bcm, 0x52) & 0x000F); - bcm43xx_radio_write16(bcm, 0x52, regstack[11]); - bcm43xx_write16(bcm, 0x03E2, regstack[3]); - if (phy->connected) { - bcm43xx_phy_write(bcm, 0x0811, regstack[12]); - bcm43xx_phy_write(bcm, 0x0812, regstack[13]); - bcm43xx_phy_write(bcm, 0x0814, regstack[14]); - bcm43xx_phy_write(bcm, 0x0815, regstack[15]); - bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, regstack[0]); - bcm43xx_phy_write(bcm, 0x0802, regstack[1]); - } - bcm43xx_radio_selectchannel(bcm, oldchannel, 1); - -#ifdef CONFIG_BCM43XX_DEBUG - { - /* Sanity check for all lopairs. */ - for (i = 0; i < BCM43xx_LO_COUNT; i++) { - tmp_control = phy->_lo_pairs + i; - if (tmp_control->low < -8 || tmp_control->low > 8 || - tmp_control->high < -8 || tmp_control->high > 8) { - printk(KERN_WARNING PFX - "WARNING: Invalid LOpair (low: %d, high: %d, index: %d)\n", - tmp_control->low, tmp_control->high, i); - } - } - } -#endif /* CONFIG_BCM43XX_DEBUG */ -} - -static -void bcm43xx_phy_lo_mark_current_used(struct bcm43xx_private *bcm) -{ - struct bcm43xx_lopair *pair; - - pair = bcm43xx_current_lopair(bcm); - pair->used = 1; -} - -void bcm43xx_phy_lo_mark_all_unused(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - struct bcm43xx_lopair *pair; - int i; - - for (i = 0; i < BCM43xx_LO_COUNT; i++) { - pair = phy->_lo_pairs + i; - pair->used = 0; - } -} - -/* http://bcm-specs.sipsolutions.net/EstimatePowerOut - * This function converts a TSSI value to dBm in Q5.2 - */ -static s8 bcm43xx_phy_estimate_power_out(struct bcm43xx_private *bcm, s8 tssi) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - s8 dbm = 0; - s32 tmp; - - tmp = phy->idle_tssi; - tmp += tssi; - tmp -= phy->savedpctlreg; - - switch (phy->type) { - case BCM43xx_PHYTYPE_A: - tmp += 0x80; - tmp = limit_value(tmp, 0x00, 0xFF); - dbm = phy->tssi2dbm[tmp]; - TODO(); //TODO: There's a FIXME on the specs - break; - case BCM43xx_PHYTYPE_B: - case BCM43xx_PHYTYPE_G: - tmp = limit_value(tmp, 0x00, 0x3F); - dbm = phy->tssi2dbm[tmp]; - break; - default: - assert(0); - } - - return dbm; -} - -/* http://bcm-specs.sipsolutions.net/RecalculateTransmissionPower */ -void bcm43xx_phy_xmitpower(struct bcm43xx_private *bcm) -{ - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - - if (phy->savedpctlreg == 0xFFFF) - return; - if ((bcm->board_type == 0x0416) && - (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM)) - return; - - switch (phy->type) { - case BCM43xx_PHYTYPE_A: { - - TODO(); //TODO: Nothing for A PHYs yet :-/ - - break; - } - case BCM43xx_PHYTYPE_B: - case BCM43xx_PHYTYPE_G: { - u16 tmp; - u16 txpower; - s8 v0, v1, v2, v3; - s8 average; - u8 max_pwr; - s16 desired_pwr, estimated_pwr, pwr_adjust; - s16 radio_att_delta, baseband_att_delta; - s16 radio_attenuation, baseband_attenuation; - unsigned long phylock_flags; - - tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0058); - v0 = (s8)(tmp & 0x00FF); - v1 = (s8)((tmp & 0xFF00) >> 8); - tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x005A); - v2 = (s8)(tmp & 0x00FF); - v3 = (s8)((tmp & 0xFF00) >> 8); - tmp = 0; - - if (v0 == 0x7F || v1 == 0x7F || v2 == 0x7F || v3 == 0x7F) { - tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0070); - v0 = (s8)(tmp & 0x00FF); - v1 = (s8)((tmp & 0xFF00) >> 8); - tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0072); - v2 = (s8)(tmp & 0x00FF); - v3 = (s8)((tmp & 0xFF00) >> 8); - if (v0 == 0x7F || v1 == 0x7F || v2 == 0x7F || v3 == 0x7F) - return; - v0 = (v0 + 0x20) & 0x3F; - v1 = (v1 + 0x20) & 0x3F; - v2 = (v2 + 0x20) & 0x3F; - v3 = (v3 + 0x20) & 0x3F; - tmp = 1; - } - bcm43xx_radio_clear_tssi(bcm); - - average = (v0 + v1 + v2 + v3 + 2) / 4; - - if (tmp && (bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x005E) & 0x8)) - average -= 13; - - estimated_pwr = bcm43xx_phy_estimate_power_out(bcm, average); - - max_pwr = bcm->sprom.maxpower_bgphy; - - if ((bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) && - (phy->type == BCM43xx_PHYTYPE_G)) - max_pwr -= 0x3; - - /*TODO: - max_pwr = min(REG - bcm->sprom.antennagain_bgphy - 0x6, max_pwr) - where REG is the max power as per the regulatory domain - */ - - desired_pwr = limit_value(radio->txpower_desired, 0, max_pwr); - /* Check if we need to adjust the current power. */ - pwr_adjust = desired_pwr - estimated_pwr; - radio_att_delta = -(pwr_adjust + 7) >> 3; - baseband_att_delta = -(pwr_adjust >> 1) - (4 * radio_att_delta); - if ((radio_att_delta == 0) && (baseband_att_delta == 0)) { - bcm43xx_phy_lo_mark_current_used(bcm); - return; - } - - /* Calculate the new attenuation values. */ - baseband_attenuation = radio->baseband_atten; - baseband_attenuation += baseband_att_delta; - radio_attenuation = radio->radio_atten; - radio_attenuation += radio_att_delta; - - /* Get baseband and radio attenuation values into their permitted ranges. - * baseband 0-11, radio 0-9. - * Radio attenuation affects power level 4 times as much as baseband. - */ - if (radio_attenuation < 0) { - baseband_attenuation -= (4 * -radio_attenuation); - radio_attenuation = 0; - } else if (radio_attenuation > 9) { - baseband_attenuation += (4 * (radio_attenuation - 9)); - radio_attenuation = 9; - } else { - while (baseband_attenuation < 0 && radio_attenuation > 0) { - baseband_attenuation += 4; - radio_attenuation--; - } - while (baseband_attenuation > 11 && radio_attenuation < 9) { - baseband_attenuation -= 4; - radio_attenuation++; - } - } - baseband_attenuation = limit_value(baseband_attenuation, 0, 11); - - txpower = radio->txctl1; - if ((radio->version == 0x2050) && (radio->revision == 2)) { - if (radio_attenuation <= 1) { - if (txpower == 0) { - txpower = 3; - radio_attenuation += 2; - baseband_attenuation += 2; - } else if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) { - baseband_attenuation += 4 * (radio_attenuation - 2); - radio_attenuation = 2; - } - } else if (radio_attenuation > 4 && txpower != 0) { - txpower = 0; - if (baseband_attenuation < 3) { - radio_attenuation -= 3; - baseband_attenuation += 2; - } else { - radio_attenuation -= 2; - baseband_attenuation -= 2; - } - } - } - radio->txctl1 = txpower; - baseband_attenuation = limit_value(baseband_attenuation, 0, 11); - radio_attenuation = limit_value(radio_attenuation, 0, 9); - - bcm43xx_phy_lock(bcm, phylock_flags); - bcm43xx_radio_lock(bcm); - bcm43xx_radio_set_txpower_bg(bcm, baseband_attenuation, - radio_attenuation, txpower); - bcm43xx_phy_lo_mark_current_used(bcm); - bcm43xx_radio_unlock(bcm); - bcm43xx_phy_unlock(bcm, phylock_flags); - break; - } - default: - assert(0); - } -} - -static inline -s32 bcm43xx_tssi2dbm_ad(s32 num, s32 den) -{ - if (num < 0) - return num/den; - else - return (num+den/2)/den; -} - -static inline -s8 bcm43xx_tssi2dbm_entry(s8 entry [], u8 index, s16 pab0, s16 pab1, s16 pab2) -{ - s32 m1, m2, f = 256, q, delta; - s8 i = 0; - - m1 = bcm43xx_tssi2dbm_ad(16 * pab0 + index * pab1, 32); - m2 = max(bcm43xx_tssi2dbm_ad(32768 + index * pab2, 256), 1); - do { - if (i > 15) - return -EINVAL; - q = bcm43xx_tssi2dbm_ad(f * 4096 - - bcm43xx_tssi2dbm_ad(m2 * f, 16) * f, 2048); - delta = abs(q - f); - f = q; - i++; - } while (delta >= 2); - entry[index] = limit_value(bcm43xx_tssi2dbm_ad(m1 * f, 8192), -127, 128); - return 0; -} - -/* http://bcm-specs.sipsolutions.net/TSSI_to_DBM_Table */ -int bcm43xx_phy_init_tssi2dbm_table(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - s16 pab0, pab1, pab2; - u8 idx; - s8 *dyn_tssi2dbm; - - if (phy->type == BCM43xx_PHYTYPE_A) { - pab0 = (s16)(bcm->sprom.pa1b0); - pab1 = (s16)(bcm->sprom.pa1b1); - pab2 = (s16)(bcm->sprom.pa1b2); - } else { - pab0 = (s16)(bcm->sprom.pa0b0); - pab1 = (s16)(bcm->sprom.pa0b1); - pab2 = (s16)(bcm->sprom.pa0b2); - } - - if ((bcm->chip_id == 0x4301) && (radio->version != 0x2050)) { - phy->idle_tssi = 0x34; - phy->tssi2dbm = bcm43xx_tssi2dbm_b_table; - return 0; - } - - if (pab0 != 0 && pab1 != 0 && pab2 != 0 && - pab0 != -1 && pab1 != -1 && pab2 != -1) { - /* The pabX values are set in SPROM. Use them. */ - if (phy->type == BCM43xx_PHYTYPE_A) { - if ((s8)bcm->sprom.idle_tssi_tgt_aphy != 0 && - (s8)bcm->sprom.idle_tssi_tgt_aphy != -1) - phy->idle_tssi = (s8)(bcm->sprom.idle_tssi_tgt_aphy); - else - phy->idle_tssi = 62; - } else { - if ((s8)bcm->sprom.idle_tssi_tgt_bgphy != 0 && - (s8)bcm->sprom.idle_tssi_tgt_bgphy != -1) - phy->idle_tssi = (s8)(bcm->sprom.idle_tssi_tgt_bgphy); - else - phy->idle_tssi = 62; - } - dyn_tssi2dbm = kmalloc(64, GFP_KERNEL); - if (dyn_tssi2dbm == NULL) { - printk(KERN_ERR PFX "Could not allocate memory " - "for tssi2dbm table\n"); - return -ENOMEM; - } - for (idx = 0; idx < 64; idx++) - if (bcm43xx_tssi2dbm_entry(dyn_tssi2dbm, idx, pab0, pab1, pab2)) { - phy->tssi2dbm = NULL; - printk(KERN_ERR PFX "Could not generate " - "tssi2dBm table\n"); - kfree(dyn_tssi2dbm); - return -ENODEV; - } - phy->tssi2dbm = dyn_tssi2dbm; - phy->dyn_tssi_tbl = 1; - } else { - /* pabX values not set in SPROM. */ - switch (phy->type) { - case BCM43xx_PHYTYPE_A: - /* APHY needs a generated table. */ - phy->tssi2dbm = NULL; - printk(KERN_ERR PFX "Could not generate tssi2dBm " - "table (wrong SPROM info)!\n"); - return -ENODEV; - case BCM43xx_PHYTYPE_B: - phy->idle_tssi = 0x34; - phy->tssi2dbm = bcm43xx_tssi2dbm_b_table; - break; - case BCM43xx_PHYTYPE_G: - phy->idle_tssi = 0x34; - phy->tssi2dbm = bcm43xx_tssi2dbm_g_table; - break; - } - } - - return 0; -} - -int bcm43xx_phy_init(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - int err = -ENODEV; - - switch (phy->type) { - case BCM43xx_PHYTYPE_A: - if (phy->rev == 2 || phy->rev == 3) { - bcm43xx_phy_inita(bcm); - err = 0; - } - break; - case BCM43xx_PHYTYPE_B: - switch (phy->rev) { - case 2: - bcm43xx_phy_initb2(bcm); - err = 0; - break; - case 4: - bcm43xx_phy_initb4(bcm); - err = 0; - break; - case 5: - bcm43xx_phy_initb5(bcm); - err = 0; - break; - case 6: - bcm43xx_phy_initb6(bcm); - err = 0; - break; - } - break; - case BCM43xx_PHYTYPE_G: - bcm43xx_phy_initg(bcm); - err = 0; - break; - } - if (err) - printk(KERN_WARNING PFX "Unknown PHYTYPE found!\n"); - - return err; -} - -void bcm43xx_phy_set_antenna_diversity(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - u16 antennadiv; - u16 offset; - u16 value; - u32 ucodeflags; - - antennadiv = phy->antenna_diversity; - - if (antennadiv == 0xFFFF) - antennadiv = 3; - assert(antennadiv <= 3); - - ucodeflags = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, - BCM43xx_UCODEFLAGS_OFFSET); - bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, - BCM43xx_UCODEFLAGS_OFFSET, - ucodeflags & ~BCM43xx_UCODEFLAG_AUTODIV); - - switch (phy->type) { - case BCM43xx_PHYTYPE_A: - case BCM43xx_PHYTYPE_G: - if (phy->type == BCM43xx_PHYTYPE_A) - offset = 0x0000; - else - offset = 0x0400; - - if (antennadiv == 2) - value = (3/*automatic*/ << 7); - else - value = (antennadiv << 7); - bcm43xx_phy_write(bcm, offset + 1, - (bcm43xx_phy_read(bcm, offset + 1) - & 0x7E7F) | value); - - if (antennadiv >= 2) { - if (antennadiv == 2) - value = (antennadiv << 7); - else - value = (0/*force0*/ << 7); - bcm43xx_phy_write(bcm, offset + 0x2B, - (bcm43xx_phy_read(bcm, offset + 0x2B) - & 0xFEFF) | value); - } - - if (phy->type == BCM43xx_PHYTYPE_G) { - if (antennadiv >= 2) - bcm43xx_phy_write(bcm, 0x048C, - bcm43xx_phy_read(bcm, 0x048C) - | 0x2000); - else - bcm43xx_phy_write(bcm, 0x048C, - bcm43xx_phy_read(bcm, 0x048C) - & ~0x2000); - if (phy->rev >= 2) { - bcm43xx_phy_write(bcm, 0x0461, - bcm43xx_phy_read(bcm, 0x0461) - | 0x0010); - bcm43xx_phy_write(bcm, 0x04AD, - (bcm43xx_phy_read(bcm, 0x04AD) - & 0x00FF) | 0x0015); - if (phy->rev == 2) - bcm43xx_phy_write(bcm, 0x0427, 0x0008); - else - bcm43xx_phy_write(bcm, 0x0427, - (bcm43xx_phy_read(bcm, 0x0427) - & 0x00FF) | 0x0008); - } - else if (phy->rev >= 6) - bcm43xx_phy_write(bcm, 0x049B, 0x00DC); - } else { - if (phy->rev < 3) - bcm43xx_phy_write(bcm, 0x002B, - (bcm43xx_phy_read(bcm, 0x002B) - & 0x00FF) | 0x0024); - else { - bcm43xx_phy_write(bcm, 0x0061, - bcm43xx_phy_read(bcm, 0x0061) - | 0x0010); - if (phy->rev == 3) { - bcm43xx_phy_write(bcm, 0x0093, 0x001D); - bcm43xx_phy_write(bcm, 0x0027, 0x0008); - } else { - bcm43xx_phy_write(bcm, 0x0093, 0x003A); - bcm43xx_phy_write(bcm, 0x0027, - (bcm43xx_phy_read(bcm, 0x0027) - & 0x00FF) | 0x0008); - } - } - } - break; - case BCM43xx_PHYTYPE_B: - if (bcm->current_core->rev == 2) - value = (3/*automatic*/ << 7); - else - value = (antennadiv << 7); - bcm43xx_phy_write(bcm, 0x03E2, - (bcm43xx_phy_read(bcm, 0x03E2) - & 0xFE7F) | value); - break; - default: - assert(0); - } - - if (antennadiv >= 2) { - ucodeflags = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, - BCM43xx_UCODEFLAGS_OFFSET); - bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, - BCM43xx_UCODEFLAGS_OFFSET, - ucodeflags | BCM43xx_UCODEFLAG_AUTODIV); - } - - phy->antenna_diversity = antennadiv; -} diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.h b/drivers/net/wireless/bcm43xx/bcm43xx_phy.h deleted file mode 100644 index 73118364b552..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - - Broadcom BCM43xx wireless driver - - Copyright (c) 2005 Martin Langer , - Stefano Brivio - Michael Buesch - Danny van Dyk - Andreas Jaggi - - Some parts of the code in this file are derived from the ipw2200 - driver Copyright(c) 2003 - 2004 Intel Corporation. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#ifndef BCM43xx_PHY_H_ -#define BCM43xx_PHY_H_ - -#include - -struct bcm43xx_private; - -void bcm43xx_raw_phy_lock(struct bcm43xx_private *bcm); -#define bcm43xx_phy_lock(bcm, flags) \ - do { \ - local_irq_save(flags); \ - bcm43xx_raw_phy_lock(bcm); \ - } while (0) -void bcm43xx_raw_phy_unlock(struct bcm43xx_private *bcm); -#define bcm43xx_phy_unlock(bcm, flags) \ - do { \ - bcm43xx_raw_phy_unlock(bcm); \ - local_irq_restore(flags); \ - } while (0) - -/* Card uses the loopback gain stuff */ -#define has_loopback_gain(phy) \ - (((phy)->rev > 1) || ((phy)->connected)) - -u16 bcm43xx_phy_read(struct bcm43xx_private *bcm, u16 offset); -void bcm43xx_phy_write(struct bcm43xx_private *bcm, u16 offset, u16 val); - -int bcm43xx_phy_init_tssi2dbm_table(struct bcm43xx_private *bcm); -int bcm43xx_phy_init(struct bcm43xx_private *bcm); - -void bcm43xx_phy_set_antenna_diversity(struct bcm43xx_private *bcm); -void bcm43xx_phy_calibrate(struct bcm43xx_private *bcm); -int bcm43xx_phy_connect(struct bcm43xx_private *bcm, int connect); - -void bcm43xx_phy_lo_b_measure(struct bcm43xx_private *bcm); -void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm); -void bcm43xx_phy_xmitpower(struct bcm43xx_private *bcm); - -/* Adjust the LocalOscillator to the saved values. - * "fixed" is only set to 1 once in initialization. Set to 0 otherwise. - */ -void bcm43xx_phy_lo_adjust(struct bcm43xx_private *bcm, int fixed); -void bcm43xx_phy_lo_mark_all_unused(struct bcm43xx_private *bcm); - -void bcm43xx_phy_set_baseband_attenuation(struct bcm43xx_private *bcm, - u16 baseband_attenuation); - -#endif /* BCM43xx_PHY_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c deleted file mode 100644 index 76ab109cd2db..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c +++ /dev/null @@ -1,674 +0,0 @@ -/* - - Broadcom BCM43xx wireless driver - - PIO Transmission - - Copyright (c) 2005 Michael Buesch - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include "bcm43xx.h" -#include "bcm43xx_pio.h" -#include "bcm43xx_main.h" -#include "bcm43xx_xmit.h" -#include "bcm43xx_power.h" - -#include - - -static void tx_start(struct bcm43xx_pioqueue *queue) -{ - bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, - BCM43xx_PIO_TXCTL_INIT); -} - -static void tx_octet(struct bcm43xx_pioqueue *queue, - u8 octet) -{ - if (queue->need_workarounds) { - bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, - octet); - bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, - BCM43xx_PIO_TXCTL_WRITELO); - } else { - bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, - BCM43xx_PIO_TXCTL_WRITELO); - bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, - octet); - } -} - -static u16 tx_get_next_word(struct bcm43xx_txhdr *txhdr, - const u8 *packet, - unsigned int *pos) -{ - const u8 *source; - unsigned int i = *pos; - u16 ret; - - if (i < sizeof(*txhdr)) { - source = (const u8 *)txhdr; - } else { - source = packet; - i -= sizeof(*txhdr); - } - ret = le16_to_cpu( *((__le16 *)(source + i)) ); - *pos += 2; - - return ret; -} - -static void tx_data(struct bcm43xx_pioqueue *queue, - struct bcm43xx_txhdr *txhdr, - const u8 *packet, - unsigned int octets) -{ - u16 data; - unsigned int i = 0; - - if (queue->need_workarounds) { - data = tx_get_next_word(txhdr, packet, &i); - bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, data); - } - bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, - BCM43xx_PIO_TXCTL_WRITELO | - BCM43xx_PIO_TXCTL_WRITEHI); - while (i < octets - 1) { - data = tx_get_next_word(txhdr, packet, &i); - bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, data); - } - if (octets % 2) - tx_octet(queue, packet[octets - sizeof(*txhdr) - 1]); -} - -static void tx_complete(struct bcm43xx_pioqueue *queue, - struct sk_buff *skb) -{ - if (queue->need_workarounds) { - bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, - skb->data[skb->len - 1]); - bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, - BCM43xx_PIO_TXCTL_WRITELO | - BCM43xx_PIO_TXCTL_COMPLETE); - } else { - bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, - BCM43xx_PIO_TXCTL_COMPLETE); - } -} - -static u16 generate_cookie(struct bcm43xx_pioqueue *queue, - struct bcm43xx_pio_txpacket *packet) -{ - u16 cookie = 0x0000; - int packetindex; - - /* We use the upper 4 bits for the PIO - * controller ID and the lower 12 bits - * for the packet index (in the cache). - */ - switch (queue->mmio_base) { - case BCM43xx_MMIO_PIO1_BASE: - break; - case BCM43xx_MMIO_PIO2_BASE: - cookie = 0x1000; - break; - case BCM43xx_MMIO_PIO3_BASE: - cookie = 0x2000; - break; - case BCM43xx_MMIO_PIO4_BASE: - cookie = 0x3000; - break; - default: - assert(0); - } - packetindex = pio_txpacket_getindex(packet); - assert(((u16)packetindex & 0xF000) == 0x0000); - cookie |= (u16)packetindex; - - return cookie; -} - -static -struct bcm43xx_pioqueue * parse_cookie(struct bcm43xx_private *bcm, - u16 cookie, - struct bcm43xx_pio_txpacket **packet) -{ - struct bcm43xx_pio *pio = bcm43xx_current_pio(bcm); - struct bcm43xx_pioqueue *queue = NULL; - int packetindex; - - switch (cookie & 0xF000) { - case 0x0000: - queue = pio->queue0; - break; - case 0x1000: - queue = pio->queue1; - break; - case 0x2000: - queue = pio->queue2; - break; - case 0x3000: - queue = pio->queue3; - break; - default: - assert(0); - } - packetindex = (cookie & 0x0FFF); - assert(packetindex >= 0 && packetindex < BCM43xx_PIO_MAXTXPACKETS); - *packet = &(queue->tx_packets_cache[packetindex]); - - return queue; -} - -static void pio_tx_write_fragment(struct bcm43xx_pioqueue *queue, - struct sk_buff *skb, - struct bcm43xx_pio_txpacket *packet) -{ - struct bcm43xx_txhdr txhdr; - unsigned int octets; - - assert(skb_shinfo(skb)->nr_frags == 0); - bcm43xx_generate_txhdr(queue->bcm, - &txhdr, skb->data, skb->len, - (packet->xmitted_frags == 0), - generate_cookie(queue, packet)); - - tx_start(queue); - octets = skb->len + sizeof(txhdr); - if (queue->need_workarounds) - octets--; - tx_data(queue, &txhdr, (u8 *)skb->data, octets); - tx_complete(queue, skb); -} - -static void free_txpacket(struct bcm43xx_pio_txpacket *packet, - int irq_context) -{ - struct bcm43xx_pioqueue *queue = packet->queue; - - ieee80211_txb_free(packet->txb); - list_move(&packet->list, &queue->txfree); - queue->nr_txfree++; - - assert(queue->tx_devq_used >= packet->xmitted_octets); - assert(queue->tx_devq_packets >= packet->xmitted_frags); - queue->tx_devq_used -= packet->xmitted_octets; - queue->tx_devq_packets -= packet->xmitted_frags; -} - -static int pio_tx_packet(struct bcm43xx_pio_txpacket *packet) -{ - struct bcm43xx_pioqueue *queue = packet->queue; - struct ieee80211_txb *txb = packet->txb; - struct sk_buff *skb; - u16 octets; - int i; - - for (i = packet->xmitted_frags; i < txb->nr_frags; i++) { - skb = txb->fragments[i]; - - octets = (u16)skb->len + sizeof(struct bcm43xx_txhdr); - assert(queue->tx_devq_size >= octets); - assert(queue->tx_devq_packets <= BCM43xx_PIO_MAXTXDEVQPACKETS); - assert(queue->tx_devq_used <= queue->tx_devq_size); - /* Check if there is sufficient free space on the device - * TX queue. If not, return and let the TX tasklet - * retry later. - */ - if (queue->tx_devq_packets == BCM43xx_PIO_MAXTXDEVQPACKETS) - return -EBUSY; - if (queue->tx_devq_used + octets > queue->tx_devq_size) - return -EBUSY; - /* Now poke the device. */ - pio_tx_write_fragment(queue, skb, packet); - - /* Account for the packet size. - * (We must not overflow the device TX queue) - */ - queue->tx_devq_packets++; - queue->tx_devq_used += octets; - - assert(packet->xmitted_frags < packet->txb->nr_frags); - packet->xmitted_frags++; - packet->xmitted_octets += octets; - } - list_move_tail(&packet->list, &queue->txrunning); - - return 0; -} - -static void tx_tasklet(unsigned long d) -{ - struct bcm43xx_pioqueue *queue = (struct bcm43xx_pioqueue *)d; - struct bcm43xx_private *bcm = queue->bcm; - unsigned long flags; - struct bcm43xx_pio_txpacket *packet, *tmp_packet; - int err; - u16 txctl; - - spin_lock_irqsave(&bcm->irq_lock, flags); - - if (queue->tx_frozen) - goto out_unlock; - txctl = bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL); - if (txctl & BCM43xx_PIO_TXCTL_SUSPEND) - goto out_unlock; - - list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list) { - assert(packet->xmitted_frags < packet->txb->nr_frags); - if (packet->xmitted_frags == 0) { - int i; - struct sk_buff *skb; - - /* Check if the device queue is big - * enough for every fragment. If not, drop the - * whole packet. - */ - for (i = 0; i < packet->txb->nr_frags; i++) { - skb = packet->txb->fragments[i]; - if (unlikely(skb->len > queue->tx_devq_size)) { - dprintkl(KERN_ERR PFX "PIO TX device queue too small. " - "Dropping packet.\n"); - free_txpacket(packet, 1); - goto next_packet; - } - } - } - /* Try to transmit the packet. - * This may not completely succeed. - */ - err = pio_tx_packet(packet); - if (err) - break; - next_packet: - continue; - } -out_unlock: - spin_unlock_irqrestore(&bcm->irq_lock, flags); -} - -static void setup_txqueues(struct bcm43xx_pioqueue *queue) -{ - struct bcm43xx_pio_txpacket *packet; - int i; - - queue->nr_txfree = BCM43xx_PIO_MAXTXPACKETS; - for (i = 0; i < BCM43xx_PIO_MAXTXPACKETS; i++) { - packet = &(queue->tx_packets_cache[i]); - - packet->queue = queue; - INIT_LIST_HEAD(&packet->list); - - list_add(&packet->list, &queue->txfree); - } -} - -static -struct bcm43xx_pioqueue * bcm43xx_setup_pioqueue(struct bcm43xx_private *bcm, - u16 pio_mmio_base) -{ - struct bcm43xx_pioqueue *queue; - u32 value; - u16 qsize; - - queue = kzalloc(sizeof(*queue), GFP_KERNEL); - if (!queue) - goto out; - - queue->bcm = bcm; - queue->mmio_base = pio_mmio_base; - queue->need_workarounds = (bcm->current_core->rev < 3); - - INIT_LIST_HEAD(&queue->txfree); - INIT_LIST_HEAD(&queue->txqueue); - INIT_LIST_HEAD(&queue->txrunning); - tasklet_init(&queue->txtask, tx_tasklet, - (unsigned long)queue); - - value = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); - value &= ~BCM43xx_SBF_XFER_REG_BYTESWAP; - bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value); - - qsize = bcm43xx_read16(bcm, queue->mmio_base + BCM43xx_PIO_TXQBUFSIZE); - if (qsize == 0) { - printk(KERN_ERR PFX "ERROR: This card does not support PIO " - "operation mode. Please use DMA mode " - "(module parameter pio=0).\n"); - goto err_freequeue; - } - if (qsize <= BCM43xx_PIO_TXQADJUST) { - printk(KERN_ERR PFX "PIO tx device-queue too small (%u)\n", - qsize); - goto err_freequeue; - } - qsize -= BCM43xx_PIO_TXQADJUST; - queue->tx_devq_size = qsize; - - setup_txqueues(queue); - -out: - return queue; - -err_freequeue: - kfree(queue); - queue = NULL; - goto out; -} - -static void cancel_transfers(struct bcm43xx_pioqueue *queue) -{ - struct bcm43xx_pio_txpacket *packet, *tmp_packet; - - netif_tx_disable(queue->bcm->net_dev); - tasklet_disable(&queue->txtask); - - list_for_each_entry_safe(packet, tmp_packet, &queue->txrunning, list) - free_txpacket(packet, 0); - list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list) - free_txpacket(packet, 0); -} - -static void bcm43xx_destroy_pioqueue(struct bcm43xx_pioqueue *queue) -{ - if (!queue) - return; - - cancel_transfers(queue); - kfree(queue); -} - -void bcm43xx_pio_free(struct bcm43xx_private *bcm) -{ - struct bcm43xx_pio *pio; - - if (!bcm43xx_using_pio(bcm)) - return; - pio = bcm43xx_current_pio(bcm); - - bcm43xx_destroy_pioqueue(pio->queue3); - pio->queue3 = NULL; - bcm43xx_destroy_pioqueue(pio->queue2); - pio->queue2 = NULL; - bcm43xx_destroy_pioqueue(pio->queue1); - pio->queue1 = NULL; - bcm43xx_destroy_pioqueue(pio->queue0); - pio->queue0 = NULL; -} - -int bcm43xx_pio_init(struct bcm43xx_private *bcm) -{ - struct bcm43xx_pio *pio = bcm43xx_current_pio(bcm); - struct bcm43xx_pioqueue *queue; - int err = -ENOMEM; - - queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO1_BASE); - if (!queue) - goto out; - pio->queue0 = queue; - - queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO2_BASE); - if (!queue) - goto err_destroy0; - pio->queue1 = queue; - - queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO3_BASE); - if (!queue) - goto err_destroy1; - pio->queue2 = queue; - - queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO4_BASE); - if (!queue) - goto err_destroy2; - pio->queue3 = queue; - - if (bcm->current_core->rev < 3) - bcm->irq_savedstate |= BCM43xx_IRQ_PIO_WORKAROUND; - - dprintk(KERN_INFO PFX "PIO initialized\n"); - err = 0; -out: - return err; - -err_destroy2: - bcm43xx_destroy_pioqueue(pio->queue2); - pio->queue2 = NULL; -err_destroy1: - bcm43xx_destroy_pioqueue(pio->queue1); - pio->queue1 = NULL; -err_destroy0: - bcm43xx_destroy_pioqueue(pio->queue0); - pio->queue0 = NULL; - goto out; -} - -int bcm43xx_pio_tx(struct bcm43xx_private *bcm, - struct ieee80211_txb *txb) -{ - struct bcm43xx_pioqueue *queue = bcm43xx_current_pio(bcm)->queue1; - struct bcm43xx_pio_txpacket *packet; - - assert(!queue->tx_suspended); - assert(!list_empty(&queue->txfree)); - - packet = list_entry(queue->txfree.next, struct bcm43xx_pio_txpacket, list); - packet->txb = txb; - packet->xmitted_frags = 0; - packet->xmitted_octets = 0; - list_move_tail(&packet->list, &queue->txqueue); - queue->nr_txfree--; - assert(queue->nr_txfree < BCM43xx_PIO_MAXTXPACKETS); - - /* Suspend TX, if we are out of packets in the "free" queue. */ - if (list_empty(&queue->txfree)) { - netif_stop_queue(queue->bcm->net_dev); - queue->tx_suspended = 1; - } - - tasklet_schedule(&queue->txtask); - - return 0; -} - -void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm, - struct bcm43xx_xmitstatus *status) -{ - struct bcm43xx_pioqueue *queue; - struct bcm43xx_pio_txpacket *packet; - - queue = parse_cookie(bcm, status->cookie, &packet); - assert(queue); - - free_txpacket(packet, 1); - if (queue->tx_suspended) { - queue->tx_suspended = 0; - netif_wake_queue(queue->bcm->net_dev); - } - /* If there are packets on the txqueue, poke the tasklet - * to transmit them. - */ - if (!list_empty(&queue->txqueue)) - tasklet_schedule(&queue->txtask); -} - -static void pio_rx_error(struct bcm43xx_pioqueue *queue, - int clear_buffers, - const char *error) -{ - int i; - - printkl("PIO RX error: %s\n", error); - bcm43xx_pio_write(queue, BCM43xx_PIO_RXCTL, - BCM43xx_PIO_RXCTL_READY); - if (clear_buffers) { - assert(queue->mmio_base == BCM43xx_MMIO_PIO1_BASE); - for (i = 0; i < 15; i++) { - /* Dummy read. */ - bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); - } - } -} - -void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue) -{ - __le16 preamble[21] = { 0 }; - struct bcm43xx_rxhdr *rxhdr; - u16 tmp, len, rxflags2; - int i, preamble_readwords; - struct sk_buff *skb; - - tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXCTL); - if (!(tmp & BCM43xx_PIO_RXCTL_DATAAVAILABLE)) - return; - bcm43xx_pio_write(queue, BCM43xx_PIO_RXCTL, - BCM43xx_PIO_RXCTL_DATAAVAILABLE); - - for (i = 0; i < 10; i++) { - tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXCTL); - if (tmp & BCM43xx_PIO_RXCTL_READY) - goto data_ready; - udelay(10); - } - dprintkl(KERN_ERR PFX "PIO RX timed out\n"); - return; -data_ready: - - len = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); - if (unlikely(len > 0x700)) { - pio_rx_error(queue, 0, "len > 0x700"); - return; - } - if (unlikely(len == 0 && queue->mmio_base != BCM43xx_MMIO_PIO4_BASE)) { - pio_rx_error(queue, 0, "len == 0"); - return; - } - preamble[0] = cpu_to_le16(len); - if (queue->mmio_base == BCM43xx_MMIO_PIO4_BASE) - preamble_readwords = 14 / sizeof(u16); - else - preamble_readwords = 18 / sizeof(u16); - for (i = 0; i < preamble_readwords; i++) { - tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); - preamble[i + 1] = cpu_to_le16(tmp); - } - rxhdr = (struct bcm43xx_rxhdr *)preamble; - rxflags2 = le16_to_cpu(rxhdr->flags2); - if (unlikely(rxflags2 & BCM43xx_RXHDR_FLAGS2_INVALIDFRAME)) { - pio_rx_error(queue, - (queue->mmio_base == BCM43xx_MMIO_PIO1_BASE), - "invalid frame"); - return; - } - if (queue->mmio_base == BCM43xx_MMIO_PIO4_BASE) { - /* We received an xmit status. */ - struct bcm43xx_hwxmitstatus *hw; - struct bcm43xx_xmitstatus stat; - - hw = (struct bcm43xx_hwxmitstatus *)(preamble + 1); - stat.cookie = le16_to_cpu(hw->cookie); - stat.flags = hw->flags; - stat.cnt1 = hw->cnt1; - stat.cnt2 = hw->cnt2; - stat.seq = le16_to_cpu(hw->seq); - stat.unknown = le16_to_cpu(hw->unknown); - - bcm43xx_debugfs_log_txstat(queue->bcm, &stat); - bcm43xx_pio_handle_xmitstatus(queue->bcm, &stat); - - return; - } - - skb = dev_alloc_skb(len); - if (unlikely(!skb)) { - pio_rx_error(queue, 1, "OOM"); - return; - } - skb_put(skb, len); - for (i = 0; i < len - 1; i += 2) { - tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); - *((__le16 *)(skb->data + i)) = cpu_to_le16(tmp); - } - if (len % 2) { - tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); - skb->data[len - 1] = (tmp & 0x00FF); -/* The specs say the following is required, but - * it is wrong and corrupts the PLCP. If we don't do - * this, the PLCP seems to be correct. So ifdef it out for now. - */ -#if 0 - if (rxflags2 & BCM43xx_RXHDR_FLAGS2_TYPE2FRAME) - skb->data[2] = (tmp & 0xFF00) >> 8; - else - skb->data[0] = (tmp & 0xFF00) >> 8; -#endif - } - skb_trim(skb, len - IEEE80211_FCS_LEN); - bcm43xx_rx(queue->bcm, skb, rxhdr); -} - -void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue) -{ - bcm43xx_power_saving_ctl_bits(queue->bcm, -1, 1); - bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, - bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL) - | BCM43xx_PIO_TXCTL_SUSPEND); -} - -void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue) -{ - bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, - bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL) - & ~BCM43xx_PIO_TXCTL_SUSPEND); - bcm43xx_power_saving_ctl_bits(queue->bcm, -1, -1); - if (!list_empty(&queue->txqueue)) - tasklet_schedule(&queue->txtask); -} - -void bcm43xx_pio_freeze_txqueues(struct bcm43xx_private *bcm) -{ - struct bcm43xx_pio *pio; - - assert(bcm43xx_using_pio(bcm)); - pio = bcm43xx_current_pio(bcm); - pio->queue0->tx_frozen = 1; - pio->queue1->tx_frozen = 1; - pio->queue2->tx_frozen = 1; - pio->queue3->tx_frozen = 1; -} - -void bcm43xx_pio_thaw_txqueues(struct bcm43xx_private *bcm) -{ - struct bcm43xx_pio *pio; - - assert(bcm43xx_using_pio(bcm)); - pio = bcm43xx_current_pio(bcm); - pio->queue0->tx_frozen = 0; - pio->queue1->tx_frozen = 0; - pio->queue2->tx_frozen = 0; - pio->queue3->tx_frozen = 0; - if (!list_empty(&pio->queue0->txqueue)) - tasklet_schedule(&pio->queue0->txtask); - if (!list_empty(&pio->queue1->txqueue)) - tasklet_schedule(&pio->queue1->txtask); - if (!list_empty(&pio->queue2->txqueue)) - tasklet_schedule(&pio->queue2->txtask); - if (!list_empty(&pio->queue3->txqueue)) - tasklet_schedule(&pio->queue3->txtask); -} - - diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.h b/drivers/net/wireless/bcm43xx/bcm43xx_pio.h deleted file mode 100644 index bc78a3c2cafb..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.h +++ /dev/null @@ -1,163 +0,0 @@ -#ifndef BCM43xx_PIO_H_ -#define BCM43xx_PIO_H_ - -#include "bcm43xx.h" - -#include -#include -#include - - -#define BCM43xx_PIO_TXCTL 0x00 -#define BCM43xx_PIO_TXDATA 0x02 -#define BCM43xx_PIO_TXQBUFSIZE 0x04 -#define BCM43xx_PIO_RXCTL 0x08 -#define BCM43xx_PIO_RXDATA 0x0A - -#define BCM43xx_PIO_TXCTL_WRITELO (1 << 0) -#define BCM43xx_PIO_TXCTL_WRITEHI (1 << 1) -#define BCM43xx_PIO_TXCTL_COMPLETE (1 << 2) -#define BCM43xx_PIO_TXCTL_INIT (1 << 3) -#define BCM43xx_PIO_TXCTL_SUSPEND (1 << 7) - -#define BCM43xx_PIO_RXCTL_DATAAVAILABLE (1 << 0) -#define BCM43xx_PIO_RXCTL_READY (1 << 1) - -/* PIO constants */ -#define BCM43xx_PIO_MAXTXDEVQPACKETS 31 -#define BCM43xx_PIO_TXQADJUST 80 - -/* PIO tuning knobs */ -#define BCM43xx_PIO_MAXTXPACKETS 256 - - - -#ifdef CONFIG_BCM43XX_PIO - - -struct bcm43xx_pioqueue; -struct bcm43xx_xmitstatus; - -struct bcm43xx_pio_txpacket { - struct bcm43xx_pioqueue *queue; - struct ieee80211_txb *txb; - struct list_head list; - - u8 xmitted_frags; - u16 xmitted_octets; -}; - -#define pio_txpacket_getindex(packet) ((int)((packet) - (packet)->queue->tx_packets_cache)) - -struct bcm43xx_pioqueue { - struct bcm43xx_private *bcm; - u16 mmio_base; - - u8 tx_suspended:1, - tx_frozen:1, - need_workarounds:1; /* Workarounds needed for core.rev < 3 */ - - /* Adjusted size of the device internal TX buffer. */ - u16 tx_devq_size; - /* Used octets of the device internal TX buffer. */ - u16 tx_devq_used; - /* Used packet slots in the device internal TX buffer. */ - u8 tx_devq_packets; - /* Packets from the txfree list can - * be taken on incoming TX requests. - */ - struct list_head txfree; - unsigned int nr_txfree; - /* Packets on the txqueue are queued, - * but not completely written to the chip, yet. - */ - struct list_head txqueue; - /* Packets on the txrunning queue are completely - * posted to the device. We are waiting for the txstatus. - */ - struct list_head txrunning; - /* Total number or packets sent. - * (This counter can obviously wrap). - */ - unsigned int nr_tx_packets; - struct tasklet_struct txtask; - struct bcm43xx_pio_txpacket tx_packets_cache[BCM43xx_PIO_MAXTXPACKETS]; -}; - -static inline -u16 bcm43xx_pio_read(struct bcm43xx_pioqueue *queue, - u16 offset) -{ - return bcm43xx_read16(queue->bcm, queue->mmio_base + offset); -} - -static inline -void bcm43xx_pio_write(struct bcm43xx_pioqueue *queue, - u16 offset, u16 value) -{ - bcm43xx_write16(queue->bcm, queue->mmio_base + offset, value); - mmiowb(); -} - - -int bcm43xx_pio_init(struct bcm43xx_private *bcm); -void bcm43xx_pio_free(struct bcm43xx_private *bcm); - -int bcm43xx_pio_tx(struct bcm43xx_private *bcm, - struct ieee80211_txb *txb); -void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm, - struct bcm43xx_xmitstatus *status); -void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue); - -/* Suspend a TX queue on hardware level. */ -void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue); -void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue); -/* Suspend (freeze) the TX tasklet (software level). */ -void bcm43xx_pio_freeze_txqueues(struct bcm43xx_private *bcm); -void bcm43xx_pio_thaw_txqueues(struct bcm43xx_private *bcm); - -#else /* CONFIG_BCM43XX_PIO */ - -static inline -int bcm43xx_pio_init(struct bcm43xx_private *bcm) -{ - return 0; -} -static inline -void bcm43xx_pio_free(struct bcm43xx_private *bcm) -{ -} -static inline -int bcm43xx_pio_tx(struct bcm43xx_private *bcm, - struct ieee80211_txb *txb) -{ - return 0; -} -static inline -void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm, - struct bcm43xx_xmitstatus *status) -{ -} -static inline -void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue) -{ -} -static inline -void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue) -{ -} -static inline -void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue) -{ -} -static inline -void bcm43xx_pio_freeze_txqueues(struct bcm43xx_private *bcm) -{ -} -static inline -void bcm43xx_pio_thaw_txqueues(struct bcm43xx_private *bcm) -{ -} - -#endif /* CONFIG_BCM43XX_PIO */ -#endif /* BCM43xx_PIO_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_power.c b/drivers/net/wireless/bcm43xx/bcm43xx_power.c deleted file mode 100644 index 7e774f410953..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx_power.c +++ /dev/null @@ -1,393 +0,0 @@ -/* - - Broadcom BCM43xx wireless driver - - Copyright (c) 2005 Martin Langer , - Stefano Brivio - Michael Buesch - Danny van Dyk - Andreas Jaggi - - Some parts of the code in this file are derived from the ipw2200 - driver Copyright(c) 2003 - 2004 Intel Corporation. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include - -#include "bcm43xx.h" -#include "bcm43xx_power.h" -#include "bcm43xx_main.h" - - -/* Get the Slow Clock Source */ -static int bcm43xx_pctl_get_slowclksrc(struct bcm43xx_private *bcm) -{ - u32 tmp; - int err; - - assert(bcm->current_core == &bcm->core_chipcommon); - if (bcm->current_core->rev < 6) { - if (bcm->bustype == BCM43xx_BUSTYPE_PCMCIA || - bcm->bustype == BCM43xx_BUSTYPE_SB) - return BCM43xx_PCTL_CLKSRC_XTALOS; - if (bcm->bustype == BCM43xx_BUSTYPE_PCI) { - err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_OUT, &tmp); - assert(!err); - if (tmp & 0x10) - return BCM43xx_PCTL_CLKSRC_PCI; - return BCM43xx_PCTL_CLKSRC_XTALOS; - } - } - if (bcm->current_core->rev < 10) { - tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL); - tmp &= 0x7; - if (tmp == 0) - return BCM43xx_PCTL_CLKSRC_LOPWROS; - if (tmp == 1) - return BCM43xx_PCTL_CLKSRC_XTALOS; - if (tmp == 2) - return BCM43xx_PCTL_CLKSRC_PCI; - } - - return BCM43xx_PCTL_CLKSRC_XTALOS; -} - -/* Get max/min slowclock frequency - * as described in http://bcm-specs.sipsolutions.net/PowerControl - */ -static int bcm43xx_pctl_clockfreqlimit(struct bcm43xx_private *bcm, - int get_max) -{ - int limit; - int clocksrc; - int divisor; - u32 tmp; - - assert(bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL); - assert(bcm->current_core == &bcm->core_chipcommon); - - clocksrc = bcm43xx_pctl_get_slowclksrc(bcm); - if (bcm->current_core->rev < 6) { - switch (clocksrc) { - case BCM43xx_PCTL_CLKSRC_PCI: - divisor = 64; - break; - case BCM43xx_PCTL_CLKSRC_XTALOS: - divisor = 32; - break; - default: - assert(0); - divisor = 1; - } - } else if (bcm->current_core->rev < 10) { - switch (clocksrc) { - case BCM43xx_PCTL_CLKSRC_LOPWROS: - divisor = 1; - break; - case BCM43xx_PCTL_CLKSRC_XTALOS: - case BCM43xx_PCTL_CLKSRC_PCI: - tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL); - divisor = ((tmp & 0xFFFF0000) >> 16) + 1; - divisor *= 4; - break; - default: - assert(0); - divisor = 1; - } - } else { - tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SYSCLKCTL); - divisor = ((tmp & 0xFFFF0000) >> 16) + 1; - divisor *= 4; - } - - switch (clocksrc) { - case BCM43xx_PCTL_CLKSRC_LOPWROS: - if (get_max) - limit = 43000; - else - limit = 25000; - break; - case BCM43xx_PCTL_CLKSRC_XTALOS: - if (get_max) - limit = 20200000; - else - limit = 19800000; - break; - case BCM43xx_PCTL_CLKSRC_PCI: - if (get_max) - limit = 34000000; - else - limit = 25000000; - break; - default: - assert(0); - limit = 0; - } - limit /= divisor; - - return limit; -} - - -/* init power control - * as described in http://bcm-specs.sipsolutions.net/PowerControl - */ -int bcm43xx_pctl_init(struct bcm43xx_private *bcm) -{ - int err, maxfreq; - struct bcm43xx_coreinfo *old_core; - - old_core = bcm->current_core; - err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon); - if (err == -ENODEV) - return 0; - if (err) - goto out; - - if (bcm->chip_id == 0x4321) { - if (bcm->chip_rev == 0) - bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_CTL, 0x03A4); - if (bcm->chip_rev == 1) - bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_CTL, 0x00A4); - } - - if (bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL) { - if (bcm->current_core->rev >= 10) { - /* Set Idle Power clock rate to 1Mhz */ - bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_SYSCLKCTL, - (bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SYSCLKCTL) - & 0x0000FFFF) | 0x40000); - } else { - maxfreq = bcm43xx_pctl_clockfreqlimit(bcm, 1); - bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_PLLONDELAY, - (maxfreq * 150 + 999999) / 1000000); - bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_FREFSELDELAY, - (maxfreq * 15 + 999999) / 1000000); - } - } - - err = bcm43xx_switch_core(bcm, old_core); - assert(err == 0); - -out: - return err; -} - -u16 bcm43xx_pctl_powerup_delay(struct bcm43xx_private *bcm) -{ - u16 delay = 0; - int err; - u32 pll_on_delay; - struct bcm43xx_coreinfo *old_core; - int minfreq; - - if (bcm->bustype != BCM43xx_BUSTYPE_PCI) - goto out; - if (!(bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL)) - goto out; - old_core = bcm->current_core; - err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon); - if (err == -ENODEV) - goto out; - - minfreq = bcm43xx_pctl_clockfreqlimit(bcm, 0); - pll_on_delay = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_PLLONDELAY); - delay = (((pll_on_delay + 2) * 1000000) + (minfreq - 1)) / minfreq; - - err = bcm43xx_switch_core(bcm, old_core); - assert(err == 0); - -out: - return delay; -} - -/* set the powercontrol clock - * as described in http://bcm-specs.sipsolutions.net/PowerControl - */ -int bcm43xx_pctl_set_clock(struct bcm43xx_private *bcm, u16 mode) -{ - int err; - struct bcm43xx_coreinfo *old_core; - u32 tmp; - - old_core = bcm->current_core; - err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon); - if (err == -ENODEV) - return 0; - if (err) - goto out; - - if (bcm->core_chipcommon.rev < 6) { - if (mode == BCM43xx_PCTL_CLK_FAST) { - err = bcm43xx_pctl_set_crystal(bcm, 1); - if (err) - goto out; - } - } else { - if ((bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL) && - (bcm->core_chipcommon.rev < 10)) { - switch (mode) { - case BCM43xx_PCTL_CLK_FAST: - tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL); - tmp = (tmp & ~BCM43xx_PCTL_FORCE_SLOW) | BCM43xx_PCTL_FORCE_PLL; - bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL, tmp); - break; - case BCM43xx_PCTL_CLK_SLOW: - tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL); - tmp |= BCM43xx_PCTL_FORCE_SLOW; - bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL, tmp); - break; - case BCM43xx_PCTL_CLK_DYNAMIC: - tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL); - tmp &= ~BCM43xx_PCTL_FORCE_SLOW; - tmp |= BCM43xx_PCTL_FORCE_PLL; - tmp &= ~BCM43xx_PCTL_DYN_XTAL; - bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL, tmp); - } - } - } - - err = bcm43xx_switch_core(bcm, old_core); - assert(err == 0); - -out: - return err; -} - -int bcm43xx_pctl_set_crystal(struct bcm43xx_private *bcm, int on) -{ - int err; - u32 in, out, outenable; - - err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_IN, &in); - if (err) - goto err_pci; - err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_OUT, &out); - if (err) - goto err_pci; - err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_OUTENABLE, &outenable); - if (err) - goto err_pci; - - outenable |= (BCM43xx_PCTL_XTAL_POWERUP | BCM43xx_PCTL_PLL_POWERDOWN); - - if (on) { - if (in & 0x40) - return 0; - - out |= (BCM43xx_PCTL_XTAL_POWERUP | BCM43xx_PCTL_PLL_POWERDOWN); - - err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUT, out); - if (err) - goto err_pci; - err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUTENABLE, outenable); - if (err) - goto err_pci; - udelay(1000); - - out &= ~BCM43xx_PCTL_PLL_POWERDOWN; - err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUT, out); - if (err) - goto err_pci; - udelay(5000); - } else { - if (bcm->current_core->rev < 5) - return 0; - if (bcm->sprom.boardflags & BCM43xx_BFL_XTAL_NOSLOW) - return 0; - -/* XXX: Why BCM43xx_MMIO_RADIO_HWENABLED_xx can't be read at this time? - * err = bcm43xx_switch_core(bcm, bcm->active_80211_core); - * if (err) - * return err; - * if (((bcm->current_core->rev >= 3) && - * (bcm43xx_read32(bcm, BCM43xx_MMIO_RADIO_HWENABLED_HI) & (1 << 16))) || - * ((bcm->current_core->rev < 3) && - * !(bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_HWENABLED_LO) & (1 << 4)))) - * return 0; - * err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon); - * if (err) - * return err; - */ - - err = bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_SLOW); - if (err) - goto out; - out &= ~BCM43xx_PCTL_XTAL_POWERUP; - out |= BCM43xx_PCTL_PLL_POWERDOWN; - err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUT, out); - if (err) - goto err_pci; - err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUTENABLE, outenable); - if (err) - goto err_pci; - } - -out: - return err; - -err_pci: - printk(KERN_ERR PFX "Error: pctl_set_clock() could not access PCI config space!\n"); - err = -EBUSY; - goto out; -} - -/* Set the PowerSavingControlBits. - * Bitvalues: - * 0 => unset the bit - * 1 => set the bit - * -1 => calculate the bit - */ -void bcm43xx_power_saving_ctl_bits(struct bcm43xx_private *bcm, - int bit25, int bit26) -{ - int i; - u32 status; - -//FIXME: Force 25 to off and 26 to on for now: -bit25 = 0; -bit26 = 1; - - if (bit25 == -1) { - //TODO: If powersave is not off and FIXME is not set and we are not in adhoc - // and thus is not an AP and we are associated, set bit 25 - } - if (bit26 == -1) { - //TODO: If the device is awake or this is an AP, or we are scanning, or FIXME, - // or we are associated, or FIXME, or the latest PS-Poll packet sent was - // successful, set bit26 - } - status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); - if (bit25) - status |= BCM43xx_SBF_PS1; - else - status &= ~BCM43xx_SBF_PS1; - if (bit26) - status |= BCM43xx_SBF_PS2; - else - status &= ~BCM43xx_SBF_PS2; - bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status); - if (bit26 && bcm->current_core->rev >= 5) { - for (i = 0; i < 100; i++) { - if (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0040) != 4) - break; - udelay(10); - } - } -} diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_power.h b/drivers/net/wireless/bcm43xx/bcm43xx_power.h deleted file mode 100644 index c966ab3a5a8c..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx_power.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - - Broadcom BCM43xx wireless driver - - Copyright (c) 2005 Martin Langer , - Stefano Brivio - Michael Buesch - Danny van Dyk - Andreas Jaggi - - Some parts of the code in this file are derived from the ipw2200 - driver Copyright(c) 2003 - 2004 Intel Corporation. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#ifndef BCM43xx_POWER_H_ -#define BCM43xx_POWER_H_ - -#include - -/* Clock sources */ -enum { - /* PCI clock */ - BCM43xx_PCTL_CLKSRC_PCI, - /* Crystal slow clock oscillator */ - BCM43xx_PCTL_CLKSRC_XTALOS, - /* Low power oscillator */ - BCM43xx_PCTL_CLKSRC_LOPWROS, -}; - -struct bcm43xx_private; - -int bcm43xx_pctl_init(struct bcm43xx_private *bcm); -int bcm43xx_pctl_set_clock(struct bcm43xx_private *bcm, u16 mode); -int bcm43xx_pctl_set_crystal(struct bcm43xx_private *bcm, int on); -u16 bcm43xx_pctl_powerup_delay(struct bcm43xx_private *bcm); - -void bcm43xx_power_saving_ctl_bits(struct bcm43xx_private *bcm, - int bit25, int bit26); - -#endif /* BCM43xx_POWER_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c deleted file mode 100644 index c605099c9baf..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c +++ /dev/null @@ -1,2170 +0,0 @@ -/* - - Broadcom BCM43xx wireless driver - - Copyright (c) 2005 Martin Langer , - Stefano Brivio - Michael Buesch - Danny van Dyk - Andreas Jaggi - - Some parts of the code in this file are derived from the ipw2200 - driver Copyright(c) 2003 - 2004 Intel Corporation. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include - -#include "bcm43xx.h" -#include "bcm43xx_main.h" -#include "bcm43xx_phy.h" -#include "bcm43xx_radio.h" -#include "bcm43xx_ilt.h" - - -/* Table for bcm43xx_radio_calibrationvalue() */ -static const u16 rcc_table[16] = { - 0x0002, 0x0003, 0x0001, 0x000F, - 0x0006, 0x0007, 0x0005, 0x000F, - 0x000A, 0x000B, 0x0009, 0x000F, - 0x000E, 0x000F, 0x000D, 0x000F, -}; - -/* Reverse the bits of a 4bit value. - * Example: 1101 is flipped 1011 - */ -static u16 flip_4bit(u16 value) -{ - u16 flipped = 0x0000; - - assert((value & ~0x000F) == 0x0000); - - flipped |= (value & 0x0001) << 3; - flipped |= (value & 0x0002) << 1; - flipped |= (value & 0x0004) >> 1; - flipped |= (value & 0x0008) >> 3; - - return flipped; -} - -/* Get the freq, as it has to be written to the device. */ -static inline -u16 channel2freq_bg(u8 channel) -{ - /* Frequencies are given as frequencies_bg[index] + 2.4GHz - * Starting with channel 1 - */ - static const u16 frequencies_bg[14] = { - 12, 17, 22, 27, - 32, 37, 42, 47, - 52, 57, 62, 67, - 72, 84, - }; - - assert(channel >= 1 && channel <= 14); - - return frequencies_bg[channel - 1]; -} - -/* Get the freq, as it has to be written to the device. */ -static inline -u16 channel2freq_a(u8 channel) -{ - assert(channel <= 200); - - return (5000 + 5 * channel); -} - -void bcm43xx_radio_lock(struct bcm43xx_private *bcm) -{ - u32 status; - - status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); - status |= BCM43xx_SBF_RADIOREG_LOCK; - bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status); - mmiowb(); - udelay(10); -} - -void bcm43xx_radio_unlock(struct bcm43xx_private *bcm) -{ - u32 status; - - bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_VER); /* dummy read */ - status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); - status &= ~BCM43xx_SBF_RADIOREG_LOCK; - bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status); - mmiowb(); -} - -u16 bcm43xx_radio_read16(struct bcm43xx_private *bcm, u16 offset) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - - switch (phy->type) { - case BCM43xx_PHYTYPE_A: - offset |= 0x0040; - break; - case BCM43xx_PHYTYPE_B: - if (radio->version == 0x2053) { - if (offset < 0x70) - offset += 0x80; - else if (offset < 0x80) - offset += 0x70; - } else if (radio->version == 0x2050) { - offset |= 0x80; - } else - assert(0); - break; - case BCM43xx_PHYTYPE_G: - offset |= 0x80; - break; - } - - bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_CONTROL, offset); - return bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_DATA_LOW); -} - -void bcm43xx_radio_write16(struct bcm43xx_private *bcm, u16 offset, u16 val) -{ - bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_CONTROL, offset); - mmiowb(); - bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_DATA_LOW, val); -} - -static void bcm43xx_set_all_gains(struct bcm43xx_private *bcm, - s16 first, s16 second, s16 third) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - u16 i; - u16 start = 0x08, end = 0x18; - u16 offset = 0x0400; - u16 tmp; - - if (phy->rev <= 1) { - offset = 0x5000; - start = 0x10; - end = 0x20; - } - - for (i = 0; i < 4; i++) - bcm43xx_ilt_write(bcm, offset + i, first); - - for (i = start; i < end; i++) - bcm43xx_ilt_write(bcm, offset + i, second); - - if (third != -1) { - tmp = ((u16)third << 14) | ((u16)third << 6); - bcm43xx_phy_write(bcm, 0x04A0, - (bcm43xx_phy_read(bcm, 0x04A0) & 0xBFBF) | tmp); - bcm43xx_phy_write(bcm, 0x04A1, - (bcm43xx_phy_read(bcm, 0x04A1) & 0xBFBF) | tmp); - bcm43xx_phy_write(bcm, 0x04A2, - (bcm43xx_phy_read(bcm, 0x04A2) & 0xBFBF) | tmp); - } - bcm43xx_dummy_transmission(bcm); -} - -static void bcm43xx_set_original_gains(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - u16 i, tmp; - u16 offset = 0x0400; - u16 start = 0x0008, end = 0x0018; - - if (phy->rev <= 1) { - offset = 0x5000; - start = 0x0010; - end = 0x0020; - } - - for (i = 0; i < 4; i++) { - tmp = (i & 0xFFFC); - tmp |= (i & 0x0001) << 1; - tmp |= (i & 0x0002) >> 1; - - bcm43xx_ilt_write(bcm, offset + i, tmp); - } - - for (i = start; i < end; i++) - bcm43xx_ilt_write(bcm, offset + i, i - start); - - bcm43xx_phy_write(bcm, 0x04A0, - (bcm43xx_phy_read(bcm, 0x04A0) & 0xBFBF) | 0x4040); - bcm43xx_phy_write(bcm, 0x04A1, - (bcm43xx_phy_read(bcm, 0x04A1) & 0xBFBF) | 0x4040); - bcm43xx_phy_write(bcm, 0x04A2, - (bcm43xx_phy_read(bcm, 0x04A2) & 0xBFBF) | 0x4000); - bcm43xx_dummy_transmission(bcm); -} - -/* Synthetic PU workaround */ -static void bcm43xx_synth_pu_workaround(struct bcm43xx_private *bcm, u8 channel) -{ - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - - if (radio->version != 0x2050 || radio->revision >= 6) { - /* We do not need the workaround. */ - return; - } - - if (channel <= 10) { - bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL, - channel2freq_bg(channel + 4)); - } else { - bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL, - channel2freq_bg(1)); - } - udelay(100); - bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL, - channel2freq_bg(channel)); -} - -u8 bcm43xx_radio_aci_detect(struct bcm43xx_private *bcm, u8 channel) -{ - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - u8 ret = 0; - u16 saved, rssi, temp; - int i, j = 0; - - saved = bcm43xx_phy_read(bcm, 0x0403); - bcm43xx_radio_selectchannel(bcm, channel, 0); - bcm43xx_phy_write(bcm, 0x0403, (saved & 0xFFF8) | 5); - if (radio->aci_hw_rssi) - rssi = bcm43xx_phy_read(bcm, 0x048A) & 0x3F; - else - rssi = saved & 0x3F; - /* clamp temp to signed 5bit */ - if (rssi > 32) - rssi -= 64; - for (i = 0;i < 100; i++) { - temp = (bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x3F; - if (temp > 32) - temp -= 64; - if (temp < rssi) - j++; - if (j >= 20) - ret = 1; - } - bcm43xx_phy_write(bcm, 0x0403, saved); - - return ret; -} - -u8 bcm43xx_radio_aci_scan(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - u8 ret[13]; - unsigned int channel = radio->channel; - unsigned int i, j, start, end; - unsigned long phylock_flags; - - if (!((phy->type == BCM43xx_PHYTYPE_G) && (phy->rev > 0))) - return 0; - - bcm43xx_phy_lock(bcm, phylock_flags); - bcm43xx_radio_lock(bcm); - bcm43xx_phy_write(bcm, 0x0802, - bcm43xx_phy_read(bcm, 0x0802) & 0xFFFC); - bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, - bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0x7FFF); - bcm43xx_set_all_gains(bcm, 3, 8, 1); - - start = (channel - 5 > 0) ? channel - 5 : 1; - end = (channel + 5 < 14) ? channel + 5 : 13; - - for (i = start; i <= end; i++) { - if (abs(channel - i) > 2) - ret[i-1] = bcm43xx_radio_aci_detect(bcm, i); - } - bcm43xx_radio_selectchannel(bcm, channel, 0); - bcm43xx_phy_write(bcm, 0x0802, - (bcm43xx_phy_read(bcm, 0x0802) & 0xFFFC) | 0x0003); - bcm43xx_phy_write(bcm, 0x0403, - bcm43xx_phy_read(bcm, 0x0403) & 0xFFF8); - bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, - bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) | 0x8000); - bcm43xx_set_original_gains(bcm); - for (i = 0; i < 13; i++) { - if (!ret[i]) - continue; - end = (i + 5 < 13) ? i + 5 : 13; - for (j = i; j < end; j++) - ret[j] = 1; - } - bcm43xx_radio_unlock(bcm); - bcm43xx_phy_unlock(bcm, phylock_flags); - - return ret[channel - 1]; -} - -/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */ -void bcm43xx_nrssi_hw_write(struct bcm43xx_private *bcm, u16 offset, s16 val) -{ - bcm43xx_phy_write(bcm, BCM43xx_PHY_NRSSILT_CTRL, offset); - mmiowb(); - bcm43xx_phy_write(bcm, BCM43xx_PHY_NRSSILT_DATA, (u16)val); -} - -/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */ -s16 bcm43xx_nrssi_hw_read(struct bcm43xx_private *bcm, u16 offset) -{ - u16 val; - - bcm43xx_phy_write(bcm, BCM43xx_PHY_NRSSILT_CTRL, offset); - val = bcm43xx_phy_read(bcm, BCM43xx_PHY_NRSSILT_DATA); - - return (s16)val; -} - -/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */ -void bcm43xx_nrssi_hw_update(struct bcm43xx_private *bcm, u16 val) -{ - u16 i; - s16 tmp; - - for (i = 0; i < 64; i++) { - tmp = bcm43xx_nrssi_hw_read(bcm, i); - tmp -= val; - tmp = limit_value(tmp, -32, 31); - bcm43xx_nrssi_hw_write(bcm, i, tmp); - } -} - -/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */ -void bcm43xx_nrssi_mem_update(struct bcm43xx_private *bcm) -{ - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - s16 i, delta; - s32 tmp; - - delta = 0x1F - radio->nrssi[0]; - for (i = 0; i < 64; i++) { - tmp = (i - delta) * radio->nrssislope; - tmp /= 0x10000; - tmp += 0x3A; - tmp = limit_value(tmp, 0, 0x3F); - radio->nrssi_lt[i] = tmp; - } -} - -static void bcm43xx_calc_nrssi_offset(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - u16 backup[20] = { 0 }; - s16 v47F; - u16 i; - u16 saved = 0xFFFF; - - backup[0] = bcm43xx_phy_read(bcm, 0x0001); - backup[1] = bcm43xx_phy_read(bcm, 0x0811); - backup[2] = bcm43xx_phy_read(bcm, 0x0812); - backup[3] = bcm43xx_phy_read(bcm, 0x0814); - backup[4] = bcm43xx_phy_read(bcm, 0x0815); - backup[5] = bcm43xx_phy_read(bcm, 0x005A); - backup[6] = bcm43xx_phy_read(bcm, 0x0059); - backup[7] = bcm43xx_phy_read(bcm, 0x0058); - backup[8] = bcm43xx_phy_read(bcm, 0x000A); - backup[9] = bcm43xx_phy_read(bcm, 0x0003); - backup[10] = bcm43xx_radio_read16(bcm, 0x007A); - backup[11] = bcm43xx_radio_read16(bcm, 0x0043); - - bcm43xx_phy_write(bcm, 0x0429, - bcm43xx_phy_read(bcm, 0x0429) & 0x7FFF); - bcm43xx_phy_write(bcm, 0x0001, - (bcm43xx_phy_read(bcm, 0x0001) & 0x3FFF) | 0x4000); - bcm43xx_phy_write(bcm, 0x0811, - bcm43xx_phy_read(bcm, 0x0811) | 0x000C); - bcm43xx_phy_write(bcm, 0x0812, - (bcm43xx_phy_read(bcm, 0x0812) & 0xFFF3) | 0x0004); - bcm43xx_phy_write(bcm, 0x0802, - bcm43xx_phy_read(bcm, 0x0802) & ~(0x1 | 0x2)); - if (phy->rev >= 6) { - backup[12] = bcm43xx_phy_read(bcm, 0x002E); - backup[13] = bcm43xx_phy_read(bcm, 0x002F); - backup[14] = bcm43xx_phy_read(bcm, 0x080F); - backup[15] = bcm43xx_phy_read(bcm, 0x0810); - backup[16] = bcm43xx_phy_read(bcm, 0x0801); - backup[17] = bcm43xx_phy_read(bcm, 0x0060); - backup[18] = bcm43xx_phy_read(bcm, 0x0014); - backup[19] = bcm43xx_phy_read(bcm, 0x0478); - - bcm43xx_phy_write(bcm, 0x002E, 0); - bcm43xx_phy_write(bcm, 0x002F, 0); - bcm43xx_phy_write(bcm, 0x080F, 0); - bcm43xx_phy_write(bcm, 0x0810, 0); - bcm43xx_phy_write(bcm, 0x0478, - bcm43xx_phy_read(bcm, 0x0478) | 0x0100); - bcm43xx_phy_write(bcm, 0x0801, - bcm43xx_phy_read(bcm, 0x0801) | 0x0040); - bcm43xx_phy_write(bcm, 0x0060, - bcm43xx_phy_read(bcm, 0x0060) | 0x0040); - bcm43xx_phy_write(bcm, 0x0014, - bcm43xx_phy_read(bcm, 0x0014) | 0x0200); - } - bcm43xx_radio_write16(bcm, 0x007A, - bcm43xx_radio_read16(bcm, 0x007A) | 0x0070); - bcm43xx_radio_write16(bcm, 0x007A, - bcm43xx_radio_read16(bcm, 0x007A) | 0x0080); - udelay(30); - - v47F = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F); - if (v47F >= 0x20) - v47F -= 0x40; - if (v47F == 31) { - for (i = 7; i >= 4; i--) { - bcm43xx_radio_write16(bcm, 0x007B, i); - udelay(20); - v47F = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F); - if (v47F >= 0x20) - v47F -= 0x40; - if (v47F < 31 && saved == 0xFFFF) - saved = i; - } - if (saved == 0xFFFF) - saved = 4; - } else { - bcm43xx_radio_write16(bcm, 0x007A, - bcm43xx_radio_read16(bcm, 0x007A) & 0x007F); - bcm43xx_phy_write(bcm, 0x0814, - bcm43xx_phy_read(bcm, 0x0814) | 0x0001); - bcm43xx_phy_write(bcm, 0x0815, - bcm43xx_phy_read(bcm, 0x0815) & 0xFFFE); - bcm43xx_phy_write(bcm, 0x0811, - bcm43xx_phy_read(bcm, 0x0811) | 0x000C); - bcm43xx_phy_write(bcm, 0x0812, - bcm43xx_phy_read(bcm, 0x0812) | 0x000C); - bcm43xx_phy_write(bcm, 0x0811, - bcm43xx_phy_read(bcm, 0x0811) | 0x0030); - bcm43xx_phy_write(bcm, 0x0812, - bcm43xx_phy_read(bcm, 0x0812) | 0x0030); - bcm43xx_phy_write(bcm, 0x005A, 0x0480); - bcm43xx_phy_write(bcm, 0x0059, 0x0810); - bcm43xx_phy_write(bcm, 0x0058, 0x000D); - if (phy->analog == 0) { - bcm43xx_phy_write(bcm, 0x0003, 0x0122); - } else { - bcm43xx_phy_write(bcm, 0x000A, - bcm43xx_phy_read(bcm, 0x000A) - | 0x2000); - } - bcm43xx_phy_write(bcm, 0x0814, - bcm43xx_phy_read(bcm, 0x0814) | 0x0004); - bcm43xx_phy_write(bcm, 0x0815, - bcm43xx_phy_read(bcm, 0x0815) & 0xFFFB); - bcm43xx_phy_write(bcm, 0x0003, - (bcm43xx_phy_read(bcm, 0x0003) & 0xFF9F) - | 0x0040); - bcm43xx_radio_write16(bcm, 0x007A, - bcm43xx_radio_read16(bcm, 0x007A) | 0x000F); - bcm43xx_set_all_gains(bcm, 3, 0, 1); - bcm43xx_radio_write16(bcm, 0x0043, - (bcm43xx_radio_read16(bcm, 0x0043) - & 0x00F0) | 0x000F); - udelay(30); - v47F = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F); - if (v47F >= 0x20) - v47F -= 0x40; - if (v47F == -32) { - for (i = 0; i < 4; i++) { - bcm43xx_radio_write16(bcm, 0x007B, i); - udelay(20); - v47F = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F); - if (v47F >= 0x20) - v47F -= 0x40; - if (v47F > -31 && saved == 0xFFFF) - saved = i; - } - if (saved == 0xFFFF) - saved = 3; - } else - saved = 0; - } - bcm43xx_radio_write16(bcm, 0x007B, saved); - - if (phy->rev >= 6) { - bcm43xx_phy_write(bcm, 0x002E, backup[12]); - bcm43xx_phy_write(bcm, 0x002F, backup[13]); - bcm43xx_phy_write(bcm, 0x080F, backup[14]); - bcm43xx_phy_write(bcm, 0x0810, backup[15]); - } - bcm43xx_phy_write(bcm, 0x0814, backup[3]); - bcm43xx_phy_write(bcm, 0x0815, backup[4]); - bcm43xx_phy_write(bcm, 0x005A, backup[5]); - bcm43xx_phy_write(bcm, 0x0059, backup[6]); - bcm43xx_phy_write(bcm, 0x0058, backup[7]); - bcm43xx_phy_write(bcm, 0x000A, backup[8]); - bcm43xx_phy_write(bcm, 0x0003, backup[9]); - bcm43xx_radio_write16(bcm, 0x0043, backup[11]); - bcm43xx_radio_write16(bcm, 0x007A, backup[10]); - bcm43xx_phy_write(bcm, 0x0802, - bcm43xx_phy_read(bcm, 0x0802) | 0x1 | 0x2); - bcm43xx_phy_write(bcm, 0x0429, - bcm43xx_phy_read(bcm, 0x0429) | 0x8000); - bcm43xx_set_original_gains(bcm); - if (phy->rev >= 6) { - bcm43xx_phy_write(bcm, 0x0801, backup[16]); - bcm43xx_phy_write(bcm, 0x0060, backup[17]); - bcm43xx_phy_write(bcm, 0x0014, backup[18]); - bcm43xx_phy_write(bcm, 0x0478, backup[19]); - } - bcm43xx_phy_write(bcm, 0x0001, backup[0]); - bcm43xx_phy_write(bcm, 0x0812, backup[2]); - bcm43xx_phy_write(bcm, 0x0811, backup[1]); -} - -void bcm43xx_calc_nrssi_slope(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - u16 backup[18] = { 0 }; - u16 tmp; - s16 nrssi0, nrssi1; - - switch (phy->type) { - case BCM43xx_PHYTYPE_B: - backup[0] = bcm43xx_radio_read16(bcm, 0x007A); - backup[1] = bcm43xx_radio_read16(bcm, 0x0052); - backup[2] = bcm43xx_radio_read16(bcm, 0x0043); - backup[3] = bcm43xx_phy_read(bcm, 0x0030); - backup[4] = bcm43xx_phy_read(bcm, 0x0026); - backup[5] = bcm43xx_phy_read(bcm, 0x0015); - backup[6] = bcm43xx_phy_read(bcm, 0x002A); - backup[7] = bcm43xx_phy_read(bcm, 0x0020); - backup[8] = bcm43xx_phy_read(bcm, 0x005A); - backup[9] = bcm43xx_phy_read(bcm, 0x0059); - backup[10] = bcm43xx_phy_read(bcm, 0x0058); - backup[11] = bcm43xx_read16(bcm, 0x03E2); - backup[12] = bcm43xx_read16(bcm, 0x03E6); - backup[13] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT); - - tmp = bcm43xx_radio_read16(bcm, 0x007A); - tmp &= (phy->rev >= 5) ? 0x007F : 0x000F; - bcm43xx_radio_write16(bcm, 0x007A, tmp); - bcm43xx_phy_write(bcm, 0x0030, 0x00FF); - bcm43xx_write16(bcm, 0x03EC, 0x7F7F); - bcm43xx_phy_write(bcm, 0x0026, 0x0000); - bcm43xx_phy_write(bcm, 0x0015, - bcm43xx_phy_read(bcm, 0x0015) | 0x0020); - bcm43xx_phy_write(bcm, 0x002A, 0x08A3); - bcm43xx_radio_write16(bcm, 0x007A, - bcm43xx_radio_read16(bcm, 0x007A) | 0x0080); - - nrssi0 = (s16)bcm43xx_phy_read(bcm, 0x0027); - bcm43xx_radio_write16(bcm, 0x007A, - bcm43xx_radio_read16(bcm, 0x007A) & 0x007F); - if (phy->analog >= 2) { - bcm43xx_write16(bcm, 0x03E6, 0x0040); - } else if (phy->analog == 0) { - bcm43xx_write16(bcm, 0x03E6, 0x0122); - } else { - bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, - bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT) & 0x2000); - } - bcm43xx_phy_write(bcm, 0x0020, 0x3F3F); - bcm43xx_phy_write(bcm, 0x0015, 0xF330); - bcm43xx_radio_write16(bcm, 0x005A, 0x0060); - bcm43xx_radio_write16(bcm, 0x0043, - bcm43xx_radio_read16(bcm, 0x0043) & 0x00F0); - bcm43xx_phy_write(bcm, 0x005A, 0x0480); - bcm43xx_phy_write(bcm, 0x0059, 0x0810); - bcm43xx_phy_write(bcm, 0x0058, 0x000D); - udelay(20); - - nrssi1 = (s16)bcm43xx_phy_read(bcm, 0x0027); - bcm43xx_phy_write(bcm, 0x0030, backup[3]); - bcm43xx_radio_write16(bcm, 0x007A, backup[0]); - bcm43xx_write16(bcm, 0x03E2, backup[11]); - bcm43xx_phy_write(bcm, 0x0026, backup[4]); - bcm43xx_phy_write(bcm, 0x0015, backup[5]); - bcm43xx_phy_write(bcm, 0x002A, backup[6]); - bcm43xx_synth_pu_workaround(bcm, radio->channel); - if (phy->analog != 0) - bcm43xx_write16(bcm, 0x03F4, backup[13]); - - bcm43xx_phy_write(bcm, 0x0020, backup[7]); - bcm43xx_phy_write(bcm, 0x005A, backup[8]); - bcm43xx_phy_write(bcm, 0x0059, backup[9]); - bcm43xx_phy_write(bcm, 0x0058, backup[10]); - bcm43xx_radio_write16(bcm, 0x0052, backup[1]); - bcm43xx_radio_write16(bcm, 0x0043, backup[2]); - - if (nrssi0 == nrssi1) - radio->nrssislope = 0x00010000; - else - radio->nrssislope = 0x00400000 / (nrssi0 - nrssi1); - - if (nrssi0 <= -4) { - radio->nrssi[0] = nrssi0; - radio->nrssi[1] = nrssi1; - } - break; - case BCM43xx_PHYTYPE_G: - if (radio->revision >= 9) - return; - if (radio->revision == 8) - bcm43xx_calc_nrssi_offset(bcm); - - bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, - bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0x7FFF); - bcm43xx_phy_write(bcm, 0x0802, - bcm43xx_phy_read(bcm, 0x0802) & 0xFFFC); - backup[7] = bcm43xx_read16(bcm, 0x03E2); - bcm43xx_write16(bcm, 0x03E2, - bcm43xx_read16(bcm, 0x03E2) | 0x8000); - backup[0] = bcm43xx_radio_read16(bcm, 0x007A); - backup[1] = bcm43xx_radio_read16(bcm, 0x0052); - backup[2] = bcm43xx_radio_read16(bcm, 0x0043); - backup[3] = bcm43xx_phy_read(bcm, 0x0015); - backup[4] = bcm43xx_phy_read(bcm, 0x005A); - backup[5] = bcm43xx_phy_read(bcm, 0x0059); - backup[6] = bcm43xx_phy_read(bcm, 0x0058); - backup[8] = bcm43xx_read16(bcm, 0x03E6); - backup[9] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT); - if (phy->rev >= 3) { - backup[10] = bcm43xx_phy_read(bcm, 0x002E); - backup[11] = bcm43xx_phy_read(bcm, 0x002F); - backup[12] = bcm43xx_phy_read(bcm, 0x080F); - backup[13] = bcm43xx_phy_read(bcm, BCM43xx_PHY_G_LO_CONTROL); - backup[14] = bcm43xx_phy_read(bcm, 0x0801); - backup[15] = bcm43xx_phy_read(bcm, 0x0060); - backup[16] = bcm43xx_phy_read(bcm, 0x0014); - backup[17] = bcm43xx_phy_read(bcm, 0x0478); - bcm43xx_phy_write(bcm, 0x002E, 0); - bcm43xx_phy_write(bcm, BCM43xx_PHY_G_LO_CONTROL, 0); - switch (phy->rev) { - case 4: case 6: case 7: - bcm43xx_phy_write(bcm, 0x0478, - bcm43xx_phy_read(bcm, 0x0478) - | 0x0100); - bcm43xx_phy_write(bcm, 0x0801, - bcm43xx_phy_read(bcm, 0x0801) - | 0x0040); - break; - case 3: case 5: - bcm43xx_phy_write(bcm, 0x0801, - bcm43xx_phy_read(bcm, 0x0801) - & 0xFFBF); - break; - } - bcm43xx_phy_write(bcm, 0x0060, - bcm43xx_phy_read(bcm, 0x0060) - | 0x0040); - bcm43xx_phy_write(bcm, 0x0014, - bcm43xx_phy_read(bcm, 0x0014) - | 0x0200); - } - bcm43xx_radio_write16(bcm, 0x007A, - bcm43xx_radio_read16(bcm, 0x007A) | 0x0070); - bcm43xx_set_all_gains(bcm, 0, 8, 0); - bcm43xx_radio_write16(bcm, 0x007A, - bcm43xx_radio_read16(bcm, 0x007A) & 0x00F7); - if (phy->rev >= 2) { - bcm43xx_phy_write(bcm, 0x0811, - (bcm43xx_phy_read(bcm, 0x0811) & 0xFFCF) | 0x0030); - bcm43xx_phy_write(bcm, 0x0812, - (bcm43xx_phy_read(bcm, 0x0812) & 0xFFCF) | 0x0010); - } - bcm43xx_radio_write16(bcm, 0x007A, - bcm43xx_radio_read16(bcm, 0x007A) | 0x0080); - udelay(20); - - nrssi0 = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F); - if (nrssi0 >= 0x0020) - nrssi0 -= 0x0040; - - bcm43xx_radio_write16(bcm, 0x007A, - bcm43xx_radio_read16(bcm, 0x007A) & 0x007F); - if (phy->analog >= 2) { - bcm43xx_phy_write(bcm, 0x0003, - (bcm43xx_phy_read(bcm, 0x0003) - & 0xFF9F) | 0x0040); - } - - bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, - bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT) - | 0x2000); - bcm43xx_radio_write16(bcm, 0x007A, - bcm43xx_radio_read16(bcm, 0x007A) | 0x000F); - bcm43xx_phy_write(bcm, 0x0015, 0xF330); - if (phy->rev >= 2) { - bcm43xx_phy_write(bcm, 0x0812, - (bcm43xx_phy_read(bcm, 0x0812) & 0xFFCF) | 0x0020); - bcm43xx_phy_write(bcm, 0x0811, - (bcm43xx_phy_read(bcm, 0x0811) & 0xFFCF) | 0x0020); - } - - bcm43xx_set_all_gains(bcm, 3, 0, 1); - if (radio->revision == 8) { - bcm43xx_radio_write16(bcm, 0x0043, 0x001F); - } else { - tmp = bcm43xx_radio_read16(bcm, 0x0052) & 0xFF0F; - bcm43xx_radio_write16(bcm, 0x0052, tmp | 0x0060); - tmp = bcm43xx_radio_read16(bcm, 0x0043) & 0xFFF0; - bcm43xx_radio_write16(bcm, 0x0043, tmp | 0x0009); - } - bcm43xx_phy_write(bcm, 0x005A, 0x0480); - bcm43xx_phy_write(bcm, 0x0059, 0x0810); - bcm43xx_phy_write(bcm, 0x0058, 0x000D); - udelay(20); - nrssi1 = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F); - if (nrssi1 >= 0x0020) - nrssi1 -= 0x0040; - if (nrssi0 == nrssi1) - radio->nrssislope = 0x00010000; - else - radio->nrssislope = 0x00400000 / (nrssi0 - nrssi1); - if (nrssi0 >= -4) { - radio->nrssi[0] = nrssi1; - radio->nrssi[1] = nrssi0; - } - if (phy->rev >= 3) { - bcm43xx_phy_write(bcm, 0x002E, backup[10]); - bcm43xx_phy_write(bcm, 0x002F, backup[11]); - bcm43xx_phy_write(bcm, 0x080F, backup[12]); - bcm43xx_phy_write(bcm, BCM43xx_PHY_G_LO_CONTROL, backup[13]); - } - if (phy->rev >= 2) { - bcm43xx_phy_write(bcm, 0x0812, - bcm43xx_phy_read(bcm, 0x0812) & 0xFFCF); - bcm43xx_phy_write(bcm, 0x0811, - bcm43xx_phy_read(bcm, 0x0811) & 0xFFCF); - } - - bcm43xx_radio_write16(bcm, 0x007A, backup[0]); - bcm43xx_radio_write16(bcm, 0x0052, backup[1]); - bcm43xx_radio_write16(bcm, 0x0043, backup[2]); - bcm43xx_write16(bcm, 0x03E2, backup[7]); - bcm43xx_write16(bcm, 0x03E6, backup[8]); - bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, backup[9]); - bcm43xx_phy_write(bcm, 0x0015, backup[3]); - bcm43xx_phy_write(bcm, 0x005A, backup[4]); - bcm43xx_phy_write(bcm, 0x0059, backup[5]); - bcm43xx_phy_write(bcm, 0x0058, backup[6]); - bcm43xx_synth_pu_workaround(bcm, radio->channel); - bcm43xx_phy_write(bcm, 0x0802, - bcm43xx_phy_read(bcm, 0x0802) | (0x0001 | 0x0002)); - bcm43xx_set_original_gains(bcm); - bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, - bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) | 0x8000); - if (phy->rev >= 3) { - bcm43xx_phy_write(bcm, 0x0801, backup[14]); - bcm43xx_phy_write(bcm, 0x0060, backup[15]); - bcm43xx_phy_write(bcm, 0x0014, backup[16]); - bcm43xx_phy_write(bcm, 0x0478, backup[17]); - } - bcm43xx_nrssi_mem_update(bcm); - bcm43xx_calc_nrssi_threshold(bcm); - break; - default: - assert(0); - } -} - -void bcm43xx_calc_nrssi_threshold(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - s32 threshold; - s32 a, b; - s16 tmp16; - u16 tmp_u16; - - switch (phy->type) { - case BCM43xx_PHYTYPE_B: { - if (radio->version != 0x2050) - return; - if (!(bcm->sprom.boardflags & BCM43xx_BFL_RSSI)) - return; - - if (radio->revision >= 6) { - threshold = (radio->nrssi[1] - radio->nrssi[0]) * 32; - threshold += 20 * (radio->nrssi[0] + 1); - threshold /= 40; - } else - threshold = radio->nrssi[1] - 5; - - threshold = limit_value(threshold, 0, 0x3E); - bcm43xx_phy_read(bcm, 0x0020); /* dummy read */ - bcm43xx_phy_write(bcm, 0x0020, (((u16)threshold) << 8) | 0x001C); - - if (radio->revision >= 6) { - bcm43xx_phy_write(bcm, 0x0087, 0x0E0D); - bcm43xx_phy_write(bcm, 0x0086, 0x0C0B); - bcm43xx_phy_write(bcm, 0x0085, 0x0A09); - bcm43xx_phy_write(bcm, 0x0084, 0x0808); - bcm43xx_phy_write(bcm, 0x0083, 0x0808); - bcm43xx_phy_write(bcm, 0x0082, 0x0604); - bcm43xx_phy_write(bcm, 0x0081, 0x0302); - bcm43xx_phy_write(bcm, 0x0080, 0x0100); - } - break; - } - case BCM43xx_PHYTYPE_G: - if (!phy->connected || - !(bcm->sprom.boardflags & BCM43xx_BFL_RSSI)) { - tmp16 = bcm43xx_nrssi_hw_read(bcm, 0x20); - if (tmp16 >= 0x20) - tmp16 -= 0x40; - if (tmp16 < 3) { - bcm43xx_phy_write(bcm, 0x048A, - (bcm43xx_phy_read(bcm, 0x048A) - & 0xF000) | 0x09EB); - } else { - bcm43xx_phy_write(bcm, 0x048A, - (bcm43xx_phy_read(bcm, 0x048A) - & 0xF000) | 0x0AED); - } - } else { - if (radio->interfmode == BCM43xx_RADIO_INTERFMODE_NONWLAN) { - a = 0xE; - b = 0xA; - } else if (!radio->aci_wlan_automatic && radio->aci_enable) { - a = 0x13; - b = 0x12; - } else { - a = 0xE; - b = 0x11; - } - - a = a * (radio->nrssi[1] - radio->nrssi[0]); - a += (radio->nrssi[0] << 6); - if (a < 32) - a += 31; - else - a += 32; - a = a >> 6; - a = limit_value(a, -31, 31); - - b = b * (radio->nrssi[1] - radio->nrssi[0]); - b += (radio->nrssi[0] << 6); - if (b < 32) - b += 31; - else - b += 32; - b = b >> 6; - b = limit_value(b, -31, 31); - - tmp_u16 = bcm43xx_phy_read(bcm, 0x048A) & 0xF000; - tmp_u16 |= ((u32)b & 0x0000003F); - tmp_u16 |= (((u32)a & 0x0000003F) << 6); - bcm43xx_phy_write(bcm, 0x048A, tmp_u16); - } - break; - default: - assert(0); - } -} - -/* Stack implementation to save/restore values from the - * interference mitigation code. - * It is save to restore values in random order. - */ -static void _stack_save(u32 *_stackptr, size_t *stackidx, - u8 id, u16 offset, u16 value) -{ - u32 *stackptr = &(_stackptr[*stackidx]); - - assert((offset & 0xE000) == 0x0000); - assert((id & 0xF8) == 0x00); - *stackptr = offset; - *stackptr |= ((u32)id) << 13; - *stackptr |= ((u32)value) << 16; - (*stackidx)++; - assert(*stackidx < BCM43xx_INTERFSTACK_SIZE); -} - -static u16 _stack_restore(u32 *stackptr, - u8 id, u16 offset) -{ - size_t i; - - assert((offset & 0xE000) == 0x0000); - assert((id & 0xF8) == 0x00); - for (i = 0; i < BCM43xx_INTERFSTACK_SIZE; i++, stackptr++) { - if ((*stackptr & 0x00001FFF) != offset) - continue; - if (((*stackptr & 0x00007000) >> 13) != id) - continue; - return ((*stackptr & 0xFFFF0000) >> 16); - } - assert(0); - - return 0; -} - -#define phy_stacksave(offset) \ - do { \ - _stack_save(stack, &stackidx, 0x1, (offset), \ - bcm43xx_phy_read(bcm, (offset))); \ - } while (0) -#define phy_stackrestore(offset) \ - do { \ - bcm43xx_phy_write(bcm, (offset), \ - _stack_restore(stack, 0x1, \ - (offset))); \ - } while (0) -#define radio_stacksave(offset) \ - do { \ - _stack_save(stack, &stackidx, 0x2, (offset), \ - bcm43xx_radio_read16(bcm, (offset))); \ - } while (0) -#define radio_stackrestore(offset) \ - do { \ - bcm43xx_radio_write16(bcm, (offset), \ - _stack_restore(stack, 0x2, \ - (offset))); \ - } while (0) -#define ilt_stacksave(offset) \ - do { \ - _stack_save(stack, &stackidx, 0x3, (offset), \ - bcm43xx_ilt_read(bcm, (offset))); \ - } while (0) -#define ilt_stackrestore(offset) \ - do { \ - bcm43xx_ilt_write(bcm, (offset), \ - _stack_restore(stack, 0x3, \ - (offset))); \ - } while (0) - -static void -bcm43xx_radio_interference_mitigation_enable(struct bcm43xx_private *bcm, - int mode) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - u16 tmp, flipped; - u32 tmp32; - size_t stackidx = 0; - u32 *stack = radio->interfstack; - - switch (mode) { - case BCM43xx_RADIO_INTERFMODE_NONWLAN: - if (phy->rev != 1) { - bcm43xx_phy_write(bcm, 0x042B, - bcm43xx_phy_read(bcm, 0x042B) | 0x0800); - bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, - bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & ~0x4000); - break; - } - radio_stacksave(0x0078); - tmp = (bcm43xx_radio_read16(bcm, 0x0078) & 0x001E); - flipped = flip_4bit(tmp); - if (flipped < 10 && flipped >= 8) - flipped = 7; - else if (flipped >= 10) - flipped -= 3; - flipped = flip_4bit(flipped); - flipped = (flipped << 1) | 0x0020; - bcm43xx_radio_write16(bcm, 0x0078, flipped); - - bcm43xx_calc_nrssi_threshold(bcm); - - phy_stacksave(0x0406); - bcm43xx_phy_write(bcm, 0x0406, 0x7E28); - - bcm43xx_phy_write(bcm, 0x042B, - bcm43xx_phy_read(bcm, 0x042B) | 0x0800); - bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD, - bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) | 0x1000); - - phy_stacksave(0x04A0); - bcm43xx_phy_write(bcm, 0x04A0, - (bcm43xx_phy_read(bcm, 0x04A0) & 0xC0C0) | 0x0008); - phy_stacksave(0x04A1); - bcm43xx_phy_write(bcm, 0x04A1, - (bcm43xx_phy_read(bcm, 0x04A1) & 0xC0C0) | 0x0605); - phy_stacksave(0x04A2); - bcm43xx_phy_write(bcm, 0x04A2, - (bcm43xx_phy_read(bcm, 0x04A2) & 0xC0C0) | 0x0204); - phy_stacksave(0x04A8); - bcm43xx_phy_write(bcm, 0x04A8, - (bcm43xx_phy_read(bcm, 0x04A8) & 0xC0C0) | 0x0803); - phy_stacksave(0x04AB); - bcm43xx_phy_write(bcm, 0x04AB, - (bcm43xx_phy_read(bcm, 0x04AB) & 0xC0C0) | 0x0605); - - phy_stacksave(0x04A7); - bcm43xx_phy_write(bcm, 0x04A7, 0x0002); - phy_stacksave(0x04A3); - bcm43xx_phy_write(bcm, 0x04A3, 0x287A); - phy_stacksave(0x04A9); - bcm43xx_phy_write(bcm, 0x04A9, 0x2027); - phy_stacksave(0x0493); - bcm43xx_phy_write(bcm, 0x0493, 0x32F5); - phy_stacksave(0x04AA); - bcm43xx_phy_write(bcm, 0x04AA, 0x2027); - phy_stacksave(0x04AC); - bcm43xx_phy_write(bcm, 0x04AC, 0x32F5); - break; - case BCM43xx_RADIO_INTERFMODE_MANUALWLAN: - if (bcm43xx_phy_read(bcm, 0x0033) & 0x0800) - break; - - radio->aci_enable = 1; - - phy_stacksave(BCM43xx_PHY_RADIO_BITFIELD); - phy_stacksave(BCM43xx_PHY_G_CRS); - if (phy->rev < 2) { - phy_stacksave(0x0406); - } else { - phy_stacksave(0x04C0); - phy_stacksave(0x04C1); - } - phy_stacksave(0x0033); - phy_stacksave(0x04A7); - phy_stacksave(0x04A3); - phy_stacksave(0x04A9); - phy_stacksave(0x04AA); - phy_stacksave(0x04AC); - phy_stacksave(0x0493); - phy_stacksave(0x04A1); - phy_stacksave(0x04A0); - phy_stacksave(0x04A2); - phy_stacksave(0x048A); - phy_stacksave(0x04A8); - phy_stacksave(0x04AB); - if (phy->rev == 2) { - phy_stacksave(0x04AD); - phy_stacksave(0x04AE); - } else if (phy->rev >= 3) { - phy_stacksave(0x04AD); - phy_stacksave(0x0415); - phy_stacksave(0x0416); - phy_stacksave(0x0417); - ilt_stacksave(0x1A00 + 0x2); - ilt_stacksave(0x1A00 + 0x3); - } - phy_stacksave(0x042B); - phy_stacksave(0x048C); - - bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD, - bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) - & ~0x1000); - bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, - (bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) - & 0xFFFC) | 0x0002); - - bcm43xx_phy_write(bcm, 0x0033, 0x0800); - bcm43xx_phy_write(bcm, 0x04A3, 0x2027); - bcm43xx_phy_write(bcm, 0x04A9, 0x1CA8); - bcm43xx_phy_write(bcm, 0x0493, 0x287A); - bcm43xx_phy_write(bcm, 0x04AA, 0x1CA8); - bcm43xx_phy_write(bcm, 0x04AC, 0x287A); - - bcm43xx_phy_write(bcm, 0x04A0, - (bcm43xx_phy_read(bcm, 0x04A0) - & 0xFFC0) | 0x001A); - bcm43xx_phy_write(bcm, 0x04A7, 0x000D); - - if (phy->rev < 2) { - bcm43xx_phy_write(bcm, 0x0406, 0xFF0D); - } else if (phy->rev == 2) { - bcm43xx_phy_write(bcm, 0x04C0, 0xFFFF); - bcm43xx_phy_write(bcm, 0x04C1, 0x00A9); - } else { - bcm43xx_phy_write(bcm, 0x04C0, 0x00C1); - bcm43xx_phy_write(bcm, 0x04C1, 0x0059); - } - - bcm43xx_phy_write(bcm, 0x04A1, - (bcm43xx_phy_read(bcm, 0x04A1) - & 0xC0FF) | 0x1800); - bcm43xx_phy_write(bcm, 0x04A1, - (bcm43xx_phy_read(bcm, 0x04A1) - & 0xFFC0) | 0x0015); - bcm43xx_phy_write(bcm, 0x04A8, - (bcm43xx_phy_read(bcm, 0x04A8) - & 0xCFFF) | 0x1000); - bcm43xx_phy_write(bcm, 0x04A8, - (bcm43xx_phy_read(bcm, 0x04A8) - & 0xF0FF) | 0x0A00); - bcm43xx_phy_write(bcm, 0x04AB, - (bcm43xx_phy_read(bcm, 0x04AB) - & 0xCFFF) | 0x1000); - bcm43xx_phy_write(bcm, 0x04AB, - (bcm43xx_phy_read(bcm, 0x04AB) - & 0xF0FF) | 0x0800); - bcm43xx_phy_write(bcm, 0x04AB, - (bcm43xx_phy_read(bcm, 0x04AB) - & 0xFFCF) | 0x0010); - bcm43xx_phy_write(bcm, 0x04AB, - (bcm43xx_phy_read(bcm, 0x04AB) - & 0xFFF0) | 0x0005); - bcm43xx_phy_write(bcm, 0x04A8, - (bcm43xx_phy_read(bcm, 0x04A8) - & 0xFFCF) | 0x0010); - bcm43xx_phy_write(bcm, 0x04A8, - (bcm43xx_phy_read(bcm, 0x04A8) - & 0xFFF0) | 0x0006); - bcm43xx_phy_write(bcm, 0x04A2, - (bcm43xx_phy_read(bcm, 0x04A2) - & 0xF0FF) | 0x0800); - bcm43xx_phy_write(bcm, 0x04A0, - (bcm43xx_phy_read(bcm, 0x04A0) - & 0xF0FF) | 0x0500); - bcm43xx_phy_write(bcm, 0x04A2, - (bcm43xx_phy_read(bcm, 0x04A2) - & 0xFFF0) | 0x000B); - - if (phy->rev >= 3) { - bcm43xx_phy_write(bcm, 0x048A, - bcm43xx_phy_read(bcm, 0x048A) - & ~0x8000); - bcm43xx_phy_write(bcm, 0x0415, - (bcm43xx_phy_read(bcm, 0x0415) - & 0x8000) | 0x36D8); - bcm43xx_phy_write(bcm, 0x0416, - (bcm43xx_phy_read(bcm, 0x0416) - & 0x8000) | 0x36D8); - bcm43xx_phy_write(bcm, 0x0417, - (bcm43xx_phy_read(bcm, 0x0417) - & 0xFE00) | 0x016D); - } else { - bcm43xx_phy_write(bcm, 0x048A, - bcm43xx_phy_read(bcm, 0x048A) - | 0x1000); - bcm43xx_phy_write(bcm, 0x048A, - (bcm43xx_phy_read(bcm, 0x048A) - & 0x9FFF) | 0x2000); - tmp32 = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, - BCM43xx_UCODEFLAGS_OFFSET); - if (!(tmp32 & 0x800)) { - tmp32 |= 0x800; - bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, - BCM43xx_UCODEFLAGS_OFFSET, - tmp32); - } - } - if (phy->rev >= 2) { - bcm43xx_phy_write(bcm, 0x042B, - bcm43xx_phy_read(bcm, 0x042B) - | 0x0800); - } - bcm43xx_phy_write(bcm, 0x048C, - (bcm43xx_phy_read(bcm, 0x048C) - & 0xF0FF) | 0x0200); - if (phy->rev == 2) { - bcm43xx_phy_write(bcm, 0x04AE, - (bcm43xx_phy_read(bcm, 0x04AE) - & 0xFF00) | 0x007F); - bcm43xx_phy_write(bcm, 0x04AD, - (bcm43xx_phy_read(bcm, 0x04AD) - & 0x00FF) | 0x1300); - } else if (phy->rev >= 6) { - bcm43xx_ilt_write(bcm, 0x1A00 + 0x3, 0x007F); - bcm43xx_ilt_write(bcm, 0x1A00 + 0x2, 0x007F); - bcm43xx_phy_write(bcm, 0x04AD, - bcm43xx_phy_read(bcm, 0x04AD) - & 0x00FF); - } - bcm43xx_calc_nrssi_slope(bcm); - break; - default: - assert(0); - } -} - -static void -bcm43xx_radio_interference_mitigation_disable(struct bcm43xx_private *bcm, - int mode) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - u32 tmp32; - u32 *stack = radio->interfstack; - - switch (mode) { - case BCM43xx_RADIO_INTERFMODE_NONWLAN: - if (phy->rev != 1) { - bcm43xx_phy_write(bcm, 0x042B, - bcm43xx_phy_read(bcm, 0x042B) & ~0x0800); - bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, - bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) | 0x4000); - break; - } - phy_stackrestore(0x0078); - bcm43xx_calc_nrssi_threshold(bcm); - phy_stackrestore(0x0406); - bcm43xx_phy_write(bcm, 0x042B, - bcm43xx_phy_read(bcm, 0x042B) & ~0x0800); - if (!bcm->bad_frames_preempt) { - bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD, - bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) - & ~(1 << 11)); - } - bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, - bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) | 0x4000); - phy_stackrestore(0x04A0); - phy_stackrestore(0x04A1); - phy_stackrestore(0x04A2); - phy_stackrestore(0x04A8); - phy_stackrestore(0x04AB); - phy_stackrestore(0x04A7); - phy_stackrestore(0x04A3); - phy_stackrestore(0x04A9); - phy_stackrestore(0x0493); - phy_stackrestore(0x04AA); - phy_stackrestore(0x04AC); - break; - case BCM43xx_RADIO_INTERFMODE_MANUALWLAN: - if (!(bcm43xx_phy_read(bcm, 0x0033) & 0x0800)) - break; - - radio->aci_enable = 0; - - phy_stackrestore(BCM43xx_PHY_RADIO_BITFIELD); - phy_stackrestore(BCM43xx_PHY_G_CRS); - phy_stackrestore(0x0033); - phy_stackrestore(0x04A3); - phy_stackrestore(0x04A9); - phy_stackrestore(0x0493); - phy_stackrestore(0x04AA); - phy_stackrestore(0x04AC); - phy_stackrestore(0x04A0); - phy_stackrestore(0x04A7); - if (phy->rev >= 2) { - phy_stackrestore(0x04C0); - phy_stackrestore(0x04C1); - } else - phy_stackrestore(0x0406); - phy_stackrestore(0x04A1); - phy_stackrestore(0x04AB); - phy_stackrestore(0x04A8); - if (phy->rev == 2) { - phy_stackrestore(0x04AD); - phy_stackrestore(0x04AE); - } else if (phy->rev >= 3) { - phy_stackrestore(0x04AD); - phy_stackrestore(0x0415); - phy_stackrestore(0x0416); - phy_stackrestore(0x0417); - ilt_stackrestore(0x1A00 + 0x2); - ilt_stackrestore(0x1A00 + 0x3); - } - phy_stackrestore(0x04A2); - phy_stackrestore(0x04A8); - phy_stackrestore(0x042B); - phy_stackrestore(0x048C); - tmp32 = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, - BCM43xx_UCODEFLAGS_OFFSET); - if (tmp32 & 0x800) { - tmp32 &= ~0x800; - bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, - BCM43xx_UCODEFLAGS_OFFSET, - tmp32); - } - bcm43xx_calc_nrssi_slope(bcm); - break; - default: - assert(0); - } -} - -#undef phy_stacksave -#undef phy_stackrestore -#undef radio_stacksave -#undef radio_stackrestore -#undef ilt_stacksave -#undef ilt_stackrestore - -int bcm43xx_radio_set_interference_mitigation(struct bcm43xx_private *bcm, - int mode) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - int currentmode; - - if ((phy->type != BCM43xx_PHYTYPE_G) || - (phy->rev == 0) || - (!phy->connected)) - return -ENODEV; - - radio->aci_wlan_automatic = 0; - switch (mode) { - case BCM43xx_RADIO_INTERFMODE_AUTOWLAN: - radio->aci_wlan_automatic = 1; - if (radio->aci_enable) - mode = BCM43xx_RADIO_INTERFMODE_MANUALWLAN; - else - mode = BCM43xx_RADIO_INTERFMODE_NONE; - break; - case BCM43xx_RADIO_INTERFMODE_NONE: - case BCM43xx_RADIO_INTERFMODE_NONWLAN: - case BCM43xx_RADIO_INTERFMODE_MANUALWLAN: - break; - default: - return -EINVAL; - } - - currentmode = radio->interfmode; - if (currentmode == mode) - return 0; - if (currentmode != BCM43xx_RADIO_INTERFMODE_NONE) - bcm43xx_radio_interference_mitigation_disable(bcm, currentmode); - - if (mode == BCM43xx_RADIO_INTERFMODE_NONE) { - radio->aci_enable = 0; - radio->aci_hw_rssi = 0; - } else - bcm43xx_radio_interference_mitigation_enable(bcm, mode); - radio->interfmode = mode; - - return 0; -} - -u16 bcm43xx_radio_calibrationvalue(struct bcm43xx_private *bcm) -{ - u16 reg, index, ret; - - reg = bcm43xx_radio_read16(bcm, 0x0060); - index = (reg & 0x001E) >> 1; - ret = rcc_table[index] << 1; - ret |= (reg & 0x0001); - ret |= 0x0020; - - return ret; -} - -#define LPD(L, P, D) (((L) << 2) | ((P) << 1) | ((D) << 0)) -static u16 bcm43xx_get_812_value(struct bcm43xx_private *bcm, u8 lpd) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - u16 loop_or = 0; - u16 adj_loopback_gain = phy->loopback_gain[0]; - u8 loop; - u16 extern_lna_control; - - if (!phy->connected) - return 0; - if (!has_loopback_gain(phy)) { - if (phy->rev < 7 || !(bcm->sprom.boardflags - & BCM43xx_BFL_EXTLNA)) { - switch (lpd) { - case LPD(0, 1, 1): - return 0x0FB2; - case LPD(0, 0, 1): - return 0x00B2; - case LPD(1, 0, 1): - return 0x30B2; - case LPD(1, 0, 0): - return 0x30B3; - default: - assert(0); - } - } else { - switch (lpd) { - case LPD(0, 1, 1): - return 0x8FB2; - case LPD(0, 0, 1): - return 0x80B2; - case LPD(1, 0, 1): - return 0x20B2; - case LPD(1, 0, 0): - return 0x20B3; - default: - assert(0); - } - } - } else { - if (radio->revision == 8) - adj_loopback_gain += 0x003E; - else - adj_loopback_gain += 0x0026; - if (adj_loopback_gain >= 0x46) { - adj_loopback_gain -= 0x46; - extern_lna_control = 0x3000; - } else if (adj_loopback_gain >= 0x3A) { - adj_loopback_gain -= 0x3A; - extern_lna_control = 0x2000; - } else if (adj_loopback_gain >= 0x2E) { - adj_loopback_gain -= 0x2E; - extern_lna_control = 0x1000; - } else { - adj_loopback_gain -= 0x10; - extern_lna_control = 0x0000; - } - for (loop = 0; loop < 16; loop++) { - u16 tmp = adj_loopback_gain - 6 * loop; - if (tmp < 6) - break; - } - - loop_or = (loop << 8) | extern_lna_control; - if (phy->rev >= 7 && bcm->sprom.boardflags - & BCM43xx_BFL_EXTLNA) { - if (extern_lna_control) - loop_or |= 0x8000; - switch (lpd) { - case LPD(0, 1, 1): - return 0x8F92; - case LPD(0, 0, 1): - return (0x8092 | loop_or); - case LPD(1, 0, 1): - return (0x2092 | loop_or); - case LPD(1, 0, 0): - return (0x2093 | loop_or); - default: - assert(0); - } - } else { - switch (lpd) { - case LPD(0, 1, 1): - return 0x0F92; - case LPD(0, 0, 1): - case LPD(1, 0, 1): - return (0x0092 | loop_or); - case LPD(1, 0, 0): - return (0x0093 | loop_or); - default: - assert(0); - } - } - } - return 0; -} - -u16 bcm43xx_radio_init2050(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - u16 backup[21] = { 0 }; - u16 ret; - u16 i, j; - u32 tmp1 = 0, tmp2 = 0; - - backup[0] = bcm43xx_radio_read16(bcm, 0x0043); - backup[14] = bcm43xx_radio_read16(bcm, 0x0051); - backup[15] = bcm43xx_radio_read16(bcm, 0x0052); - backup[1] = bcm43xx_phy_read(bcm, 0x0015); - backup[16] = bcm43xx_phy_read(bcm, 0x005A); - backup[17] = bcm43xx_phy_read(bcm, 0x0059); - backup[18] = bcm43xx_phy_read(bcm, 0x0058); - if (phy->type == BCM43xx_PHYTYPE_B) { - backup[2] = bcm43xx_phy_read(bcm, 0x0030); - backup[3] = bcm43xx_read16(bcm, 0x03EC); - bcm43xx_phy_write(bcm, 0x0030, 0x00FF); - bcm43xx_write16(bcm, 0x03EC, 0x3F3F); - } else { - if (phy->connected) { - backup[4] = bcm43xx_phy_read(bcm, 0x0811); - backup[5] = bcm43xx_phy_read(bcm, 0x0812); - backup[6] = bcm43xx_phy_read(bcm, 0x0814); - backup[7] = bcm43xx_phy_read(bcm, 0x0815); - backup[8] = bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS); - backup[9] = bcm43xx_phy_read(bcm, 0x0802); - bcm43xx_phy_write(bcm, 0x0814, - (bcm43xx_phy_read(bcm, 0x0814) - | 0x0003)); - bcm43xx_phy_write(bcm, 0x0815, - (bcm43xx_phy_read(bcm, 0x0815) - & 0xFFFC)); - bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, - (bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) - & 0x7FFF)); - bcm43xx_phy_write(bcm, 0x0802, - (bcm43xx_phy_read(bcm, 0x0802) & 0xFFFC)); - if (phy->rev > 1) { /* loopback gain enabled */ - backup[19] = bcm43xx_phy_read(bcm, 0x080F); - backup[20] = bcm43xx_phy_read(bcm, 0x0810); - if (phy->rev >= 3) - bcm43xx_phy_write(bcm, 0x080F, 0xC020); - else - bcm43xx_phy_write(bcm, 0x080F, 0x8020); - bcm43xx_phy_write(bcm, 0x0810, 0x0000); - } - bcm43xx_phy_write(bcm, 0x0812, - bcm43xx_get_812_value(bcm, LPD(0, 1, 1))); - if (phy->rev < 7 || !(bcm->sprom.boardflags - & BCM43xx_BFL_EXTLNA)) - bcm43xx_phy_write(bcm, 0x0811, 0x01B3); - else - bcm43xx_phy_write(bcm, 0x0811, 0x09B3); - } - } - bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_RADIO, - (bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_RADIO) | 0x8000)); - backup[10] = bcm43xx_phy_read(bcm, 0x0035); - bcm43xx_phy_write(bcm, 0x0035, - (bcm43xx_phy_read(bcm, 0x0035) & 0xFF7F)); - backup[11] = bcm43xx_read16(bcm, 0x03E6); - backup[12] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT); - - // Initialization - if (phy->analog == 0) { - bcm43xx_write16(bcm, 0x03E6, 0x0122); - } else { - if (phy->analog >= 2) - bcm43xx_phy_write(bcm, 0x0003, - (bcm43xx_phy_read(bcm, 0x0003) - & 0xFFBF) | 0x0040); - bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, - (bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT) - | 0x2000)); - } - - ret = bcm43xx_radio_calibrationvalue(bcm); - - if (phy->type == BCM43xx_PHYTYPE_B) - bcm43xx_radio_write16(bcm, 0x0078, 0x0026); - - if (phy->connected) - bcm43xx_phy_write(bcm, 0x0812, - bcm43xx_get_812_value(bcm, LPD(0, 1, 1))); - bcm43xx_phy_write(bcm, 0x0015, 0xBFAF); - bcm43xx_phy_write(bcm, 0x002B, 0x1403); - if (phy->connected) - bcm43xx_phy_write(bcm, 0x0812, - bcm43xx_get_812_value(bcm, LPD(0, 0, 1))); - bcm43xx_phy_write(bcm, 0x0015, 0xBFA0); - bcm43xx_radio_write16(bcm, 0x0051, - (bcm43xx_radio_read16(bcm, 0x0051) | 0x0004)); - if (radio->revision == 8) - bcm43xx_radio_write16(bcm, 0x0043, 0x001F); - else { - bcm43xx_radio_write16(bcm, 0x0052, 0x0000); - bcm43xx_radio_write16(bcm, 0x0043, - (bcm43xx_radio_read16(bcm, 0x0043) & 0xFFF0) - | 0x0009); - } - bcm43xx_phy_write(bcm, 0x0058, 0x0000); - - for (i = 0; i < 16; i++) { - bcm43xx_phy_write(bcm, 0x005A, 0x0480); - bcm43xx_phy_write(bcm, 0x0059, 0xC810); - bcm43xx_phy_write(bcm, 0x0058, 0x000D); - if (phy->connected) - bcm43xx_phy_write(bcm, 0x0812, - bcm43xx_get_812_value(bcm, LPD(1, 0, 1))); - bcm43xx_phy_write(bcm, 0x0015, 0xAFB0); - udelay(10); - if (phy->connected) - bcm43xx_phy_write(bcm, 0x0812, - bcm43xx_get_812_value(bcm, LPD(1, 0, 1))); - bcm43xx_phy_write(bcm, 0x0015, 0xEFB0); - udelay(10); - if (phy->connected) - bcm43xx_phy_write(bcm, 0x0812, - bcm43xx_get_812_value(bcm, LPD(1, 0, 0))); - bcm43xx_phy_write(bcm, 0x0015, 0xFFF0); - udelay(20); - tmp1 += bcm43xx_phy_read(bcm, 0x002D); - bcm43xx_phy_write(bcm, 0x0058, 0x0000); - if (phy->connected) - bcm43xx_phy_write(bcm, 0x0812, - bcm43xx_get_812_value(bcm, LPD(1, 0, 1))); - bcm43xx_phy_write(bcm, 0x0015, 0xAFB0); - } - - tmp1++; - tmp1 >>= 9; - udelay(10); - bcm43xx_phy_write(bcm, 0x0058, 0x0000); - - for (i = 0; i < 16; i++) { - bcm43xx_radio_write16(bcm, 0x0078, (flip_4bit(i) << 1) | 0x0020); - backup[13] = bcm43xx_radio_read16(bcm, 0x0078); - udelay(10); - for (j = 0; j < 16; j++) { - bcm43xx_phy_write(bcm, 0x005A, 0x0D80); - bcm43xx_phy_write(bcm, 0x0059, 0xC810); - bcm43xx_phy_write(bcm, 0x0058, 0x000D); - if (phy->connected) - bcm43xx_phy_write(bcm, 0x0812, - bcm43xx_get_812_value(bcm, - LPD(1, 0, 1))); - bcm43xx_phy_write(bcm, 0x0015, 0xAFB0); - udelay(10); - if (phy->connected) - bcm43xx_phy_write(bcm, 0x0812, - bcm43xx_get_812_value(bcm, - LPD(1, 0, 1))); - bcm43xx_phy_write(bcm, 0x0015, 0xEFB0); - udelay(10); - if (phy->connected) - bcm43xx_phy_write(bcm, 0x0812, - bcm43xx_get_812_value(bcm, - LPD(1, 0, 0))); - bcm43xx_phy_write(bcm, 0x0015, 0xFFF0); - udelay(10); - tmp2 += bcm43xx_phy_read(bcm, 0x002D); - bcm43xx_phy_write(bcm, 0x0058, 0x0000); - if (phy->connected) - bcm43xx_phy_write(bcm, 0x0812, - bcm43xx_get_812_value(bcm, - LPD(1, 0, 1))); - bcm43xx_phy_write(bcm, 0x0015, 0xAFB0); - } - tmp2++; - tmp2 >>= 8; - if (tmp1 < tmp2) - break; - } - - /* Restore the registers */ - bcm43xx_phy_write(bcm, 0x0015, backup[1]); - bcm43xx_radio_write16(bcm, 0x0051, backup[14]); - bcm43xx_radio_write16(bcm, 0x0052, backup[15]); - bcm43xx_radio_write16(bcm, 0x0043, backup[0]); - bcm43xx_phy_write(bcm, 0x005A, backup[16]); - bcm43xx_phy_write(bcm, 0x0059, backup[17]); - bcm43xx_phy_write(bcm, 0x0058, backup[18]); - bcm43xx_write16(bcm, 0x03E6, backup[11]); - if (phy->analog != 0) - bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, backup[12]); - bcm43xx_phy_write(bcm, 0x0035, backup[10]); - bcm43xx_radio_selectchannel(bcm, radio->channel, 1); - if (phy->type == BCM43xx_PHYTYPE_B) { - bcm43xx_phy_write(bcm, 0x0030, backup[2]); - bcm43xx_write16(bcm, 0x03EC, backup[3]); - } else { - if (phy->connected) { - bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_RADIO, - (bcm43xx_read16(bcm, - BCM43xx_MMIO_PHY_RADIO) & 0x7FFF)); - bcm43xx_phy_write(bcm, 0x0811, backup[4]); - bcm43xx_phy_write(bcm, 0x0812, backup[5]); - bcm43xx_phy_write(bcm, 0x0814, backup[6]); - bcm43xx_phy_write(bcm, 0x0815, backup[7]); - bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, backup[8]); - bcm43xx_phy_write(bcm, 0x0802, backup[9]); - if (phy->rev > 1) { - bcm43xx_phy_write(bcm, 0x080F, backup[19]); - bcm43xx_phy_write(bcm, 0x0810, backup[20]); - } - } - } - if (i >= 15) - ret = backup[13]; - - return ret; -} - -void bcm43xx_radio_init2060(struct bcm43xx_private *bcm) -{ - int err; - - bcm43xx_radio_write16(bcm, 0x0004, 0x00C0); - bcm43xx_radio_write16(bcm, 0x0005, 0x0008); - bcm43xx_radio_write16(bcm, 0x0009, 0x0040); - bcm43xx_radio_write16(bcm, 0x0005, 0x00AA); - bcm43xx_radio_write16(bcm, 0x0032, 0x008F); - bcm43xx_radio_write16(bcm, 0x0006, 0x008F); - bcm43xx_radio_write16(bcm, 0x0034, 0x008F); - bcm43xx_radio_write16(bcm, 0x002C, 0x0007); - bcm43xx_radio_write16(bcm, 0x0082, 0x0080); - bcm43xx_radio_write16(bcm, 0x0080, 0x0000); - bcm43xx_radio_write16(bcm, 0x003F, 0x00DA); - bcm43xx_radio_write16(bcm, 0x0005, bcm43xx_radio_read16(bcm, 0x0005) & ~0x0008); - bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0010); - bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0020); - bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0020); - udelay(400); - - bcm43xx_radio_write16(bcm, 0x0081, (bcm43xx_radio_read16(bcm, 0x0081) & ~0x0020) | 0x0010); - udelay(400); - - bcm43xx_radio_write16(bcm, 0x0005, (bcm43xx_radio_read16(bcm, 0x0005) & ~0x0008) | 0x0008); - bcm43xx_radio_write16(bcm, 0x0085, bcm43xx_radio_read16(bcm, 0x0085) & ~0x0010); - bcm43xx_radio_write16(bcm, 0x0005, bcm43xx_radio_read16(bcm, 0x0005) & ~0x0008); - bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0040); - bcm43xx_radio_write16(bcm, 0x0081, (bcm43xx_radio_read16(bcm, 0x0081) & ~0x0040) | 0x0040); - bcm43xx_radio_write16(bcm, 0x0005, (bcm43xx_radio_read16(bcm, 0x0081) & ~0x0008) | 0x0008); - bcm43xx_phy_write(bcm, 0x0063, 0xDDC6); - bcm43xx_phy_write(bcm, 0x0069, 0x07BE); - bcm43xx_phy_write(bcm, 0x006A, 0x0000); - - err = bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_A, 0); - assert(err == 0); - udelay(1000); -} - -static inline -u16 freq_r3A_value(u16 frequency) -{ - u16 value; - - if (frequency < 5091) - value = 0x0040; - else if (frequency < 5321) - value = 0x0000; - else if (frequency < 5806) - value = 0x0080; - else - value = 0x0040; - - return value; -} - -void bcm43xx_radio_set_tx_iq(struct bcm43xx_private *bcm) -{ - static const u8 data_high[5] = { 0x00, 0x40, 0x80, 0x90, 0xD0 }; - static const u8 data_low[5] = { 0x00, 0x01, 0x05, 0x06, 0x0A }; - u16 tmp = bcm43xx_radio_read16(bcm, 0x001E); - int i, j; - - for (i = 0; i < 5; i++) { - for (j = 0; j < 5; j++) { - if (tmp == (data_high[i] | data_low[j])) { - bcm43xx_phy_write(bcm, 0x0069, (i - j) << 8 | 0x00C0); - return; - } - } - } -} - -int bcm43xx_radio_selectchannel(struct bcm43xx_private *bcm, - u8 channel, - int synthetic_pu_workaround) -{ - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - u16 r8, tmp; - u16 freq; - - if (!ieee80211_is_valid_channel(bcm->ieee, channel)) - return -EINVAL; - if ((radio->manufact == 0x17F) && - (radio->version == 0x2060) && - (radio->revision == 1)) { - freq = channel2freq_a(channel); - - r8 = bcm43xx_radio_read16(bcm, 0x0008); - bcm43xx_write16(bcm, 0x03F0, freq); - bcm43xx_radio_write16(bcm, 0x0008, r8); - - TODO();//TODO: write max channel TX power? to Radio 0x2D - tmp = bcm43xx_radio_read16(bcm, 0x002E); - tmp &= 0x0080; - TODO();//TODO: OR tmp with the Power out estimation for this channel? - bcm43xx_radio_write16(bcm, 0x002E, tmp); - - if (freq >= 4920 && freq <= 5500) { - /* - * r8 = (((freq * 15 * 0xE1FC780F) >> 32) / 29) & 0x0F; - * = (freq * 0.025862069 - */ - r8 = 3 * freq / 116; /* is equal to r8 = freq * 0.025862 */ - } - bcm43xx_radio_write16(bcm, 0x0007, (r8 << 4) | r8); - bcm43xx_radio_write16(bcm, 0x0020, (r8 << 4) | r8); - bcm43xx_radio_write16(bcm, 0x0021, (r8 << 4) | r8); - bcm43xx_radio_write16(bcm, 0x0022, - (bcm43xx_radio_read16(bcm, 0x0022) - & 0x000F) | (r8 << 4)); - bcm43xx_radio_write16(bcm, 0x002A, (r8 << 4)); - bcm43xx_radio_write16(bcm, 0x002B, (r8 << 4)); - bcm43xx_radio_write16(bcm, 0x0008, - (bcm43xx_radio_read16(bcm, 0x0008) - & 0x00F0) | (r8 << 4)); - bcm43xx_radio_write16(bcm, 0x0029, - (bcm43xx_radio_read16(bcm, 0x0029) - & 0xFF0F) | 0x00B0); - bcm43xx_radio_write16(bcm, 0x0035, 0x00AA); - bcm43xx_radio_write16(bcm, 0x0036, 0x0085); - bcm43xx_radio_write16(bcm, 0x003A, - (bcm43xx_radio_read16(bcm, 0x003A) - & 0xFF20) | freq_r3A_value(freq)); - bcm43xx_radio_write16(bcm, 0x003D, - bcm43xx_radio_read16(bcm, 0x003D) & 0x00FF); - bcm43xx_radio_write16(bcm, 0x0081, - (bcm43xx_radio_read16(bcm, 0x0081) - & 0xFF7F) | 0x0080); - bcm43xx_radio_write16(bcm, 0x0035, - bcm43xx_radio_read16(bcm, 0x0035) & 0xFFEF); - bcm43xx_radio_write16(bcm, 0x0035, - (bcm43xx_radio_read16(bcm, 0x0035) - & 0xFFEF) | 0x0010); - bcm43xx_radio_set_tx_iq(bcm); - TODO(); //TODO: TSSI2dbm workaround - bcm43xx_phy_xmitpower(bcm);//FIXME correct? - } else { - if (synthetic_pu_workaround) - bcm43xx_synth_pu_workaround(bcm, channel); - - bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL, - channel2freq_bg(channel)); - - if (channel == 14) { - if (bcm->sprom.locale == BCM43xx_LOCALE_JAPAN) { - bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, - BCM43xx_UCODEFLAGS_OFFSET, - bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, - BCM43xx_UCODEFLAGS_OFFSET) - & ~(1 << 7)); - } else { - bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, - BCM43xx_UCODEFLAGS_OFFSET, - bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, - BCM43xx_UCODEFLAGS_OFFSET) - | (1 << 7)); - } - bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, - bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT) - | (1 << 11)); - } else { - bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, - bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT) - & 0xF7BF); - } - } - - radio->channel = channel; - //XXX: Using the longer of 2 timeouts (8000 vs 2000 usecs). Specs states - // that 2000 usecs might suffice. - udelay(8000); - - return 0; -} - -void bcm43xx_radio_set_txantenna(struct bcm43xx_private *bcm, u32 val) -{ - u16 tmp; - - val <<= 8; - tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0022) & 0xFCFF; - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0022, tmp | val); - tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x03A8) & 0xFCFF; - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x03A8, tmp | val); - tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0054) & 0xFCFF; - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0054, tmp | val); -} - -/* http://bcm-specs.sipsolutions.net/TX_Gain_Base_Band */ -static u16 bcm43xx_get_txgain_base_band(u16 txpower) -{ - u16 ret; - - assert(txpower <= 63); - - if (txpower >= 54) - ret = 2; - else if (txpower >= 49) - ret = 4; - else if (txpower >= 44) - ret = 5; - else - ret = 6; - - return ret; -} - -/* http://bcm-specs.sipsolutions.net/TX_Gain_Radio_Frequency_Power_Amplifier */ -static u16 bcm43xx_get_txgain_freq_power_amp(u16 txpower) -{ - u16 ret; - - assert(txpower <= 63); - - if (txpower >= 32) - ret = 0; - else if (txpower >= 25) - ret = 1; - else if (txpower >= 20) - ret = 2; - else if (txpower >= 12) - ret = 3; - else - ret = 4; - - return ret; -} - -/* http://bcm-specs.sipsolutions.net/TX_Gain_Digital_Analog_Converter */ -static u16 bcm43xx_get_txgain_dac(u16 txpower) -{ - u16 ret; - - assert(txpower <= 63); - - if (txpower >= 54) - ret = txpower - 53; - else if (txpower >= 49) - ret = txpower - 42; - else if (txpower >= 44) - ret = txpower - 37; - else if (txpower >= 32) - ret = txpower - 32; - else if (txpower >= 25) - ret = txpower - 20; - else if (txpower >= 20) - ret = txpower - 13; - else if (txpower >= 12) - ret = txpower - 8; - else - ret = txpower; - - return ret; -} - -void bcm43xx_radio_set_txpower_a(struct bcm43xx_private *bcm, u16 txpower) -{ - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - u16 pamp, base, dac, ilt; - - txpower = limit_value(txpower, 0, 63); - - pamp = bcm43xx_get_txgain_freq_power_amp(txpower); - pamp <<= 5; - pamp &= 0x00E0; - bcm43xx_phy_write(bcm, 0x0019, pamp); - - base = bcm43xx_get_txgain_base_band(txpower); - base &= 0x000F; - bcm43xx_phy_write(bcm, 0x0017, base | 0x0020); - - ilt = bcm43xx_ilt_read(bcm, 0x3001); - ilt &= 0x0007; - - dac = bcm43xx_get_txgain_dac(txpower); - dac <<= 3; - dac |= ilt; - - bcm43xx_ilt_write(bcm, 0x3001, dac); - - radio->txpwr_offset = txpower; - - TODO(); - //TODO: FuncPlaceholder (Adjust BB loft cancel) -} - -void bcm43xx_radio_set_txpower_bg(struct bcm43xx_private *bcm, - u16 baseband_attenuation, u16 radio_attenuation, - u16 txpower) -{ - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - - if (baseband_attenuation == 0xFFFF) - baseband_attenuation = radio->baseband_atten; - if (radio_attenuation == 0xFFFF) - radio_attenuation = radio->radio_atten; - if (txpower == 0xFFFF) - txpower = radio->txctl1; - radio->baseband_atten = baseband_attenuation; - radio->radio_atten = radio_attenuation; - radio->txctl1 = txpower; - - assert(/*baseband_attenuation >= 0 &&*/ baseband_attenuation <= 11); - if (radio->revision < 6) - assert(/*radio_attenuation >= 0 &&*/ radio_attenuation <= 9); - else - assert(/* radio_attenuation >= 0 &&*/ radio_attenuation <= 31); - assert(/*txpower >= 0 &&*/ txpower <= 7); - - bcm43xx_phy_set_baseband_attenuation(bcm, baseband_attenuation); - bcm43xx_radio_write16(bcm, 0x0043, radio_attenuation); - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0064, radio_attenuation); - if (radio->version == 0x2050) { - bcm43xx_radio_write16(bcm, 0x0052, - (bcm43xx_radio_read16(bcm, 0x0052) & ~0x0070) - | ((txpower << 4) & 0x0070)); - } - //FIXME: The spec is very weird and unclear here. - if (phy->type == BCM43xx_PHYTYPE_G) - bcm43xx_phy_lo_adjust(bcm, 0); -} - -u16 bcm43xx_default_baseband_attenuation(struct bcm43xx_private *bcm) -{ - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - - if (radio->version == 0x2050 && radio->revision < 6) - return 0; - return 2; -} - -u16 bcm43xx_default_radio_attenuation(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - u16 att = 0xFFFF; - - if (phy->type == BCM43xx_PHYTYPE_A) - return 0x60; - - switch (radio->version) { - case 0x2053: - switch (radio->revision) { - case 1: - att = 6; - break; - } - break; - case 0x2050: - switch (radio->revision) { - case 0: - att = 5; - break; - case 1: - if (phy->type == BCM43xx_PHYTYPE_G) { - if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM && - bcm->board_type == 0x421 && - bcm->board_revision >= 30) - att = 3; - else if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM && - bcm->board_type == 0x416) - att = 3; - else - att = 1; - } else { - if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM && - bcm->board_type == 0x421 && - bcm->board_revision >= 30) - att = 7; - else - att = 6; - } - break; - case 2: - if (phy->type == BCM43xx_PHYTYPE_G) { - if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM && - bcm->board_type == 0x421 && - bcm->board_revision >= 30) - att = 3; - else if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM && - bcm->board_type == 0x416) - att = 5; - else if (bcm->chip_id == 0x4320) - att = 4; - else - att = 3; - } else - att = 6; - break; - case 3: - att = 5; - break; - case 4: - case 5: - att = 1; - break; - case 6: - case 7: - att = 5; - break; - case 8: - att = 0x1A; - break; - case 9: - default: - att = 5; - } - } - if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM && - bcm->board_type == 0x421) { - if (bcm->board_revision < 0x43) - att = 2; - else if (bcm->board_revision < 0x51) - att = 3; - } - if (att == 0xFFFF) - att = 5; - - return att; -} - -u16 bcm43xx_default_txctl1(struct bcm43xx_private *bcm) -{ - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - - if (radio->version != 0x2050) - return 0; - if (radio->revision == 1) - return 3; - if (radio->revision < 6) - return 2; - if (radio->revision == 8) - return 1; - return 0; -} - -void bcm43xx_radio_turn_on(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - int err; - - if (radio->enabled) - return; - - switch (phy->type) { - case BCM43xx_PHYTYPE_A: - bcm43xx_radio_write16(bcm, 0x0004, 0x00C0); - bcm43xx_radio_write16(bcm, 0x0005, 0x0008); - bcm43xx_phy_write(bcm, 0x0010, bcm43xx_phy_read(bcm, 0x0010) & 0xFFF7); - bcm43xx_phy_write(bcm, 0x0011, bcm43xx_phy_read(bcm, 0x0011) & 0xFFF7); - bcm43xx_radio_init2060(bcm); - break; - case BCM43xx_PHYTYPE_B: - case BCM43xx_PHYTYPE_G: - bcm43xx_phy_write(bcm, 0x0015, 0x8000); - bcm43xx_phy_write(bcm, 0x0015, 0xCC00); - bcm43xx_phy_write(bcm, 0x0015, (phy->connected ? 0x00C0 : 0x0000)); - err = bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_BG, 1); - assert(err == 0); - break; - default: - assert(0); - } - radio->enabled = 1; - dprintk(KERN_INFO PFX "Radio turned on\n"); - bcm43xx_leds_update(bcm, 0); -} - -void bcm43xx_radio_turn_off(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - - if (phy->type == BCM43xx_PHYTYPE_A) { - bcm43xx_radio_write16(bcm, 0x0004, 0x00FF); - bcm43xx_radio_write16(bcm, 0x0005, 0x00FB); - bcm43xx_phy_write(bcm, 0x0010, bcm43xx_phy_read(bcm, 0x0010) | 0x0008); - bcm43xx_phy_write(bcm, 0x0011, bcm43xx_phy_read(bcm, 0x0011) | 0x0008); - } - if (phy->type == BCM43xx_PHYTYPE_G && bcm->current_core->rev >= 5) { - bcm43xx_phy_write(bcm, 0x0811, bcm43xx_phy_read(bcm, 0x0811) | 0x008C); - bcm43xx_phy_write(bcm, 0x0812, bcm43xx_phy_read(bcm, 0x0812) & 0xFF73); - } else - bcm43xx_phy_write(bcm, 0x0015, 0xAA00); - radio->enabled = 0; - dprintk(KERN_INFO PFX "Radio initialized\n"); - bcm43xx_leds_update(bcm, 0); -} - -void bcm43xx_radio_clear_tssi(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - - switch (phy->type) { - case BCM43xx_PHYTYPE_A: - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0068, 0x7F7F); - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x006a, 0x7F7F); - break; - case BCM43xx_PHYTYPE_B: - case BCM43xx_PHYTYPE_G: - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0058, 0x7F7F); - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x005a, 0x7F7F); - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0070, 0x7F7F); - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0072, 0x7F7F); - break; - } -} diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_radio.h b/drivers/net/wireless/bcm43xx/bcm43xx_radio.h deleted file mode 100644 index 77a98a53a2e2..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx_radio.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - - Broadcom BCM43xx wireless driver - - Copyright (c) 2005 Martin Langer , - Stefano Brivio - Michael Buesch - Danny van Dyk - Andreas Jaggi - - Some parts of the code in this file are derived from the ipw2200 - driver Copyright(c) 2003 - 2004 Intel Corporation. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#ifndef BCM43xx_RADIO_H_ -#define BCM43xx_RADIO_H_ - -#include "bcm43xx.h" - - -#define BCM43xx_RADIO_DEFAULT_CHANNEL_A 36 -#define BCM43xx_RADIO_DEFAULT_CHANNEL_BG 6 - -/* Force antenna 0. */ -#define BCM43xx_RADIO_TXANTENNA_0 0 -/* Force antenna 1. */ -#define BCM43xx_RADIO_TXANTENNA_1 1 -/* Use the RX antenna, that was selected for the most recently - * received good PLCP header. - */ -#define BCM43xx_RADIO_TXANTENNA_LASTPLCP 3 -#define BCM43xx_RADIO_TXANTENNA_DEFAULT BCM43xx_RADIO_TXANTENNA_LASTPLCP - -#define BCM43xx_RADIO_INTERFMODE_NONE 0 -#define BCM43xx_RADIO_INTERFMODE_NONWLAN 1 -#define BCM43xx_RADIO_INTERFMODE_MANUALWLAN 2 -#define BCM43xx_RADIO_INTERFMODE_AUTOWLAN 3 - - -void bcm43xx_radio_lock(struct bcm43xx_private *bcm); -void bcm43xx_radio_unlock(struct bcm43xx_private *bcm); - -u16 bcm43xx_radio_read16(struct bcm43xx_private *bcm, u16 offset); -void bcm43xx_radio_write16(struct bcm43xx_private *bcm, u16 offset, u16 val); - -u16 bcm43xx_radio_init2050(struct bcm43xx_private *bcm); -void bcm43xx_radio_init2060(struct bcm43xx_private *bcm); - -void bcm43xx_radio_turn_on(struct bcm43xx_private *bcm); -void bcm43xx_radio_turn_off(struct bcm43xx_private *bcm); - -static inline -int bcm43xx_is_hw_radio_enabled(struct bcm43xx_private *bcm) -{ - /* function to return state of hardware enable of radio - * returns 0 if radio disabled, 1 if radio enabled - */ - if (bcm->current_core->rev >= 3) - return ((bcm43xx_read32(bcm, BCM43xx_MMIO_RADIO_HWENABLED_HI) - & BCM43xx_MMIO_RADIO_HWENABLED_HI_MASK) - == 0) ? 1 : 0; - else - return ((bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_HWENABLED_LO) - & BCM43xx_MMIO_RADIO_HWENABLED_LO_MASK) - == 0) ? 0 : 1; -} - -int bcm43xx_radio_selectchannel(struct bcm43xx_private *bcm, u8 channel, - int synthetic_pu_workaround); - -void bcm43xx_radio_set_txpower_a(struct bcm43xx_private *bcm, u16 txpower); -void bcm43xx_radio_set_txpower_bg(struct bcm43xx_private *bcm, - u16 baseband_attenuation, u16 attenuation, - u16 txpower); - -u16 bcm43xx_default_baseband_attenuation(struct bcm43xx_private *bcm); -u16 bcm43xx_default_radio_attenuation(struct bcm43xx_private *bcm); -u16 bcm43xx_default_txctl1(struct bcm43xx_private *bcm); - -void bcm43xx_radio_set_txantenna(struct bcm43xx_private *bcm, u32 val); - -void bcm43xx_radio_clear_tssi(struct bcm43xx_private *bcm); - -u8 bcm43xx_radio_aci_detect(struct bcm43xx_private *bcm, u8 channel); -u8 bcm43xx_radio_aci_scan(struct bcm43xx_private *bcm); - -int bcm43xx_radio_set_interference_mitigation(struct bcm43xx_private *bcm, int mode); - -void bcm43xx_calc_nrssi_slope(struct bcm43xx_private *bcm); -void bcm43xx_calc_nrssi_threshold(struct bcm43xx_private *bcm); -s16 bcm43xx_nrssi_hw_read(struct bcm43xx_private *bcm, u16 offset); -void bcm43xx_nrssi_hw_write(struct bcm43xx_private *bcm, u16 offset, s16 val); -void bcm43xx_nrssi_hw_update(struct bcm43xx_private *bcm, u16 val); -void bcm43xx_nrssi_mem_update(struct bcm43xx_private *bcm); - -void bcm43xx_radio_set_tx_iq(struct bcm43xx_private *bcm); -u16 bcm43xx_radio_calibrationvalue(struct bcm43xx_private *bcm); - -#endif /* BCM43xx_RADIO_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c deleted file mode 100644 index 8ab5f93d192a..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c +++ /dev/null @@ -1,471 +0,0 @@ -/* - - Broadcom BCM43xx wireless driver - - SYSFS support routines - - Copyright (c) 2006 Michael Buesch - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include "bcm43xx_sysfs.h" -#include "bcm43xx.h" -#include "bcm43xx_main.h" -#include "bcm43xx_radio.h" - -#include - - -#define GENERIC_FILESIZE 64 - - -static int get_integer(const char *buf, size_t count) -{ - char tmp[10 + 1] = { 0 }; - int ret = -EINVAL; - - if (count == 0) - goto out; - count = min(count, (size_t)10); - memcpy(tmp, buf, count); - ret = simple_strtol(tmp, NULL, 10); -out: - return ret; -} - -static int get_boolean(const char *buf, size_t count) -{ - if (count != 0) { - if (buf[0] == '1') - return 1; - if (buf[0] == '0') - return 0; - if (count >= 4 && memcmp(buf, "true", 4) == 0) - return 1; - if (count >= 5 && memcmp(buf, "false", 5) == 0) - return 0; - if (count >= 3 && memcmp(buf, "yes", 3) == 0) - return 1; - if (count >= 2 && memcmp(buf, "no", 2) == 0) - return 0; - if (count >= 2 && memcmp(buf, "on", 2) == 0) - return 1; - if (count >= 3 && memcmp(buf, "off", 3) == 0) - return 0; - } - return -EINVAL; -} - -static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len) -{ - int i, pos = 0; - - for (i = 0; i < BCM43xx_SPROM_SIZE; i++) { - pos += snprintf(buf + pos, buf_len - pos - 1, - "%04X", swab16(sprom[i]) & 0xFFFF); - } - pos += snprintf(buf + pos, buf_len - pos - 1, "\n"); - - return pos + 1; -} - -static int hex2sprom(u16 *sprom, const char *dump, size_t len) -{ - char tmp[5] = { 0 }; - int cnt = 0; - unsigned long parsed; - - if (len < BCM43xx_SPROM_SIZE * sizeof(u16) * 2) - return -EINVAL; - - while (cnt < BCM43xx_SPROM_SIZE) { - memcpy(tmp, dump, 4); - dump += 4; - parsed = simple_strtoul(tmp, NULL, 16); - sprom[cnt++] = swab16((u16)parsed); - } - - return 0; -} - -static ssize_t bcm43xx_attr_sprom_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct bcm43xx_private *bcm = dev_to_bcm(dev); - u16 *sprom; - unsigned long flags; - int err; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - assert(BCM43xx_SPROM_SIZE * sizeof(u16) <= PAGE_SIZE); - sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom), - GFP_KERNEL); - if (!sprom) - return -ENOMEM; - mutex_lock(&bcm->mutex); - spin_lock_irqsave(&bcm->irq_lock, flags); - err = bcm43xx_sprom_read(bcm, sprom); - if (!err) - err = sprom2hex(sprom, buf, PAGE_SIZE); - mmiowb(); - spin_unlock_irqrestore(&bcm->irq_lock, flags); - mutex_unlock(&bcm->mutex); - kfree(sprom); - - return err; -} - -static ssize_t bcm43xx_attr_sprom_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct bcm43xx_private *bcm = dev_to_bcm(dev); - u16 *sprom; - unsigned long flags; - int err; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom), - GFP_KERNEL); - if (!sprom) - return -ENOMEM; - err = hex2sprom(sprom, buf, count); - if (err) - goto out_kfree; - mutex_lock(&bcm->mutex); - spin_lock_irqsave(&bcm->irq_lock, flags); - spin_lock(&bcm->leds_lock); - err = bcm43xx_sprom_write(bcm, sprom); - mmiowb(); - spin_unlock(&bcm->leds_lock); - spin_unlock_irqrestore(&bcm->irq_lock, flags); - mutex_unlock(&bcm->mutex); -out_kfree: - kfree(sprom); - - return err ? err : count; - -} - -static DEVICE_ATTR(sprom, 0600, - bcm43xx_attr_sprom_show, - bcm43xx_attr_sprom_store); - -static ssize_t bcm43xx_attr_interfmode_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct bcm43xx_private *bcm = dev_to_bcm(dev); - ssize_t count = 0; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - mutex_lock(&bcm->mutex); - - switch (bcm43xx_current_radio(bcm)->interfmode) { - case BCM43xx_RADIO_INTERFMODE_NONE: - count = snprintf(buf, PAGE_SIZE, "0 (No Interference Mitigation)\n"); - break; - case BCM43xx_RADIO_INTERFMODE_NONWLAN: - count = snprintf(buf, PAGE_SIZE, "1 (Non-WLAN Interference Mitigation)\n"); - break; - case BCM43xx_RADIO_INTERFMODE_MANUALWLAN: - count = snprintf(buf, PAGE_SIZE, "2 (WLAN Interference Mitigation)\n"); - break; - default: - assert(0); - } - - mutex_unlock(&bcm->mutex); - - return count; - -} - -static ssize_t bcm43xx_attr_interfmode_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct bcm43xx_private *bcm = dev_to_bcm(dev); - unsigned long flags; - int err; - int mode; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - mode = get_integer(buf, count); - switch (mode) { - case 0: - mode = BCM43xx_RADIO_INTERFMODE_NONE; - break; - case 1: - mode = BCM43xx_RADIO_INTERFMODE_NONWLAN; - break; - case 2: - mode = BCM43xx_RADIO_INTERFMODE_MANUALWLAN; - break; - case 3: - mode = BCM43xx_RADIO_INTERFMODE_AUTOWLAN; - break; - default: - return -EINVAL; - } - - mutex_lock(&bcm->mutex); - spin_lock_irqsave(&bcm->irq_lock, flags); - - err = bcm43xx_radio_set_interference_mitigation(bcm, mode); - if (err) { - printk(KERN_ERR PFX "Interference Mitigation not " - "supported by device\n"); - } - mmiowb(); - spin_unlock_irqrestore(&bcm->irq_lock, flags); - mutex_unlock(&bcm->mutex); - - return err ? err : count; -} - -static DEVICE_ATTR(interference, 0644, - bcm43xx_attr_interfmode_show, - bcm43xx_attr_interfmode_store); - -static ssize_t bcm43xx_attr_preamble_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct bcm43xx_private *bcm = dev_to_bcm(dev); - ssize_t count; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - mutex_lock(&bcm->mutex); - - if (bcm->short_preamble) - count = snprintf(buf, PAGE_SIZE, "1 (Short Preamble enabled)\n"); - else - count = snprintf(buf, PAGE_SIZE, "0 (Short Preamble disabled)\n"); - - mutex_unlock(&bcm->mutex); - - return count; -} - -static ssize_t bcm43xx_attr_preamble_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct bcm43xx_private *bcm = dev_to_bcm(dev); - unsigned long flags; - int value; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - value = get_boolean(buf, count); - if (value < 0) - return value; - mutex_lock(&bcm->mutex); - spin_lock_irqsave(&bcm->irq_lock, flags); - - bcm->short_preamble = !!value; - - spin_unlock_irqrestore(&bcm->irq_lock, flags); - mutex_unlock(&bcm->mutex); - - return count; -} - -static DEVICE_ATTR(shortpreamble, 0644, - bcm43xx_attr_preamble_show, - bcm43xx_attr_preamble_store); - -static ssize_t bcm43xx_attr_phymode_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct bcm43xx_private *bcm = dev_to_bcm(dev); - int phytype; - int err = -EINVAL; - - if (count < 1) - goto out; - switch (buf[0]) { - case 'a': case 'A': - phytype = BCM43xx_PHYTYPE_A; - break; - case 'b': case 'B': - phytype = BCM43xx_PHYTYPE_B; - break; - case 'g': case 'G': - phytype = BCM43xx_PHYTYPE_G; - break; - default: - goto out; - } - - bcm43xx_cancel_work(bcm); - mutex_lock(&(bcm)->mutex); - err = bcm43xx_select_wireless_core(bcm, phytype); - if (!err) - bcm43xx_periodic_tasks_setup(bcm); - mutex_unlock(&(bcm)->mutex); - if (err == -ESRCH) - err = -ENODEV; - -out: - return err ? err : count; -} - -static ssize_t bcm43xx_attr_phymode_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct bcm43xx_private *bcm = dev_to_bcm(dev); - ssize_t count = 0; - - mutex_lock(&(bcm)->mutex); - switch (bcm43xx_current_phy(bcm)->type) { - case BCM43xx_PHYTYPE_A: - snprintf(buf, PAGE_SIZE, "A"); - break; - case BCM43xx_PHYTYPE_B: - snprintf(buf, PAGE_SIZE, "B"); - break; - case BCM43xx_PHYTYPE_G: - snprintf(buf, PAGE_SIZE, "G"); - break; - default: - assert(0); - } - mutex_unlock(&(bcm)->mutex); - - return count; -} - -static DEVICE_ATTR(phymode, 0644, - bcm43xx_attr_phymode_show, - bcm43xx_attr_phymode_store); - -static ssize_t bcm43xx_attr_microcode_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - unsigned long flags; - struct bcm43xx_private *bcm = dev_to_bcm(dev); - ssize_t count = 0; - u16 status; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - mutex_lock(&(bcm)->mutex); - spin_lock_irqsave(&bcm->irq_lock, flags); - status = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, - BCM43xx_UCODE_STATUS); - - spin_unlock_irqrestore(&bcm->irq_lock, flags); - mutex_unlock(&(bcm)->mutex); - switch (status) { - case 0x0000: - count = snprintf(buf, PAGE_SIZE, "0x%.4x (invalid)\n", - status); - break; - case 0x0001: - count = snprintf(buf, PAGE_SIZE, "0x%.4x (init)\n", - status); - break; - case 0x0002: - count = snprintf(buf, PAGE_SIZE, "0x%.4x (active)\n", - status); - break; - case 0x0003: - count = snprintf(buf, PAGE_SIZE, "0x%.4x (suspended)\n", - status); - break; - case 0x0004: - count = snprintf(buf, PAGE_SIZE, "0x%.4x (asleep)\n", - status); - break; - default: - count = snprintf(buf, PAGE_SIZE, "0x%.4x (unknown)\n", - status); - break; - } - - return count; -} - -static DEVICE_ATTR(microcodestatus, 0444, - bcm43xx_attr_microcode_show, - NULL); - -int bcm43xx_sysfs_register(struct bcm43xx_private *bcm) -{ - struct device *dev = &bcm->pci_dev->dev; - int err; - - assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED); - - err = device_create_file(dev, &dev_attr_sprom); - if (err) - goto out; - err = device_create_file(dev, &dev_attr_interference); - if (err) - goto err_remove_sprom; - err = device_create_file(dev, &dev_attr_shortpreamble); - if (err) - goto err_remove_interfmode; - err = device_create_file(dev, &dev_attr_phymode); - if (err) - goto err_remove_shortpreamble; - err = device_create_file(dev, &dev_attr_microcodestatus); - if (err) - goto err_remove_phymode; - -out: - return err; -err_remove_phymode: - device_remove_file(dev, &dev_attr_phymode); -err_remove_shortpreamble: - device_remove_file(dev, &dev_attr_shortpreamble); -err_remove_interfmode: - device_remove_file(dev, &dev_attr_interference); -err_remove_sprom: - device_remove_file(dev, &dev_attr_sprom); - goto out; -} - -void bcm43xx_sysfs_unregister(struct bcm43xx_private *bcm) -{ - struct device *dev = &bcm->pci_dev->dev; - - device_remove_file(dev, &dev_attr_microcodestatus); - device_remove_file(dev, &dev_attr_phymode); - device_remove_file(dev, &dev_attr_shortpreamble); - device_remove_file(dev, &dev_attr_interference); - device_remove_file(dev, &dev_attr_sprom); -} diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h deleted file mode 100644 index cc701df71e2a..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef BCM43xx_SYSFS_H_ -#define BCM43xx_SYSFS_H_ - -struct bcm43xx_private; - -int bcm43xx_sysfs_register(struct bcm43xx_private *bcm); -void bcm43xx_sysfs_unregister(struct bcm43xx_private *bcm); - -#endif /* BCM43xx_SYSFS_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c deleted file mode 100644 index 6acfdc49dccd..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c +++ /dev/null @@ -1,1035 +0,0 @@ -/* - - Broadcom BCM43xx wireless driver - - Copyright (c) 2005 Martin Langer , - Stefano Brivio - Michael Buesch - Danny van Dyk - Andreas Jaggi - - Some parts of the code in this file are derived from the ipw2200 - driver Copyright(c) 2003 - 2004 Intel Corporation. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include -#include -#include -#include -#include -#include - -#include "bcm43xx.h" -#include "bcm43xx_wx.h" -#include "bcm43xx_main.h" -#include "bcm43xx_radio.h" -#include "bcm43xx_phy.h" - - -/* The WIRELESS_EXT version, which is implemented by this driver. */ -#define BCM43xx_WX_VERSION 18 - -#define MAX_WX_STRING 80 - -static int bcm43xx_wx_get_name(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - int i; - struct bcm43xx_phyinfo *phy; - char suffix[7] = { 0 }; - int have_a = 0, have_b = 0, have_g = 0; - - mutex_lock(&bcm->mutex); - for (i = 0; i < bcm->nr_80211_available; i++) { - phy = &(bcm->core_80211_ext[i].phy); - switch (phy->type) { - case BCM43xx_PHYTYPE_A: - have_a = 1; - break; - case BCM43xx_PHYTYPE_G: - have_g = 1; - case BCM43xx_PHYTYPE_B: - have_b = 1; - break; - default: - assert(0); - } - } - mutex_unlock(&bcm->mutex); - - i = 0; - if (have_a) { - suffix[i++] = 'a'; - suffix[i++] = '/'; - } - if (have_b) { - suffix[i++] = 'b'; - suffix[i++] = '/'; - } - if (have_g) { - suffix[i++] = 'g'; - suffix[i++] = '/'; - } - if (i != 0) - suffix[i - 1] = '\0'; - - snprintf(data->name, IFNAMSIZ, "IEEE 802.11%s", suffix); - - return 0; -} - -static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - unsigned long flags; - u8 channel; - s8 expon; - int freq; - int err = -EINVAL; - - mutex_lock(&bcm->mutex); - spin_lock_irqsave(&bcm->irq_lock, flags); - - if ((data->freq.e == 0) && - (data->freq.m >= 0) && (data->freq.m <= 1000)) { - channel = data->freq.m; - freq = bcm43xx_channel_to_freq(bcm, channel); - } else { - freq = data->freq.m; - expon = 6 - data->freq.e; - while (--expon >= 0) /* scale down the frequency to MHz */ - freq /= 10; - assert(freq > 1000); - channel = bcm43xx_freq_to_channel(bcm, freq); - } - if (!ieee80211_is_valid_channel(bcm->ieee, channel)) - goto out_unlock; - if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) { - //ieee80211softmac_disassoc(softmac, $REASON); - bcm43xx_mac_suspend(bcm); - err = bcm43xx_radio_selectchannel(bcm, channel, 0); - bcm43xx_mac_enable(bcm); - } else { - bcm43xx_current_radio(bcm)->initial_channel = channel; - err = 0; - } -out_unlock: - spin_unlock_irqrestore(&bcm->irq_lock, flags); - mutex_unlock(&bcm->mutex); - - return err; -} - -static int bcm43xx_wx_get_channelfreq(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - struct bcm43xx_radioinfo *radio; - int err = -ENODEV; - u16 channel; - - mutex_lock(&bcm->mutex); - radio = bcm43xx_current_radio(bcm); - channel = radio->channel; - if (channel == 0xFF) { - channel = radio->initial_channel; - if (channel == 0xFF) - goto out_unlock; - } - assert(channel > 0 && channel <= 1000); - data->freq.e = 1; - data->freq.m = bcm43xx_channel_to_freq(bcm, channel) * 100000; - data->freq.flags = 1; - - err = 0; -out_unlock: - mutex_unlock(&bcm->mutex); - - return err; -} - -static int bcm43xx_wx_set_mode(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - unsigned long flags; - int mode; - - mode = data->mode; - if (mode == IW_MODE_AUTO) - mode = BCM43xx_INITIAL_IWMODE; - - mutex_lock(&bcm->mutex); - spin_lock_irqsave(&bcm->irq_lock, flags); - if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) { - if (bcm->ieee->iw_mode != mode) - bcm43xx_set_iwmode(bcm, mode); - } else - bcm->ieee->iw_mode = mode; - spin_unlock_irqrestore(&bcm->irq_lock, flags); - mutex_unlock(&bcm->mutex); - - return 0; -} - -static int bcm43xx_wx_get_mode(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - - mutex_lock(&bcm->mutex); - data->mode = bcm->ieee->iw_mode; - mutex_unlock(&bcm->mutex); - - return 0; -} - -static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - struct iw_range *range = (struct iw_range *)extra; - const struct ieee80211_geo *geo; - int i, j; - struct bcm43xx_phyinfo *phy; - - data->data.length = sizeof(*range); - memset(range, 0, sizeof(*range)); - - //TODO: What about 802.11b? - /* 54Mb/s == ~27Mb/s payload throughput (802.11g) */ - range->throughput = 27 * 1000 * 1000; - - range->max_qual.qual = 100; - range->max_qual.level = 146; /* set floor at -110 dBm (146 - 256) */ - range->max_qual.noise = 146; - range->max_qual.updated = IW_QUAL_ALL_UPDATED; - - range->avg_qual.qual = 50; - range->avg_qual.level = 0; - range->avg_qual.noise = 0; - range->avg_qual.updated = IW_QUAL_ALL_UPDATED; - - range->min_rts = BCM43xx_MIN_RTS_THRESHOLD; - range->max_rts = BCM43xx_MAX_RTS_THRESHOLD; - range->min_frag = MIN_FRAG_THRESHOLD; - range->max_frag = MAX_FRAG_THRESHOLD; - - range->encoding_size[0] = 5; - range->encoding_size[1] = 13; - range->num_encoding_sizes = 2; - range->max_encoding_tokens = WEP_KEYS; - - range->we_version_compiled = WIRELESS_EXT; - range->we_version_source = BCM43xx_WX_VERSION; - - range->enc_capa = IW_ENC_CAPA_WPA | - IW_ENC_CAPA_WPA2 | - IW_ENC_CAPA_CIPHER_TKIP | - IW_ENC_CAPA_CIPHER_CCMP; - - mutex_lock(&bcm->mutex); - phy = bcm43xx_current_phy(bcm); - - range->num_bitrates = 0; - i = 0; - if (phy->type == BCM43xx_PHYTYPE_A || - phy->type == BCM43xx_PHYTYPE_G) { - range->num_bitrates = 8; - range->bitrate[i++] = IEEE80211_OFDM_RATE_6MB * 500000; - range->bitrate[i++] = IEEE80211_OFDM_RATE_9MB * 500000; - range->bitrate[i++] = IEEE80211_OFDM_RATE_12MB * 500000; - range->bitrate[i++] = IEEE80211_OFDM_RATE_18MB * 500000; - range->bitrate[i++] = IEEE80211_OFDM_RATE_24MB * 500000; - range->bitrate[i++] = IEEE80211_OFDM_RATE_36MB * 500000; - range->bitrate[i++] = IEEE80211_OFDM_RATE_48MB * 500000; - range->bitrate[i++] = IEEE80211_OFDM_RATE_54MB * 500000; - } - if (phy->type == BCM43xx_PHYTYPE_B || - phy->type == BCM43xx_PHYTYPE_G) { - range->num_bitrates += 4; - range->bitrate[i++] = IEEE80211_CCK_RATE_1MB * 500000; - range->bitrate[i++] = IEEE80211_CCK_RATE_2MB * 500000; - range->bitrate[i++] = IEEE80211_CCK_RATE_5MB * 500000; - range->bitrate[i++] = IEEE80211_CCK_RATE_11MB * 500000; - } - - geo = ieee80211_get_geo(bcm->ieee); - range->num_channels = geo->a_channels + geo->bg_channels; - j = 0; - for (i = 0; i < geo->a_channels; i++) { - if (j == IW_MAX_FREQUENCIES) - break; - range->freq[j].i = j + 1; - range->freq[j].m = geo->a[i].freq * 100000; - range->freq[j].e = 1; - j++; - } - for (i = 0; i < geo->bg_channels; i++) { - if (j == IW_MAX_FREQUENCIES) - break; - range->freq[j].i = j + 1; - range->freq[j].m = geo->bg[i].freq * 100000; - range->freq[j].e = 1; - j++; - } - range->num_frequency = j; - - mutex_unlock(&bcm->mutex); - - return 0; -} - -static int bcm43xx_wx_set_nick(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - size_t len; - - mutex_lock(&bcm->mutex); - len = min((size_t)data->data.length, (size_t)IW_ESSID_MAX_SIZE); - memcpy(bcm->nick, extra, len); - bcm->nick[len] = '\0'; - mutex_unlock(&bcm->mutex); - - return 0; -} - -static int bcm43xx_wx_get_nick(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - size_t len; - - mutex_lock(&bcm->mutex); - len = strlen(bcm->nick); - memcpy(extra, bcm->nick, len); - data->data.length = (__u16)len; - data->data.flags = 1; - mutex_unlock(&bcm->mutex); - - return 0; -} - -static int bcm43xx_wx_set_rts(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - unsigned long flags; - int err = -EINVAL; - - mutex_lock(&bcm->mutex); - spin_lock_irqsave(&bcm->irq_lock, flags); - if (data->rts.disabled) { - bcm->rts_threshold = BCM43xx_MAX_RTS_THRESHOLD; - err = 0; - } else { - if (data->rts.value >= BCM43xx_MIN_RTS_THRESHOLD && - data->rts.value <= BCM43xx_MAX_RTS_THRESHOLD) { - bcm->rts_threshold = data->rts.value; - err = 0; - } - } - spin_unlock_irqrestore(&bcm->irq_lock, flags); - mutex_unlock(&bcm->mutex); - - return err; -} - -static int bcm43xx_wx_get_rts(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - - mutex_lock(&bcm->mutex); - data->rts.value = bcm->rts_threshold; - data->rts.fixed = 0; - data->rts.disabled = (bcm->rts_threshold == BCM43xx_MAX_RTS_THRESHOLD); - mutex_unlock(&bcm->mutex); - - return 0; -} - -static int bcm43xx_wx_set_frag(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - unsigned long flags; - int err = -EINVAL; - - mutex_lock(&bcm->mutex); - spin_lock_irqsave(&bcm->irq_lock, flags); - if (data->frag.disabled) { - bcm->ieee->fts = MAX_FRAG_THRESHOLD; - err = 0; - } else { - if (data->frag.value >= MIN_FRAG_THRESHOLD && - data->frag.value <= MAX_FRAG_THRESHOLD) { - bcm->ieee->fts = data->frag.value & ~0x1; - err = 0; - } - } - spin_unlock_irqrestore(&bcm->irq_lock, flags); - mutex_unlock(&bcm->mutex); - - return err; -} - -static int bcm43xx_wx_get_frag(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - - mutex_lock(&bcm->mutex); - data->frag.value = bcm->ieee->fts; - data->frag.fixed = 0; - data->frag.disabled = (bcm->ieee->fts == MAX_FRAG_THRESHOLD); - mutex_unlock(&bcm->mutex); - - return 0; -} - -static int bcm43xx_wx_set_xmitpower(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - struct bcm43xx_radioinfo *radio; - struct bcm43xx_phyinfo *phy; - unsigned long flags; - int err = -ENODEV; - u16 maxpower; - - if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM) { - printk(KERN_ERR PFX "TX power not in dBm.\n"); - return -EOPNOTSUPP; - } - - mutex_lock(&bcm->mutex); - spin_lock_irqsave(&bcm->irq_lock, flags); - if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) - goto out_unlock; - radio = bcm43xx_current_radio(bcm); - phy = bcm43xx_current_phy(bcm); - if (data->txpower.disabled != (!(radio->enabled))) { - if (data->txpower.disabled) - bcm43xx_radio_turn_off(bcm); - else - bcm43xx_radio_turn_on(bcm); - } - if (data->txpower.value > 0) { - /* desired and maxpower dBm values are in Q5.2 */ - if (phy->type == BCM43xx_PHYTYPE_A) - maxpower = bcm->sprom.maxpower_aphy; - else - maxpower = bcm->sprom.maxpower_bgphy; - radio->txpower_desired = limit_value(data->txpower.value << 2, - 0, maxpower); - bcm43xx_phy_xmitpower(bcm); - } - err = 0; - -out_unlock: - spin_unlock_irqrestore(&bcm->irq_lock, flags); - mutex_unlock(&bcm->mutex); - - return err; -} - -static int bcm43xx_wx_get_xmitpower(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - struct bcm43xx_radioinfo *radio; - int err = -ENODEV; - - mutex_lock(&bcm->mutex); - if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) - goto out_unlock; - radio = bcm43xx_current_radio(bcm); - /* desired dBm value is in Q5.2 */ - data->txpower.value = radio->txpower_desired >> 2; - data->txpower.fixed = 1; - data->txpower.flags = IW_TXPOW_DBM; - data->txpower.disabled = !(radio->enabled); - - err = 0; -out_unlock: - mutex_unlock(&bcm->mutex); - - return err; -} - -static int bcm43xx_wx_set_encoding(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - int err; - - err = ieee80211_wx_set_encode(bcm->ieee, info, data, extra); - - return err; -} - -static int bcm43xx_wx_set_encodingext(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - int err; - - err = ieee80211_wx_set_encodeext(bcm->ieee, info, data, extra); - - return err; -} - -static int bcm43xx_wx_get_encoding(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - int err; - - err = ieee80211_wx_get_encode(bcm->ieee, info, data, extra); - - return err; -} - -static int bcm43xx_wx_get_encodingext(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - int err; - - err = ieee80211_wx_get_encodeext(bcm->ieee, info, data, extra); - - return err; -} - -static int bcm43xx_wx_set_interfmode(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - unsigned long flags; - int mode, err = 0; - - mode = *((int *)extra); - switch (mode) { - case 0: - mode = BCM43xx_RADIO_INTERFMODE_NONE; - break; - case 1: - mode = BCM43xx_RADIO_INTERFMODE_NONWLAN; - break; - case 2: - mode = BCM43xx_RADIO_INTERFMODE_MANUALWLAN; - break; - case 3: - mode = BCM43xx_RADIO_INTERFMODE_AUTOWLAN; - break; - default: - printk(KERN_ERR PFX "set_interfmode allowed parameters are: " - "0 => None, 1 => Non-WLAN, 2 => WLAN, " - "3 => Auto-WLAN\n"); - return -EINVAL; - } - - mutex_lock(&bcm->mutex); - spin_lock_irqsave(&bcm->irq_lock, flags); - if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) { - err = bcm43xx_radio_set_interference_mitigation(bcm, mode); - if (err) { - printk(KERN_ERR PFX "Interference Mitigation not " - "supported by device\n"); - } - } else { - if (mode == BCM43xx_RADIO_INTERFMODE_AUTOWLAN) { - printk(KERN_ERR PFX "Interference Mitigation mode Auto-WLAN " - "not supported while the interface is down.\n"); - err = -ENODEV; - } else - bcm43xx_current_radio(bcm)->interfmode = mode; - } - spin_unlock_irqrestore(&bcm->irq_lock, flags); - mutex_unlock(&bcm->mutex); - - return err; -} - -static int bcm43xx_wx_get_interfmode(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - int mode; - - mutex_lock(&bcm->mutex); - mode = bcm43xx_current_radio(bcm)->interfmode; - mutex_unlock(&bcm->mutex); - - switch (mode) { - case BCM43xx_RADIO_INTERFMODE_NONE: - strncpy(extra, "0 (No Interference Mitigation)", MAX_WX_STRING); - break; - case BCM43xx_RADIO_INTERFMODE_NONWLAN: - strncpy(extra, "1 (Non-WLAN Interference Mitigation)", MAX_WX_STRING); - break; - case BCM43xx_RADIO_INTERFMODE_MANUALWLAN: - strncpy(extra, "2 (WLAN Interference Mitigation)", MAX_WX_STRING); - break; - default: - assert(0); - } - data->data.length = strlen(extra) + 1; - - return 0; -} - -static int bcm43xx_wx_set_shortpreamble(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - unsigned long flags; - int on; - - on = *((int *)extra); - mutex_lock(&bcm->mutex); - spin_lock_irqsave(&bcm->irq_lock, flags); - bcm->short_preamble = !!on; - spin_unlock_irqrestore(&bcm->irq_lock, flags); - mutex_unlock(&bcm->mutex); - - return 0; -} - -static int bcm43xx_wx_get_shortpreamble(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - int on; - - mutex_lock(&bcm->mutex); - on = bcm->short_preamble; - mutex_unlock(&bcm->mutex); - - if (on) - strncpy(extra, "1 (Short Preamble enabled)", MAX_WX_STRING); - else - strncpy(extra, "0 (Short Preamble disabled)", MAX_WX_STRING); - data->data.length = strlen(extra) + 1; - - return 0; -} - -static int bcm43xx_wx_set_swencryption(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - unsigned long flags; - int on; - - on = *((int *)extra); - - mutex_lock(&bcm->mutex); - spin_lock_irqsave(&bcm->irq_lock, flags); - bcm->ieee->host_encrypt = !!on; - bcm->ieee->host_decrypt = !!on; - bcm->ieee->host_build_iv = !on; - bcm->ieee->host_strip_iv_icv = !on; - spin_unlock_irqrestore(&bcm->irq_lock, flags); - mutex_unlock(&bcm->mutex); - - return 0; -} - -static int bcm43xx_wx_get_swencryption(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - int on; - - mutex_lock(&bcm->mutex); - on = bcm->ieee->host_encrypt; - mutex_unlock(&bcm->mutex); - - if (on) - strncpy(extra, "1 (SW encryption enabled) ", MAX_WX_STRING); - else - strncpy(extra, "0 (SW encryption disabled) ", MAX_WX_STRING); - data->data.length = strlen(extra + 1); - - return 0; -} - -/* Enough buffer to hold a hexdump of the sprom data. */ -#define SPROM_BUFFERSIZE 512 - -static int sprom2hex(const u16 *sprom, char *dump) -{ - int i, pos = 0; - - for (i = 0; i < BCM43xx_SPROM_SIZE; i++) { - pos += snprintf(dump + pos, SPROM_BUFFERSIZE - pos - 1, - "%04X", swab16(sprom[i]) & 0xFFFF); - } - - return pos + 1; -} - -static int hex2sprom(u16 *sprom, const char *dump, unsigned int len) -{ - char tmp[5] = { 0 }; - int cnt = 0; - unsigned long parsed; - - if (len < BCM43xx_SPROM_SIZE * sizeof(u16) * 2) - return -EINVAL; - while (cnt < BCM43xx_SPROM_SIZE) { - memcpy(tmp, dump, 4); - dump += 4; - parsed = simple_strtoul(tmp, NULL, 16); - sprom[cnt++] = swab16((u16)parsed); - } - - return 0; -} - -static int bcm43xx_wx_sprom_read(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - int err = -EPERM; - u16 *sprom; - unsigned long flags; - - if (!capable(CAP_SYS_RAWIO)) - goto out; - - err = -ENOMEM; - sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom), - GFP_KERNEL); - if (!sprom) - goto out; - - mutex_lock(&bcm->mutex); - spin_lock_irqsave(&bcm->irq_lock, flags); - err = -ENODEV; - if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) - err = bcm43xx_sprom_read(bcm, sprom); - spin_unlock_irqrestore(&bcm->irq_lock, flags); - mutex_unlock(&bcm->mutex); - if (!err) - data->data.length = sprom2hex(sprom, extra); - kfree(sprom); -out: - return err; -} - -static int bcm43xx_wx_sprom_write(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - int err = -EPERM; - u16 *sprom; - unsigned long flags; - char *input; - unsigned int len; - - if (!capable(CAP_SYS_RAWIO)) - goto out; - - err = -ENOMEM; - sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom), - GFP_KERNEL); - if (!sprom) - goto out; - - len = data->data.length; - extra[len - 1] = '\0'; - input = strchr(extra, ':'); - if (input) { - input++; - len -= input - extra; - } else - input = extra; - err = hex2sprom(sprom, input, len); - if (err) - goto out_kfree; - - mutex_lock(&bcm->mutex); - spin_lock_irqsave(&bcm->irq_lock, flags); - spin_lock(&bcm->leds_lock); - err = -ENODEV; - if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) - err = bcm43xx_sprom_write(bcm, sprom); - spin_unlock(&bcm->leds_lock); - spin_unlock_irqrestore(&bcm->irq_lock, flags); - mutex_unlock(&bcm->mutex); -out_kfree: - kfree(sprom); -out: - return err; -} - -/* Get wireless statistics. Called by /proc/net/wireless and by SIOCGIWSTATS */ - -static struct iw_statistics *bcm43xx_get_wireless_stats(struct net_device *net_dev) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - struct ieee80211softmac_device *mac = ieee80211_priv(net_dev); - struct iw_statistics *wstats; - struct ieee80211_network *network = NULL; - static int tmp_level = 0; - static int tmp_qual = 0; - unsigned long flags; - - wstats = &bcm->stats.wstats; - if (!mac->associnfo.associated) { - wstats->miss.beacon = 0; -// bcm->ieee->ieee_stats.tx_retry_limit_exceeded = 0; // FIXME: should this be cleared here? - wstats->discard.retries = 0; -// bcm->ieee->ieee_stats.tx_discards_wrong_sa = 0; // FIXME: same question - wstats->discard.nwid = 0; -// bcm->ieee->ieee_stats.rx_discards_undecryptable = 0; // FIXME: ditto - wstats->discard.code = 0; -// bcm->ieee->ieee_stats.rx_fragments = 0; // FIXME: same here - wstats->discard.fragment = 0; - wstats->discard.misc = 0; - wstats->qual.qual = 0; - wstats->qual.level = 0; - wstats->qual.noise = 0; - wstats->qual.updated = 7; - wstats->qual.updated |= IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; - return wstats; - } - /* fill in the real statistics when iface associated */ - spin_lock_irqsave(&mac->ieee->lock, flags); - list_for_each_entry(network, &mac->ieee->network_list, list) { - if (!memcmp(mac->associnfo.bssid, network->bssid, ETH_ALEN)) { - if (!tmp_level) { /* get initial values */ - tmp_level = network->stats.signal; - tmp_qual = network->stats.rssi; - } else { /* smooth results */ - tmp_level = (15 * tmp_level + network->stats.signal)/16; - tmp_qual = (15 * tmp_qual + network->stats.rssi)/16; - } - break; - } - } - spin_unlock_irqrestore(&mac->ieee->lock, flags); - wstats->qual.level = tmp_level; - wstats->qual.qual = 100 * tmp_qual / RX_RSSI_MAX; - wstats->qual.noise = bcm->stats.noise; - wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; - wstats->discard.code = bcm->ieee->ieee_stats.rx_discards_undecryptable; - wstats->discard.retries = bcm->ieee->ieee_stats.tx_retry_limit_exceeded; - wstats->discard.nwid = bcm->ieee->ieee_stats.tx_discards_wrong_sa; - wstats->discard.fragment = bcm->ieee->ieee_stats.rx_fragments; - wstats->discard.misc = 0; // FIXME - wstats->miss.beacon = 0; // FIXME - return wstats; -} - - -#ifdef WX -# undef WX -#endif -#define WX(ioctl) [(ioctl) - SIOCSIWCOMMIT] -static const iw_handler bcm43xx_wx_handlers[] = { - /* Wireless Identification */ - WX(SIOCGIWNAME) = bcm43xx_wx_get_name, - /* Basic operations */ - WX(SIOCSIWFREQ) = bcm43xx_wx_set_channelfreq, - WX(SIOCGIWFREQ) = bcm43xx_wx_get_channelfreq, - WX(SIOCSIWMODE) = bcm43xx_wx_set_mode, - WX(SIOCGIWMODE) = bcm43xx_wx_get_mode, - /* Informative stuff */ - WX(SIOCGIWRANGE) = bcm43xx_wx_get_rangeparams, - /* Access Point manipulation */ - WX(SIOCSIWAP) = ieee80211softmac_wx_set_wap, - WX(SIOCGIWAP) = ieee80211softmac_wx_get_wap, - WX(SIOCSIWSCAN) = ieee80211softmac_wx_trigger_scan, - WX(SIOCGIWSCAN) = ieee80211softmac_wx_get_scan_results, - /* 802.11 specific support */ - WX(SIOCSIWESSID) = ieee80211softmac_wx_set_essid, - WX(SIOCGIWESSID) = ieee80211softmac_wx_get_essid, - WX(SIOCSIWNICKN) = bcm43xx_wx_set_nick, - WX(SIOCGIWNICKN) = bcm43xx_wx_get_nick, - /* Other parameters */ - WX(SIOCSIWRATE) = ieee80211softmac_wx_set_rate, - WX(SIOCGIWRATE) = ieee80211softmac_wx_get_rate, - WX(SIOCSIWRTS) = bcm43xx_wx_set_rts, - WX(SIOCGIWRTS) = bcm43xx_wx_get_rts, - WX(SIOCSIWFRAG) = bcm43xx_wx_set_frag, - WX(SIOCGIWFRAG) = bcm43xx_wx_get_frag, - WX(SIOCSIWTXPOW) = bcm43xx_wx_set_xmitpower, - WX(SIOCGIWTXPOW) = bcm43xx_wx_get_xmitpower, -//TODO WX(SIOCSIWRETRY) = bcm43xx_wx_set_retry, -//TODO WX(SIOCGIWRETRY) = bcm43xx_wx_get_retry, - /* Encoding */ - WX(SIOCSIWENCODE) = bcm43xx_wx_set_encoding, - WX(SIOCGIWENCODE) = bcm43xx_wx_get_encoding, - WX(SIOCSIWENCODEEXT) = bcm43xx_wx_set_encodingext, - WX(SIOCGIWENCODEEXT) = bcm43xx_wx_get_encodingext, - /* Power saving */ -//TODO WX(SIOCSIWPOWER) = bcm43xx_wx_set_power, -//TODO WX(SIOCGIWPOWER) = bcm43xx_wx_get_power, - WX(SIOCSIWGENIE) = ieee80211softmac_wx_set_genie, - WX(SIOCGIWGENIE) = ieee80211softmac_wx_get_genie, - WX(SIOCSIWAUTH) = ieee80211_wx_set_auth, - WX(SIOCGIWAUTH) = ieee80211_wx_get_auth, -}; -#undef WX - -static const iw_handler bcm43xx_priv_wx_handlers[] = { - /* Set Interference Mitigation Mode. */ - bcm43xx_wx_set_interfmode, - /* Get Interference Mitigation Mode. */ - bcm43xx_wx_get_interfmode, - /* Enable/Disable Short Preamble mode. */ - bcm43xx_wx_set_shortpreamble, - /* Get Short Preamble mode. */ - bcm43xx_wx_get_shortpreamble, - /* Enable/Disable Software Encryption mode */ - bcm43xx_wx_set_swencryption, - /* Get Software Encryption mode */ - bcm43xx_wx_get_swencryption, - /* Write SRPROM data. */ - bcm43xx_wx_sprom_write, - /* Read SPROM data. */ - bcm43xx_wx_sprom_read, -}; - -#define PRIV_WX_SET_INTERFMODE (SIOCIWFIRSTPRIV + 0) -#define PRIV_WX_GET_INTERFMODE (SIOCIWFIRSTPRIV + 1) -#define PRIV_WX_SET_SHORTPREAMBLE (SIOCIWFIRSTPRIV + 2) -#define PRIV_WX_GET_SHORTPREAMBLE (SIOCIWFIRSTPRIV + 3) -#define PRIV_WX_SET_SWENCRYPTION (SIOCIWFIRSTPRIV + 4) -#define PRIV_WX_GET_SWENCRYPTION (SIOCIWFIRSTPRIV + 5) -#define PRIV_WX_SPROM_WRITE (SIOCIWFIRSTPRIV + 6) -#define PRIV_WX_SPROM_READ (SIOCIWFIRSTPRIV + 7) - -#define PRIV_WX_DUMMY(ioctl) \ - { \ - .cmd = (ioctl), \ - .name = "__unused" \ - } - -static const struct iw_priv_args bcm43xx_priv_wx_args[] = { - { - .cmd = PRIV_WX_SET_INTERFMODE, - .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - .name = "set_interfmode", - }, - { - .cmd = PRIV_WX_GET_INTERFMODE, - .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING, - .name = "get_interfmode", - }, - { - .cmd = PRIV_WX_SET_SHORTPREAMBLE, - .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - .name = "set_shortpreamb", - }, - { - .cmd = PRIV_WX_GET_SHORTPREAMBLE, - .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING, - .name = "get_shortpreamb", - }, - { - .cmd = PRIV_WX_SET_SWENCRYPTION, - .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - .name = "set_swencrypt", - }, - { - .cmd = PRIV_WX_GET_SWENCRYPTION, - .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING, - .name = "get_swencrypt", - }, - { - .cmd = PRIV_WX_SPROM_WRITE, - .set_args = IW_PRIV_TYPE_CHAR | SPROM_BUFFERSIZE, - .name = "write_sprom", - }, - { - .cmd = PRIV_WX_SPROM_READ, - .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | SPROM_BUFFERSIZE, - .name = "read_sprom", - }, -}; - -const struct iw_handler_def bcm43xx_wx_handlers_def = { - .standard = bcm43xx_wx_handlers, - .num_standard = ARRAY_SIZE(bcm43xx_wx_handlers), - .num_private = ARRAY_SIZE(bcm43xx_priv_wx_handlers), - .num_private_args = ARRAY_SIZE(bcm43xx_priv_wx_args), - .private = bcm43xx_priv_wx_handlers, - .private_args = bcm43xx_priv_wx_args, - .get_wireless_stats = bcm43xx_get_wireless_stats, -}; diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.h b/drivers/net/wireless/bcm43xx/bcm43xx_wx.h deleted file mode 100644 index 1f29ff3aa4c3..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - - Broadcom BCM43xx wireless driver - - Copyright (c) 2005 Martin Langer , - Stefano Brivio - Michael Buesch - Danny van Dyk - Andreas Jaggi - - Some parts of the code in this file are derived from the ipw2200 - driver Copyright(c) 2003 - 2004 Intel Corporation. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#ifndef BCM43xx_WX_H_ -#define BCM43xx_WX_H_ - -extern const struct iw_handler_def bcm43xx_wx_handlers_def; - -#endif /* BCM43xx_WX_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c deleted file mode 100644 index f79fe11f9e81..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c +++ /dev/null @@ -1,565 +0,0 @@ -/* - - Broadcom BCM43xx wireless driver - - Transmission (TX/RX) related functions. - - Copyright (c) 2005 Martin Langer , - Stefano Brivio - Michael Buesch - Danny van Dyk - Andreas Jaggi - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include "bcm43xx_xmit.h" - -#include - - -/* Extract the bitrate out of a CCK PLCP header. */ -static u8 bcm43xx_plcp_get_bitrate_cck(struct bcm43xx_plcp_hdr4 *plcp) -{ - switch (plcp->raw[0]) { - case 0x0A: - return IEEE80211_CCK_RATE_1MB; - case 0x14: - return IEEE80211_CCK_RATE_2MB; - case 0x37: - return IEEE80211_CCK_RATE_5MB; - case 0x6E: - return IEEE80211_CCK_RATE_11MB; - } - assert(0); - return 0; -} - -/* Extract the bitrate out of an OFDM PLCP header. */ -static u8 bcm43xx_plcp_get_bitrate_ofdm(struct bcm43xx_plcp_hdr4 *plcp) -{ - switch (plcp->raw[0] & 0xF) { - case 0xB: - return IEEE80211_OFDM_RATE_6MB; - case 0xF: - return IEEE80211_OFDM_RATE_9MB; - case 0xA: - return IEEE80211_OFDM_RATE_12MB; - case 0xE: - return IEEE80211_OFDM_RATE_18MB; - case 0x9: - return IEEE80211_OFDM_RATE_24MB; - case 0xD: - return IEEE80211_OFDM_RATE_36MB; - case 0x8: - return IEEE80211_OFDM_RATE_48MB; - case 0xC: - return IEEE80211_OFDM_RATE_54MB; - } - assert(0); - return 0; -} - -u8 bcm43xx_plcp_get_ratecode_cck(const u8 bitrate) -{ - switch (bitrate) { - case IEEE80211_CCK_RATE_1MB: - return 0x0A; - case IEEE80211_CCK_RATE_2MB: - return 0x14; - case IEEE80211_CCK_RATE_5MB: - return 0x37; - case IEEE80211_CCK_RATE_11MB: - return 0x6E; - } - assert(0); - return 0; -} - -u8 bcm43xx_plcp_get_ratecode_ofdm(const u8 bitrate) -{ - switch (bitrate) { - case IEEE80211_OFDM_RATE_6MB: - return 0xB; - case IEEE80211_OFDM_RATE_9MB: - return 0xF; - case IEEE80211_OFDM_RATE_12MB: - return 0xA; - case IEEE80211_OFDM_RATE_18MB: - return 0xE; - case IEEE80211_OFDM_RATE_24MB: - return 0x9; - case IEEE80211_OFDM_RATE_36MB: - return 0xD; - case IEEE80211_OFDM_RATE_48MB: - return 0x8; - case IEEE80211_OFDM_RATE_54MB: - return 0xC; - } - assert(0); - return 0; -} - -static void bcm43xx_generate_plcp_hdr(struct bcm43xx_plcp_hdr4 *plcp, - const u16 octets, const u8 bitrate, - const int ofdm_modulation) -{ - __le32 *data = &(plcp->data); - __u8 *raw = plcp->raw; - - if (ofdm_modulation) { - u32 val = bcm43xx_plcp_get_ratecode_ofdm(bitrate); - assert(!(octets & 0xF000)); - val |= (octets << 5); - *data = cpu_to_le32(val); - } else { - u32 plen; - - plen = octets * 16 / bitrate; - if ((octets * 16 % bitrate) > 0) { - plen++; - if ((bitrate == IEEE80211_CCK_RATE_11MB) - && ((octets * 8 % 11) < 4)) { - raw[1] = 0x84; - } else - raw[1] = 0x04; - } else - raw[1] = 0x04; - *data |= cpu_to_le32(plen << 16); - raw[0] = bcm43xx_plcp_get_ratecode_cck(bitrate); - } -} - -static u8 bcm43xx_calc_fallback_rate(u8 bitrate) -{ - switch (bitrate) { - case IEEE80211_CCK_RATE_1MB: - return IEEE80211_CCK_RATE_1MB; - case IEEE80211_CCK_RATE_2MB: - return IEEE80211_CCK_RATE_1MB; - case IEEE80211_CCK_RATE_5MB: - return IEEE80211_CCK_RATE_2MB; - case IEEE80211_CCK_RATE_11MB: - return IEEE80211_CCK_RATE_5MB; - case IEEE80211_OFDM_RATE_6MB: - return IEEE80211_CCK_RATE_5MB; - case IEEE80211_OFDM_RATE_9MB: - return IEEE80211_OFDM_RATE_6MB; - case IEEE80211_OFDM_RATE_12MB: - return IEEE80211_OFDM_RATE_9MB; - case IEEE80211_OFDM_RATE_18MB: - return IEEE80211_OFDM_RATE_12MB; - case IEEE80211_OFDM_RATE_24MB: - return IEEE80211_OFDM_RATE_18MB; - case IEEE80211_OFDM_RATE_36MB: - return IEEE80211_OFDM_RATE_24MB; - case IEEE80211_OFDM_RATE_48MB: - return IEEE80211_OFDM_RATE_36MB; - case IEEE80211_OFDM_RATE_54MB: - return IEEE80211_OFDM_RATE_48MB; - } - assert(0); - return 0; -} - -static -__le16 bcm43xx_calc_duration_id(const struct ieee80211_hdr *wireless_header, - u8 bitrate) -{ - const u16 frame_ctl = le16_to_cpu(wireless_header->frame_ctl); - __le16 duration_id = wireless_header->duration_id; - - switch (WLAN_FC_GET_TYPE(frame_ctl)) { - case IEEE80211_FTYPE_DATA: - case IEEE80211_FTYPE_MGMT: - //TODO: Steal the code from ieee80211, once it is completed there. - break; - case IEEE80211_FTYPE_CTL: - /* Use the original duration/id. */ - break; - default: - assert(0); - } - - return duration_id; -} - -static inline -u16 ceiling_div(u16 dividend, u16 divisor) -{ - return ((dividend + divisor - 1) / divisor); -} - -static void bcm43xx_generate_rts(const struct bcm43xx_phyinfo *phy, - struct bcm43xx_txhdr *txhdr, - u16 *flags, - u8 bitrate, - const struct ieee80211_hdr_4addr *wlhdr) -{ - u16 fctl; - u16 dur; - u8 fallback_bitrate; - int ofdm_modulation; - int fallback_ofdm_modulation; -// u8 *sa, *da; - u16 flen; - -//FIXME sa = ieee80211_get_SA((struct ieee80211_hdr *)wlhdr); -//FIXME da = ieee80211_get_DA((struct ieee80211_hdr *)wlhdr); - fallback_bitrate = bcm43xx_calc_fallback_rate(bitrate); - ofdm_modulation = !(ieee80211_is_cck_rate(bitrate)); - fallback_ofdm_modulation = !(ieee80211_is_cck_rate(fallback_bitrate)); - - flen = sizeof(u16) + sizeof(u16) + ETH_ALEN + ETH_ALEN + IEEE80211_FCS_LEN, - bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->rts_cts_plcp), - flen, bitrate, - !ieee80211_is_cck_rate(bitrate)); - bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->rts_cts_fallback_plcp), - flen, fallback_bitrate, - !ieee80211_is_cck_rate(fallback_bitrate)); - fctl = IEEE80211_FTYPE_CTL; - fctl |= IEEE80211_STYPE_RTS; - dur = le16_to_cpu(wlhdr->duration_id); -/*FIXME: should we test for dur==0 here and let it unmodified in this case? - * The following assert checks for this case... - */ -assert(dur); -/*FIXME: The duration calculation is not really correct. - * I am not 100% sure which bitrate to use. We use the RTS rate here, - * but this is likely to be wrong. - */ - if (phy->type == BCM43xx_PHYTYPE_A) { - /* Three times SIFS */ - dur += 16 * 3; - /* Add ACK duration. */ - dur += ceiling_div((16 + 8 * (14 /*bytes*/) + 6) * 10, - bitrate * 4); - /* Add CTS duration. */ - dur += ceiling_div((16 + 8 * (14 /*bytes*/) + 6) * 10, - bitrate * 4); - } else { - /* Three times SIFS */ - dur += 10 * 3; - /* Add ACK duration. */ - dur += ceiling_div(8 * (14 /*bytes*/) * 10, - bitrate); - /* Add CTS duration. */ - dur += ceiling_div(8 * (14 /*bytes*/) * 10, - bitrate); - } - - txhdr->rts_cts_frame_control = cpu_to_le16(fctl); - txhdr->rts_cts_dur = cpu_to_le16(dur); -//printk(BCM43xx_MACFMT " " BCM43xx_MACFMT " " BCM43xx_MACFMT "\n", BCM43xx_MACARG(wlhdr->addr1), BCM43xx_MACARG(wlhdr->addr2), BCM43xx_MACARG(wlhdr->addr3)); -//printk(BCM43xx_MACFMT " " BCM43xx_MACFMT "\n", BCM43xx_MACARG(sa), BCM43xx_MACARG(da)); - memcpy(txhdr->rts_cts_mac1, wlhdr->addr1, ETH_ALEN);//FIXME! -// memcpy(txhdr->rts_cts_mac2, sa, ETH_ALEN); - - *flags |= BCM43xx_TXHDRFLAG_RTSCTS; - *flags |= BCM43xx_TXHDRFLAG_RTS; - if (ofdm_modulation) - *flags |= BCM43xx_TXHDRFLAG_RTSCTS_OFDM; - if (fallback_ofdm_modulation) - *flags |= BCM43xx_TXHDRFLAG_RTSCTSFALLBACK_OFDM; -} - -void bcm43xx_generate_txhdr(struct bcm43xx_private *bcm, - struct bcm43xx_txhdr *txhdr, - const unsigned char *fragment_data, - const unsigned int fragment_len, - const int is_first_fragment, - const u16 cookie) -{ - const struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - const struct ieee80211_hdr_4addr *wireless_header = (const struct ieee80211_hdr_4addr *)fragment_data; - const struct ieee80211_security *secinfo = &bcm->ieee->sec; - u8 bitrate; - u8 fallback_bitrate; - int ofdm_modulation; - int fallback_ofdm_modulation; - u16 plcp_fragment_len = fragment_len; - u16 flags = 0; - u16 control = 0; - u16 wsec_rate = 0; - u16 encrypt_frame; - const u16 ftype = WLAN_FC_GET_TYPE(le16_to_cpu(wireless_header->frame_ctl)); - const int is_mgt = (ftype == IEEE80211_FTYPE_MGMT); - - /* Now construct the TX header. */ - memset(txhdr, 0, sizeof(*txhdr)); - - bitrate = ieee80211softmac_suggest_txrate(bcm->softmac, - is_multicast_ether_addr(wireless_header->addr1), is_mgt); - ofdm_modulation = !(ieee80211_is_cck_rate(bitrate)); - fallback_bitrate = bcm43xx_calc_fallback_rate(bitrate); - fallback_ofdm_modulation = !(ieee80211_is_cck_rate(fallback_bitrate)); - - /* Set Frame Control from 80211 header. */ - txhdr->frame_control = wireless_header->frame_ctl; - /* Copy address1 from 80211 header. */ - memcpy(txhdr->mac1, wireless_header->addr1, 6); - /* Set the fallback duration ID. */ - txhdr->fallback_dur_id = bcm43xx_calc_duration_id((const struct ieee80211_hdr *)wireless_header, - fallback_bitrate); - /* Set the cookie (used as driver internal ID for the frame) */ - txhdr->cookie = cpu_to_le16(cookie); - - /* Hardware appends FCS. */ - plcp_fragment_len += IEEE80211_FCS_LEN; - - /* Hardware encryption. */ - encrypt_frame = le16_to_cpup(&wireless_header->frame_ctl) & IEEE80211_FCTL_PROTECTED; - if (encrypt_frame && !bcm->ieee->host_encrypt) { - const struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *)wireless_header; - memcpy(txhdr->wep_iv, hdr->payload, 4); - /* Hardware appends ICV. */ - plcp_fragment_len += 4; - - wsec_rate |= (bcm->key[secinfo->active_key].algorithm << BCM43xx_TXHDR_WSEC_ALGO_SHIFT) - & BCM43xx_TXHDR_WSEC_ALGO_MASK; - wsec_rate |= (secinfo->active_key << BCM43xx_TXHDR_WSEC_KEYINDEX_SHIFT) - & BCM43xx_TXHDR_WSEC_KEYINDEX_MASK; - } - - /* Generate the PLCP header and the fallback PLCP header. */ - bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->plcp), - plcp_fragment_len, - bitrate, ofdm_modulation); - bcm43xx_generate_plcp_hdr(&txhdr->fallback_plcp, plcp_fragment_len, - fallback_bitrate, fallback_ofdm_modulation); - - /* Set the CONTROL field */ - if (ofdm_modulation) - control |= BCM43xx_TXHDRCTL_OFDM; - if (bcm->short_preamble) //FIXME: could be the other way around, please test - control |= BCM43xx_TXHDRCTL_SHORT_PREAMBLE; - control |= (phy->antenna_diversity << BCM43xx_TXHDRCTL_ANTENNADIV_SHIFT) - & BCM43xx_TXHDRCTL_ANTENNADIV_MASK; - - /* Set the FLAGS field */ - if (!is_multicast_ether_addr(wireless_header->addr1) && - !is_broadcast_ether_addr(wireless_header->addr1)) - flags |= BCM43xx_TXHDRFLAG_EXPECTACK; - if (1 /* FIXME: PS poll?? */) - flags |= 0x10; // FIXME: unknown meaning. - if (fallback_ofdm_modulation) - flags |= BCM43xx_TXHDRFLAG_FALLBACKOFDM; - if (is_first_fragment) - flags |= BCM43xx_TXHDRFLAG_FIRSTFRAGMENT; - - /* Set WSEC/RATE field */ - wsec_rate |= (txhdr->plcp.raw[0] << BCM43xx_TXHDR_RATE_SHIFT) - & BCM43xx_TXHDR_RATE_MASK; - - /* Generate the RTS/CTS packet, if required. */ - /* FIXME: We should first try with CTS-to-self, - * if we are on 80211g. If we get too many - * failures (hidden nodes), we should switch back to RTS/CTS. - */ - if (0/*FIXME txctl->use_rts_cts*/) { - bcm43xx_generate_rts(phy, txhdr, &flags, - 0/*FIXME txctl->rts_cts_rate*/, - wireless_header); - } - - txhdr->flags = cpu_to_le16(flags); - txhdr->control = cpu_to_le16(control); - txhdr->wsec_rate = cpu_to_le16(wsec_rate); -} - -static s8 bcm43xx_rssi_postprocess(struct bcm43xx_private *bcm, - u8 in_rssi, int ofdm, - int adjust_2053, int adjust_2050) -{ - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - s32 tmp; - - switch (radio->version) { - case 0x2050: - if (ofdm) { - tmp = in_rssi; - if (tmp > 127) - tmp -= 256; - tmp *= 73; - tmp /= 64; - if (adjust_2050) - tmp += 25; - else - tmp -= 3; - } else { - if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) { - if (in_rssi > 63) - in_rssi = 63; - tmp = radio->nrssi_lt[in_rssi]; - tmp = 31 - tmp; - tmp *= -131; - tmp /= 128; - tmp -= 57; - } else { - tmp = in_rssi; - tmp = 31 - tmp; - tmp *= -149; - tmp /= 128; - tmp -= 68; - } - if (phy->type == BCM43xx_PHYTYPE_G && - adjust_2050) - tmp += 25; - } - break; - case 0x2060: - if (in_rssi > 127) - tmp = in_rssi - 256; - else - tmp = in_rssi; - break; - default: - tmp = in_rssi; - tmp -= 11; - tmp *= 103; - tmp /= 64; - if (adjust_2053) - tmp -= 109; - else - tmp -= 83; - } - - return (s8)tmp; -} - -//TODO -#if 0 -static s8 bcm43xx_rssinoise_postprocess(struct bcm43xx_private *bcm, - u8 in_rssi) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - s8 ret; - - if (phy->type == BCM43xx_PHYTYPE_A) { - //TODO: Incomplete specs. - ret = 0; - } else - ret = bcm43xx_rssi_postprocess(bcm, in_rssi, 0, 1, 1); - - return ret; -} -#endif - -int bcm43xx_rx(struct bcm43xx_private *bcm, - struct sk_buff *skb, - struct bcm43xx_rxhdr *rxhdr) -{ - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - struct bcm43xx_plcp_hdr4 *plcp; - struct ieee80211_rx_stats stats; - struct ieee80211_hdr_4addr *wlhdr; - u16 frame_ctl; - int is_packet_for_us = 0; - int err = -EINVAL; - const u16 rxflags1 = le16_to_cpu(rxhdr->flags1); - const u16 rxflags2 = le16_to_cpu(rxhdr->flags2); - const u16 rxflags3 = le16_to_cpu(rxhdr->flags3); - const int is_ofdm = !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_OFDM); - - if (rxflags2 & BCM43xx_RXHDR_FLAGS2_TYPE2FRAME) { - plcp = (struct bcm43xx_plcp_hdr4 *)(skb->data + 2); - /* Skip two unknown bytes and the PLCP header. */ - skb_pull(skb, 2 + sizeof(struct bcm43xx_plcp_hdr6)); - } else { - plcp = (struct bcm43xx_plcp_hdr4 *)(skb->data); - /* Skip the PLCP header. */ - skb_pull(skb, sizeof(struct bcm43xx_plcp_hdr6)); - } - /* The SKB contains the PAYLOAD (wireless header + data) - * at this point. The FCS at the end is stripped. - */ - - memset(&stats, 0, sizeof(stats)); - stats.mac_time = le16_to_cpu(rxhdr->mactime); - stats.rssi = rxhdr->rssi; - stats.signal = bcm43xx_rssi_postprocess(bcm, rxhdr->rssi, is_ofdm, - !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_2053RSSIADJ), - !!(rxflags3 & BCM43xx_RXHDR_FLAGS3_2050RSSIADJ)); - stats.noise = bcm->stats.noise; - if (is_ofdm) - stats.rate = bcm43xx_plcp_get_bitrate_ofdm(plcp); - else - stats.rate = bcm43xx_plcp_get_bitrate_cck(plcp); - stats.received_channel = radio->channel; - stats.mask = IEEE80211_STATMASK_SIGNAL | - IEEE80211_STATMASK_NOISE | - IEEE80211_STATMASK_RATE | - IEEE80211_STATMASK_RSSI; - if (phy->type == BCM43xx_PHYTYPE_A) - stats.freq = IEEE80211_52GHZ_BAND; - else - stats.freq = IEEE80211_24GHZ_BAND; - stats.len = skb->len; - - bcm->stats.last_rx = jiffies; - if (bcm->ieee->iw_mode == IW_MODE_MONITOR) { - err = ieee80211_rx(bcm->ieee, skb, &stats); - return (err == 0) ? -EINVAL : 0; - } - - wlhdr = (struct ieee80211_hdr_4addr *)(skb->data); - - switch (bcm->ieee->iw_mode) { - case IW_MODE_ADHOC: - if (memcmp(wlhdr->addr1, bcm->net_dev->dev_addr, ETH_ALEN) == 0 || - memcmp(wlhdr->addr3, bcm->ieee->bssid, ETH_ALEN) == 0 || - is_broadcast_ether_addr(wlhdr->addr1) || - is_multicast_ether_addr(wlhdr->addr1) || - bcm->net_dev->flags & IFF_PROMISC) - is_packet_for_us = 1; - break; - case IW_MODE_INFRA: - default: - /* When receiving multicast or broadcast packets, filter out - the packets we send ourself; we shouldn't see those */ - if (memcmp(wlhdr->addr3, bcm->ieee->bssid, ETH_ALEN) == 0 || - memcmp(wlhdr->addr1, bcm->net_dev->dev_addr, ETH_ALEN) == 0 || - (memcmp(wlhdr->addr3, bcm->net_dev->dev_addr, ETH_ALEN) && - (is_broadcast_ether_addr(wlhdr->addr1) || - is_multicast_ether_addr(wlhdr->addr1) || - bcm->net_dev->flags & IFF_PROMISC))) - is_packet_for_us = 1; - break; - } - - frame_ctl = le16_to_cpu(wlhdr->frame_ctl); - switch (WLAN_FC_GET_TYPE(frame_ctl)) { - case IEEE80211_FTYPE_MGMT: - ieee80211_rx_mgt(bcm->ieee, wlhdr, &stats); - break; - case IEEE80211_FTYPE_DATA: - if (is_packet_for_us) { - err = ieee80211_rx(bcm->ieee, skb, &stats); - err = (err == 0) ? -EINVAL : 0; - } - break; - case IEEE80211_FTYPE_CTL: - break; - default: - assert(0); - return -EINVAL; - } - - return err; -} diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.h b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.h deleted file mode 100644 index 47c135a7f4dc..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.h +++ /dev/null @@ -1,150 +0,0 @@ -#ifndef BCM43xx_XMIT_H_ -#define BCM43xx_XMIT_H_ - -#include "bcm43xx_main.h" - - -#define _bcm43xx_declare_plcp_hdr(size) \ - struct bcm43xx_plcp_hdr##size { \ - union { \ - __le32 data; \ - __u8 raw[size]; \ - } __attribute__((__packed__)); \ - } __attribute__((__packed__)) - -/* struct bcm43xx_plcp_hdr4 */ -_bcm43xx_declare_plcp_hdr(4); -/* struct bcm43xx_plcp_hdr6 */ -_bcm43xx_declare_plcp_hdr(6); - -#undef _bcm43xx_declare_plcp_hdr - -/* Device specific TX header. To be prepended to TX frames. */ -struct bcm43xx_txhdr { - union { - struct { - __le16 flags; - __le16 wsec_rate; - __le16 frame_control; - u16 unknown_zeroed_0; - __le16 control; - u8 wep_iv[10]; - u8 unknown_wsec_tkip_data[3]; //FIXME - PAD_BYTES(3); - u8 mac1[6]; - u16 unknown_zeroed_1; - struct bcm43xx_plcp_hdr4 rts_cts_fallback_plcp; - __le16 rts_cts_dur_fallback; - struct bcm43xx_plcp_hdr4 fallback_plcp; - __le16 fallback_dur_id; - PAD_BYTES(2); - __le16 cookie; - __le16 unknown_scb_stuff; //FIXME - struct bcm43xx_plcp_hdr6 rts_cts_plcp; - __le16 rts_cts_frame_control; - __le16 rts_cts_dur; - u8 rts_cts_mac1[6]; - u8 rts_cts_mac2[6]; - PAD_BYTES(2); - struct bcm43xx_plcp_hdr6 plcp; - } __attribute__((__packed__)); - u8 raw[82]; - } __attribute__((__packed__)); -} __attribute__((__packed__)); - -/* Values/Masks for the device TX header */ -#define BCM43xx_TXHDRFLAG_EXPECTACK 0x0001 -#define BCM43xx_TXHDRFLAG_RTSCTS 0x0002 -#define BCM43xx_TXHDRFLAG_RTS 0x0004 -#define BCM43xx_TXHDRFLAG_FIRSTFRAGMENT 0x0008 -#define BCM43xx_TXHDRFLAG_DESTPSMODE 0x0020 -#define BCM43xx_TXHDRFLAG_RTSCTS_OFDM 0x0080 -#define BCM43xx_TXHDRFLAG_FALLBACKOFDM 0x0100 -#define BCM43xx_TXHDRFLAG_RTSCTSFALLBACK_OFDM 0x0200 -#define BCM43xx_TXHDRFLAG_CTS 0x0400 -#define BCM43xx_TXHDRFLAG_FRAMEBURST 0x0800 - -#define BCM43xx_TXHDRCTL_OFDM 0x0001 -#define BCM43xx_TXHDRCTL_SHORT_PREAMBLE 0x0010 -#define BCM43xx_TXHDRCTL_ANTENNADIV_MASK 0x0030 -#define BCM43xx_TXHDRCTL_ANTENNADIV_SHIFT 8 - -#define BCM43xx_TXHDR_RATE_MASK 0x0F00 -#define BCM43xx_TXHDR_RATE_SHIFT 8 -#define BCM43xx_TXHDR_RTSRATE_MASK 0xF000 -#define BCM43xx_TXHDR_RTSRATE_SHIFT 12 -#define BCM43xx_TXHDR_WSEC_KEYINDEX_MASK 0x00F0 -#define BCM43xx_TXHDR_WSEC_KEYINDEX_SHIFT 4 -#define BCM43xx_TXHDR_WSEC_ALGO_MASK 0x0003 -#define BCM43xx_TXHDR_WSEC_ALGO_SHIFT 0 - -void bcm43xx_generate_txhdr(struct bcm43xx_private *bcm, - struct bcm43xx_txhdr *txhdr, - const unsigned char *fragment_data, - const unsigned int fragment_len, - const int is_first_fragment, - const u16 cookie); - -/* RX header as received from the hardware. */ -struct bcm43xx_rxhdr { - /* Frame Length. Must be generated explicitly in PIO mode. */ - __le16 frame_length; - PAD_BYTES(2); - /* Flags field 1 */ - __le16 flags1; - u8 rssi; - u8 signal_quality; - PAD_BYTES(2); - /* Flags field 3 */ - __le16 flags3; - /* Flags field 2 */ - __le16 flags2; - /* Lower 16bits of the TSF at the time the frame started. */ - __le16 mactime; - PAD_BYTES(14); -} __attribute__((__packed__)); - -#define BCM43xx_RXHDR_FLAGS1_OFDM (1 << 0) -/*#define BCM43xx_RXHDR_FLAGS1_SIGNAL??? (1 << 3) FIXME */ -#define BCM43xx_RXHDR_FLAGS1_SHORTPREAMBLE (1 << 7) -#define BCM43xx_RXHDR_FLAGS1_2053RSSIADJ (1 << 14) - -#define BCM43xx_RXHDR_FLAGS2_INVALIDFRAME (1 << 0) -#define BCM43xx_RXHDR_FLAGS2_TYPE2FRAME (1 << 2) -/*FIXME: WEP related flags */ - -#define BCM43xx_RXHDR_FLAGS3_2050RSSIADJ (1 << 10) - -/* Transmit Status as received from the hardware. */ -struct bcm43xx_hwxmitstatus { - PAD_BYTES(4); - __le16 cookie; - u8 flags; - u8 cnt1:4, - cnt2:4; - PAD_BYTES(2); - __le16 seq; - __le16 unknown; //FIXME -} __attribute__((__packed__)); - -/* Transmit Status in CPU byteorder. */ -struct bcm43xx_xmitstatus { - u16 cookie; - u8 flags; - u8 cnt1:4, - cnt2:4; - u16 seq; - u16 unknown; //FIXME -}; - -#define BCM43xx_TXSTAT_FLAG_AMPDU 0x10 -#define BCM43xx_TXSTAT_FLAG_INTER 0x20 - -u8 bcm43xx_plcp_get_ratecode_cck(const u8 bitrate); -u8 bcm43xx_plcp_get_ratecode_ofdm(const u8 bitrate); - -int bcm43xx_rx(struct bcm43xx_private *bcm, - struct sk_buff *skb, - struct bcm43xx_rxhdr *rxhdr); - -#endif /* BCM43xx_XMIT_H_ */ -- cgit v1.2.1 From 52933d815bff78605a490582a2212a8131482e00 Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Wed, 5 Mar 2008 07:05:32 +0100 Subject: libertas: implement SSID scanning for SIOCSIWSCAN After my bit scan re-writing the SIOCSIWSCAN wext ioctl no longer supported scanning for a specific SSID. However, wpa_supplicant is a possible user of this ioctl, so here is code that add's this. While passing, removed even more of the debugfs-based scanning. You can (and should) the SIOCSIWSCAN to ask for scans, so there is no need for proprietary interfaces for scanning. And, besides, the scan result couldn't be used further, e.g. not for associating. Signed-off-by: Holger Schurig Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/assoc.c | 4 +- drivers/net/wireless/libertas/debugfs.c | 169 -------------------------------- drivers/net/wireless/libertas/dev.h | 2 + drivers/net/wireless/libertas/scan.c | 145 +++++++++++++-------------- drivers/net/wireless/libertas/scan.h | 69 +------------ drivers/net/wireless/libertas/wext.c | 3 + 6 files changed, 76 insertions(+), 316 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c index 7fe37bedf313..707b7ff592ec 100644 --- a/drivers/net/wireless/libertas/assoc.c +++ b/drivers/net/wireless/libertas/assoc.c @@ -38,7 +38,7 @@ static int assoc_helper_essid(struct lbs_private *priv, escape_essid(assoc_req->ssid, assoc_req->ssid_len)); if (assoc_req->mode == IW_MODE_INFRA) { lbs_send_specific_ssid_scan(priv, assoc_req->ssid, - assoc_req->ssid_len, 0); + assoc_req->ssid_len); bss = lbs_find_ssid_in_list(priv, assoc_req->ssid, assoc_req->ssid_len, NULL, IW_MODE_INFRA, channel); @@ -53,7 +53,7 @@ static int assoc_helper_essid(struct lbs_private *priv, * scan data will cause us to join a non-existant adhoc network */ lbs_send_specific_ssid_scan(priv, assoc_req->ssid, - assoc_req->ssid_len, 1); + assoc_req->ssid_len); /* Search for the requested SSID in the scan table */ bss = lbs_find_ssid_in_list(priv, assoc_req->ssid, diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c index b600f2439b57..8f88786b036f 100644 --- a/drivers/net/wireless/libertas/debugfs.c +++ b/drivers/net/wireless/libertas/debugfs.c @@ -164,173 +164,6 @@ out_unlock: return ret; } -static ssize_t lbs_extscan(struct file *file, const char __user *userbuf, - size_t count, loff_t *ppos) -{ - struct lbs_private *priv = file->private_data; - ssize_t res, buf_size; - union iwreq_data wrqu; - unsigned long addr = get_zeroed_page(GFP_KERNEL); - char *buf = (char *)addr; - - buf_size = min(count, len - 1); - if (copy_from_user(buf, userbuf, buf_size)) { - res = -EFAULT; - goto out_unlock; - } - - lbs_send_specific_ssid_scan(priv, buf, strlen(buf)-1, 0); - - memset(&wrqu, 0, sizeof(union iwreq_data)); - wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL); - -out_unlock: - free_page(addr); - return count; -} - -static void lbs_parse_bssid(char *buf, size_t count, - struct lbs_ioctl_user_scan_cfg *scan_cfg) -{ - char *hold; - unsigned int mac[ETH_ALEN]; - - hold = strstr(buf, "bssid="); - if (!hold) - return; - hold += 6; - sscanf(hold, "%02x:%02x:%02x:%02x:%02x:%02x", - mac, mac+1, mac+2, mac+3, mac+4, mac+5); - memcpy(scan_cfg->bssid, mac, ETH_ALEN); -} - -static void lbs_parse_ssid(char *buf, size_t count, - struct lbs_ioctl_user_scan_cfg *scan_cfg) -{ - char *hold, *end; - ssize_t size; - - hold = strstr(buf, "ssid="); - if (!hold) - return; - hold += 5; - end = strchr(hold, ' '); - if (!end) - end = buf + count - 1; - - size = min((size_t)IW_ESSID_MAX_SIZE, (size_t) (end - hold)); - strncpy(scan_cfg->ssid, hold, size); - - return; -} - -static int lbs_parse_clear(char *buf, size_t count, const char *tag) -{ - char *hold; - int val; - - hold = strstr(buf, tag); - if (!hold) - return 0; - hold += strlen(tag); - sscanf(hold, "%d", &val); - - if (val != 0) - val = 1; - - return val; -} - -static int lbs_parse_dur(char *buf, size_t count, - struct lbs_ioctl_user_scan_cfg *scan_cfg) -{ - char *hold; - int val; - - hold = strstr(buf, "dur="); - if (!hold) - return 0; - hold += 4; - sscanf(hold, "%d", &val); - - return val; -} - -static void lbs_parse_type(char *buf, size_t count, - struct lbs_ioctl_user_scan_cfg *scan_cfg) -{ - char *hold; - int val; - - hold = strstr(buf, "type="); - if (!hold) - return; - hold += 5; - sscanf(hold, "%d", &val); - - /* type=1,2 or 3 */ - if (val < 1 || val > 3) - return; - - scan_cfg->bsstype = val; - - return; -} - -static ssize_t lbs_setuserscan(struct file *file, - const char __user *userbuf, - size_t count, loff_t *ppos) -{ - struct lbs_private *priv = file->private_data; - ssize_t res, buf_size; - struct lbs_ioctl_user_scan_cfg *scan_cfg; - union iwreq_data wrqu; - int dur; - char *buf = (char *)get_zeroed_page(GFP_KERNEL); - - if (!buf) - return -ENOMEM; - - buf_size = min(count, len - 1); - if (copy_from_user(buf, userbuf, buf_size)) { - res = -EFAULT; - goto out_buf; - } - - scan_cfg = kzalloc(sizeof(struct lbs_ioctl_user_scan_cfg), GFP_KERNEL); - if (!scan_cfg) { - res = -ENOMEM; - goto out_buf; - } - res = count; - - scan_cfg->bsstype = LBS_SCAN_BSS_TYPE_ANY; - - dur = lbs_parse_dur(buf, count, scan_cfg); - lbs_parse_bssid(buf, count, scan_cfg); - scan_cfg->clear_bssid = lbs_parse_clear(buf, count, "clear_bssid="); - lbs_parse_ssid(buf, count, scan_cfg); - scan_cfg->clear_ssid = lbs_parse_clear(buf, count, "clear_ssid="); - lbs_parse_type(buf, count, scan_cfg); - - lbs_scan_networks(priv, scan_cfg, 1); - wait_event_interruptible(priv->cmd_pending, - priv->surpriseremoved || !priv->scan_channel); - - if (priv->surpriseremoved) - goto out_scan_cfg; - - memset(&wrqu, 0x00, sizeof(union iwreq_data)); - wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL); - - out_scan_cfg: - kfree(scan_cfg); - out_buf: - free_page((unsigned long)buf); - return res; -} - - /* * When calling CMD_802_11_SUBSCRIBE_EVENT with CMD_ACT_GET, me might * get a bunch of vendor-specific TLVs (a.k.a. IEs) back from the @@ -857,8 +690,6 @@ static struct lbs_debugfs_files debugfs_files[] = { write_file_dummy), }, { "sleepparams", 0644, FOPS(lbs_sleepparams_read, lbs_sleepparams_write), }, - { "extscan", 0600, FOPS(NULL, lbs_extscan), }, - { "setuserscan", 0600, FOPS(NULL, lbs_setuserscan), }, }; static struct lbs_debugfs_files debugfs_events_files[] = { diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index fd1fcc748010..ff2c046ca73f 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h @@ -149,6 +149,8 @@ struct lbs_private { struct work_struct sync_channel; /* remember which channel was scanned last, != 0 if currently scanning */ int scan_channel; + u8 scan_ssid[IW_ESSID_MAX_SIZE + 1]; + u8 scan_ssid_len; /** Hardware access */ int (*hw_host_to_card) (struct lbs_private *priv, u8 type, u8 *payload, u16 nb); diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c index 99f11a56d84e..0598541451d8 100644 --- a/drivers/net/wireless/libertas/scan.c +++ b/drivers/net/wireless/libertas/scan.c @@ -260,24 +260,12 @@ done: - /*********************************************************************/ /* */ /* Main scanning support */ /* */ /*********************************************************************/ -void lbs_scan_worker(struct work_struct *work) -{ - struct lbs_private *priv = - container_of(work, struct lbs_private, scan_work.work); - - lbs_deb_enter(LBS_DEB_SCAN); - lbs_scan_networks(priv, NULL, 0); - lbs_deb_leave(LBS_DEB_SCAN); -} - - /** * @brief Create a channel list for the driver to scan based on region info * @@ -289,17 +277,11 @@ void lbs_scan_worker(struct work_struct *work) * * @param priv A pointer to struct lbs_private structure * @param scanchanlist Output parameter: resulting channel list to scan - * @param filteredscan Flag indicating whether or not a BSSID or SSID filter - * is being sent in the command to firmware. Used to - * increase the number of channels sent in a scan - * command and to disable the firmware channel scan - * filter. * * @return void */ static int lbs_scan_create_channel_list(struct lbs_private *priv, - struct chanscanparamset *scanchanlist, - uint8_t filteredscan) + struct chanscanparamset *scanchanlist) { struct region_channel *scanregion; struct chan_freq_power *cfp; @@ -354,9 +336,6 @@ static int lbs_scan_create_channel_list(struct lbs_private *priv, } chan->channumber = cfp->channel; - - if (filteredscan) - chan->chanscanmode.disablechanfilt = 1; } } return chanidx; @@ -370,15 +349,14 @@ static int lbs_scan_create_channel_list(struct lbs_private *priv, * length 06 00 * ssid 4d 4e 54 45 53 54 */ -static int lbs_scan_add_ssid_tlv(uint8_t *tlv, - const struct lbs_ioctl_user_scan_cfg *user_cfg) +static int lbs_scan_add_ssid_tlv(struct lbs_private *priv, u8 *tlv) { struct mrvlietypes_ssidparamset *ssid_tlv = (void *)tlv; ssid_tlv->header.type = cpu_to_le16(TLV_TYPE_SSID); - ssid_tlv->header.len = cpu_to_le16(user_cfg->ssid_len); - memcpy(ssid_tlv->ssid, user_cfg->ssid, user_cfg->ssid_len); - return sizeof(ssid_tlv->header) + user_cfg->ssid_len; + ssid_tlv->header.len = cpu_to_le16(priv->scan_ssid_len); + memcpy(ssid_tlv->ssid, priv->scan_ssid, priv->scan_ssid_len); + return sizeof(ssid_tlv->header) + priv->scan_ssid_len; } @@ -461,8 +439,7 @@ static int lbs_scan_add_rates_tlv(uint8_t *tlv) * for a bunch of channels. */ static int lbs_do_scan(struct lbs_private *priv, uint8_t bsstype, - struct chanscanparamset *chan_list, int chan_count, - const struct lbs_ioctl_user_scan_cfg *user_cfg) + struct chanscanparamset *chan_list, int chan_count) { int ret = -ENOMEM; struct cmd_ds_802_11_scan *scan_cmd; @@ -477,13 +454,13 @@ static int lbs_do_scan(struct lbs_private *priv, uint8_t bsstype, goto out; tlv = scan_cmd->tlvbuffer; - if (user_cfg) - memcpy(scan_cmd->bssid, user_cfg->bssid, ETH_ALEN); + /* TODO: do we need to scan for a specific BSSID? + memcpy(scan_cmd->bssid, priv->scan_bssid, ETH_ALEN); */ scan_cmd->bsstype = bsstype; /* add TLVs */ - if (user_cfg && user_cfg->ssid_len) - tlv += lbs_scan_add_ssid_tlv(tlv, user_cfg); + if (priv->scan_ssid_len) + tlv += lbs_scan_add_ssid_tlv(priv, tlv); if (chan_list && chan_count) tlv += lbs_scan_add_chanlist_tlv(tlv, chan_list, chan_count); tlv += lbs_scan_add_rates_tlv(tlv); @@ -516,14 +493,11 @@ out: * update the internal driver scan table * * @param priv A pointer to struct lbs_private structure - * @param puserscanin Pointer to the input configuration for the requested - * scan. + * @param full_scan Do a full-scan (blocking) * * @return 0 or < 0 if error */ -int lbs_scan_networks(struct lbs_private *priv, - const struct lbs_ioctl_user_scan_cfg *user_cfg, - int full_scan) +static int lbs_scan_networks(struct lbs_private *priv, int full_scan) { int ret = -ENOMEM; struct chanscanparamset *chan_list; @@ -531,7 +505,6 @@ int lbs_scan_networks(struct lbs_private *priv, int chan_count; uint8_t bsstype = CMD_BSS_TYPE_ANY; int numchannels = MRVDRV_CHANNELS_PER_SCAN_CMD; - int filteredscan = 0; union iwreq_data wrqu; #ifdef CONFIG_LIBERTAS_DEBUG struct bss_descriptor *iter; @@ -547,17 +520,16 @@ int lbs_scan_networks(struct lbs_private *priv, if (full_scan && delayed_work_pending(&priv->scan_work)) cancel_delayed_work(&priv->scan_work); - /* Determine same scan parameters */ + /* User-specified bsstype or channel list + TODO: this can be implemented if some user-space application + need the feature. Formerly, it was accessible from debugfs, + but then nowhere used. if (user_cfg) { if (user_cfg->bsstype) - bsstype = user_cfg->bsstype; - if (!is_zero_ether_addr(user_cfg->bssid)) { - numchannels = MRVDRV_MAX_CHANNELS_PER_SCAN; - filteredscan = 1; - } - } - lbs_deb_scan("numchannels %d, bsstype %d, filteredscan %d\n", - numchannels, bsstype, filteredscan); + bsstype = user_cfg->bsstype; + } */ + + lbs_deb_scan("numchannels %d, bsstype %d\n", numchannels, bsstype); /* Create list of channels to scan */ chan_list = kzalloc(sizeof(struct chanscanparamset) * @@ -568,7 +540,7 @@ int lbs_scan_networks(struct lbs_private *priv, } /* We want to scan all channels */ - chan_count = lbs_scan_create_channel_list(priv, chan_list, filteredscan); + chan_count = lbs_scan_create_channel_list(priv, chan_list); netif_stop_queue(priv->dev); netif_carrier_off(priv->dev); @@ -597,7 +569,7 @@ int lbs_scan_networks(struct lbs_private *priv, lbs_deb_scan("scanning %d of %d channels\n", to_scan, chan_count); ret = lbs_do_scan(priv, bsstype, curr_chans, - to_scan, user_cfg); + to_scan); if (ret) { lbs_pr_err("SCAN_CMD failed\n"); goto out2; @@ -658,6 +630,17 @@ out: +void lbs_scan_worker(struct work_struct *work) +{ + struct lbs_private *priv = + container_of(work, struct lbs_private, scan_work.work); + + lbs_deb_enter(LBS_DEB_SCAN); + lbs_scan_networks(priv, 0); + lbs_deb_leave(LBS_DEB_SCAN); +} + + /*********************************************************************/ /* */ /* Result interpretation */ @@ -1068,7 +1051,7 @@ static struct bss_descriptor *lbs_find_best_ssid_in_list(struct lbs_private *pri } /** - * @brief Find the AP with specific ssid in the scan list + * @brief Find the best AP * * Used from association worker. * @@ -1086,7 +1069,8 @@ int lbs_find_best_network_ssid(struct lbs_private *priv, uint8_t *out_ssid, lbs_deb_enter(LBS_DEB_SCAN); - lbs_scan_networks(priv, NULL, 1); + priv->scan_ssid_len = 0; + lbs_scan_networks(priv, 1); if (priv->surpriseremoved) goto out; @@ -1112,29 +1096,24 @@ out: * @param priv A pointer to struct lbs_private structure * @param ssid A pointer to the SSID to scan for * @param ssid_len Length of the SSID - * @param clear_ssid Should existing scan results with this SSID - * be cleared? * * @return 0-success, otherwise fail */ int lbs_send_specific_ssid_scan(struct lbs_private *priv, uint8_t *ssid, - uint8_t ssid_len, uint8_t clear_ssid) + uint8_t ssid_len) { - struct lbs_ioctl_user_scan_cfg scancfg; int ret = 0; - lbs_deb_enter_args(LBS_DEB_SCAN, "SSID '%s', clear %d", - escape_essid(ssid, ssid_len), clear_ssid); + lbs_deb_enter_args(LBS_DEB_SCAN, "SSID '%s'\n", + escape_essid(ssid, ssid_len)); if (!ssid_len) goto out; - memset(&scancfg, 0x00, sizeof(scancfg)); - memcpy(scancfg.ssid, ssid, ssid_len); - scancfg.ssid_len = ssid_len; - scancfg.clear_ssid = clear_ssid; + memcpy(priv->scan_ssid, ssid, ssid_len); + priv->scan_ssid_len = ssid_len; - lbs_scan_networks(priv, &scancfg, 1); + lbs_scan_networks(priv, 1); if (priv->surpriseremoved) { ret = -1; goto out; @@ -1317,27 +1296,36 @@ out: * @return 0 --success, otherwise fail */ int lbs_set_scan(struct net_device *dev, struct iw_request_info *info, - struct iw_param *wrqu, char *extra) + union iwreq_data *wrqu, char *extra) { struct lbs_private *priv = dev->priv; + int ret = 0; - lbs_deb_enter(LBS_DEB_SCAN); + lbs_deb_enter(LBS_DEB_WEXT); - if (!netif_running(dev)) - return -ENETDOWN; + if (!netif_running(dev)) { + ret = -ENETDOWN; + goto out; + } /* mac80211 does this: struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (sdata->type != IEEE80211_IF_TYPE_xxx) - return -EOPNOTSUPP; + if (sdata->type != IEEE80211_IF_TYPE_xxx) { + ret = -EOPNOTSUPP; + goto out; + } + */ if (wrqu->data.length == sizeof(struct iw_scan_req) && wrqu->data.flags & IW_SCAN_THIS_ESSID) { - req = (struct iw_scan_req *)extra; - ssid = req->essid; - ssid_len = req->essid_len; + struct iw_scan_req *req = (struct iw_scan_req *)extra; + priv->scan_ssid_len = req->essid_len; + memcpy(priv->scan_ssid, req->essid, priv->scan_ssid_len); + lbs_deb_wext("set_scan, essid '%s'\n", + escape_essid(priv->scan_ssid, priv->scan_ssid_len)); + } else { + priv->scan_ssid_len = 0; } - */ if (!delayed_work_pending(&priv->scan_work)) queue_delayed_work(priv->work_thread, &priv->scan_work, @@ -1346,10 +1334,11 @@ int lbs_set_scan(struct net_device *dev, struct iw_request_info *info, priv->scan_channel = -1; if (priv->surpriseremoved) - return -EIO; + ret = -EIO; - lbs_deb_leave(LBS_DEB_SCAN); - return 0; +out: + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); + return ret; } @@ -1374,7 +1363,7 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info, struct bss_descriptor *iter_bss; struct bss_descriptor *safe; - lbs_deb_enter(LBS_DEB_SCAN); + lbs_deb_enter(LBS_DEB_WEXT); /* iwlist should wait until the current scan is finished */ if (priv->scan_channel) @@ -1418,7 +1407,7 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info, dwrq->length = (ev - extra); dwrq->flags = 0; - lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", err); + lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", err); return err; } diff --git a/drivers/net/wireless/libertas/scan.h b/drivers/net/wireless/libertas/scan.h index 10d1196acf78..c50c8b74714b 100644 --- a/drivers/net/wireless/libertas/scan.h +++ b/drivers/net/wireless/libertas/scan.h @@ -12,8 +12,6 @@ /** * @brief Maximum number of channels that can be sent in a setuserscan ioctl - * - * @sa lbs_ioctl_user_scan_cfg */ #define LBS_IOCTL_USER_SCAN_CHAN_MAX 50 @@ -26,60 +24,6 @@ //! Adhoc or Infrastructure BSS scan type in cmd_ds_802_11_scan, no filter #define LBS_SCAN_BSS_TYPE_ANY 3 -/** - * @brief IOCTL channel sub-structure sent in lbs_ioctl_user_scan_cfg - * - * Multiple instances of this structure are included in the IOCTL command - * to configure a instance of a scan on the specific channel. - */ -struct lbs_ioctl_user_scan_chan { - u8 channumber; //!< channel Number to scan - u8 radiotype; //!< Radio type: 'B/G' band = 0, 'A' band = 1 - u8 scantype; //!< Scan type: Active = 0, Passive = 1 - u16 scantime; //!< Scan duration in milliseconds; if 0 default used -}; - -/** - * @brief IOCTL input structure to configure an immediate scan cmd to firmware - * - * Used in the setuserscan (LBS_SET_USER_SCAN) private ioctl. Specifies - * a number of parameters to be used in general for the scan as well - * as a channel list (lbs_ioctl_user_scan_chan) for each scan period - * desired. - * - * @sa lbs_set_user_scan_ioctl - */ -struct lbs_ioctl_user_scan_cfg { - /** - * @brief BSS type to be sent in the firmware command - * - * Field can be used to restrict the types of networks returned in the - * scan. valid settings are: - * - * - LBS_SCAN_BSS_TYPE_BSS (infrastructure) - * - LBS_SCAN_BSS_TYPE_IBSS (adhoc) - * - LBS_SCAN_BSS_TYPE_ANY (unrestricted, adhoc and infrastructure) - */ - u8 bsstype; - - /** - * @brief BSSID filter sent in the firmware command to limit the results - */ - u8 bssid[ETH_ALEN]; - - /* Clear existing scan results matching this BSSID */ - u8 clear_bssid; - - /** - * @brief SSID filter sent in the firmware command to limit the results - */ - char ssid[IW_ESSID_MAX_SIZE]; - u8 ssid_len; - - /* Clear existing scan results matching this SSID */ - u8 clear_ssid; -}; - /** * @brief Structure used to store information for each beacon/probe response */ @@ -136,21 +80,12 @@ int lbs_find_best_network_ssid(struct lbs_private *priv, u8 *out_ssid, u8 *out_ssid_len, u8 preferred_mode, u8 *out_mode); int lbs_send_specific_ssid_scan(struct lbs_private *priv, u8 *ssid, - u8 ssid_len, u8 clear_ssid); - -int lbs_scan_networks(struct lbs_private *priv, - const struct lbs_ioctl_user_scan_cfg *puserscanin, - int full_scan); - -struct ifreq; + u8 ssid_len); -struct iw_point; -struct iw_param; -struct iw_request_info; int lbs_get_scan(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra); int lbs_set_scan(struct net_device *dev, struct iw_request_info *info, - struct iw_param *vwrq, char *extra); + union iwreq_data *wrqu, char *extra); void lbs_scan_worker(struct work_struct *work); diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c index e8bfc26b10a4..cded4bb69164 100644 --- a/drivers/net/wireless/libertas/wext.c +++ b/drivers/net/wireless/libertas/wext.c @@ -579,6 +579,9 @@ static int lbs_get_range(struct net_device *dev, struct iw_request_info *info, range->num_bitrates); range->num_frequency = 0; + + range->scan_capa = IW_SCAN_CAPA_ESSID; + if (priv->enable11d && (priv->connect_status == LBS_CONNECTED || priv->mesh_connect_status == LBS_CONNECTED)) { -- cgit v1.2.1 From e9010e2fdfe68360da374e31f7008a6d9935c783 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Fri, 7 Mar 2008 14:21:16 -0800 Subject: drivers/net/wireless/ath5k - convert == (true|false) to simple logical tests (test == true) is not nice. Signed-off-by: Joe Perches Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/hw.c | 36 ++++++++++++++++++------------------ drivers/net/wireless/ath5k/phy.c | 10 +++++----- 2 files changed, 23 insertions(+), 23 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath5k/hw.c b/drivers/net/wireless/ath5k/hw.c index a4e312d4226e..677600b302d9 100644 --- a/drivers/net/wireless/ath5k/hw.c +++ b/drivers/net/wireless/ath5k/hw.c @@ -1,4 +1,4 @@ - /* +/* * Copyright (c) 2004-2007 Reyk Floeter * Copyright (c) 2006-2007 Nick Kossifidis * Copyright (c) 2007 Matthew W. S. Bell @@ -85,12 +85,12 @@ static int ath5k_hw_disable_pspoll(struct ath5k_hw *); static inline unsigned int ath5k_hw_htoclock(unsigned int usec, bool turbo) { - return turbo == true ? (usec * 80) : (usec * 40); + return turbo ? (usec * 80) : (usec * 40); } static inline unsigned int ath5k_hw_clocktoh(unsigned int clock, bool turbo) { - return turbo == true ? (clock / 80) : (clock / 40); + return turbo ? (clock / 80) : (clock / 40); } /* @@ -104,7 +104,7 @@ int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val, for (i = AR5K_TUNE_REGISTER_TIMEOUT; i > 0; i--) { data = ath5k_hw_reg_read(ah, reg); - if ((is_set == true) && (data & flag)) + if (is_set && (data & flag)) break; else if ((data & flag) == val) break; @@ -617,7 +617,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, */ /*DCU/Antenna selection not available on 5210*/ if (ah->ah_version != AR5K_AR5210) { - if (change_channel == true) { + if (change_channel) { /* Seq number for queue 0 -do this for all queues ? */ s_seq = ath5k_hw_reg_read(ah, AR5K_QUEUE_DFS_SEQNUM(0)); @@ -631,7 +631,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, s_led[1] = ath5k_hw_reg_read(ah, AR5K_GPIOCR); s_led[2] = ath5k_hw_reg_read(ah, AR5K_GPIODO); - if (change_channel == true && ah->ah_rf_banks != NULL) + if (change_channel && ah->ah_rf_banks != NULL) ath5k_hw_get_rf_gain(ah); @@ -1122,7 +1122,7 @@ int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, staid &= ~AR5K_STA_ID1_DEFAULT_ANTENNA; /* fallthrough */ case AR5K_PM_NETWORK_SLEEP: - if (set_chip == true) + if (set_chip) ath5k_hw_reg_write(ah, AR5K_SLEEP_CTL_SLE | sleep_duration, AR5K_SLEEP_CTL); @@ -1131,7 +1131,7 @@ int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, break; case AR5K_PM_FULL_SLEEP: - if (set_chip == true) + if (set_chip) ath5k_hw_reg_write(ah, AR5K_SLEEP_CTL_SLE_SLP, AR5K_SLEEP_CTL); @@ -1139,7 +1139,7 @@ int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, break; case AR5K_PM_AWAKE: - if (set_chip == false) + if (!set_chip) goto commit; ath5k_hw_reg_write(ah, AR5K_SLEEP_CTL_SLE_WAKE, @@ -1446,7 +1446,7 @@ int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase) trigger_level = AR5K_REG_MS(ath5k_hw_reg_read(ah, AR5K_TXCFG), AR5K_TXCFG_TXFULL); - if (increase == false) { + if (!increase) { if (--trigger_level < AR5K_TUNE_MIN_TX_FIFO_THRES) goto done; } else @@ -3205,19 +3205,19 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) return 0; /* Set Slot time */ - ath5k_hw_reg_write(ah, ah->ah_turbo == true ? + ath5k_hw_reg_write(ah, ah->ah_turbo ? AR5K_INIT_SLOT_TIME_TURBO : AR5K_INIT_SLOT_TIME, AR5K_SLOT_TIME); /* Set ACK_CTS timeout */ - ath5k_hw_reg_write(ah, ah->ah_turbo == true ? + ath5k_hw_reg_write(ah, ah->ah_turbo ? AR5K_INIT_ACK_CTS_TIMEOUT_TURBO : AR5K_INIT_ACK_CTS_TIMEOUT, AR5K_SLOT_TIME); /* Set Transmit Latency */ - ath5k_hw_reg_write(ah, ah->ah_turbo == true ? + ath5k_hw_reg_write(ah, ah->ah_turbo ? AR5K_INIT_TRANSMIT_LATENCY_TURBO : AR5K_INIT_TRANSMIT_LATENCY, AR5K_USEC_5210); /* Set IFS0 */ - if (ah->ah_turbo == true) + if (ah->ah_turbo) ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS_TURBO + (ah->ah_aifs + tq->tqi_aifs) * AR5K_INIT_SLOT_TIME_TURBO) << @@ -3230,16 +3230,16 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) AR5K_INIT_SIFS, AR5K_IFS0); /* Set IFS1 */ - ath5k_hw_reg_write(ah, ah->ah_turbo == true ? + ath5k_hw_reg_write(ah, ah->ah_turbo ? AR5K_INIT_PROTO_TIME_CNTRL_TURBO : AR5K_INIT_PROTO_TIME_CNTRL, AR5K_IFS1); /* Set PHY register 0x9844 (??) */ - ath5k_hw_reg_write(ah, ah->ah_turbo == true ? + ath5k_hw_reg_write(ah, ah->ah_turbo ? (ath5k_hw_reg_read(ah, AR5K_PHY(17)) & ~0x7F) | 0x38 : (ath5k_hw_reg_read(ah, AR5K_PHY(17)) & ~0x7F) | 0x1C, AR5K_PHY(17)); /* Set Frame Control Register */ - ath5k_hw_reg_write(ah, ah->ah_turbo == true ? + ath5k_hw_reg_write(ah, ah->ah_turbo ? (AR5K_PHY_FRAME_CTL_INI | AR5K_PHY_TURBO_MODE | AR5K_PHY_TURBO_SHORT | 0x2020) : (AR5K_PHY_FRAME_CTL_INI | 0x1020), @@ -3278,7 +3278,7 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) /* * Calculate and set retry limits */ - if (ah->ah_software_retry == true) { + if (ah->ah_software_retry) { /* XXX Need to test this */ retry_lg = ah->ah_limit_tx_retries; retry_sh = retry_lg = retry_lg > AR5K_DCU_RETRY_LMT_SH_RETRY ? diff --git a/drivers/net/wireless/ath5k/phy.c b/drivers/net/wireless/ath5k/phy.c index ee1dc0fc6ea2..890ecce8bedc 100644 --- a/drivers/net/wireless/ath5k/phy.c +++ b/drivers/net/wireless/ath5k/phy.c @@ -981,14 +981,14 @@ static unsigned int ath5k_hw_rfregs_op(u32 *rf, u32 offset, u32 reg, u32 bits, entry = ((first - 1) / 8) + offset; position = (first - 1) % 8; - if (set == true) + if (set) data = ath5k_hw_bitswap(reg, bits); for (i = shift = 0, left = bits; left > 0; position = 0, entry++, i++) { last = (position + left > 8) ? 8 : position + left; mask = (((1 << last) - 1) ^ ((1 << position) - 1)) << (col * 8); - if (set == true) { + if (set) { rf[entry] &= ~mask; rf[entry] |= ((data << position) << (col * 8)) & mask; data >>= (8 - position); @@ -1001,7 +1001,7 @@ static unsigned int ath5k_hw_rfregs_op(u32 *rf, u32 offset, u32 reg, u32 bits, left -= 8 - position; } - data = set == true ? 1 : ath5k_hw_bitswap(data, bits); + data = set ? 1 : ath5k_hw_bitswap(data, bits); return data; } @@ -1986,7 +1986,7 @@ static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah, s32 iq_corr, i_coff, i_coffd, q_coff, q_coffd; ATH5K_TRACE(ah->ah_sc); - if (ah->ah_calibration == false || + if (!ah->ah_calibration || ath5k_hw_reg_read(ah, AR5K_PHY_IQ) & AR5K_PHY_IQ_RUN) goto done; @@ -2218,7 +2218,7 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, AR5K_TXPOWER_CCK(13, 16) | AR5K_TXPOWER_CCK(12, 8) | AR5K_TXPOWER_CCK(11, 0), AR5K_PHY_TXPOWER_RATE4); - if (ah->ah_txpower.txp_tpc == true) + if (ah->ah_txpower.txp_tpc) ath5k_hw_reg_write(ah, AR5K_PHY_TXPOWER_RATE_MAX_TPC_ENABLE | AR5K_TUNE_MAX_TXPOWER, AR5K_PHY_TXPOWER_RATE_MAX); else -- cgit v1.2.1 From 1e41e1d2771456274ae2c748ed2cc74524a5863f Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Sat, 8 Mar 2008 01:23:17 +0200 Subject: rndis_wlan: cleanup, rename and reorder enums and structures Rename enums and structures to ndis_80211_* for greater readability. Also change order so that enumerations are presented first. Signed-off-by: Jussi Kivilinna Signed-off-by: John W. Linville --- drivers/net/wireless/rndis_wlan.c | 213 ++++++++++++++++++-------------------- 1 file changed, 103 insertions(+), 110 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 10b776c1adc5..157c46463429 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -154,107 +154,100 @@ MODULE_PARM_DESC(workaround_interval, #define NDIS_802_11_LENGTH_RATES 8 #define NDIS_802_11_LENGTH_RATES_EX 16 -struct NDIS_802_11_SSID { +enum ndis_80211_net_type { + ndis_80211_type_freq_hop, + ndis_80211_type_direct_seq, + ndis_80211_type_ofdm_a, + ndis_80211_type_ofdm_g +}; + +enum ndis_80211_net_infra { + ndis_80211_infra_adhoc, + ndis_80211_infra_infra, + ndis_80211_infra_auto_unknown +}; + +enum ndis_80211_auth_mode { + ndis_80211_auth_open, + ndis_80211_auth_shared, + ndis_80211_auth_auto_switch, + ndis_80211_auth_wpa, + ndis_80211_auth_wpa_psk, + ndis_80211_auth_wpa_none, + ndis_80211_auth_wpa2, + ndis_80211_auth_wpa2_psk +}; + +enum ndis_80211_encr_status { + ndis_80211_encr_wep_enabled, + ndis_80211_encr_disabled, + ndis_80211_encr_wep_key_absent, + ndis_80211_encr_not_supported, + ndis_80211_encr_tkip_enabled, + ndis_80211_encr_tkip_key_absent, + ndis_80211_encr_ccmp_enabled, + ndis_80211_encr_ccmp_key_absent +}; + +enum ndis_80211_priv_filter { + ndis_80211_priv_accept_all, + ndis_80211_priv_8021x_wep +}; + +struct ndis_80211_ssid { __le32 SsidLength; u8 Ssid[NDIS_802_11_LENGTH_SSID]; } __attribute__((packed)); -enum NDIS_802_11_NETWORK_TYPE { - Ndis802_11FH, - Ndis802_11DS, - Ndis802_11OFDM5, - Ndis802_11OFDM24, - Ndis802_11NetworkTypeMax -}; - -struct NDIS_802_11_CONFIGURATION_FH { +struct ndis_80211_conf_freq_hop { __le32 Length; __le32 HopPattern; __le32 HopSet; __le32 DwellTime; } __attribute__((packed)); -struct NDIS_802_11_CONFIGURATION { +struct ndis_80211_conf { __le32 Length; __le32 BeaconPeriod; __le32 ATIMWindow; __le32 DSConfig; - struct NDIS_802_11_CONFIGURATION_FH FHConfig; + struct ndis_80211_conf_freq_hop FHConfig; } __attribute__((packed)); -enum NDIS_802_11_NETWORK_INFRASTRUCTURE { - Ndis802_11IBSS, - Ndis802_11Infrastructure, - Ndis802_11AutoUnknown, - Ndis802_11InfrastructureMax -}; - -enum NDIS_802_11_AUTHENTICATION_MODE { - Ndis802_11AuthModeOpen, - Ndis802_11AuthModeShared, - Ndis802_11AuthModeAutoSwitch, - Ndis802_11AuthModeWPA, - Ndis802_11AuthModeWPAPSK, - Ndis802_11AuthModeWPANone, - Ndis802_11AuthModeWPA2, - Ndis802_11AuthModeWPA2PSK, - Ndis802_11AuthModeMax -}; - -enum NDIS_802_11_ENCRYPTION_STATUS { - Ndis802_11WEPEnabled, - Ndis802_11Encryption1Enabled = Ndis802_11WEPEnabled, - Ndis802_11WEPDisabled, - Ndis802_11EncryptionDisabled = Ndis802_11WEPDisabled, - Ndis802_11WEPKeyAbsent, - Ndis802_11Encryption1KeyAbsent = Ndis802_11WEPKeyAbsent, - Ndis802_11WEPNotSupported, - Ndis802_11EncryptionNotSupported = Ndis802_11WEPNotSupported, - Ndis802_11Encryption2Enabled, - Ndis802_11Encryption2KeyAbsent, - Ndis802_11Encryption3Enabled, - Ndis802_11Encryption3KeyAbsent -}; - -enum NDIS_802_11_PRIVACY_FILTER { - Ndis802_11PrivFilterAcceptAll, - Ndis802_11PrivFilter8021xWEP -}; - -struct NDIS_WLAN_BSSID_EX { +struct ndis_80211_bssid_ex { __le32 Length; u8 MacAddress[6]; u8 Padding[2]; - struct NDIS_802_11_SSID Ssid; + struct ndis_80211_ssid Ssid; __le32 Privacy; __le32 Rssi; __le32 NetworkTypeInUse; - struct NDIS_802_11_CONFIGURATION Configuration; + struct ndis_80211_conf Configuration; __le32 InfrastructureMode; u8 SupportedRates[NDIS_802_11_LENGTH_RATES_EX]; __le32 IELength; u8 IEs[0]; } __attribute__((packed)); -struct NDIS_802_11_BSSID_LIST_EX { +struct ndis_80211_bssid_list_ex { __le32 NumberOfItems; - struct NDIS_WLAN_BSSID_EX Bssid[0]; + struct ndis_80211_bssid_ex Bssid[0]; } __attribute__((packed)); -struct NDIS_802_11_FIXED_IEs { +struct ndis_80211_fixed_ies { u8 Timestamp[8]; __le16 BeaconInterval; __le16 Capabilities; } __attribute__((packed)); -struct NDIS_802_11_WEP { +struct ndis_80211_wep_key { __le32 Length; __le32 KeyIndex; __le32 KeyLength; u8 KeyMaterial[32]; } __attribute__((packed)); -struct NDIS_802_11_KEY { +struct ndis_80211_key { __le32 Length; __le32 KeyIndex; __le32 KeyLength; @@ -264,13 +257,13 @@ struct NDIS_802_11_KEY { u8 KeyMaterial[32]; } __attribute__((packed)); -struct NDIS_802_11_REMOVE_KEY { +struct ndis_80211_remove_key { __le32 Length; __le32 KeyIndex; u8 Bssid[6]; } __attribute__((packed)); -struct RNDIS_CONFIG_PARAMETER_INFOBUFFER { +struct ndis_config_param { __le32 ParameterNameOffset; __le32 ParameterNameLength; __le32 ParameterType; @@ -334,7 +327,7 @@ struct rndis_wext_private { /* hardware state */ int radio_on; int infra_mode; - struct NDIS_802_11_SSID essid; + struct ndis_80211_ssid essid; /* encryption stuff */ int encr_tx_key_index; @@ -484,7 +477,7 @@ static int rndis_set_oid(struct usbnet *dev, __le32 oid, void *data, int len) static int rndis_set_config_parameter(struct usbnet *dev, char *param, int value_type, void *value) { - struct RNDIS_CONFIG_PARAMETER_INFOBUFFER *infobuf; + struct ndis_config_param *infobuf; int value_len, info_len, param_len, ret, i; __le16 *unibuf; __le32 *dst_value; @@ -630,7 +623,7 @@ static int freq_to_dsconfig(struct iw_freq *freq, unsigned int *dsconfig) static int add_wep_key(struct usbnet *usbdev, char *key, int key_len, int index); -static int get_essid(struct usbnet *usbdev, struct NDIS_802_11_SSID *ssid) +static int get_essid(struct usbnet *usbdev, struct ndis_80211_ssid *ssid) { int ret, len; @@ -653,7 +646,7 @@ static int get_essid(struct usbnet *usbdev, struct NDIS_802_11_SSID *ssid) } -static int set_essid(struct usbnet *usbdev, struct NDIS_802_11_SSID *ssid) +static int set_essid(struct usbnet *usbdev, struct ndis_80211_ssid *ssid) { struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); int ret; @@ -697,7 +690,7 @@ static int is_associated(struct usbnet *usbdev) static int disassociate(struct usbnet *usbdev, int reset_ssid) { struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); - struct NDIS_802_11_SSID ssid; + struct ndis_80211_ssid ssid; int i, ret = 0; if (priv->radio_on) { @@ -737,23 +730,23 @@ static int set_auth_mode(struct usbnet *usbdev, int wpa_version, int authalg) if (wpa_version & IW_AUTH_WPA_VERSION_WPA2) { if (priv->wpa_keymgmt & IW_AUTH_KEY_MGMT_802_1X) - auth_mode = Ndis802_11AuthModeWPA2; + auth_mode = ndis_80211_auth_wpa2; else - auth_mode = Ndis802_11AuthModeWPA2PSK; + auth_mode = ndis_80211_auth_wpa2_psk; } else if (wpa_version & IW_AUTH_WPA_VERSION_WPA) { if (priv->wpa_keymgmt & IW_AUTH_KEY_MGMT_802_1X) - auth_mode = Ndis802_11AuthModeWPA; + auth_mode = ndis_80211_auth_wpa; else if (priv->wpa_keymgmt & IW_AUTH_KEY_MGMT_PSK) - auth_mode = Ndis802_11AuthModeWPAPSK; + auth_mode = ndis_80211_auth_wpa_psk; else - auth_mode = Ndis802_11AuthModeWPANone; + auth_mode = ndis_80211_auth_wpa_none; } else if (authalg & IW_AUTH_ALG_SHARED_KEY) { if (authalg & IW_AUTH_ALG_OPEN_SYSTEM) - auth_mode = Ndis802_11AuthModeAutoSwitch; + auth_mode = ndis_80211_auth_auto_switch; else - auth_mode = Ndis802_11AuthModeShared; + auth_mode = ndis_80211_auth_shared; } else - auth_mode = Ndis802_11AuthModeOpen; + auth_mode = ndis_80211_auth_open; tmp = cpu_to_le32(auth_mode); ret = rndis_set_oid(usbdev, OID_802_11_AUTHENTICATION_MODE, &tmp, @@ -778,9 +771,9 @@ static int set_priv_filter(struct usbnet *usbdev) if (priv->wpa_version & IW_AUTH_WPA_VERSION_WPA2 || priv->wpa_version & IW_AUTH_WPA_VERSION_WPA) - tmp = cpu_to_le32(Ndis802_11PrivFilter8021xWEP); + tmp = cpu_to_le32(ndis_80211_priv_8021x_wep); else - tmp = cpu_to_le32(Ndis802_11PrivFilterAcceptAll); + tmp = cpu_to_le32(ndis_80211_priv_accept_all); return rndis_set_oid(usbdev, OID_802_11_PRIVACY_FILTER, &tmp, sizeof(tmp)); @@ -798,18 +791,18 @@ static int set_encr_mode(struct usbnet *usbdev, int pairwise, int groupwise) groupwise); if (pairwise & IW_AUTH_CIPHER_CCMP) - encr_mode = Ndis802_11Encryption3Enabled; + encr_mode = ndis_80211_encr_ccmp_enabled; else if (pairwise & IW_AUTH_CIPHER_TKIP) - encr_mode = Ndis802_11Encryption2Enabled; + encr_mode = ndis_80211_encr_tkip_enabled; else if (pairwise & (IW_AUTH_CIPHER_WEP40 | IW_AUTH_CIPHER_WEP104)) - encr_mode = Ndis802_11Encryption1Enabled; + encr_mode = ndis_80211_encr_wep_enabled; else if (groupwise & IW_AUTH_CIPHER_CCMP) - encr_mode = Ndis802_11Encryption3Enabled; + encr_mode = ndis_80211_encr_ccmp_enabled; else if (groupwise & IW_AUTH_CIPHER_TKIP) - encr_mode = Ndis802_11Encryption2Enabled; + encr_mode = ndis_80211_encr_tkip_enabled; else - encr_mode = Ndis802_11EncryptionDisabled; + encr_mode = ndis_80211_encr_disabled; tmp = cpu_to_le32(encr_mode); ret = rndis_set_oid(usbdev, OID_802_11_ENCRYPTION_STATUS, &tmp, @@ -877,7 +870,7 @@ static void set_default_iw_params(struct usbnet *usbdev) priv->wpa_keymgmt = 0; priv->wpa_version = 0; - set_infra_mode(usbdev, Ndis802_11Infrastructure); + set_infra_mode(usbdev, ndis_80211_infra_infra); set_auth_mode(usbdev, IW_AUTH_WPA_VERSION_DISABLED, IW_AUTH_ALG_OPEN_SYSTEM); set_priv_filter(usbdev); @@ -899,7 +892,7 @@ static int deauthenticate(struct usbnet *usbdev) static int add_wep_key(struct usbnet *usbdev, char *key, int key_len, int index) { struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); - struct NDIS_802_11_WEP ndis_key; + struct ndis_80211_wep_key ndis_key; int ret; if (key_len <= 0 || key_len > 32 || index < 0 || index >= 4) @@ -940,7 +933,7 @@ static int add_wep_key(struct usbnet *usbdev, char *key, int key_len, int index) static int remove_key(struct usbnet *usbdev, int index, u8 bssid[ETH_ALEN]) { struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); - struct NDIS_802_11_REMOVE_KEY remove_key; + struct ndis_80211_remove_key remove_key; __le32 keyindex; int ret; @@ -1184,7 +1177,7 @@ static int rndis_iw_get_name(struct net_device *dev, static int rndis_iw_set_essid(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *essid) { - struct NDIS_802_11_SSID ssid; + struct ndis_80211_ssid ssid; int length = wrqu->essid.length; struct usbnet *usbdev = dev->priv; @@ -1212,7 +1205,7 @@ static int rndis_iw_set_essid(struct net_device *dev, static int rndis_iw_get_essid(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *essid) { - struct NDIS_802_11_SSID ssid; + struct ndis_80211_ssid ssid; struct usbnet *usbdev = dev->priv; int ret; @@ -1398,13 +1391,13 @@ static int rndis_iw_get_mode(struct net_device *dev, struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); switch (priv->infra_mode) { - case Ndis802_11IBSS: + case ndis_80211_infra_adhoc: wrqu->mode = IW_MODE_ADHOC; break; - case Ndis802_11Infrastructure: + case ndis_80211_infra_infra: wrqu->mode = IW_MODE_INFRA; break; - /*case Ndis802_11AutoUnknown:*/ + /*case ndis_80211_infra_auto_unknown:*/ default: wrqu->mode = IW_MODE_AUTO; break; @@ -1424,14 +1417,14 @@ static int rndis_iw_set_mode(struct net_device *dev, switch (wrqu->mode) { case IW_MODE_ADHOC: - mode = Ndis802_11IBSS; + mode = ndis_80211_infra_adhoc; break; case IW_MODE_INFRA: - mode = Ndis802_11Infrastructure; + mode = ndis_80211_infra_infra; break; /*case IW_MODE_AUTO:*/ default: - mode = Ndis802_11AutoUnknown; + mode = ndis_80211_infra_auto_unknown; break; } @@ -1507,7 +1500,7 @@ static int rndis_iw_set_encode_ext(struct net_device *dev, struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; struct usbnet *usbdev = dev->priv; struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); - struct NDIS_802_11_KEY ndis_key; + struct ndis_80211_key ndis_key; int keyidx, ret; u8 *addr; @@ -1550,7 +1543,7 @@ static int rndis_iw_set_encode_ext(struct net_device *dev, addr = ext->addr.sa_data; if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { /* group key */ - if (priv->infra_mode == Ndis802_11IBSS) + if (priv->infra_mode == ndis_80211_infra_adhoc) memset(ndis_key.Bssid, 0xff, ETH_ALEN); else get_bssid(usbdev, ndis_key.Bssid); @@ -1611,7 +1604,7 @@ static int rndis_iw_set_scan(struct net_device *dev, static char *rndis_translate_scan(struct net_device *dev, - char *cev, char *end_buf, struct NDIS_WLAN_BSSID_EX *bssid) + char *cev, char *end_buf, struct ndis_80211_bssid_ex *bssid) { #ifdef DEBUG struct usbnet *usbdev = dev->priv; @@ -1645,13 +1638,13 @@ static char *rndis_translate_scan(struct net_device *dev, le32_to_cpu(bssid->InfrastructureMode)); iwe.cmd = SIOCGIWMODE; switch (le32_to_cpu(bssid->InfrastructureMode)) { - case Ndis802_11IBSS: + case ndis_80211_infra_adhoc: iwe.u.mode = IW_MODE_ADHOC; break; - case Ndis802_11Infrastructure: + case ndis_80211_infra_infra: iwe.u.mode = IW_MODE_INFRA; break; - /*case Ndis802_11AutoUnknown:*/ + /*case ndis_80211_infra_auto_unknown:*/ default: iwe.u.mode = IW_MODE_AUTO; break; @@ -1677,7 +1670,7 @@ static char *rndis_translate_scan(struct net_device *dev, devdbg(usbdev, "ENCODE %d", le32_to_cpu(bssid->Privacy)); iwe.cmd = SIOCGIWENCODE; iwe.u.data.length = 0; - if (le32_to_cpu(bssid->Privacy) == Ndis802_11PrivFilterAcceptAll) + if (le32_to_cpu(bssid->Privacy) == ndis_80211_priv_accept_all) iwe.u.data.flags = IW_ENCODE_DISABLED; else iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; @@ -1716,10 +1709,10 @@ static char *rndis_translate_scan(struct net_device *dev, iwe.u.data.length = strlen(sbuf); cev = iwe_stream_add_point(cev, end_buf, &iwe, sbuf); - ie = (void *)(bssid->IEs + sizeof(struct NDIS_802_11_FIXED_IEs)); + ie = (void *)(bssid->IEs + sizeof(struct ndis_80211_fixed_ies)); ie_len = min(bssid_len - (int)sizeof(*bssid), (int)le32_to_cpu(bssid->IELength)); - ie_len -= sizeof(struct NDIS_802_11_FIXED_IEs); + ie_len -= sizeof(struct ndis_80211_fixed_ies); while (ie_len >= sizeof(*ie) && sizeof(*ie) + ie->len <= ie_len) { if ((ie->id == MFIE_TYPE_GENERIC && ie->len >= 4 && memcmp(ie->data, "\x00\x50\xf2\x01", 4) == 0) || @@ -1746,8 +1739,8 @@ static int rndis_iw_get_scan(struct net_device *dev, struct usbnet *usbdev = dev->priv; void *buf = NULL; char *cev = extra; - struct NDIS_802_11_BSSID_LIST_EX *bssid_list; - struct NDIS_WLAN_BSSID_EX *bssid; + struct ndis_80211_bssid_list_ex *bssid_list; + struct ndis_80211_bssid_ex *bssid; int ret = -EINVAL, len, count, bssid_len; devdbg(usbdev, "SIOCGIWSCAN"); @@ -1948,7 +1941,7 @@ static int rndis_iw_set_freq(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { struct usbnet *usbdev = dev->priv; - struct NDIS_802_11_CONFIGURATION config; + struct ndis_80211_conf config; unsigned int dsconfig; int len, ret; @@ -1979,7 +1972,7 @@ static int rndis_iw_get_freq(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { struct usbnet *usbdev = dev->priv; - struct NDIS_802_11_CONFIGURATION config; + struct ndis_80211_conf config; int len, ret; len = sizeof(config); @@ -2266,14 +2259,14 @@ static int rndis_wext_get_caps(struct usbnet *dev) n = 8; for (i = 0; i < n; i++) { switch (le32_to_cpu(networks_supported.items[i])) { - case Ndis802_11FH: - case Ndis802_11DS: + case ndis_80211_type_freq_hop: + case ndis_80211_type_direct_seq: priv->caps |= CAP_MODE_80211B; break; - case Ndis802_11OFDM5: + case ndis_80211_type_ofdm_a: priv->caps |= CAP_MODE_80211A; break; - case Ndis802_11OFDM24: + case ndis_80211_type_ofdm_g: priv->caps |= CAP_MODE_80211G; break; } -- cgit v1.2.1 From 461b3f2aa3c45eb2e85751b6a3b75a8dd1abd04a Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Sat, 8 Mar 2008 01:23:25 +0200 Subject: rndis_wlan: cleanup, rename structure members Rename members of ndis_80211_* structures to match the style of the rest of the code. Signed-off-by: Jussi Kivilinna Signed-off-by: John W. Linville --- drivers/net/wireless/rndis_wlan.c | 258 +++++++++++++++++++------------------- 1 file changed, 126 insertions(+), 132 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 157c46463429..977751f372ff 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -195,80 +195,80 @@ enum ndis_80211_priv_filter { }; struct ndis_80211_ssid { - __le32 SsidLength; - u8 Ssid[NDIS_802_11_LENGTH_SSID]; + __le32 length; + u8 essid[NDIS_802_11_LENGTH_SSID]; } __attribute__((packed)); struct ndis_80211_conf_freq_hop { - __le32 Length; - __le32 HopPattern; - __le32 HopSet; - __le32 DwellTime; + __le32 length; + __le32 hop_pattern; + __le32 hop_set; + __le32 dwell_time; } __attribute__((packed)); struct ndis_80211_conf { - __le32 Length; - __le32 BeaconPeriod; - __le32 ATIMWindow; - __le32 DSConfig; - struct ndis_80211_conf_freq_hop FHConfig; + __le32 length; + __le32 beacon_period; + __le32 atim_window; + __le32 ds_config; + struct ndis_80211_conf_freq_hop fh_config; } __attribute__((packed)); struct ndis_80211_bssid_ex { - __le32 Length; - u8 MacAddress[6]; - u8 Padding[2]; - struct ndis_80211_ssid Ssid; - __le32 Privacy; - __le32 Rssi; - __le32 NetworkTypeInUse; - struct ndis_80211_conf Configuration; - __le32 InfrastructureMode; - u8 SupportedRates[NDIS_802_11_LENGTH_RATES_EX]; - __le32 IELength; - u8 IEs[0]; + __le32 length; + u8 mac[6]; + u8 padding[2]; + struct ndis_80211_ssid ssid; + __le32 privacy; + __le32 rssi; + __le32 net_type; + struct ndis_80211_conf config; + __le32 net_infra; + u8 rates[NDIS_802_11_LENGTH_RATES_EX]; + __le32 ie_length; + u8 ies[0]; } __attribute__((packed)); struct ndis_80211_bssid_list_ex { - __le32 NumberOfItems; - struct ndis_80211_bssid_ex Bssid[0]; + __le32 num_items; + struct ndis_80211_bssid_ex bssid[0]; } __attribute__((packed)); struct ndis_80211_fixed_ies { - u8 Timestamp[8]; - __le16 BeaconInterval; - __le16 Capabilities; + u8 timestamp[8]; + __le16 beacon_interval; + __le16 capabilities; } __attribute__((packed)); struct ndis_80211_wep_key { - __le32 Length; - __le32 KeyIndex; - __le32 KeyLength; - u8 KeyMaterial[32]; + __le32 size; + __le32 index; + __le32 length; + u8 material[32]; } __attribute__((packed)); struct ndis_80211_key { - __le32 Length; - __le32 KeyIndex; - __le32 KeyLength; - u8 Bssid[6]; - u8 Padding[6]; - u8 KeyRSC[8]; - u8 KeyMaterial[32]; + __le32 size; + __le32 index; + __le32 length; + u8 bssid[6]; + u8 padding[6]; + u8 rsc[8]; + u8 material[32]; } __attribute__((packed)); struct ndis_80211_remove_key { - __le32 Length; - __le32 KeyIndex; - u8 Bssid[6]; + __le32 size; + __le32 index; + u8 bssid[6]; } __attribute__((packed)); struct ndis_config_param { - __le32 ParameterNameOffset; - __le32 ParameterNameLength; - __le32 ParameterType; - __le32 ParameterValueOffset; - __le32 ParameterValueLength; + __le32 name_offs; + __le32 name_length; + __le32 type; + __le32 value_offs; + __le32 value_length; } __attribute__((packed)); /* these have to match what is in wpa_supplicant */ @@ -512,12 +512,11 @@ static int rndis_set_config_parameter(struct usbnet *dev, char *param, devdbg(dev, "setting config parameter: %s, value: %d", param, *(u32 *)value); - infobuf->ParameterNameOffset = cpu_to_le32(sizeof(*infobuf)); - infobuf->ParameterNameLength = cpu_to_le32(param_len); - infobuf->ParameterType = cpu_to_le32(value_type); - infobuf->ParameterValueOffset = cpu_to_le32(sizeof(*infobuf) + - param_len); - infobuf->ParameterValueLength = cpu_to_le32(value_len); + infobuf->name_offs = cpu_to_le32(sizeof(*infobuf)); + infobuf->name_length = cpu_to_le32(param_len); + infobuf->type = cpu_to_le32(value_type); + infobuf->value_offs = cpu_to_le32(sizeof(*infobuf) + param_len); + infobuf->value_length = cpu_to_le32(value_len); /* simple string to unicode string conversion */ unibuf = (void *)infobuf + sizeof(*infobuf); @@ -631,14 +630,14 @@ static int get_essid(struct usbnet *usbdev, struct ndis_80211_ssid *ssid) ret = rndis_query_oid(usbdev, OID_802_11_SSID, ssid, &len); if (ret != 0) - ssid->SsidLength = 0; + ssid->length = 0; #ifdef DEBUG { unsigned char tmp[NDIS_802_11_LENGTH_SSID + 1]; - memcpy(tmp, ssid->Ssid, le32_to_cpu(ssid->SsidLength)); - tmp[le32_to_cpu(ssid->SsidLength)] = 0; + memcpy(tmp, ssid->essid, le32_to_cpu(ssid->length)); + tmp[le32_to_cpu(ssid->length)] = 0; devdbg(usbdev, "get_essid: '%s', ret: %d", tmp, ret); } #endif @@ -707,12 +706,12 @@ static int disassociate(struct usbnet *usbdev, int reset_ssid) /* disassociate causes radio to be turned off; if reset_ssid * is given, set random ssid to enable radio */ if (reset_ssid) { - ssid.SsidLength = cpu_to_le32(sizeof(ssid.Ssid)); - get_random_bytes(&ssid.Ssid[2], sizeof(ssid.Ssid)-2); - ssid.Ssid[0] = 0x1; - ssid.Ssid[1] = 0xff; - for (i = 2; i < sizeof(ssid.Ssid); i++) - ssid.Ssid[i] = 0x1 + (ssid.Ssid[i] * 0xfe / 0xff); + ssid.length = cpu_to_le32(sizeof(ssid.essid)); + get_random_bytes(&ssid.essid[2], sizeof(ssid.essid)-2); + ssid.essid[0] = 0x1; + ssid.essid[1] = 0xff; + for (i = 2; i < sizeof(ssid.essid); i++) + ssid.essid[i] = 0x1 + (ssid.essid[i] * 0xfe / 0xff); ret = set_essid(usbdev, &ssid); } return ret; @@ -900,13 +899,13 @@ static int add_wep_key(struct usbnet *usbdev, char *key, int key_len, int index) memset(&ndis_key, 0, sizeof(ndis_key)); - ndis_key.Length = cpu_to_le32(sizeof(ndis_key)); - ndis_key.KeyLength = cpu_to_le32(key_len); - ndis_key.KeyIndex = cpu_to_le32(index); - memcpy(&ndis_key.KeyMaterial, key, key_len); + ndis_key.size = cpu_to_le32(sizeof(ndis_key)); + ndis_key.length = cpu_to_le32(key_len); + ndis_key.index = cpu_to_le32(index); + memcpy(&ndis_key.material, key, key_len); if (index == priv->encr_tx_key_index) { - ndis_key.KeyIndex |= cpu_to_le32(1 << 31); + ndis_key.index |= cpu_to_le32(1 << 31); ret = set_encr_mode(usbdev, IW_AUTH_CIPHER_WEP104, IW_AUTH_CIPHER_NONE); if (ret) @@ -947,17 +946,17 @@ static int remove_key(struct usbnet *usbdev, int index, u8 bssid[ETH_ALEN]) priv->wpa_cipher_pair == IW_AUTH_CIPHER_CCMP || priv->wpa_cipher_group == IW_AUTH_CIPHER_TKIP || priv->wpa_cipher_group == IW_AUTH_CIPHER_CCMP) { - remove_key.Length = cpu_to_le32(sizeof(remove_key)); - remove_key.KeyIndex = cpu_to_le32(index); + remove_key.size = cpu_to_le32(sizeof(remove_key)); + remove_key.index = cpu_to_le32(index); if (bssid) { /* pairwise key */ if (memcmp(bssid, ffff_bssid, ETH_ALEN) != 0) - remove_key.KeyIndex |= cpu_to_le32(1 << 30); - memcpy(remove_key.Bssid, bssid, - sizeof(remove_key.Bssid)); + remove_key.index |= cpu_to_le32(1 << 30); + memcpy(remove_key.bssid, bssid, + sizeof(remove_key.bssid)); } else - memset(remove_key.Bssid, 0xff, - sizeof(remove_key.Bssid)); + memset(remove_key.bssid, 0xff, + sizeof(remove_key.bssid)); ret = rndis_set_oid(usbdev, OID_802_11_REMOVE_KEY, &remove_key, sizeof(remove_key)); @@ -1187,11 +1186,11 @@ static int rndis_iw_set_essid(struct net_device *dev, if (length > NDIS_802_11_LENGTH_SSID) length = NDIS_802_11_LENGTH_SSID; - ssid.SsidLength = cpu_to_le32(length); + ssid.length = cpu_to_le32(length); if (length > 0) - memcpy(ssid.Ssid, essid, length); + memcpy(ssid.essid, essid, length); else - memset(ssid.Ssid, 0, NDIS_802_11_LENGTH_SSID); + memset(ssid.essid, 0, NDIS_802_11_LENGTH_SSID); set_assoc_params(usbdev); @@ -1211,10 +1210,10 @@ static int rndis_iw_get_essid(struct net_device *dev, ret = get_essid(usbdev, &ssid); - if (ret == 0 && le32_to_cpu(ssid.SsidLength) > 0) { + if (ret == 0 && le32_to_cpu(ssid.length) > 0) { wrqu->essid.flags = 1; - wrqu->essid.length = le32_to_cpu(ssid.SsidLength); - memcpy(essid, ssid.Ssid, wrqu->essid.length); + wrqu->essid.length = le32_to_cpu(ssid.length); + memcpy(essid, ssid.essid, wrqu->essid.length); essid[wrqu->essid.length] = 0; } else { memset(essid, 0, sizeof(NDIS_802_11_LENGTH_SSID)); @@ -1525,54 +1524,54 @@ static int rndis_iw_set_encode_ext(struct net_device *dev, ext->alg == IW_ENCODE_ALG_NONE || ext->key_len == 0) return remove_key(usbdev, keyidx, NULL); - if (ext->key_len > sizeof(ndis_key.KeyMaterial)) + if (ext->key_len > sizeof(ndis_key.material)) return -1; memset(&ndis_key, 0, sizeof(ndis_key)); - ndis_key.Length = cpu_to_le32(sizeof(ndis_key) - - sizeof(ndis_key.KeyMaterial) + ext->key_len); - ndis_key.KeyLength = cpu_to_le32(ext->key_len); - ndis_key.KeyIndex = cpu_to_le32(keyidx); + ndis_key.size = cpu_to_le32(sizeof(ndis_key) - + sizeof(ndis_key.material) + ext->key_len); + ndis_key.length = cpu_to_le32(ext->key_len); + ndis_key.index = cpu_to_le32(keyidx); if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) { - memcpy(ndis_key.KeyRSC, ext->rx_seq, 6); - ndis_key.KeyIndex |= cpu_to_le32(1 << 29); + memcpy(ndis_key.rsc, ext->rx_seq, 6); + ndis_key.index |= cpu_to_le32(1 << 29); } addr = ext->addr.sa_data; if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { /* group key */ if (priv->infra_mode == ndis_80211_infra_adhoc) - memset(ndis_key.Bssid, 0xff, ETH_ALEN); + memset(ndis_key.bssid, 0xff, ETH_ALEN); else - get_bssid(usbdev, ndis_key.Bssid); + get_bssid(usbdev, ndis_key.bssid); } else { /* pairwise key */ - ndis_key.KeyIndex |= cpu_to_le32(1 << 30); - memcpy(ndis_key.Bssid, addr, ETH_ALEN); + ndis_key.index |= cpu_to_le32(1 << 30); + memcpy(ndis_key.bssid, addr, ETH_ALEN); } if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) - ndis_key.KeyIndex |= cpu_to_le32(1 << 31); + ndis_key.index |= cpu_to_le32(1 << 31); if (ext->alg == IW_ENCODE_ALG_TKIP && ext->key_len == 32) { /* wpa_supplicant gives us the Michael MIC RX/TX keys in * different order than NDIS spec, so swap the order here. */ - memcpy(ndis_key.KeyMaterial, ext->key, 16); - memcpy(ndis_key.KeyMaterial + 16, ext->key + 24, 8); - memcpy(ndis_key.KeyMaterial + 24, ext->key + 16, 8); + memcpy(ndis_key.material, ext->key, 16); + memcpy(ndis_key.material + 16, ext->key + 24, 8); + memcpy(ndis_key.material + 24, ext->key + 16, 8); } else - memcpy(ndis_key.KeyMaterial, ext->key, ext->key_len); + memcpy(ndis_key.material, ext->key, ext->key_len); ret = rndis_set_oid(usbdev, OID_802_11_ADD_KEY, &ndis_key, - le32_to_cpu(ndis_key.Length)); + le32_to_cpu(ndis_key.size)); devdbg(usbdev, "SIOCSIWENCODEEXT: OID_802_11_ADD_KEY -> %08X", ret); if (ret != 0) return ret; priv->encr_key_len[keyidx] = ext->key_len; - memcpy(&priv->encr_keys[keyidx], ndis_key.KeyMaterial, ext->key_len); + memcpy(&priv->encr_keys[keyidx], ndis_key.material, ext->key_len); if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) priv->encr_tx_key_index = keyidx; @@ -1617,27 +1616,24 @@ static char *rndis_translate_scan(struct net_device *dev, unsigned char sbuf[32]; DECLARE_MAC_BUF(mac); - bssid_len = le32_to_cpu(bssid->Length); + bssid_len = le32_to_cpu(bssid->length); - devdbg(usbdev, "BSSID %s", print_mac(mac, bssid->MacAddress)); + devdbg(usbdev, "BSSID %s", print_mac(mac, bssid->mac)); iwe.cmd = SIOCGIWAP; iwe.u.ap_addr.sa_family = ARPHRD_ETHER; - memcpy(iwe.u.ap_addr.sa_data, bssid->MacAddress, ETH_ALEN); + memcpy(iwe.u.ap_addr.sa_data, bssid->mac, ETH_ALEN); cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_ADDR_LEN); - devdbg(usbdev, "SSID(%d) %s", - le32_to_cpu(bssid->Ssid.SsidLength), - bssid->Ssid.Ssid); + devdbg(usbdev, "SSID(%d) %s", le32_to_cpu(bssid->ssid.length), + bssid->ssid.essid); iwe.cmd = SIOCGIWESSID; - iwe.u.essid.length = le32_to_cpu(bssid->Ssid.SsidLength); + iwe.u.essid.length = le32_to_cpu(bssid->ssid.length); iwe.u.essid.flags = 1; - cev = iwe_stream_add_point(cev, end_buf, &iwe, - bssid->Ssid.Ssid); + cev = iwe_stream_add_point(cev, end_buf, &iwe, bssid->ssid.essid); - devdbg(usbdev, "MODE %d", - le32_to_cpu(bssid->InfrastructureMode)); + devdbg(usbdev, "MODE %d", le32_to_cpu(bssid->net_infra)); iwe.cmd = SIOCGIWMODE; - switch (le32_to_cpu(bssid->InfrastructureMode)) { + switch (le32_to_cpu(bssid->net_infra)) { case ndis_80211_infra_adhoc: iwe.u.mode = IW_MODE_ADHOC; break; @@ -1651,26 +1647,24 @@ static char *rndis_translate_scan(struct net_device *dev, } cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_UINT_LEN); - devdbg(usbdev, "FREQ %d kHz", - le32_to_cpu(bssid->Configuration.DSConfig)); + devdbg(usbdev, "FREQ %d kHz", le32_to_cpu(bssid->config.ds_config)); iwe.cmd = SIOCGIWFREQ; - dsconfig_to_freq(le32_to_cpu(bssid->Configuration.DSConfig), - &iwe.u.freq); + dsconfig_to_freq(le32_to_cpu(bssid->config.ds_config), &iwe.u.freq); cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_FREQ_LEN); - devdbg(usbdev, "QUAL %d", le32_to_cpu(bssid->Rssi)); + devdbg(usbdev, "QUAL %d", le32_to_cpu(bssid->rssi)); iwe.cmd = IWEVQUAL; - iwe.u.qual.qual = level_to_qual(le32_to_cpu(bssid->Rssi)); - iwe.u.qual.level = le32_to_cpu(bssid->Rssi); + iwe.u.qual.qual = level_to_qual(le32_to_cpu(bssid->rssi)); + iwe.u.qual.level = le32_to_cpu(bssid->rssi); iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_INVALID; cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_QUAL_LEN); - devdbg(usbdev, "ENCODE %d", le32_to_cpu(bssid->Privacy)); + devdbg(usbdev, "ENCODE %d", le32_to_cpu(bssid->privacy)); iwe.cmd = SIOCGIWENCODE; iwe.u.data.length = 0; - if (le32_to_cpu(bssid->Privacy) == ndis_80211_priv_accept_all) + if (le32_to_cpu(bssid->privacy) == ndis_80211_priv_accept_all) iwe.u.data.flags = IW_ENCODE_DISABLED; else iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; @@ -1680,10 +1674,10 @@ static char *rndis_translate_scan(struct net_device *dev, devdbg(usbdev, "RATES:"); current_val = cev + IW_EV_LCP_LEN; iwe.cmd = SIOCGIWRATE; - for (i = 0; i < sizeof(bssid->SupportedRates); i++) { - if (bssid->SupportedRates[i] & 0x7f) { + for (i = 0; i < sizeof(bssid->rates); i++) { + if (bssid->rates[i] & 0x7f) { iwe.u.bitrate.value = - ((bssid->SupportedRates[i] & 0x7f) * + ((bssid->rates[i] & 0x7f) * 500000); devdbg(usbdev, " %d", iwe.u.bitrate.value); current_val = iwe_stream_add_value(cev, @@ -1695,23 +1689,23 @@ static char *rndis_translate_scan(struct net_device *dev, if ((current_val - cev) > IW_EV_LCP_LEN) cev = current_val; - beacon = le32_to_cpu(bssid->Configuration.BeaconPeriod); + beacon = le32_to_cpu(bssid->config.beacon_period); devdbg(usbdev, "BCN_INT %d", beacon); iwe.cmd = IWEVCUSTOM; snprintf(sbuf, sizeof(sbuf), "bcn_int=%d", beacon); iwe.u.data.length = strlen(sbuf); cev = iwe_stream_add_point(cev, end_buf, &iwe, sbuf); - atim = le32_to_cpu(bssid->Configuration.ATIMWindow); + atim = le32_to_cpu(bssid->config.atim_window); devdbg(usbdev, "ATIM %d", atim); iwe.cmd = IWEVCUSTOM; snprintf(sbuf, sizeof(sbuf), "atim=%u", atim); iwe.u.data.length = strlen(sbuf); cev = iwe_stream_add_point(cev, end_buf, &iwe, sbuf); - ie = (void *)(bssid->IEs + sizeof(struct ndis_80211_fixed_ies)); + ie = (void *)(bssid->ies + sizeof(struct ndis_80211_fixed_ies)); ie_len = min(bssid_len - (int)sizeof(*bssid), - (int)le32_to_cpu(bssid->IELength)); + (int)le32_to_cpu(bssid->ie_length)); ie_len -= sizeof(struct ndis_80211_fixed_ies); while (ie_len >= sizeof(*ie) && sizeof(*ie) + ie->len <= ie_len) { if ((ie->id == MFIE_TYPE_GENERIC && ie->len >= 4 && @@ -1758,16 +1752,16 @@ static int rndis_iw_get_scan(struct net_device *dev, goto out; bssid_list = buf; - bssid = bssid_list->Bssid; - bssid_len = le32_to_cpu(bssid->Length); - count = le32_to_cpu(bssid_list->NumberOfItems); + bssid = bssid_list->bssid; + bssid_len = le32_to_cpu(bssid->length); + count = le32_to_cpu(bssid_list->num_items); devdbg(usbdev, "SIOCGIWSCAN: %d BSSIDs found", count); while (count && ((void *)bssid + bssid_len) <= (buf + len)) { cev = rndis_translate_scan(dev, cev, extra + IW_SCAN_MAX_DATA, bssid); bssid = (void *)bssid + bssid_len; - bssid_len = le32_to_cpu(bssid->Length); + bssid_len = le32_to_cpu(bssid->length); count--; } @@ -1960,7 +1954,7 @@ static int rndis_iw_set_freq(struct net_device *dev, return 0; } - config.DSConfig = cpu_to_le32(dsconfig); + config.ds_config = cpu_to_le32(dsconfig); devdbg(usbdev, "SIOCSIWFREQ: %d * 10^%d", wrqu->freq.m, wrqu->freq.e); return rndis_set_oid(usbdev, OID_802_11_CONFIGURATION, &config, @@ -1978,7 +1972,7 @@ static int rndis_iw_get_freq(struct net_device *dev, len = sizeof(config); ret = rndis_query_oid(usbdev, OID_802_11_CONFIGURATION, &config, &len); if (ret == 0) - dsconfig_to_freq(le32_to_cpu(config.DSConfig), &wrqu->freq); + dsconfig_to_freq(le32_to_cpu(config.ds_config), &wrqu->freq); devdbg(usbdev, "SIOCGIWFREQ: %d", wrqu->freq.m); return ret; -- cgit v1.2.1 From 40e024de932cca8b54fbcd0e5faf8f364cc84ec0 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Sat, 8 Mar 2008 02:40:38 -0800 Subject: b43: pull out helpers for writing noise table Signed-off-by: Harvey Harrison Signed-off-by: John W. Linville --- drivers/net/wireless/b43/wa.c | 45 ++++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 22 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/b43/wa.c b/drivers/net/wireless/b43/wa.c index e632125cb772..daa94211f838 100644 --- a/drivers/net/wireless/b43/wa.c +++ b/drivers/net/wireless/b43/wa.c @@ -204,42 +204,43 @@ static void b43_wa_rt(struct b43_wldev *dev) /* Rotor table */ b43_ofdmtab_write32(dev, B43_OFDMTAB_ROTOR, i, b43_tab_rotor[i]); } +static void b43_write_null_nst(struct b43_wldev *dev) +{ + int i; + + for (i = 0; i < B43_TAB_NOISESCALE_SIZE; i++) + b43_ofdmtab_write16(dev, B43_OFDMTAB_NOISESCALE, i, 0); +} + +static void b43_write_nst(struct b43_wldev *dev, const u16 *nst) +{ + int i; + + for (i = 0; i < B43_TAB_NOISESCALE_SIZE; i++) + b43_ofdmtab_write16(dev, B43_OFDMTAB_NOISESCALE, i, nst[i]); +} + static void b43_wa_nst(struct b43_wldev *dev) /* Noise scale table */ { struct b43_phy *phy = &dev->phy; - int i; if (phy->type == B43_PHYTYPE_A) { if (phy->rev <= 1) - for (i = 0; i < B43_TAB_NOISESCALE_SIZE; i++) - b43_ofdmtab_write16(dev, B43_OFDMTAB_NOISESCALE, - i, 0); + b43_write_null_nst(dev); else if (phy->rev == 2) - for (i = 0; i < B43_TAB_NOISESCALE_SIZE; i++) - b43_ofdmtab_write16(dev, B43_OFDMTAB_NOISESCALE, - i, b43_tab_noisescalea2[i]); + b43_write_nst(dev, b43_tab_noisescalea2); else if (phy->rev == 3) - for (i = 0; i < B43_TAB_NOISESCALE_SIZE; i++) - b43_ofdmtab_write16(dev, B43_OFDMTAB_NOISESCALE, - i, b43_tab_noisescalea3[i]); + b43_write_nst(dev, b43_tab_noisescalea3); else - for (i = 0; i < B43_TAB_NOISESCALE_SIZE; i++) - b43_ofdmtab_write16(dev, B43_OFDMTAB_NOISESCALE, - i, b43_tab_noisescaleg3[i]); + b43_write_nst(dev, b43_tab_noisescaleg3); } else { if (phy->rev >= 6) { if (b43_phy_read(dev, B43_PHY_ENCORE) & B43_PHY_ENCORE_EN) - for (i = 0; i < B43_TAB_NOISESCALE_SIZE; i++) - b43_ofdmtab_write16(dev, B43_OFDMTAB_NOISESCALE, - i, b43_tab_noisescaleg3[i]); + b43_write_nst(dev, b43_tab_noisescaleg3); else - for (i = 0; i < B43_TAB_NOISESCALE_SIZE; i++) - b43_ofdmtab_write16(dev, B43_OFDMTAB_NOISESCALE, - i, b43_tab_noisescaleg2[i]); + b43_write_nst(dev, b43_tab_noisescaleg2); } else { - for (i = 0; i < B43_TAB_NOISESCALE_SIZE; i++) - b43_ofdmtab_write16(dev, B43_OFDMTAB_NOISESCALE, - i, b43_tab_noisescaleg1[i]); + b43_write_nst(dev, b43_tab_noisescaleg1); } } } -- cgit v1.2.1 From f855c10b6e7b0c448c35b88266f788dd3738375e Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 9 Mar 2008 22:38:18 +0100 Subject: rt2x00: Align RX descriptor to 4 bytes Some architectures give problems when reading RX frame descriptor words when the descriptor is not aligned on a 4 byte boundrary. Due to optimalizations for the ieee80211 payload 4 byte alignment, it is no longer guarenteed that the descriptor is placed on the 4 byte boundrary (In fact, for rt73usb it is absolutely never aligned to 4 bytes, for rt2500usb it depends on the length of the payload). This will copy the descriptor to a 4 byte aligned location before it is read for the first time. This will also move the payload data alignment in rt2x00usb (instead of inside the driver) where it has always belonged. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2500usb.c | 37 ++++++++++++++----------------- drivers/net/wireless/rt2x00/rt2x00usb.c | 17 ++++++++++++-- drivers/net/wireless/rt2x00/rt73usb.c | 39 ++++++++++++++------------------- 3 files changed, 49 insertions(+), 44 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 9f59db91cfc2..86cd9a5eee2b 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1117,11 +1117,24 @@ static void rt2500usb_fill_rxdone(struct queue_entry *entry, __le32 *rxd = (__le32 *)(entry->skb->data + (priv_rx->urb->actual_length - entry->queue->desc_size)); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data; - int header_size = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control)); + unsigned int offset = entry->queue->desc_size + 2; u32 word0; u32 word1; + /* + * Copy descriptor to the available headroom inside the skbuffer. + * Remove the original copy by trimming the skbuffer. + */ + skb_push(entry->skb, offset); + memcpy(entry->skb->data, rxd, entry->queue->desc_size); + rxd = (__le32 *)entry->skb->data; + skb_pull(entry->skb, offset); + skb_trim(entry->skb, rxdesc->size); + + /* + * The descriptor is now aligned to 4 bytes and thus it is + * now safe to read it on all architectures. + */ rt2x00_desc_read(rxd, 0, &word0); rt2x00_desc_read(rxd, 1, &word1); @@ -1142,28 +1155,12 @@ static void rt2500usb_fill_rxdone(struct queue_entry *entry, rxdesc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS); /* - * The data behind the ieee80211 header must be - * aligned on a 4 byte boundary. - */ - if (header_size % 4 == 0) { - skb_push(entry->skb, 2); - memmove(entry->skb->data, entry->skb->data + 2, - entry->skb->len - 2); - } - - /* - * Set descriptor pointer. + * Set descriptor and data pointer. */ skbdesc->data = entry->skb->data; skbdesc->data_len = rxdesc->size; - skbdesc->desc = entry->skb->data + rxdesc->size; + skbdesc->desc = entry->skb->data - offset; skbdesc->desc_len = entry->queue->desc_size; - - /* - * Remove descriptor from skb buffer and trim the whole thing - * down to only contain data. - */ - skb_trim(entry->skb, rxdesc->size); } /* diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 063b167da31e..512ff3914813 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -247,11 +247,11 @@ static struct sk_buff* rt2x00usb_alloc_rxskb(struct data_queue *queue) * advance. */ frame_size = queue->data_size + queue->desc_size; - skb = dev_alloc_skb(frame_size + 2); + skb = dev_alloc_skb(queue->desc_size + frame_size + 2); if (!skb) return NULL; - skb_reserve(skb, 2); + skb_reserve(skb, queue->desc_size + 2); skb_put(skb, frame_size); return skb; @@ -264,6 +264,7 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) struct sk_buff *skb; struct skb_frame_desc *skbdesc; struct rxdone_entry_desc rxdesc; + int header_size; if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags) || !test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) @@ -287,6 +288,18 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) memset(&rxdesc, 0, sizeof(rxdesc)); rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc); + /* + * The data behind the ieee80211 header must be + * aligned on a 4 byte boundary. + */ + header_size = ieee80211_get_hdrlen_from_skb(entry->skb); + if (header_size % 4 == 0) { + skb_push(entry->skb, 2); + memmove(entry->skb->data, entry->skb->data + 2, + entry->skb->len - 2); + skbdesc->data = entry->skb->data; + } + /* * Allocate a new sk buffer to replace the current one. * If allocation fails, we should drop the current frame diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 6546b0d607b9..b4b70850edfc 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -1370,12 +1370,24 @@ static void rt73usb_fill_rxdone(struct queue_entry *entry, { struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); __le32 *rxd = (__le32 *)entry->skb->data; - struct ieee80211_hdr *hdr = - (struct ieee80211_hdr *)entry->skb->data + entry->queue->desc_size; - int header_size = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control)); + unsigned int offset = entry->queue->desc_size + 2; u32 word0; u32 word1; + /* + * Copy descriptor to the available headroom inside the skbuffer. + * Remove the original copy by pulling the skbuffer. + */ + skb_push(entry->skb, offset); + memcpy(entry->skb->data, rxd, entry->queue->desc_size); + rxd = (__le32 *)entry->skb->data; + skb_pull(entry->skb, offset + skbdesc->desc_len); + skb_trim(entry->skb, rxdesc->size); + + /* + * The descriptor is now aligned to 4 bytes and thus it is + * now safe to read it on all architectures. + */ rt2x00_desc_read(rxd, 0, &word0); rt2x00_desc_read(rxd, 1, &word1); @@ -1392,30 +1404,13 @@ static void rt73usb_fill_rxdone(struct queue_entry *entry, rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); rxdesc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS); - /* - * The data behind the ieee80211 header must be - * aligned on a 4 byte boundary. - */ - if (header_size % 4 == 0) { - skb_push(entry->skb, 2); - memmove(entry->skb->data, entry->skb->data + 2, - entry->skb->len - 2); - } - /* * Set descriptor and data pointer. */ - skbdesc->data = entry->skb->data + entry->queue->desc_size; + skbdesc->data = entry->skb->data; skbdesc->data_len = rxdesc->size; - skbdesc->desc = entry->skb->data; + skbdesc->desc = entry->skb->data - offset; skbdesc->desc_len = entry->queue->desc_size; - - /* - * Remove descriptor from skb buffer and trim the whole thing - * down to only contain data. - */ - skb_pull(entry->skb, skbdesc->desc_len); - skb_trim(entry->skb, rxdesc->size); } /* -- cgit v1.2.1 From 92f5ac6320d74fbb7230626cb88141f3ec9a694c Mon Sep 17 00:00:00 2001 From: Mattias Nissler Date: Sun, 9 Mar 2008 22:38:54 +0100 Subject: rt2x00: Initialize TX control field in data entries In the TX path, the driver didn't copy the TX control data structure. Thus, it was invalid in the TX done handler, causing serious trouble and misbehaviour. Signed-off-by: Mattias Nissler Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00pci.c | 1 + drivers/net/wireless/rt2x00/rt2x00usb.c | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index 1960d938d73b..7867ec64bd2c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c @@ -67,6 +67,7 @@ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev, skbdesc->desc_len = queue->desc_size; skbdesc->entry = entry; + memcpy(&priv_tx->control, control, sizeof(priv_tx->control)); memcpy(priv_tx->data, skb->data, skb->len); rt2x00lib_write_tx_desc(rt2x00dev, skb, control); diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 512ff3914813..eec91111e765 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -206,6 +206,7 @@ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev, skbdesc->desc_len = queue->desc_size; skbdesc->entry = entry; + memcpy(&priv_tx->control, control, sizeof(priv_tx->control)); rt2x00lib_write_tx_desc(rt2x00dev, skb, control); /* -- cgit v1.2.1 From 95db4d4d5f00cc9b2aa703a05a70902776d8c2f2 Mon Sep 17 00:00:00 2001 From: Mattias Nissler Date: Sun, 9 Mar 2008 22:39:32 +0100 Subject: rt2x00: Use the correct size when copying the control info in txdone The sizeof() operator was incorrectly applied to the pointer, not the struct. Signed-off-by: Mattias Nissler Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index b3a639aa0540..141b9b8a1997 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -521,7 +521,7 @@ void rt2x00lib_txdone(struct queue_entry *entry, tx_status.ack_signal = 0; tx_status.excessive_retries = (txdesc->status == TX_FAIL_RETRY); tx_status.retry_count = txdesc->retry; - memcpy(&tx_status.control, txdesc->control, sizeof(txdesc->control)); + memcpy(&tx_status.control, txdesc->control, sizeof(*txdesc->control)); if (!(tx_status.control.flags & IEEE80211_TXCTL_NO_ACK)) { if (success) -- cgit v1.2.1 From 2d1be5b0d17134ddba65c752557b1f47c8009db2 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 9 Mar 2008 22:40:06 +0100 Subject: rt2x00: Don't use uninitialized desc_len skbdesc->desc_len is uninitialized at the start of the function. So it is a _bad_ idea to use it... Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt73usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index b4b70850edfc..a48c82f09216 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -1381,7 +1381,7 @@ static void rt73usb_fill_rxdone(struct queue_entry *entry, skb_push(entry->skb, offset); memcpy(entry->skb->data, rxd, entry->queue->desc_size); rxd = (__le32 *)entry->skb->data; - skb_pull(entry->skb, offset + skbdesc->desc_len); + skb_pull(entry->skb, offset + entry->queue->desc_size); skb_trim(entry->skb, rxdesc->size); /* -- cgit v1.2.1 From 2ae23854dc0af617d9a0e3ab51a0cc51485ebbf2 Mon Sep 17 00:00:00 2001 From: Mattias Nissler Date: Sun, 9 Mar 2008 22:41:22 +0100 Subject: rt2x00: Don't use unitialized rxdesc->size rxdesc->size is unitialized before the desriptor has been read. Move the truncation of the sk buffer to the moment all variables have been initialized. Signed-off-by: Mattias Nissler Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2500usb.c | 11 +++++++---- drivers/net/wireless/rt2x00/rt73usb.c | 11 +++++++---- 2 files changed, 14 insertions(+), 8 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 86cd9a5eee2b..559131fc6d53 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1123,13 +1123,10 @@ static void rt2500usb_fill_rxdone(struct queue_entry *entry, /* * Copy descriptor to the available headroom inside the skbuffer. - * Remove the original copy by trimming the skbuffer. */ skb_push(entry->skb, offset); memcpy(entry->skb->data, rxd, entry->queue->desc_size); rxd = (__le32 *)entry->skb->data; - skb_pull(entry->skb, offset); - skb_trim(entry->skb, rxdesc->size); /* * The descriptor is now aligned to 4 bytes and thus it is @@ -1154,12 +1151,18 @@ static void rt2500usb_fill_rxdone(struct queue_entry *entry, rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); rxdesc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS); + /* + * Adjust the skb memory window to the frame boundaries. + */ + skb_pull(entry->skb, offset); + skb_trim(entry->skb, rxdesc->size); + /* * Set descriptor and data pointer. */ skbdesc->data = entry->skb->data; skbdesc->data_len = rxdesc->size; - skbdesc->desc = entry->skb->data - offset; + skbdesc->desc = rxd; skbdesc->desc_len = entry->queue->desc_size; } diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index a48c82f09216..468039f1bff9 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -1376,13 +1376,10 @@ static void rt73usb_fill_rxdone(struct queue_entry *entry, /* * Copy descriptor to the available headroom inside the skbuffer. - * Remove the original copy by pulling the skbuffer. */ skb_push(entry->skb, offset); memcpy(entry->skb->data, rxd, entry->queue->desc_size); rxd = (__le32 *)entry->skb->data; - skb_pull(entry->skb, offset + entry->queue->desc_size); - skb_trim(entry->skb, rxdesc->size); /* * The descriptor is now aligned to 4 bytes and thus it is @@ -1404,12 +1401,18 @@ static void rt73usb_fill_rxdone(struct queue_entry *entry, rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); rxdesc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS); + /* + * Adjust the skb memory window to the frame boundaries. + */ + skb_pull(entry->skb, offset + entry->queue->desc_size); + skb_trim(entry->skb, rxdesc->size); + /* * Set descriptor and data pointer. */ skbdesc->data = entry->skb->data; skbdesc->data_len = rxdesc->size; - skbdesc->desc = entry->skb->data - offset; + skbdesc->desc = rxd; skbdesc->desc_len = entry->queue->desc_size; } -- cgit v1.2.1 From 3976ae6c2b09608cd6a13663737a6b219245b651 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 9 Mar 2008 22:41:53 +0100 Subject: rt2x00: Use skbdesc fields for descriptor initialization In rt2x00lib_write_tx_desc() the skb->data and skb->len fields were incorrectly used. For USB drivers both of those values contain invalid data (skb->data points to the device descriptor, skb->len contains the frame _and_ descriptor length). Instead of using the skbuffer fields we should use the skbdesc fields which are correctly initialized and contain all the data that we need. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00dev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 141b9b8a1997..455d0763503e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -630,7 +630,7 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev, { struct txentry_desc txdesc; struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skbdesc->data; const struct rt2x00_rate *rate; int tx_rate; int length; @@ -710,7 +710,7 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev, txdesc.signal = rate->plcp; txdesc.service = 0x04; - length = skb->len + FCS_LEN; + length = skbdesc->data_len + FCS_LEN; if (rate->flags & DEV_RATE_OFDM) { __set_bit(ENTRY_TXD_OFDM_RATE, &txdesc.flags); -- cgit v1.2.1 From 8af244ccb14a4367568db11c5e78b45a4c2cf77e Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 9 Mar 2008 22:42:59 +0100 Subject: rt2x00: Only disable beaconing just before beacon update We should not write 0 to the beacon sync register during config_intf() since that will clear out the beacon interval and forces the beacon to be send out at the lowest interval. (reported by Mattias Nissler). The side effect of the same bug was that while working with multiple virtual AP interfaces a change for any of those interfaces would disable beaconing untill an beacon update was provided. This is resolved by only updating the TSF_SYNC value during config_intf(). In update_beacon() we disable beaconing temporarily to prevent fake beacons to be transmitted. Finally kick_tx_queue() will enable beaconing again. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 20 +++++++++++++------- drivers/net/wireless/rt2x00/rt2500pci.c | 19 +++++++++++++------ drivers/net/wireless/rt2x00/rt2500usb.c | 19 +++++++++++++------ drivers/net/wireless/rt2x00/rt61pci.c | 18 +++++++++++++----- drivers/net/wireless/rt2x00/rt73usb.c | 18 +++++++++++++----- 5 files changed, 65 insertions(+), 29 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 460ef2fb5104..a1c38a144149 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -279,8 +279,6 @@ static void rt2400pci_config_intf(struct rt2x00_dev *rt2x00dev, u32 reg; if (flags & CONFIG_UPDATE_TYPE) { - rt2x00pci_register_write(rt2x00dev, CSR14, 0); - /* * Enable beacon config */ @@ -293,10 +291,6 @@ static void rt2400pci_config_intf(struct rt2x00_dev *rt2x00dev, * Enable synchronisation. */ rt2x00pci_register_read(rt2x00dev, CSR14, ®); - rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); - rt2x00_set_field32(®, CSR14_TBCN, - (conf->sync == TSF_SYNC_BEACON)); - rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); rt2x00_set_field32(®, CSR14_TSF_SYNC, conf->sync); rt2x00pci_register_write(rt2x00dev, CSR14, reg); } @@ -1040,6 +1034,8 @@ static void rt2400pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, if (queue == RT2X00_BCN_QUEUE_BEACON) { rt2x00pci_register_read(rt2x00dev, CSR14, ®); if (!rt2x00_get_field32(reg, CSR14_BEACON_GEN)) { + rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); + rt2x00_set_field32(®, CSR14_TBCN, 1); rt2x00_set_field32(®, CSR14_BEACON_GEN, 1); rt2x00pci_register_write(rt2x00dev, CSR14, reg); } @@ -1517,10 +1513,10 @@ static int rt2400pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, struct rt2x00_intf *intf = vif_to_intf(control->vif); struct queue_entry_priv_pci_tx *priv_tx; struct skb_frame_desc *skbdesc; + u32 reg; if (unlikely(!intf->beacon)) return -ENOBUFS; - priv_tx = intf->beacon->priv_data; /* @@ -1535,6 +1531,16 @@ static int rt2400pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, skbdesc->desc_len = intf->beacon->queue->desc_size; skbdesc->entry = intf->beacon; + /* + * Disable beaconing while we are reloading the beacon data, + * otherwise we might be sending out invalid data. + */ + rt2x00pci_register_read(rt2x00dev, CSR14, ®); + rt2x00_set_field32(®, CSR14_TSF_COUNT, 0); + rt2x00_set_field32(®, CSR14_TBCN, 0); + rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); + rt2x00pci_register_write(rt2x00dev, CSR14, reg); + /* * mac80211 doesn't provide the control->queue variable * for beacons. Set our own queue identification so diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index ffcd996df064..096232763055 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -281,8 +281,6 @@ static void rt2500pci_config_intf(struct rt2x00_dev *rt2x00dev, u32 reg; if (flags & CONFIG_UPDATE_TYPE) { - rt2x00pci_register_write(rt2x00dev, CSR14, 0); - /* * Enable beacon config */ @@ -296,10 +294,6 @@ static void rt2500pci_config_intf(struct rt2x00_dev *rt2x00dev, * Enable synchronisation. */ rt2x00pci_register_read(rt2x00dev, CSR14, ®); - rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); - rt2x00_set_field32(®, CSR14_TBCN, - (conf->sync == TSF_SYNC_BEACON)); - rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); rt2x00_set_field32(®, CSR14_TSF_SYNC, conf->sync); rt2x00pci_register_write(rt2x00dev, CSR14, reg); } @@ -1193,6 +1187,8 @@ static void rt2500pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, if (queue == RT2X00_BCN_QUEUE_BEACON) { rt2x00pci_register_read(rt2x00dev, CSR14, ®); if (!rt2x00_get_field32(reg, CSR14_BEACON_GEN)) { + rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); + rt2x00_set_field32(®, CSR14_TBCN, 1); rt2x00_set_field32(®, CSR14_BEACON_GEN, 1); rt2x00pci_register_write(rt2x00dev, CSR14, reg); } @@ -1828,6 +1824,7 @@ static int rt2500pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, struct rt2x00_intf *intf = vif_to_intf(control->vif); struct queue_entry_priv_pci_tx *priv_tx; struct skb_frame_desc *skbdesc; + u32 reg; if (unlikely(!intf->beacon)) return -ENOBUFS; @@ -1846,6 +1843,16 @@ static int rt2500pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, skbdesc->desc_len = intf->beacon->queue->desc_size; skbdesc->entry = intf->beacon; + /* + * Disable beaconing while we are reloading the beacon data, + * otherwise we might be sending out invalid data. + */ + rt2x00pci_register_read(rt2x00dev, CSR14, ®); + rt2x00_set_field32(®, CSR14_TSF_COUNT, 0); + rt2x00_set_field32(®, CSR14_TBCN, 0); + rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); + rt2x00pci_register_write(rt2x00dev, CSR14, reg); + /* * mac80211 doesn't provide the control->queue variable * for beacons. Set our own queue identification so diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 559131fc6d53..b6c6f7dd9eda 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -324,8 +324,6 @@ static void rt2500usb_config_intf(struct rt2x00_dev *rt2x00dev, u16 reg; if (flags & CONFIG_UPDATE_TYPE) { - rt2500usb_register_write(rt2x00dev, TXRX_CSR19, 0); - /* * Enable beacon config */ @@ -344,10 +342,6 @@ static void rt2500usb_config_intf(struct rt2x00_dev *rt2x00dev, rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg); rt2500usb_register_read(rt2x00dev, TXRX_CSR19, ®); - rt2x00_set_field16(®, TXRX_CSR19_TSF_COUNT, 1); - rt2x00_set_field16(®, TXRX_CSR19_TBCN, - (conf->sync == TSF_SYNC_BEACON)); - rt2x00_set_field16(®, TXRX_CSR19_BEACON_GEN, 0); rt2x00_set_field16(®, TXRX_CSR19_TSF_SYNC, conf->sync); rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); } @@ -1092,6 +1086,8 @@ static void rt2500usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, rt2500usb_register_read(rt2x00dev, TXRX_CSR19, ®); if (!rt2x00_get_field16(reg, TXRX_CSR19_BEACON_GEN)) { + rt2x00_set_field16(®, TXRX_CSR19_TSF_COUNT, 1); + rt2x00_set_field16(®, TXRX_CSR19_TBCN, 1); rt2x00_set_field16(®, TXRX_CSR19_BEACON_GEN, 1); /* * Beacon generation will fail initially. @@ -1740,6 +1736,7 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw, struct skb_frame_desc *skbdesc; int pipe = usb_sndbulkpipe(usb_dev, 1); int length; + u16 reg; if (unlikely(!intf->beacon)) return -ENOBUFS; @@ -1764,6 +1761,16 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw, skbdesc->desc_len = intf->beacon->queue->desc_size; skbdesc->entry = intf->beacon; + /* + * Disable beaconing while we are reloading the beacon data, + * otherwise we might be sending out invalid data. + */ + rt2500usb_register_read(rt2x00dev, TXRX_CSR19, ®); + rt2x00_set_field16(®, TXRX_CSR19_TSF_COUNT, 0); + rt2x00_set_field16(®, TXRX_CSR19_TBCN, 0); + rt2x00_set_field16(®, TXRX_CSR19_BEACON_GEN, 0); + rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); + /* * mac80211 doesn't provide the control->queue variable * for beacons. Set our own queue identification so diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 091fe398676d..13b918db1850 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -336,17 +336,12 @@ static void rt61pci_config_intf(struct rt2x00_dev *rt2x00dev, * bits which (when set to 0) will invalidate the entire beacon. */ beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx); - rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, 0); rt2x00pci_register_write(rt2x00dev, beacon_base, 0); /* * Enable synchronisation. */ rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); - rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); - rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, - (conf->sync == TSF_SYNC_BEACON)); - rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, conf->sync); rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); } @@ -1562,6 +1557,8 @@ static void rt61pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); if (!rt2x00_get_field32(reg, TXRX_CSR9_BEACON_GEN)) { + rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); + rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1); rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 1); rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); } @@ -2373,6 +2370,7 @@ static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, struct rt2x00_intf *intf = vif_to_intf(control->vif); struct skb_frame_desc *skbdesc; unsigned int beacon_base; + u32 reg; if (unlikely(!intf->beacon)) return -ENOBUFS; @@ -2407,6 +2405,16 @@ static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, skbdesc->desc_len = intf->beacon->queue->desc_size; skbdesc->entry = intf->beacon; + /* + * Disable beaconing while we are reloading the beacon data, + * otherwise we might be sending out invalid data. + */ + rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); + rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 0); + rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 0); + rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); + rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); + /* * mac80211 doesn't provide the control->queue variable * for beacons. Set our own queue identification so diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 468039f1bff9..a28c1d84ba95 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -347,17 +347,12 @@ static void rt73usb_config_intf(struct rt2x00_dev *rt2x00dev, * bits which (when set to 0) will invalidate the entire beacon. */ beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx); - rt73usb_register_write(rt2x00dev, TXRX_CSR9, 0); rt73usb_register_write(rt2x00dev, beacon_base, 0); /* * Enable synchronisation. */ rt73usb_register_read(rt2x00dev, TXRX_CSR9, ®); - rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); - rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, - (conf->sync == TSF_SYNC_BEACON)); - rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, conf->sync); rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg); } @@ -1312,6 +1307,8 @@ static void rt73usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, rt73usb_register_read(rt2x00dev, TXRX_CSR9, ®); if (!rt2x00_get_field32(reg, TXRX_CSR9_BEACON_GEN)) { + rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); + rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1); rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 1); rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg); } @@ -1987,6 +1984,7 @@ static int rt73usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, struct skb_frame_desc *skbdesc; unsigned int beacon_base; unsigned int timeout; + u32 reg; if (unlikely(!intf->beacon)) return -ENOBUFS; @@ -2009,6 +2007,16 @@ static int rt73usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, skbdesc->desc_len = intf->beacon->queue->desc_size; skbdesc->entry = intf->beacon; + /* + * Disable beaconing while we are reloading the beacon data, + * otherwise we might be sending out invalid data. + */ + rt73usb_register_read(rt2x00dev, TXRX_CSR9, ®); + rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 0); + rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 0); + rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); + rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg); + /* * mac80211 doesn't provide the control->queue variable * for beacons. Set our own queue identification so -- cgit v1.2.1 From fd07e06380a1fe2b2c505d00563a63cfb63d7ceb Mon Sep 17 00:00:00 2001 From: Adam Baker Date: Sun, 9 Mar 2008 22:43:27 +0100 Subject: rt2x00:correct rx packet length for USB devices When fixing up the packet alignment, if we had to add 2 bytes to the front of the skb we need to remember to take them off the end afterwards. This fixes reception of encrypted packets which were otherwise failing with an invalid ICV. Signed-off-by: Adam Baker Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00usb.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index eec91111e765..5a331674dcb2 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -299,6 +299,7 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) memmove(entry->skb->data, entry->skb->data + 2, entry->skb->len - 2); skbdesc->data = entry->skb->data; + skb_trim(entry->skb,entry->skb->len - 2); } /* -- cgit v1.2.1 From 61191fb272dfa413763416ee828aae28bfd9746e Mon Sep 17 00:00:00 2001 From: Luis Correia Date: Sun, 9 Mar 2008 22:43:58 +0100 Subject: rt2x00: Fix trivial log message Fix trivial log message. Signed-off-by: Luis Correia Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2500usb.c | 3 ++- drivers/net/wireless/rt2x00/rt73usb.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index b6c6f7dd9eda..b9e2f3a4990b 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -294,7 +294,8 @@ static void rt2500usb_led_brightness(struct led_classdev *led_cdev, if (in_atomic()) { NOTICE(led->rt2x00dev, - "Ignoring LED brightness command for led %d", led->type); + "Ignoring LED brightness command for led %d\n", + led->type); return; } diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index a28c1d84ba95..82dd4ced4005 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -292,7 +292,8 @@ static void rt73usb_led_brightness(struct led_classdev *led_cdev, if (in_atomic()) { NOTICE(led->rt2x00dev, - "Ignoring LED brightness command for led %d", led->type); + "Ignoring LED brightness command for led %d\n", + led->type); return; } -- cgit v1.2.1 From 5f46c4d0537a870f9d9c1fd998aa9d6dac682595 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 9 Mar 2008 22:44:30 +0100 Subject: rt2x00: Upgrade queue->lock to use irqsave The queue->lock could be grabbed from interrupt context, which could lead to lockdep panic like this: kernel: ====================================================== kernel: [ INFO: soft-safe -> soft-unsafe lock order detected ] kernel: 2.6.25-0.95.rc4.fc9 #1 kernel: ------------------------------------------------------ kernel: rt2500pci/1251 [HC0[0]:SC0[1]:HE1:SE0] is trying to acquire: kernel: (&queue->lock){--..}, at: [] rt2x00queue_get_entry+0x5a/0x81 [rt2x00lib] kernel: kernel: and this task is already holding: kernel: (_xmit_IEEE80211){-...}, at: [] __qdisc_run+0x84/0x1a9 kernel: which would create a new lock dependency: kernel: (_xmit_IEEE80211){-...} -> (&queue->lock){--..} kernel: kernel: but this new dependency connects a soft-irq-safe lock: kernel: (_xmit_ETHER){-+..} kernel: ... which became soft-irq-safe at: kernel: [] 0xffffffffffffffff kernel: kernel: to a soft-irq-unsafe lock: kernel: (&queue->lock){--..} kernel: ... which became soft-irq-unsafe at: kernel: ... [] __lock_acquire+0x62d/0xd63 kernel: [] lock_acquire+0x5e/0x78 kernel: [] _spin_lock+0x26/0x53 kernel: [] rt2x00queue_reset+0x16/0x40 [rt2x00lib] kernel: [] rt2x00queue_alloc_entries+0x12/0xab [rt2x00lib] kernel: [] rt2x00queue_initialize+0x24/0xf2 [rt2x00lib] kernel: [] rt2x00lib_start+0x3b/0xd4 [rt2x00lib] kernel: [] rt2x00mac_start+0x18/0x1a [rt2x00lib] kernel: [] ieee80211_open+0x1f3/0x46d [mac80211] kernel: [] dev_open+0x4d/0x8b kernel: [] dev_change_flags+0xaf/0x172 kernel: [] do_setlink+0x276/0x338 kernel: [] rtnl_setlink+0x114/0x116 kernel: [] rtnetlink_rcv_msg+0x1d8/0x1f9 kernel: [] netlink_rcv_skb+0x3e/0xac kernel: [] rtnetlink_rcv+0x29/0x33 kernel: [] netlink_unicast+0x1fe/0x26b kernel: [] netlink_sendmsg+0x2ca/0x2dd kernel: [] sock_sendmsg+0xfd/0x120 kernel: [] sys_sendmsg+0x1d2/0x23c kernel: [] tracesys+0xdc/0xe1 kernel: [] 0xffffffffffffffff This can be fixed by using the irqsave/irqrestore versions during the queue->lock handling. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00debug.c | 5 +++-- drivers/net/wireless/rt2x00/rt2x00queue.c | 17 +++++++++++------ 2 files changed, 14 insertions(+), 8 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c index 21af11a97334..bfab3b8780d6 100644 --- a/drivers/net/wireless/rt2x00/rt2x00debug.c +++ b/drivers/net/wireless/rt2x00/rt2x00debug.c @@ -278,6 +278,7 @@ static ssize_t rt2x00debug_read_queue_stats(struct file *file, { struct rt2x00debug_intf *intf = file->private_data; struct data_queue *queue; + unsigned long irqflags; unsigned int lines = 1 + intf->rt2x00dev->data_queues; size_t size; char *data; @@ -294,7 +295,7 @@ static ssize_t rt2x00debug_read_queue_stats(struct file *file, sprintf(data, "qid\tcount\tlimit\tlength\tindex\tdone\tcrypto\n"); queue_for_each(intf->rt2x00dev, queue) { - spin_lock(&queue->lock); + spin_lock_irqsave(&queue->lock, irqflags); temp += sprintf(temp, "%d\t%d\t%d\t%d\t%d\t%d\t%d\n", queue->qid, queue->count, queue->limit, queue->length, @@ -302,7 +303,7 @@ static ssize_t rt2x00debug_read_queue_stats(struct file *file, queue->index[Q_INDEX_DONE], queue->index[Q_INDEX_CRYPTO]); - spin_unlock(&queue->lock); + spin_unlock_irqrestore(&queue->lock, irqflags); } size = strlen(data); diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 9188323f067b..659e9f44c40c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -53,6 +53,7 @@ struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue, enum queue_index index) { struct queue_entry *entry; + unsigned long irqflags; if (unlikely(index >= Q_INDEX_MAX)) { ERROR(queue->rt2x00dev, @@ -60,11 +61,11 @@ struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue, return NULL; } - spin_lock(&queue->lock); + spin_lock_irqsave(&queue->lock, irqflags); entry = &queue->entries[queue->index[index]]; - spin_unlock(&queue->lock); + spin_unlock_irqrestore(&queue->lock, irqflags); return entry; } @@ -72,13 +73,15 @@ EXPORT_SYMBOL_GPL(rt2x00queue_get_entry); void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index) { + unsigned long irqflags; + if (unlikely(index >= Q_INDEX_MAX)) { ERROR(queue->rt2x00dev, "Index change on invalid index type (%d)\n", index); return; } - spin_lock(&queue->lock); + spin_lock_irqsave(&queue->lock, irqflags); queue->index[index]++; if (queue->index[index] >= queue->limit) @@ -91,19 +94,21 @@ void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index) queue->count ++; } - spin_unlock(&queue->lock); + spin_unlock_irqrestore(&queue->lock, irqflags); } EXPORT_SYMBOL_GPL(rt2x00queue_index_inc); static void rt2x00queue_reset(struct data_queue *queue) { - spin_lock(&queue->lock); + unsigned long irqflags; + + spin_lock_irqsave(&queue->lock, irqflags); queue->count = 0; queue->length = 0; memset(queue->index, 0, sizeof(queue->index)); - spin_unlock(&queue->lock); + spin_unlock_irqrestore(&queue->lock, irqflags); } void rt2x00queue_init_rx(struct rt2x00_dev *rt2x00dev) -- cgit v1.2.1 From a7f3a06cbb63a16ad7a1720506591d8d12a03029 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 9 Mar 2008 22:44:54 +0100 Subject: rt2x00: Move firmware checksumming to driver rt2x00lib depended on 2 crc algorithms because rt61/rt73 use a different algorithm then rt2800. This means that even when only 1 algorithm was needed, the dependency was still present for both. By moving the checksum generation to the driver we can clean up 2 annoying flags (which indicated which checksum was required) and move the dependency to where it belongs: the driver. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/Kconfig | 4 ++-- drivers/net/wireless/rt2x00/rt2x00.h | 3 +-- drivers/net/wireless/rt2x00/rt2x00firmware.c | 34 +--------------------------- drivers/net/wireless/rt2x00/rt61pci.c | 28 +++++++++++++++++++---- drivers/net/wireless/rt2x00/rt73usb.c | 28 +++++++++++++++++++---- 5 files changed, 50 insertions(+), 47 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index d5240aa06233..4709c11da419 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig @@ -27,8 +27,6 @@ config RT2X00_LIB_USB config RT2X00_LIB_FIRMWARE boolean depends on RT2X00_LIB - select CRC_CCITT - select CRC_ITU_T select FW_LOADER config RT2X00_LIB_RFKILL @@ -102,6 +100,7 @@ config RT61PCI depends on PCI select RT2X00_LIB_PCI select RT2X00_LIB_FIRMWARE + select CRC_ITU_T select EEPROM_93CX6 ---help--- This is an experimental driver for the Ralink rt61 wireless chip. @@ -145,6 +144,7 @@ config RT73USB depends on USB select RT2X00_LIB_USB select RT2X00_LIB_FIRMWARE + select CRC_ITU_T ---help--- This is an experimental driver for the Ralink rt73 wireless chip. diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index fd65fccbdae7..8718ad3dcc00 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -495,6 +495,7 @@ struct rt2x00lib_ops { */ int (*probe_hw) (struct rt2x00_dev *rt2x00dev); char *(*get_firmware_name) (struct rt2x00_dev *rt2x00dev); + u16 (*get_firmware_crc) (void *data, const size_t len); int (*load_firmware) (struct rt2x00_dev *rt2x00dev, void *data, const size_t len); @@ -613,8 +614,6 @@ enum rt2x00_flags { */ DRIVER_SUPPORT_MIXED_INTERFACES, DRIVER_REQUIRE_FIRMWARE, - DRIVER_REQUIRE_FIRMWARE_CRC_ITU_T, - DRIVER_REQUIRE_FIRMWARE_CCITT, DRIVER_REQUIRE_BEACON_GUARD, DRIVER_REQUIRE_ATIM_QUEUE, diff --git a/drivers/net/wireless/rt2x00/rt2x00firmware.c b/drivers/net/wireless/rt2x00/rt2x00firmware.c index 4f9fe56f4f2e..b971bc6e7ee2 100644 --- a/drivers/net/wireless/rt2x00/rt2x00firmware.c +++ b/drivers/net/wireless/rt2x00/rt2x00firmware.c @@ -23,8 +23,6 @@ Abstract: rt2x00 firmware loading routines. */ -#include -#include #include #include @@ -63,36 +61,7 @@ static int rt2x00lib_request_firmware(struct rt2x00_dev *rt2x00dev) return -ENOENT; } - /* - * Perform crc validation on the firmware. - * The last 2 bytes in the firmware array are the crc checksum itself, - * this means that we should never pass those 2 bytes to the crc - * algorithm. - */ - if (test_bit(DRIVER_REQUIRE_FIRMWARE_CRC_ITU_T, &rt2x00dev->flags)) { - /* - * Use the crc itu-t algorithm. - * Use 0 for the last 2 bytes to complete the checksum. - */ - crc = crc_itu_t(0, fw->data, fw->size - 2); - crc = crc_itu_t_byte(crc, 0); - crc = crc_itu_t_byte(crc, 0); - } else if (test_bit(DRIVER_REQUIRE_FIRMWARE_CCITT, &rt2x00dev->flags)) { - /* - * Use the crc ccitt algorithm. - * This will return the same value as the legacy driver which - * used bit ordering reversion on the both the firmware bytes - * before input input as well as on the final output. - * Obviously using crc ccitt directly is much more efficient. - */ - crc = crc_ccitt(~0, fw->data, fw->size - 2); - } else { - ERROR(rt2x00dev, "No checksum algorithm selected " - "for firmware validation.\n"); - retval = -ENOENT; - goto exit; - } - + crc = rt2x00dev->ops->lib->get_firmware_crc(fw->data, fw->size); if (crc != (fw->data[fw->size - 2] << 8 | fw->data[fw->size - 1])) { ERROR(rt2x00dev, "Firmware checksum error.\n"); retval = -ENOENT; @@ -139,4 +108,3 @@ void rt2x00lib_free_firmware(struct rt2x00_dev *rt2x00dev) release_firmware(rt2x00dev->fw); rt2x00dev->fw = NULL; } - diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 13b918db1850..23b3e163b9ba 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -24,6 +24,7 @@ Supported chipsets: RT2561, RT2561s, RT2661. */ +#include #include #include #include @@ -856,7 +857,7 @@ dynamic_cca_tune: } /* - * Firmware name function. + * Firmware functions */ static char *rt61pci_get_firmware_name(struct rt2x00_dev *rt2x00dev) { @@ -880,9 +881,23 @@ static char *rt61pci_get_firmware_name(struct rt2x00_dev *rt2x00dev) return fw_name; } -/* - * Initialization functions. - */ +static u16 rt61pci_get_firmware_crc(void *data, const size_t len) +{ + u16 crc; + + /* + * Use the crc itu-t algorithm. + * The last 2 bytes in the firmware array are the crc checksum itself, + * this means that we should never pass those 2 bytes to the crc + * algorithm. + */ + crc = crc_itu_t(0, data, len - 2); + crc = crc_itu_t_byte(crc, 0); + crc = crc_itu_t_byte(crc, 0); + + return crc; +} + static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev, void *data, const size_t len) { @@ -963,6 +978,9 @@ static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev, void *data, return 0; } +/* + * Initialization functions. + */ static void rt61pci_init_rxentry(struct rt2x00_dev *rt2x00dev, struct queue_entry *entry) { @@ -2257,7 +2275,6 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev) * This device requires firmware. */ __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); - __set_bit(DRIVER_REQUIRE_FIRMWARE_CRC_ITU_T, &rt2x00dev->flags); /* * Set the rssi offset. @@ -2457,6 +2474,7 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { .irq_handler = rt61pci_interrupt, .probe_hw = rt61pci_probe_hw, .get_firmware_name = rt61pci_get_firmware_name, + .get_firmware_crc = rt61pci_get_firmware_crc, .load_firmware = rt61pci_load_firmware, .initialize = rt2x00pci_initialize, .uninitialize = rt2x00pci_uninitialize, diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 82dd4ced4005..72c2827ee57c 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -24,6 +24,7 @@ Supported chipsets: rt2571W & rt2671. */ +#include #include #include #include @@ -817,16 +818,30 @@ dynamic_cca_tune: } /* - * Firmware name function. + * Firmware functions */ static char *rt73usb_get_firmware_name(struct rt2x00_dev *rt2x00dev) { return FIRMWARE_RT2571; } -/* - * Initialization functions. - */ +static u16 rt73usb_get_firmware_crc(void *data, const size_t len) +{ + u16 crc; + + /* + * Use the crc itu-t algorithm. + * The last 2 bytes in the firmware array are the crc checksum itself, + * this means that we should never pass those 2 bytes to the crc + * algorithm. + */ + crc = crc_itu_t(0, data, len - 2); + crc = crc_itu_t_byte(crc, 0); + crc = crc_itu_t_byte(crc, 0); + + return crc; +} + static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev, void *data, const size_t len) { @@ -896,6 +911,9 @@ static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev, void *data, return 0; } +/* + * Initialization functions. + */ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev) { u32 reg; @@ -1852,7 +1870,6 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev) * This device requires firmware. */ __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); - __set_bit(DRIVER_REQUIRE_FIRMWARE_CRC_ITU_T, &rt2x00dev->flags); /* * Set the rssi offset. @@ -2061,6 +2078,7 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = { static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { .probe_hw = rt73usb_probe_hw, .get_firmware_name = rt73usb_get_firmware_name, + .get_firmware_crc = rt73usb_get_firmware_crc, .load_firmware = rt73usb_load_firmware, .initialize = rt2x00usb_initialize, .uninitialize = rt2x00usb_uninitialize, -- cgit v1.2.1 From a4fe07d913096f4573512c9369f8ca824fbc2d8f Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 9 Mar 2008 22:45:21 +0100 Subject: rt2x00: Start bugging when rt2x00lib doesn't filter SW diversity rt2x00lib should filter SW diversity out before sending any configuration changes to the driver. When rt2x00lib fails to do this, it is important that such events are reported because it _must_ be fixed. So upgrading the error level to a BUG_ON() which will make sure this bug gets noticed whenever it happens. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 23 +++++++++------------ drivers/net/wireless/rt2x00/rt2500pci.c | 25 +++++++++-------------- drivers/net/wireless/rt2x00/rt2500usb.c | 23 +++++++++------------ drivers/net/wireless/rt2x00/rt61pci.c | 36 ++++++++++++--------------------- drivers/net/wireless/rt2x00/rt73usb.c | 23 +++++++++------------ 5 files changed, 49 insertions(+), 81 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index a1c38a144149..0ac0c6e08732 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -417,6 +417,13 @@ static void rt2400pci_config_antenna(struct rt2x00_dev *rt2x00dev, u8 r1; u8 r4; + /* + * We should never come here because rt2x00lib is supposed + * to catch this and send us the correct antenna explicitely. + */ + BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY || + ant->tx == ANTENNA_SW_DIVERSITY); + rt2400pci_bbp_read(rt2x00dev, 4, &r4); rt2400pci_bbp_read(rt2x00dev, 1, &r1); @@ -430,14 +437,8 @@ static void rt2400pci_config_antenna(struct rt2x00_dev *rt2x00dev, case ANTENNA_A: rt2x00_set_field8(&r1, BBP_R1_TX_ANTENNA, 0); break; - case ANTENNA_SW_DIVERSITY: - /* - * NOTE: We should never come here because rt2x00lib is - * supposed to catch this and send us the correct antenna - * explicitely. However we are nog going to bug about this. - * Instead, just default to antenna B. - */ case ANTENNA_B: + default: rt2x00_set_field8(&r1, BBP_R1_TX_ANTENNA, 2); break; } @@ -452,14 +453,8 @@ static void rt2400pci_config_antenna(struct rt2x00_dev *rt2x00dev, case ANTENNA_A: rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 0); break; - case ANTENNA_SW_DIVERSITY: - /* - * NOTE: We should never come here because rt2x00lib is - * supposed to catch this and send us the correct antenna - * explicitely. However we are nog going to bug about this. - * Instead, just default to antenna B. - */ case ANTENNA_B: + default: rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 2); break; } diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 096232763055..d85e1a44d5cd 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -444,6 +444,13 @@ static void rt2500pci_config_antenna(struct rt2x00_dev *rt2x00dev, u8 r14; u8 r2; + /* + * We should never come here because rt2x00lib is supposed + * to catch this and send us the correct antenna explicitely. + */ + BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY || + ant->tx == ANTENNA_SW_DIVERSITY); + rt2x00pci_register_read(rt2x00dev, BBPCSR1, ®); rt2500pci_bbp_read(rt2x00dev, 14, &r14); rt2500pci_bbp_read(rt2x00dev, 2, &r2); @@ -457,15 +464,8 @@ static void rt2500pci_config_antenna(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(®, BBPCSR1_CCK, 0); rt2x00_set_field32(®, BBPCSR1_OFDM, 0); break; - case ANTENNA_HW_DIVERSITY: - case ANTENNA_SW_DIVERSITY: - /* - * NOTE: We should never come here because rt2x00lib is - * supposed to catch this and send us the correct antenna - * explicitely. However we are nog going to bug about this. - * Instead, just default to antenna B. - */ case ANTENNA_B: + default: rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 2); rt2x00_set_field32(®, BBPCSR1_CCK, 2); rt2x00_set_field32(®, BBPCSR1_OFDM, 2); @@ -479,15 +479,8 @@ static void rt2500pci_config_antenna(struct rt2x00_dev *rt2x00dev, case ANTENNA_A: rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 0); break; - case ANTENNA_HW_DIVERSITY: - case ANTENNA_SW_DIVERSITY: - /* - * NOTE: We should never come here because rt2x00lib is - * supposed to catch this and send us the correct antenna - * explicitely. However we are nog going to bug about this. - * Instead, just default to antenna B. - */ case ANTENNA_B: + default: rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 2); break; } diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index b9e2f3a4990b..7ea4247442b3 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -437,6 +437,13 @@ static void rt2500usb_config_antenna(struct rt2x00_dev *rt2x00dev, u16 csr5; u16 csr6; + /* + * We should never come here because rt2x00lib is supposed + * to catch this and send us the correct antenna explicitely. + */ + BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY || + ant->tx == ANTENNA_SW_DIVERSITY); + rt2500usb_bbp_read(rt2x00dev, 2, &r2); rt2500usb_bbp_read(rt2x00dev, 14, &r14); rt2500usb_register_read(rt2x00dev, PHY_CSR5, &csr5); @@ -456,14 +463,8 @@ static void rt2500usb_config_antenna(struct rt2x00_dev *rt2x00dev, rt2x00_set_field16(&csr5, PHY_CSR5_CCK, 0); rt2x00_set_field16(&csr6, PHY_CSR6_OFDM, 0); break; - case ANTENNA_SW_DIVERSITY: - /* - * NOTE: We should never come here because rt2x00lib is - * supposed to catch this and send us the correct antenna - * explicitely. However we are nog going to bug about this. - * Instead, just default to antenna B. - */ case ANTENNA_B: + default: rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 2); rt2x00_set_field16(&csr5, PHY_CSR5_CCK, 2); rt2x00_set_field16(&csr6, PHY_CSR6_OFDM, 2); @@ -480,14 +481,8 @@ static void rt2500usb_config_antenna(struct rt2x00_dev *rt2x00dev, case ANTENNA_A: rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 0); break; - case ANTENNA_SW_DIVERSITY: - /* - * NOTE: We should never come here because rt2x00lib is - * supposed to catch this and send us the correct antenna - * explicitely. However we are nog going to bug about this. - * Instead, just default to antenna B. - */ case ANTENNA_B: + default: rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 2); break; } diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 23b3e163b9ba..f912a8515b5c 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -481,14 +481,8 @@ static void rt61pci_config_antenna_5x(struct rt2x00_dev *rt2x00dev, else rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3); break; - case ANTENNA_SW_DIVERSITY: - /* - * NOTE: We should never come here because rt2x00lib is - * supposed to catch this and send us the correct antenna - * explicitely. However we are nog going to bug about this. - * Instead, just default to antenna B. - */ case ANTENNA_B: + default: rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1); rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0); if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) @@ -530,14 +524,8 @@ static void rt61pci_config_antenna_2x(struct rt2x00_dev *rt2x00dev, rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1); rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3); break; - case ANTENNA_SW_DIVERSITY: - /* - * NOTE: We should never come here because rt2x00lib is - * supposed to catch this and send us the correct antenna - * explicitely. However we are nog going to bug about this. - * Instead, just default to antenna B. - */ case ANTENNA_B: + default: rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1); rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0); break; @@ -575,10 +563,6 @@ static void rt61pci_config_antenna_2529(struct rt2x00_dev *rt2x00dev, rt61pci_bbp_read(rt2x00dev, 4, &r4); rt61pci_bbp_read(rt2x00dev, 77, &r77); - /* FIXME: Antenna selection for the rf 2529 is very confusing in the - * legacy driver. The code below should be ok for non-diversity setups. - */ - /* * Configure the RX antenna. */ @@ -588,15 +572,14 @@ static void rt61pci_config_antenna_2529(struct rt2x00_dev *rt2x00dev, rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0); rt61pci_config_antenna_2529_rx(rt2x00dev, 0, 0); break; - case ANTENNA_SW_DIVERSITY: case ANTENNA_HW_DIVERSITY: /* - * NOTE: We should never come here because rt2x00lib is - * supposed to catch this and send us the correct antenna - * explicitely. However we are nog going to bug about this. - * Instead, just default to antenna B. + * FIXME: Antenna selection for the rf 2529 is very confusing + * in the legacy driver. Just default to antenna B until the + * legacy code can be properly translated into rt2x00 code. */ case ANTENNA_B: + default: rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1); rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3); rt61pci_config_antenna_2529_rx(rt2x00dev, 1, 1); @@ -647,6 +630,13 @@ static void rt61pci_config_antenna(struct rt2x00_dev *rt2x00dev, unsigned int i; u32 reg; + /* + * We should never come here because rt2x00lib is supposed + * to catch this and send us the correct antenna explicitely. + */ + BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY || + ant->tx == ANTENNA_SW_DIVERSITY); + if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { sel = antenna_sel_a; lna = test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags); diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 72c2827ee57c..d0e97e1dfaf6 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -497,14 +497,8 @@ static void rt73usb_config_antenna_5x(struct rt2x00_dev *rt2x00dev, else rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3); break; - case ANTENNA_SW_DIVERSITY: - /* - * NOTE: We should never come here because rt2x00lib is - * supposed to catch this and send us the correct antenna - * explicitely. However we are nog going to bug about this. - * Instead, just default to antenna B. - */ case ANTENNA_B: + default: rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1); rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0); if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) @@ -545,14 +539,8 @@ static void rt73usb_config_antenna_2x(struct rt2x00_dev *rt2x00dev, rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3); rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1); break; - case ANTENNA_SW_DIVERSITY: - /* - * NOTE: We should never come here because rt2x00lib is - * supposed to catch this and send us the correct antenna - * explicitely. However we are nog going to bug about this. - * Instead, just default to antenna B. - */ case ANTENNA_B: + default: rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0); rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1); break; @@ -602,6 +590,13 @@ static void rt73usb_config_antenna(struct rt2x00_dev *rt2x00dev, unsigned int i; u32 reg; + /* + * We should never come here because rt2x00lib is supposed + * to catch this and send us the correct antenna explicitely. + */ + BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY || + ant->tx == ANTENNA_SW_DIVERSITY); + if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { sel = antenna_sel_a; lna = test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags); -- cgit v1.2.1 From e4030a2f40a9575bccc71c3e156ca78c7d6fded6 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 9 Mar 2008 22:45:47 +0100 Subject: rt2x00: Check IEEE80211_TXCTL_SEND_AFTER_DTIM flag When mac sets the IEEE80211_TXCTL_SEND_AFTER_DTIM flag, we should check if the ATIM queue is available in the driver and put the frame in that queue for proper behavior (send frame after beacon interval). Unfortunately not all drivers have this ATIM queue, and will lack this feature for now. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00mac.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index a54f6873e9ea..76a2a7c118b2 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -99,7 +99,11 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb, /* * Determine which queue to put packet on. */ - queue = rt2x00queue_get_queue(rt2x00dev, control->queue); + if (control->flags & IEEE80211_TXCTL_SEND_AFTER_DTIM && + test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags)) + queue = rt2x00queue_get_queue(rt2x00dev, RT2X00_BCN_QUEUE_ATIM); + else + queue = rt2x00queue_get_queue(rt2x00dev, control->queue); if (unlikely(!queue)) { ERROR(rt2x00dev, "Attempt to send packet over invalid queue %d.\n" -- cgit v1.2.1 From 728103794316f7ff8d98bc2ce044aff7a260ee21 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 9 Mar 2008 22:46:18 +0100 Subject: rt2x00: Rename config_preamble() to config_erp() Rename config_preamble() to config_erp() and cleanup argument list by putting it all into a single structure. This will make the function more meaningful and easier to expand later. This second option is mostly intended to make the patch "mac80211: proper short-slot handling" from Johannes Berg easier to apply for rt2x00. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 16 +++++------ drivers/net/wireless/rt2x00/rt2500pci.c | 16 +++++------ drivers/net/wireless/rt2x00/rt2500usb.c | 12 ++++----- drivers/net/wireless/rt2x00/rt2x00.h | 18 +++++++++---- drivers/net/wireless/rt2x00/rt2x00config.c | 43 ++++++++++++++---------------- drivers/net/wireless/rt2x00/rt2x00dev.c | 5 ++-- drivers/net/wireless/rt2x00/rt2x00lib.h | 6 ++--- drivers/net/wireless/rt2x00/rt2x00mac.c | 16 +++++------ drivers/net/wireless/rt2x00/rt61pci.c | 12 ++++----- drivers/net/wireless/rt2x00/rt73usb.c | 12 ++++----- 10 files changed, 76 insertions(+), 80 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 0ac0c6e08732..70f711e86362 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -304,10 +304,8 @@ static void rt2400pci_config_intf(struct rt2x00_dev *rt2x00dev, conf->bssid, sizeof(conf->bssid)); } -static int rt2400pci_config_preamble(struct rt2x00_dev *rt2x00dev, - const int short_preamble, - const int ack_timeout, - const int ack_consume_time) +static int rt2400pci_config_erp(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_erp *erp) { int preamble_mask; u32 reg; @@ -315,11 +313,13 @@ static int rt2400pci_config_preamble(struct rt2x00_dev *rt2x00dev, /* * When short preamble is enabled, we should set bit 0x08 */ - preamble_mask = short_preamble << 3; + preamble_mask = erp->short_preamble << 3; rt2x00pci_register_read(rt2x00dev, TXCSR1, ®); - rt2x00_set_field32(®, TXCSR1_ACK_TIMEOUT, ack_timeout); - rt2x00_set_field32(®, TXCSR1_ACK_CONSUME_TIME, ack_consume_time); + rt2x00_set_field32(®, TXCSR1_ACK_TIMEOUT, + erp->ack_timeout); + rt2x00_set_field32(®, TXCSR1_ACK_CONSUME_TIME, + erp->ack_consume_time); rt2x00pci_register_write(rt2x00dev, TXCSR1, reg); rt2x00pci_register_read(rt2x00dev, ARCSR2, ®); @@ -1601,7 +1601,7 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { .kick_tx_queue = rt2400pci_kick_tx_queue, .fill_rxdone = rt2400pci_fill_rxdone, .config_intf = rt2400pci_config_intf, - .config_preamble = rt2400pci_config_preamble, + .config_erp = rt2400pci_config_erp, .config = rt2400pci_config, }; diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index d85e1a44d5cd..a46206c69760 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -307,10 +307,8 @@ static void rt2500pci_config_intf(struct rt2x00_dev *rt2x00dev, conf->bssid, sizeof(conf->bssid)); } -static int rt2500pci_config_preamble(struct rt2x00_dev *rt2x00dev, - const int short_preamble, - const int ack_timeout, - const int ack_consume_time) +static int rt2500pci_config_erp(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_erp *erp) { int preamble_mask; u32 reg; @@ -318,11 +316,13 @@ static int rt2500pci_config_preamble(struct rt2x00_dev *rt2x00dev, /* * When short preamble is enabled, we should set bit 0x08 */ - preamble_mask = short_preamble << 3; + preamble_mask = erp->short_preamble << 3; rt2x00pci_register_read(rt2x00dev, TXCSR1, ®); - rt2x00_set_field32(®, TXCSR1_ACK_TIMEOUT, ack_timeout); - rt2x00_set_field32(®, TXCSR1_ACK_CONSUME_TIME, ack_consume_time); + rt2x00_set_field32(®, TXCSR1_ACK_TIMEOUT, + erp->ack_timeout); + rt2x00_set_field32(®, TXCSR1_ACK_CONSUME_TIME, + erp->ack_consume_time); rt2x00pci_register_write(rt2x00dev, TXCSR1, reg); rt2x00pci_register_read(rt2x00dev, ARCSR2, ®); @@ -1911,7 +1911,7 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = { .kick_tx_queue = rt2500pci_kick_tx_queue, .fill_rxdone = rt2500pci_fill_rxdone, .config_intf = rt2500pci_config_intf, - .config_preamble = rt2500pci_config_preamble, + .config_erp = rt2500pci_config_erp, .config = rt2500pci_config, }; diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 7ea4247442b3..43da93a22e77 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -356,10 +356,8 @@ static void rt2500usb_config_intf(struct rt2x00_dev *rt2x00dev, (3 * sizeof(__le16))); } -static int rt2500usb_config_preamble(struct rt2x00_dev *rt2x00dev, - const int short_preamble, - const int ack_timeout, - const int ack_consume_time) +static int rt2500usb_config_erp(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_erp *erp) { u16 reg; @@ -371,12 +369,12 @@ static int rt2500usb_config_preamble(struct rt2x00_dev *rt2x00dev, return -EAGAIN; rt2500usb_register_read(rt2x00dev, TXRX_CSR1, ®); - rt2x00_set_field16(®, TXRX_CSR1_ACK_TIMEOUT, ack_timeout); + rt2x00_set_field16(®, TXRX_CSR1_ACK_TIMEOUT, erp->ack_timeout); rt2500usb_register_write(rt2x00dev, TXRX_CSR1, reg); rt2500usb_register_read(rt2x00dev, TXRX_CSR10, ®); rt2x00_set_field16(®, TXRX_CSR10_AUTORESPOND_PREAMBLE, - !!short_preamble); + !!erp->short_preamble); rt2500usb_register_write(rt2x00dev, TXRX_CSR10, reg); return 0; @@ -1842,7 +1840,7 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { .kick_tx_queue = rt2500usb_kick_tx_queue, .fill_rxdone = rt2500usb_fill_rxdone, .config_intf = rt2500usb_config_intf, - .config_preamble = rt2500usb_config_preamble, + .config_erp = rt2500usb_config_erp, .config = rt2500usb_config, }; diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 8718ad3dcc00..a324ff3ed7e7 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -384,7 +384,7 @@ struct rt2x00_intf { */ unsigned int delayed_flags; #define DELAYED_UPDATE_BEACON 0x00000001 -#define DELAYED_CONFIG_PREAMBLE 0x00000002 +#define DELAYED_CONFIG_ERP 0x00000002 }; static inline struct rt2x00_intf* vif_to_intf(struct ieee80211_vif *vif) @@ -450,6 +450,16 @@ struct rt2x00lib_conf { short eifs; }; +/* + * Configuration structure for erp settings. + */ +struct rt2x00lib_erp { + int short_preamble; + + int ack_timeout; + int ack_consume_time; +}; + /* * Configuration structure wrapper around the * rt2x00 interface configuration handler. @@ -558,10 +568,8 @@ struct rt2x00lib_ops { #define CONFIG_UPDATE_MAC ( 1 << 2 ) #define CONFIG_UPDATE_BSSID ( 1 << 3 ) - int (*config_preamble) (struct rt2x00_dev *rt2x00dev, - const int short_preamble, - const int ack_timeout, - const int ack_consume_time); + int (*config_erp) (struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_erp *erp); void (*config) (struct rt2x00_dev *rt2x00dev, struct rt2x00lib_conf *libconf, const unsigned int flags); diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index 69959124d25d..72111694154e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -75,43 +75,40 @@ void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev, rt2x00dev->ops->lib->config_intf(rt2x00dev, intf, &conf, flags); } -void rt2x00lib_config_preamble(struct rt2x00_dev *rt2x00dev, - struct rt2x00_intf *intf, - const unsigned int short_preamble) +void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev, + struct rt2x00_intf *intf, + struct ieee80211_bss_conf *bss_conf) { + struct rt2x00lib_erp erp; int retval; - int ack_timeout; - int ack_consume_time; - ack_timeout = PLCP + get_duration(ACK_SIZE, 10); - ack_consume_time = SIFS + PLCP + get_duration(ACK_SIZE, 10); + memset(&erp, 0, sizeof(erp)); + + erp.short_preamble = bss_conf->use_short_preamble; + erp.ack_timeout = PLCP + get_duration(ACK_SIZE, 10); + erp.ack_consume_time = SIFS + PLCP + get_duration(ACK_SIZE, 10); if (rt2x00dev->hw->conf.flags & IEEE80211_CONF_SHORT_SLOT_TIME) - ack_timeout += SHORT_DIFS; + erp.ack_timeout += SHORT_DIFS; else - ack_timeout += DIFS; + erp.ack_timeout += DIFS; - if (short_preamble) { - ack_timeout += SHORT_PREAMBLE; - ack_consume_time += SHORT_PREAMBLE; + if (bss_conf->use_short_preamble) { + erp.ack_timeout += SHORT_PREAMBLE; + erp.ack_consume_time += SHORT_PREAMBLE; } else { - ack_timeout += PREAMBLE; - ack_consume_time += PREAMBLE; + erp.ack_timeout += PREAMBLE; + erp.ack_consume_time += PREAMBLE; } - retval = rt2x00dev->ops->lib->config_preamble(rt2x00dev, - short_preamble, - ack_timeout, - ack_consume_time); - - spin_lock(&intf->lock); + retval = rt2x00dev->ops->lib->config_erp(rt2x00dev, &erp); if (retval) { - intf->delayed_flags |= DELAYED_CONFIG_PREAMBLE; + spin_lock(&intf->lock); + intf->delayed_flags |= DELAYED_CONFIG_ERP; queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->intf_work); + spin_unlock(&intf->lock); } - - spin_unlock(&intf->lock); } void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 455d0763503e..d6b12789ba77 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -447,9 +447,8 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac, } } - if (delayed_flags & DELAYED_CONFIG_PREAMBLE) - rt2x00lib_config_preamble(rt2x00dev, intf, - intf->conf.use_short_preamble); + if (delayed_flags & DELAYED_CONFIG_ERP) + rt2x00lib_config_erp(rt2x00dev, intf, &intf->conf); } static void rt2x00lib_intf_scheduled(struct work_struct *work) diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index 34ccb3de687e..6bd5a01ddfce 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -100,9 +100,9 @@ void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf, enum ieee80211_if_types type, u8 *mac, u8 *bssid); -void rt2x00lib_config_preamble(struct rt2x00_dev *rt2x00dev, - struct rt2x00_intf *intf, - const unsigned int short_preamble); +void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev, + struct rt2x00_intf *intf, + struct ieee80211_bss_conf *conf); void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, enum antenna rx, enum antenna tx); void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 76a2a7c118b2..0a11c27d603b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -436,17 +436,15 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, } /* - * When the preamble mode has changed, we should perform additional - * configuration steps. For all other changes we are already done. + * When the erp information has changed, we should perform + * additional configuration steps. For all other changes we are done. */ - if (changes & BSS_CHANGED_ERP_PREAMBLE) { - rt2x00lib_config_preamble(rt2x00dev, intf, - bss_conf->use_short_preamble); + if (changes & BSS_CHANGED_ERP_PREAMBLE) + rt2x00lib_config_erp(rt2x00dev, intf, bss_conf); - spin_lock(&intf->lock); - memcpy(&intf->conf, bss_conf, sizeof(*bss_conf)); - spin_unlock(&intf->lock); - } + spin_lock(&intf->lock); + memcpy(&intf->conf, bss_conf, sizeof(*bss_conf)); + spin_unlock(&intf->lock); } EXPORT_SYMBOL_GPL(rt2x00mac_bss_info_changed); diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index f912a8515b5c..99f18d4ae855 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -366,20 +366,18 @@ static void rt61pci_config_intf(struct rt2x00_dev *rt2x00dev, } } -static int rt61pci_config_preamble(struct rt2x00_dev *rt2x00dev, - const int short_preamble, - const int ack_timeout, - const int ack_consume_time) +static int rt61pci_config_erp(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_erp *erp) { u32 reg; rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, ®); - rt2x00_set_field32(®, TXRX_CSR0_RX_ACK_TIMEOUT, ack_timeout); + rt2x00_set_field32(®, TXRX_CSR0_RX_ACK_TIMEOUT, erp->ack_timeout); rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg); rt2x00pci_register_read(rt2x00dev, TXRX_CSR4, ®); rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_PREAMBLE, - !!short_preamble); + !!erp->short_preamble); rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg); return 0; @@ -2481,7 +2479,7 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { .kick_tx_queue = rt61pci_kick_tx_queue, .fill_rxdone = rt61pci_fill_rxdone, .config_intf = rt61pci_config_intf, - .config_preamble = rt61pci_config_preamble, + .config_erp = rt61pci_config_erp, .config = rt61pci_config, }; diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index d0e97e1dfaf6..ddb59c037750 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -378,10 +378,8 @@ static void rt73usb_config_intf(struct rt2x00_dev *rt2x00dev, } } -static int rt73usb_config_preamble(struct rt2x00_dev *rt2x00dev, - const int short_preamble, - const int ack_timeout, - const int ack_consume_time) +static int rt73usb_config_erp(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_erp *erp) { u32 reg; @@ -393,12 +391,12 @@ static int rt73usb_config_preamble(struct rt2x00_dev *rt2x00dev, return -EAGAIN; rt73usb_register_read(rt2x00dev, TXRX_CSR0, ®); - rt2x00_set_field32(®, TXRX_CSR0_RX_ACK_TIMEOUT, ack_timeout); + rt2x00_set_field32(®, TXRX_CSR0_RX_ACK_TIMEOUT, erp->ack_timeout); rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg); rt73usb_register_read(rt2x00dev, TXRX_CSR4, ®); rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_PREAMBLE, - !!short_preamble); + !!erp->short_preamble); rt73usb_register_write(rt2x00dev, TXRX_CSR4, reg); return 0; @@ -2090,7 +2088,7 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { .kick_tx_queue = rt73usb_kick_tx_queue, .fill_rxdone = rt73usb_fill_rxdone, .config_intf = rt73usb_config_intf, - .config_preamble = rt73usb_config_preamble, + .config_erp = rt73usb_config_erp, .config = rt73usb_config, }; -- cgit v1.2.1 From 72fa559bf44aab30ac5fc8317472ef3441f4aa64 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 9 Mar 2008 22:47:08 +0100 Subject: rt2x00: Make rt2x00leds_register return void rt2x00dev isn't interested in the rt2x00leds_register() value anyway. So lets make it return void to even prevent people from assuming there is anybody interested in the returnvalue. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00leds.c | 7 +++---- drivers/net/wireless/rt2x00/rt2x00lib.h | 5 ++--- 2 files changed, 5 insertions(+), 7 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2x00leds.c b/drivers/net/wireless/rt2x00/rt2x00leds.c index 9c29d17e0cc2..ca2d282a9f75 100644 --- a/drivers/net/wireless/rt2x00/rt2x00leds.c +++ b/drivers/net/wireless/rt2x00/rt2x00leds.c @@ -109,7 +109,7 @@ static int rt2x00leds_register_led(struct rt2x00_dev *rt2x00dev, return 0; } -int rt2x00leds_register(struct rt2x00_dev *rt2x00dev) +void rt2x00leds_register(struct rt2x00_dev *rt2x00dev) { char *trigger; char dev_name[16]; @@ -117,7 +117,7 @@ int rt2x00leds_register(struct rt2x00_dev *rt2x00dev) int retval; if (!rt2x00dev->ops->lib->led_brightness) - return 0; + return; snprintf(dev_name, sizeof(dev_name), "%s-%s", rt2x00dev->ops->name, wiphy_name(rt2x00dev->hw->wiphy)); @@ -161,11 +161,10 @@ int rt2x00leds_register(struct rt2x00_dev *rt2x00dev) goto exit_fail; } - return 0; + return; exit_fail: rt2x00leds_unregister(rt2x00dev); - return retval; } static void rt2x00leds_unregister_trigger(struct rt2x00_trigger *trigger) diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index 6bd5a01ddfce..a15227d2fe40 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -189,7 +189,7 @@ static inline void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev) */ #ifdef CONFIG_RT2X00_LIB_LEDS void rt2x00leds_led_quality(struct rt2x00_dev *rt2x00dev, int rssi); -int rt2x00leds_register(struct rt2x00_dev *rt2x00dev); +void rt2x00leds_register(struct rt2x00_dev *rt2x00dev); void rt2x00leds_unregister(struct rt2x00_dev *rt2x00dev); void rt2x00leds_suspend(struct rt2x00_dev *rt2x00dev); void rt2x00leds_resume(struct rt2x00_dev *rt2x00dev); @@ -199,9 +199,8 @@ static inline void rt2x00leds_led_quality(struct rt2x00_dev *rt2x00dev, { } -static inline int rt2x00leds_register(struct rt2x00_dev *rt2x00dev) +static inline void rt2x00leds_register(struct rt2x00_dev *rt2x00dev) { - return 0; } static inline void rt2x00leds_unregister(struct rt2x00_dev *rt2x00dev) -- cgit v1.2.1 From fd3c91c5e57eef8db71cf52e2473832c330bf5db Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 9 Mar 2008 22:47:43 +0100 Subject: rt2x00: Always enable TSF ticking Whatever mode we are in, according to the legacy drivers we should always enable TSF ticking/counting. We should also always enable the TBCN/TBTT field, this field is only disabled during beacon regeneration. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 2 ++ drivers/net/wireless/rt2x00/rt2500pci.c | 2 ++ drivers/net/wireless/rt2x00/rt2500usb.c | 2 ++ drivers/net/wireless/rt2x00/rt61pci.c | 2 ++ drivers/net/wireless/rt2x00/rt73usb.c | 2 ++ 5 files changed, 10 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 70f711e86362..e2bb63496dbc 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -291,7 +291,9 @@ static void rt2400pci_config_intf(struct rt2x00_dev *rt2x00dev, * Enable synchronisation. */ rt2x00pci_register_read(rt2x00dev, CSR14, ®); + rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); rt2x00_set_field32(®, CSR14_TSF_SYNC, conf->sync); + rt2x00_set_field32(®, CSR14_TBCN, 1); rt2x00pci_register_write(rt2x00dev, CSR14, reg); } diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index a46206c69760..4e312cb0ff0b 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -294,7 +294,9 @@ static void rt2500pci_config_intf(struct rt2x00_dev *rt2x00dev, * Enable synchronisation. */ rt2x00pci_register_read(rt2x00dev, CSR14, ®); + rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); rt2x00_set_field32(®, CSR14_TSF_SYNC, conf->sync); + rt2x00_set_field32(®, CSR14_TBCN, 1); rt2x00pci_register_write(rt2x00dev, CSR14, reg); } diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 43da93a22e77..8dfebfd695de 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -343,7 +343,9 @@ static void rt2500usb_config_intf(struct rt2x00_dev *rt2x00dev, rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg); rt2500usb_register_read(rt2x00dev, TXRX_CSR19, ®); + rt2x00_set_field16(®, TXRX_CSR19_TSF_COUNT, 1); rt2x00_set_field16(®, TXRX_CSR19_TSF_SYNC, conf->sync); + rt2x00_set_field16(®, TXRX_CSR19_TBCN, 1); rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); } diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 99f18d4ae855..914aee0ce8ce 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -343,7 +343,9 @@ static void rt61pci_config_intf(struct rt2x00_dev *rt2x00dev, * Enable synchronisation. */ rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); + rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, conf->sync); + rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1); rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); } diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index ddb59c037750..fc38c0c5cc3a 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -355,7 +355,9 @@ static void rt73usb_config_intf(struct rt2x00_dev *rt2x00dev, * Enable synchronisation. */ rt73usb_register_read(rt2x00dev, TXRX_CSR9, ®); + rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, conf->sync); + rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1); rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg); } -- cgit v1.2.1 From aa776721b472e343a8db7f3c0673b1fa24e6c7f7 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 9 Mar 2008 22:48:08 +0100 Subject: rt2x00: Fix basic rate initialization The basic rate which is configured in the register should not match all supported rates, but only the _basic_ rates. Fix this by adding a new flag to the rt2x00_rate structure and whenever the mode is changed, loop over all available rates for that band to get the basic rate mask. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00.h | 4 ++-- drivers/net/wireless/rt2x00/rt2x00config.c | 19 ++++++++++++--- drivers/net/wireless/rt2x00/rt2x00dev.c | 38 +++++++++++++++--------------- drivers/net/wireless/rt2x00/rt2x00lib.h | 14 +---------- 4 files changed, 38 insertions(+), 37 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index a324ff3ed7e7..ea2786ce1cf5 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -441,8 +441,8 @@ struct rt2x00lib_conf { enum ieee80211_band band; - int basic_rates; - int slot_time; + u32 basic_rates; + u32 slot_time; short sifs; short pifs; diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index 72111694154e..5e2d81a9e438 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -145,12 +145,26 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON_LINK); } +static u32 rt2x00lib_get_basic_rates(struct ieee80211_supported_band *band) +{ + const struct rt2x00_rate *rate; + unsigned int i; + u32 mask = 0; + + for (i = 0; i < band->n_bitrates; i++) { + rate = rt2x00_get_rate(band->bitrates[i].hw_value); + if (rate->flags & DEV_RATE_BASIC) + mask |= rate->ratemask; + } + + return mask; +} + void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, struct ieee80211_conf *conf, const int force_config) { struct rt2x00lib_conf libconf; struct ieee80211_supported_band *band; - struct ieee80211_rate *rate; struct antenna_setup *default_ant = &rt2x00dev->default_ant; struct antenna_setup *active_ant = &rt2x00dev->link.ant.active; int flags = 0; @@ -227,10 +241,9 @@ config: if (flags & CONFIG_UPDATE_PHYMODE) { band = &rt2x00dev->bands[conf->channel->band]; - rate = &band->bitrates[band->n_bitrates - 1]; libconf.band = conf->channel->band; - libconf.basic_rates = rt2x00_get_rate(rate->hw_value)->ratemask; + libconf.basic_rates = rt2x00lib_get_basic_rates(band); } if (flags & CONFIG_UPDATE_CHANNEL) { diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index d6b12789ba77..eb2d21c4e8e9 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -766,75 +766,75 @@ EXPORT_SYMBOL_GPL(rt2x00lib_write_tx_desc); */ const struct rt2x00_rate rt2x00_supported_rates[12] = { { - .flags = DEV_RATE_CCK, + .flags = DEV_RATE_CCK | DEV_RATE_BASIC, .bitrate = 10, - .ratemask = DEV_RATEMASK_1MB, + .ratemask = BIT(0), .plcp = 0x00, }, { - .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE, + .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE | DEV_RATE_BASIC, .bitrate = 20, - .ratemask = DEV_RATEMASK_2MB, + .ratemask = BIT(1), .plcp = 0x01, }, { - .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE, + .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE | DEV_RATE_BASIC, .bitrate = 55, - .ratemask = DEV_RATEMASK_5_5MB, + .ratemask = BIT(2), .plcp = 0x02, }, { - .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE, + .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE | DEV_RATE_BASIC, .bitrate = 110, - .ratemask = DEV_RATEMASK_11MB, + .ratemask = BIT(3), .plcp = 0x03, }, { - .flags = DEV_RATE_OFDM, + .flags = DEV_RATE_OFDM | DEV_RATE_BASIC, .bitrate = 60, - .ratemask = DEV_RATEMASK_6MB, + .ratemask = BIT(4), .plcp = 0x0b, }, { .flags = DEV_RATE_OFDM, .bitrate = 90, - .ratemask = DEV_RATEMASK_9MB, + .ratemask = BIT(5), .plcp = 0x0f, }, { - .flags = DEV_RATE_OFDM, + .flags = DEV_RATE_OFDM | DEV_RATE_BASIC, .bitrate = 120, - .ratemask = DEV_RATEMASK_12MB, + .ratemask = BIT(6), .plcp = 0x0a, }, { .flags = DEV_RATE_OFDM, .bitrate = 180, - .ratemask = DEV_RATEMASK_18MB, + .ratemask = BIT(7), .plcp = 0x0e, }, { - .flags = DEV_RATE_OFDM, + .flags = DEV_RATE_OFDM | DEV_RATE_BASIC, .bitrate = 240, - .ratemask = DEV_RATEMASK_24MB, + .ratemask = BIT(8), .plcp = 0x09, }, { .flags = DEV_RATE_OFDM, .bitrate = 360, - .ratemask = DEV_RATEMASK_36MB, + .ratemask = BIT(9), .plcp = 0x0d, }, { .flags = DEV_RATE_OFDM, .bitrate = 480, - .ratemask = DEV_RATEMASK_48MB, + .ratemask = BIT(10), .plcp = 0x08, }, { .flags = DEV_RATE_OFDM, .bitrate = 540, - .ratemask = DEV_RATEMASK_54MB, + .ratemask = BIT(11), .plcp = 0x0c, }, }; diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index a15227d2fe40..e4b4dd23d611 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -41,22 +41,10 @@ struct rt2x00_rate { #define DEV_RATE_CCK 0x0001 #define DEV_RATE_OFDM 0x0002 #define DEV_RATE_SHORT_PREAMBLE 0x0004 +#define DEV_RATE_BASIC 0x0008 unsigned short bitrate; /* In 100kbit/s */ - unsigned short ratemask; -#define DEV_RATEMASK_1MB ( (1 << 1) - 1 ) -#define DEV_RATEMASK_2MB ( (1 << 2) - 1 ) -#define DEV_RATEMASK_5_5MB ( (1 << 3) - 1 ) -#define DEV_RATEMASK_11MB ( (1 << 4) - 1 ) -#define DEV_RATEMASK_6MB ( (1 << 5) - 1 ) -#define DEV_RATEMASK_9MB ( (1 << 6) - 1 ) -#define DEV_RATEMASK_12MB ( (1 << 7) - 1 ) -#define DEV_RATEMASK_18MB ( (1 << 8) - 1 ) -#define DEV_RATEMASK_24MB ( (1 << 9) - 1 ) -#define DEV_RATEMASK_36MB ( (1 << 10) - 1 ) -#define DEV_RATEMASK_48MB ( (1 << 11) - 1 ) -#define DEV_RATEMASK_54MB ( (1 << 12) - 1 ) unsigned short plcp; }; -- cgit v1.2.1 From dac37d720860bbbc535adc90249184308501c1f0 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 9 Mar 2008 22:48:46 +0100 Subject: rt2x00: Fix RX DMA ring initialization Due to a terrible typo the RX DMA base address was initialized to the beacon base address. Obviously bad things happen with bugs like that.... Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 2 +- drivers/net/wireless/rt2x00/rt2500pci.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index e2bb63496dbc..a92626bc536a 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -669,7 +669,7 @@ static int rt2400pci_init_queues(struct rt2x00_dev *rt2x00dev) priv_rx = rt2x00dev->rx->entries[0].priv_data; rt2x00pci_register_read(rt2x00dev, RXCSR2, ®); - rt2x00_set_field32(®, RXCSR2_RX_RING_REGISTER, priv_tx->desc_dma); + rt2x00_set_field32(®, RXCSR2_RX_RING_REGISTER, priv_rx->desc_dma); rt2x00pci_register_write(rt2x00dev, RXCSR2, reg); return 0; diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 4e312cb0ff0b..4ae09b418704 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -751,7 +751,7 @@ static int rt2500pci_init_queues(struct rt2x00_dev *rt2x00dev) priv_rx = rt2x00dev->rx->entries[0].priv_data; rt2x00pci_register_read(rt2x00dev, RXCSR2, ®); - rt2x00_set_field32(®, RXCSR2_RX_RING_REGISTER, priv_tx->desc_dma); + rt2x00_set_field32(®, RXCSR2_RX_RING_REGISTER, priv_rx->desc_dma); rt2x00pci_register_write(rt2x00dev, RXCSR2, reg); return 0; -- cgit v1.2.1 From 89993890aeb8fe58b2d49b2661965524802ab73c Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 9 Mar 2008 22:49:04 +0100 Subject: rt2x00: Fix rt2400pci signal After sampling hundreds of RX frame descriptors, the results were conclusive: - The Ralink documentation regarding the SIGNAL and RSSI are wrong. It turns out that of the 5 BBR registers, we should not use BBR0 and BBR1 for SIGNAL and RSSI respectively, but actually BBR1 and BBR2. BBR0 does show values, but the exact meaning remains unclear, but they cannot be translated into a SIGNAL or RSSI field. BBR3, BBR4 and BBR5 are always 0, so their meaning is unknown. As it turns out, the reported SIGNAL is the PLCP value, this in contradiction to what was expected looking at rt2500pci which only reported the PLCP values for OFDM rates and bitrate values for CCK rates. This means we should let the driver raise the flag about the contents of the SIGNAL field so rt2x00lib can always do the right thing based on what the driver reports. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 6 +++++- drivers/net/wireless/rt2x00/rt2400pci.h | 6 +++--- drivers/net/wireless/rt2x00/rt2500pci.c | 9 ++++++++- drivers/net/wireless/rt2x00/rt2500usb.c | 6 +++++- drivers/net/wireless/rt2x00/rt2x00dev.c | 16 +++++++++------- drivers/net/wireless/rt2x00/rt2x00queue.h | 3 +++ drivers/net/wireless/rt2x00/rt61pci.c | 6 +++++- drivers/net/wireless/rt2x00/rt73usb.c | 6 +++++- 8 files changed, 43 insertions(+), 15 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index a92626bc536a..4cd284209d16 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1058,9 +1058,11 @@ static void rt2400pci_fill_rxdone(struct queue_entry *entry, struct queue_entry_priv_pci_rx *priv_rx = entry->priv_data; u32 word0; u32 word2; + u32 word3; rt2x00_desc_read(priv_rx->desc, 0, &word0); rt2x00_desc_read(priv_rx->desc, 2, &word2); + rt2x00_desc_read(priv_rx->desc, 3, &word3); rxdesc->flags = 0; if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR)) @@ -1070,9 +1072,11 @@ static void rt2400pci_fill_rxdone(struct queue_entry *entry, /* * Obtain the status about this packet. + * The signal is the PLCP value. */ rxdesc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL); - rxdesc->rssi = rt2x00_get_field32(word2, RXD_W2_RSSI) - + rxdesc->signal_plcp = 1; + rxdesc->rssi = rt2x00_get_field32(word2, RXD_W3_RSSI) - entry->queue->rt2x00dev->rssi_offset; rxdesc->ofdm = 0; rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); diff --git a/drivers/net/wireless/rt2x00/rt2400pci.h b/drivers/net/wireless/rt2x00/rt2400pci.h index da178d44660e..a5210f9a3360 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.h +++ b/drivers/net/wireless/rt2x00/rt2400pci.h @@ -899,13 +899,13 @@ * Word2 */ #define RXD_W2_BUFFER_LENGTH FIELD32(0x0000ffff) -#define RXD_W2_SIGNAL FIELD32(0x00ff0000) -#define RXD_W2_RSSI FIELD32(0xff000000) +#define RXD_W2_BBR0 FIELD32(0x00ff0000) +#define RXD_W2_SIGNAL FIELD32(0xff000000) /* * Word3 */ -#define RXD_W3_BBR2 FIELD32(0x000000ff) +#define RXD_W3_RSSI FIELD32(0x000000ff) #define RXD_W3_BBR3 FIELD32(0x0000ff00) #define RXD_W3_BBR4 FIELD32(0x00ff0000) #define RXD_W3_BBR5 FIELD32(0xff000000) diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 4ae09b418704..0f5139a2f238 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1219,10 +1219,17 @@ static void rt2500pci_fill_rxdone(struct queue_entry *entry, if (rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR)) rxdesc->flags |= RX_FLAG_FAILED_PLCP_CRC; + /* + * Obtain the status about this packet. + * When frame was received with an OFDM bitrate, + * the signal is the PLCP value. If it was received with + * a CCK bitrate the signal is the rate in 100kbit/s. + */ + rxdesc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM); rxdesc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL); + rxdesc->signal_plcp = rxdesc->ofdm; rxdesc->rssi = rt2x00_get_field32(word2, RXD_W2_RSSI) - entry->queue->rt2x00dev->rssi_offset; - rxdesc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM); rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); rxdesc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS); } diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 8dfebfd695de..c8216d755835 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1135,11 +1135,15 @@ static void rt2500usb_fill_rxdone(struct queue_entry *entry, /* * Obtain the status about this packet. + * When frame was received with an OFDM bitrate, + * the signal is the PLCP value. If it was received with + * a CCK bitrate the signal is the rate in 100kbit/s. */ + rxdesc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM); rxdesc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL); + rxdesc->signal_plcp = rxdesc->ofdm; rxdesc->rssi = rt2x00_get_field32(word1, RXD_W1_RSSI) - entry->queue->rt2x00dev->rssi_offset; - rxdesc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM); rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); rxdesc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS); diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index eb2d21c4e8e9..a885254d2e85 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -573,6 +573,13 @@ void rt2x00lib_rxdone(struct queue_entry *entry, int idx = -1; u16 fc; + /* + * If the signal is the plcp value, + * we need to strip the preamble bit (0x08). + */ + if (rxdesc->signal_plcp) + rxdesc->signal &= ~0x08; + /* * Update RX statistics. */ @@ -580,13 +587,8 @@ void rt2x00lib_rxdone(struct queue_entry *entry, for (i = 0; i < sband->n_bitrates; i++) { rate = rt2x00_get_rate(sband->bitrates[i].hw_value); - /* - * When frame was received with an OFDM bitrate, - * the signal is the PLCP value. If it was received with - * a CCK bitrate the signal is the rate in 100kbit/s. - */ - if ((rxdesc->ofdm && rate->plcp == rxdesc->signal) || - (!rxdesc->ofdm && rate->bitrate == rxdesc->signal)) { + if ((rxdesc->signal_plcp && rate->plcp == rxdesc->signal) || + (!rxdesc->signal_plcp && rate->bitrate == rxdesc->signal)) { idx = i; break; } diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index fbabf389b622..c5f46f234083 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -134,6 +134,8 @@ static inline struct skb_frame_desc* get_skb_frame_desc(struct sk_buff *skb) * Summary of information that has been read from the RX frame descriptor. * * @signal: Signal of the received frame. + * @signal_plcp: Does the signal field contain the plcp value, + * or does it contain the bitrate itself. * @rssi: RSSI of the received frame. * @ofdm: Was frame send with an OFDM rate. * @size: Data size of the received frame. @@ -142,6 +144,7 @@ static inline struct skb_frame_desc* get_skb_frame_desc(struct sk_buff *skb) */ struct rxdone_entry_desc { int signal; + int signal_plcp; int rssi; int ofdm; int size; diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 914aee0ce8ce..4baa916b80cf 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -1645,10 +1645,14 @@ static void rt61pci_fill_rxdone(struct queue_entry *entry, /* * Obtain the status about this packet. + * When frame was received with an OFDM bitrate, + * the signal is the PLCP value. If it was received with + * a CCK bitrate the signal is the rate in 100kbit/s. */ + rxdesc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM); rxdesc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL); + rxdesc->signal_plcp = rxdesc->ofdm; rxdesc->rssi = rt61pci_agc_to_rssi(entry->queue->rt2x00dev, word1); - rxdesc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM); rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); rxdesc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS); } diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index fc38c0c5cc3a..48938819ee2f 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -1405,10 +1405,14 @@ static void rt73usb_fill_rxdone(struct queue_entry *entry, /* * Obtain the status about this packet. + * When frame was received with an OFDM bitrate, + * the signal is the PLCP value. If it was received with + * a CCK bitrate the signal is the rate in 100kbit/s. */ + rxdesc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM); rxdesc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL); + rxdesc->signal_plcp = rxdesc->ofdm; rxdesc->rssi = rt73usb_agc_to_rssi(entry->queue->rt2x00dev, word1); - rxdesc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM); rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); rxdesc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS); -- cgit v1.2.1 From f0e62e46c3cace185eed10ebf53ef060ba6d7bb1 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sun, 9 Mar 2008 22:49:21 +0100 Subject: rt2x00: Release rt2x00 2.1.4 Version bump to 2.1.4 Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index ea2786ce1cf5..dfd0af0e0a16 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -44,7 +44,7 @@ /* * Module information. */ -#define DRV_VERSION "2.1.3" +#define DRV_VERSION "2.1.4" #define DRV_PROJECT "http://rt2x00.serialmonkey.com" /* -- cgit v1.2.1 From 8ed09854073ae0a19556d4d93cf79cf368c23673 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 10 Mar 2008 00:30:44 +0100 Subject: rt2x00: Only strip preamble bit in rt2400pci Only rt2400pci can have the preamble bit set in the PLCP value, for all other drivers it should not be cleared since that will conflict with the plcp values for OFDM rates. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 5 +++-- drivers/net/wireless/rt2x00/rt2x00dev.c | 7 ------- 2 files changed, 3 insertions(+), 9 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 4cd284209d16..1f49561d3ddc 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1072,9 +1072,10 @@ static void rt2400pci_fill_rxdone(struct queue_entry *entry, /* * Obtain the status about this packet. - * The signal is the PLCP value. + * The signal is the PLCP value, and needs to be stripped + * of the preamble bit (0x08). */ - rxdesc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL); + rxdesc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL) & ~0x08; rxdesc->signal_plcp = 1; 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 a885254d2e85..b81efc9b058d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -573,13 +573,6 @@ void rt2x00lib_rxdone(struct queue_entry *entry, int idx = -1; u16 fc; - /* - * If the signal is the plcp value, - * we need to strip the preamble bit (0x08). - */ - if (rxdesc->signal_plcp) - rxdesc->signal &= ~0x08; - /* * Update RX statistics. */ -- cgit v1.2.1 From a4062b8fd231d2625236ad46bff07906c9bc7160 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Tue, 11 Mar 2008 16:17:16 -0700 Subject: iwlwifi: Use sta_bcast_id variable instead of BROADCAST_ID constant This patch removes iwlYYY_BROADCAST_ID from run time usage. hw_setting.sta_bcast_id is used instead. Signed-off-by: Tomas Winkler Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-4965.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 50a641c0c5b7..9a9918e5272b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -980,7 +980,7 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl3945_priv *priv, priv->stations[sta_id].current_rate.rate_n_flags = rate; if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) && - (sta_id != IWL3945_BROADCAST_ID) && + (sta_id != priv->hw_setting.bcast_sta_id) && (sta_id != IWL_MULTICAST_ID)) priv->stations[IWL_STA_ID].current_rate.rate_n_flags = rate; @@ -2595,7 +2595,7 @@ unsigned int iwl3945_hw_get_beacon_cmd(struct iwl3945_priv *priv, tx_beacon_cmd = (struct iwl3945_tx_beacon_cmd *)&frame->u; memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd)); - tx_beacon_cmd->tx.sta_id = IWL3945_BROADCAST_ID; + tx_beacon_cmd->tx.sta_id = priv->hw_setting.bcast_sta_id; tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; frame_size = iwl3945_fill_beacon_frame(priv, diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 2f01a490c9ee..1fe8cc4e74df 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -254,7 +254,7 @@ u8 iwl4965_hw_find_station(struct iwl4965_priv *priv, const u8 *addr) start = IWL_STA_ID; if (is_broadcast_ether_addr(addr)) - return IWL4965_BROADCAST_ID; + return priv->hw_setting.bcast_sta_id; spin_lock_irqsave(&priv->sta_lock, flags); for (i = start; i < priv->hw_setting.max_stations; i++) @@ -2836,7 +2836,7 @@ unsigned int iwl4965_hw_get_beacon_cmd(struct iwl4965_priv *priv, tx_beacon_cmd = &frame->u.beacon; memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd)); - tx_beacon_cmd->tx.sta_id = IWL4965_BROADCAST_ID; + tx_beacon_cmd->tx.sta_id = priv->hw_setting.bcast_sta_id; tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; frame_size = iwl4965_fill_beacon_frame(priv, @@ -4436,7 +4436,7 @@ void iwl4965_add_station(struct iwl4965_priv *priv, const u8 *addr, int is_ap) link_cmd.agg_params.agg_time_limit = cpu_to_le16(4000); /* Update the rate scaling for control frame Tx to AP */ - link_cmd.sta_id = is_ap ? IWL_AP_ID : IWL4965_BROADCAST_ID; + link_cmd.sta_id = is_ap ? IWL_AP_ID : priv->hw_setting.bcast_sta_id; iwl4965_send_cmd_pdu(priv, REPLY_TX_LINK_QUALITY_CMD, sizeof(link_cmd), &link_cmd); -- cgit v1.2.1 From eb7ae89cb0b03e6e6e39737b1c8bcc1912281a00 Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Tue, 11 Mar 2008 16:17:17 -0700 Subject: iwlwifi: update copyright year Also fix a copy and paste error in header of iwl-core.c. This file is not dual licensed. Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-commands.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-3945-debug.h | 2 +- drivers/net/wireless/iwlwifi/iwl-3945-hw.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-3945-io.h | 2 +- drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 2 +- drivers/net/wireless/iwlwifi/iwl-3945-rs.h | 2 +- drivers/net/wireless/iwlwifi/iwl-3945.c | 2 +- drivers/net/wireless/iwlwifi/iwl-3945.h | 2 +- drivers/net/wireless/iwlwifi/iwl-4965-commands.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-4965-debug.h | 2 +- drivers/net/wireless/iwlwifi/iwl-4965-hw.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-4965-io.h | 2 +- drivers/net/wireless/iwlwifi/iwl-4965-rs.c | 2 +- drivers/net/wireless/iwlwifi/iwl-4965-rs.h | 2 +- drivers/net/wireless/iwlwifi/iwl-4965.c | 2 +- drivers/net/wireless/iwlwifi/iwl-4965.h | 2 +- drivers/net/wireless/iwlwifi/iwl-core.c | 3 --- drivers/net/wireless/iwlwifi/iwl-csr.h | 2 +- drivers/net/wireless/iwlwifi/iwl-helpers.h | 2 +- drivers/net/wireless/iwlwifi/iwl-prph.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-spectrum.h | 2 +- drivers/net/wireless/iwlwifi/iwl3945-base.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl4965-base.c | 2 +- 23 files changed, 28 insertions(+), 31 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-commands.h b/drivers/net/wireless/iwlwifi/iwl-3945-commands.h index 8b7ef9f1b57b..824a6e532de7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-commands.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-debug.h b/drivers/net/wireless/iwlwifi/iwl-3945-debug.h index 28ecfe8d39a3..f1d002f7b790 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-debug.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project. * diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h index 7dc19136f41a..1ca6fa494e4b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-io.h b/drivers/net/wireless/iwlwifi/iwl-3945-io.h index 4a1872982027..0b9475114618 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-io.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project. * diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index 08604eb8291b..157e572ebc83 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.h b/drivers/net/wireless/iwlwifi/iwl-3945-rs.h index b082a093ee26..e88b1d31f56f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 9a9918e5272b..e116ed77c5ad 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 0ab22d366d93..931c465f9e5e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h index 327eabce182c..35f592dc40c6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-debug.h b/drivers/net/wireless/iwlwifi/iwl-4965-debug.h index baf07c715cf8..df329481bb45 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-debug.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project. * diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h index 24413a479a3f..4a29b44950a7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-io.h b/drivers/net/wireless/iwlwifi/iwl-4965-io.h index 4af0c0175da2..07fca8888f40 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-io.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project. * diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c index 25e73864c2a4..4b46226ff350 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.h b/drivers/net/wireless/iwlwifi/iwl-4965-rs.h index 911f21396fd0..ae827e1fb0fb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 1fe8cc4e74df..a79e8c383a39 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index 057fa15d62fd..6ce408137365 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 675b34b696b4..b8383c83f18d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1,7 +1,4 @@ /****************************************************************************** - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. * * GPL LICENSE SUMMARY * diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index 7016e5b41c58..f0a2c8d180f0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h index 736b88881b03..a443472bea62 100644 --- a/drivers/net/wireless/iwlwifi/iwl-helpers.h +++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index 4ba121634877..ecf651ae2593 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2008 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-spectrum.h b/drivers/net/wireless/iwlwifi/iwl-spectrum.h index b576ff24eb4f..a40a2174df98 100644 --- a/drivers/net/wireless/iwlwifi/iwl-spectrum.h +++ b/drivers/net/wireless/iwlwifi/iwl-spectrum.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ieee80211 subsystem header files. * diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index ecf749c2dc0a..bf3925fdb9be 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. @@ -93,7 +93,7 @@ int iwl3945_param_queues_num = IWL_MAX_NUM_QUEUES; /* def: 8 Tx queues */ #endif #define IWLWIFI_VERSION "1.2.26k" VD VS -#define DRV_COPYRIGHT "Copyright(c) 2003-2007 Intel Corporation" +#define DRV_COPYRIGHT "Copyright(c) 2003-2008 Intel Corporation" #define DRV_VERSION IWLWIFI_VERSION diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 28c64c39ef02..ce1c3f68fde0 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. -- cgit v1.2.1 From 6bc913bd965e03b5273a5366eecce5c28c9b01da Mon Sep 17 00:00:00 2001 From: Assaf Krauss Date: Tue, 11 Mar 2008 16:17:18 -0700 Subject: iwlwifi: Use eeprom form iwlcore This patch puts in use eeprom from iwlcore module Signed-off-by: Assaf Krauss Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/Makefile | 2 +- drivers/net/wireless/iwlwifi/iwl-4965-hw.h | 310 ---------------------------- drivers/net/wireless/iwlwifi/iwl-4965.c | 45 ++-- drivers/net/wireless/iwlwifi/iwl-4965.h | 4 +- drivers/net/wireless/iwlwifi/iwl-core.c | 1 + drivers/net/wireless/iwlwifi/iwl-core.h | 10 + drivers/net/wireless/iwlwifi/iwl4965-base.c | 84 +------- 7 files changed, 30 insertions(+), 426 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 6b85cca9b3f1..59d9c90d3610 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile @@ -1,5 +1,5 @@ obj-$(CONFIG_IWLCORE) += iwlcore.o -iwlcore-objs = iwl-core.o +iwlcore-objs = iwl-core.o iwl-eeprom.o obj-$(CONFIG_IWL3945) += iwl3945.o iwl3945-objs = iwl3945-base.o iwl-3945.o iwl-3945-rs.o diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h index 4a29b44950a7..c66993eb5b6a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h @@ -92,316 +92,6 @@ /* RSSI to dBm */ #define IWL_RSSI_OFFSET 44 -/* - * EEPROM related constants, enums, and structures. - */ - -/* - * EEPROM access time values: - * - * Driver initiates EEPROM read by writing byte address << 1 to CSR_EEPROM_REG, - * then clearing (with subsequent read/modify/write) CSR_EEPROM_REG bit - * CSR_EEPROM_REG_BIT_CMD (0x2). - * Driver then polls CSR_EEPROM_REG for CSR_EEPROM_REG_READ_VALID_MSK (0x1). - * When polling, wait 10 uSec between polling loops, up to a maximum 5000 uSec. - * Driver reads 16-bit value from bits 31-16 of CSR_EEPROM_REG. - */ -#define IWL_EEPROM_ACCESS_TIMEOUT 5000 /* uSec */ -#define IWL_EEPROM_ACCESS_DELAY 10 /* uSec */ - -/* - * Regulatory channel usage flags in EEPROM struct iwl4965_eeprom_channel.flags. - * - * IBSS and/or AP operation is allowed *only* on those channels with - * (VALID && IBSS && ACTIVE && !RADAR). This restriction is in place because - * RADAR detection is not supported by the 4965 driver, but is a - * requirement for establishing a new network for legal operation on channels - * requiring RADAR detection or restricting ACTIVE scanning. - * - * NOTE: "WIDE" flag does not indicate anything about "FAT" 40 MHz channels. - * It only indicates that 20 MHz channel use is supported; FAT channel - * usage is indicated by a separate set of regulatory flags for each - * FAT channel pair. - * - * NOTE: Using a channel inappropriately will result in a uCode error! - */ -enum { - EEPROM_CHANNEL_VALID = (1 << 0), /* usable for this SKU/geo */ - EEPROM_CHANNEL_IBSS = (1 << 1), /* usable as an IBSS channel */ - /* Bit 2 Reserved */ - EEPROM_CHANNEL_ACTIVE = (1 << 3), /* active scanning allowed */ - EEPROM_CHANNEL_RADAR = (1 << 4), /* radar detection required */ - EEPROM_CHANNEL_WIDE = (1 << 5), /* 20 MHz channel okay */ - EEPROM_CHANNEL_NARROW = (1 << 6), /* 10 MHz channel (not used) */ - EEPROM_CHANNEL_DFS = (1 << 7), /* dynamic freq selection candidate */ -}; - -/* SKU Capabilities */ -#define EEPROM_SKU_CAP_SW_RF_KILL_ENABLE (1 << 0) -#define EEPROM_SKU_CAP_HW_RF_KILL_ENABLE (1 << 1) - -/* *regulatory* channel data format in eeprom, one for each channel. - * There are separate entries for FAT (40 MHz) vs. normal (20 MHz) channels. */ -struct iwl4965_eeprom_channel { - u8 flags; /* EEPROM_CHANNEL_* flags copied from EEPROM */ - s8 max_power_avg; /* max power (dBm) on this chnl, limit 31 */ -} __attribute__ ((packed)); - -/* 4965 has two radio transmitters (and 3 radio receivers) */ -#define EEPROM_TX_POWER_TX_CHAINS (2) - -/* 4965 has room for up to 8 sets of txpower calibration data */ -#define EEPROM_TX_POWER_BANDS (8) - -/* 4965 factory calibration measures txpower gain settings for - * each of 3 target output levels */ -#define EEPROM_TX_POWER_MEASUREMENTS (3) - -/* 4965 driver does not work with txpower calibration version < 5. - * Look for this in calib_version member of struct iwl4965_eeprom. */ -#define EEPROM_TX_POWER_VERSION_NEW (5) - - -/* - * 4965 factory calibration data for one txpower level, on one channel, - * measured on one of the 2 tx chains (radio transmitter and associated - * antenna). EEPROM contains: - * - * 1) Temperature (degrees Celsius) of device when measurement was made. - * - * 2) Gain table index used to achieve the target measurement power. - * This refers to the "well-known" gain tables (see iwl-4965-hw.h). - * - * 3) Actual measured output power, in half-dBm ("34" = 17 dBm). - * - * 4) RF power amplifier detector level measurement (not used). - */ -struct iwl4965_eeprom_calib_measure { - u8 temperature; /* Device temperature (Celsius) */ - u8 gain_idx; /* Index into gain table */ - u8 actual_pow; /* Measured RF output power, half-dBm */ - s8 pa_det; /* Power amp detector level (not used) */ -} __attribute__ ((packed)); - - -/* - * 4965 measurement set for one channel. EEPROM contains: - * - * 1) Channel number measured - * - * 2) Measurements for each of 3 power levels for each of 2 radio transmitters - * (a.k.a. "tx chains") (6 measurements altogether) - */ -struct iwl4965_eeprom_calib_ch_info { - u8 ch_num; - struct iwl4965_eeprom_calib_measure measurements[EEPROM_TX_POWER_TX_CHAINS] - [EEPROM_TX_POWER_MEASUREMENTS]; -} __attribute__ ((packed)); - -/* - * 4965 txpower subband info. - * - * For each frequency subband, EEPROM contains the following: - * - * 1) First and last channels within range of the subband. "0" values - * indicate that this sample set is not being used. - * - * 2) Sample measurement sets for 2 channels close to the range endpoints. - */ -struct iwl4965_eeprom_calib_subband_info { - u8 ch_from; /* channel number of lowest channel in subband */ - u8 ch_to; /* channel number of highest channel in subband */ - struct iwl4965_eeprom_calib_ch_info ch1; - struct iwl4965_eeprom_calib_ch_info ch2; -} __attribute__ ((packed)); - - -/* - * 4965 txpower calibration info. EEPROM contains: - * - * 1) Factory-measured saturation power levels (maximum levels at which - * tx power amplifier can output a signal without too much distortion). - * There is one level for 2.4 GHz band and one for 5 GHz band. These - * values apply to all channels within each of the bands. - * - * 2) Factory-measured power supply voltage level. This is assumed to be - * constant (i.e. same value applies to all channels/bands) while the - * factory measurements are being made. - * - * 3) Up to 8 sets of factory-measured txpower calibration values. - * These are for different frequency ranges, since txpower gain - * characteristics of the analog radio circuitry vary with frequency. - * - * Not all sets need to be filled with data; - * struct iwl4965_eeprom_calib_subband_info contains range of channels - * (0 if unused) for each set of data. - */ -struct iwl4965_eeprom_calib_info { - u8 saturation_power24; /* half-dBm (e.g. "34" = 17 dBm) */ - u8 saturation_power52; /* half-dBm */ - s16 voltage; /* signed */ - struct iwl4965_eeprom_calib_subband_info band_info[EEPROM_TX_POWER_BANDS]; -} __attribute__ ((packed)); - - -/* - * 4965 EEPROM map - */ -struct iwl4965_eeprom { - u8 reserved0[16]; -#define EEPROM_DEVICE_ID (2*0x08) /* 2 bytes */ - u16 device_id; /* abs.ofs: 16 */ - u8 reserved1[2]; -#define EEPROM_PMC (2*0x0A) /* 2 bytes */ - u16 pmc; /* abs.ofs: 20 */ - u8 reserved2[20]; -#define EEPROM_MAC_ADDRESS (2*0x15) /* 6 bytes */ - u8 mac_address[6]; /* abs.ofs: 42 */ - u8 reserved3[58]; -#define EEPROM_BOARD_REVISION (2*0x35) /* 2 bytes */ - u16 board_revision; /* abs.ofs: 106 */ - u8 reserved4[11]; -#define EEPROM_BOARD_PBA_NUMBER (2*0x3B+1) /* 9 bytes */ - u8 board_pba_number[9]; /* abs.ofs: 119 */ - u8 reserved5[8]; -#define EEPROM_VERSION (2*0x44) /* 2 bytes */ - u16 version; /* abs.ofs: 136 */ -#define EEPROM_SKU_CAP (2*0x45) /* 1 bytes */ - u8 sku_cap; /* abs.ofs: 138 */ -#define EEPROM_LEDS_MODE (2*0x45+1) /* 1 bytes */ - u8 leds_mode; /* abs.ofs: 139 */ -#define EEPROM_OEM_MODE (2*0x46) /* 2 bytes */ - u16 oem_mode; -#define EEPROM_WOWLAN_MODE (2*0x47) /* 2 bytes */ - u16 wowlan_mode; /* abs.ofs: 142 */ -#define EEPROM_LEDS_TIME_INTERVAL (2*0x48) /* 2 bytes */ - u16 leds_time_interval; /* abs.ofs: 144 */ -#define EEPROM_LEDS_OFF_TIME (2*0x49) /* 1 bytes */ - u8 leds_off_time; /* abs.ofs: 146 */ -#define EEPROM_LEDS_ON_TIME (2*0x49+1) /* 1 bytes */ - u8 leds_on_time; /* abs.ofs: 147 */ -#define EEPROM_ALMGOR_M_VERSION (2*0x4A) /* 1 bytes */ - u8 almgor_m_version; /* abs.ofs: 148 */ -#define EEPROM_ANTENNA_SWITCH_TYPE (2*0x4A+1) /* 1 bytes */ - u8 antenna_switch_type; /* abs.ofs: 149 */ - u8 reserved6[8]; -#define EEPROM_4965_BOARD_REVISION (2*0x4F) /* 2 bytes */ - u16 board_revision_4965; /* abs.ofs: 158 */ - u8 reserved7[13]; -#define EEPROM_4965_BOARD_PBA (2*0x56+1) /* 9 bytes */ - u8 board_pba_number_4965[9]; /* abs.ofs: 173 */ - u8 reserved8[10]; -#define EEPROM_REGULATORY_SKU_ID (2*0x60) /* 4 bytes */ - u8 sku_id[4]; /* abs.ofs: 192 */ - -/* - * Per-channel regulatory data. - * - * Each channel that *might* be supported by 3945 or 4965 has a fixed location - * in EEPROM containing EEPROM_CHANNEL_* usage flags (LSB) and max regulatory - * txpower (MSB). - * - * Entries immediately below are for 20 MHz channel width. FAT (40 MHz) - * channels (only for 4965, not supported by 3945) appear later in the EEPROM. - * - * 2.4 GHz channels 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 - */ -#define EEPROM_REGULATORY_BAND_1 (2*0x62) /* 2 bytes */ - u16 band_1_count; /* abs.ofs: 196 */ -#define EEPROM_REGULATORY_BAND_1_CHANNELS (2*0x63) /* 28 bytes */ - struct iwl4965_eeprom_channel band_1_channels[14]; /* abs.ofs: 196 */ - -/* - * 4.9 GHz channels 183, 184, 185, 187, 188, 189, 192, 196, - * 5.0 GHz channels 7, 8, 11, 12, 16 - * (4915-5080MHz) (none of these is ever supported) - */ -#define EEPROM_REGULATORY_BAND_2 (2*0x71) /* 2 bytes */ - u16 band_2_count; /* abs.ofs: 226 */ -#define EEPROM_REGULATORY_BAND_2_CHANNELS (2*0x72) /* 26 bytes */ - struct iwl4965_eeprom_channel band_2_channels[13]; /* abs.ofs: 228 */ - -/* - * 5.2 GHz channels 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64 - * (5170-5320MHz) - */ -#define EEPROM_REGULATORY_BAND_3 (2*0x7F) /* 2 bytes */ - u16 band_3_count; /* abs.ofs: 254 */ -#define EEPROM_REGULATORY_BAND_3_CHANNELS (2*0x80) /* 24 bytes */ - struct iwl4965_eeprom_channel band_3_channels[12]; /* abs.ofs: 256 */ - -/* - * 5.5 GHz channels 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 - * (5500-5700MHz) - */ -#define EEPROM_REGULATORY_BAND_4 (2*0x8C) /* 2 bytes */ - u16 band_4_count; /* abs.ofs: 280 */ -#define EEPROM_REGULATORY_BAND_4_CHANNELS (2*0x8D) /* 22 bytes */ - struct iwl4965_eeprom_channel band_4_channels[11]; /* abs.ofs: 282 */ - -/* - * 5.7 GHz channels 145, 149, 153, 157, 161, 165 - * (5725-5825MHz) - */ -#define EEPROM_REGULATORY_BAND_5 (2*0x98) /* 2 bytes */ - u16 band_5_count; /* abs.ofs: 304 */ -#define EEPROM_REGULATORY_BAND_5_CHANNELS (2*0x99) /* 12 bytes */ - struct iwl4965_eeprom_channel band_5_channels[6]; /* abs.ofs: 306 */ - - u8 reserved10[2]; - - -/* - * 2.4 GHz FAT channels 1 (5), 2 (6), 3 (7), 4 (8), 5 (9), 6 (10), 7 (11) - * - * The channel listed is the center of the lower 20 MHz half of the channel. - * The overall center frequency is actually 2 channels (10 MHz) above that, - * and the upper half of each FAT channel is centered 4 channels (20 MHz) away - * from the lower half; e.g. the upper half of FAT channel 1 is channel 5, - * and the overall FAT channel width centers on channel 3. - * - * NOTE: The RXON command uses 20 MHz channel numbers to specify the - * control channel to which to tune. RXON also specifies whether the - * control channel is the upper or lower half of a FAT channel. - * - * NOTE: 4965 does not support FAT channels on 2.4 GHz. - */ -#define EEPROM_REGULATORY_BAND_24_FAT_CHANNELS (2*0xA0) /* 14 bytes */ - struct iwl4965_eeprom_channel band_24_channels[7]; /* abs.ofs: 320 */ - u8 reserved11[2]; - -/* - * 5.2 GHz FAT channels 36 (40), 44 (48), 52 (56), 60 (64), - * 100 (104), 108 (112), 116 (120), 124 (128), 132 (136), 149 (153), 157 (161) - */ -#define EEPROM_REGULATORY_BAND_52_FAT_CHANNELS (2*0xA8) /* 22 bytes */ - struct iwl4965_eeprom_channel band_52_channels[11]; /* abs.ofs: 336 */ - u8 reserved12[6]; - -/* - * 4965 driver requires txpower calibration format version 5 or greater. - * Driver does not work with txpower calibration version < 5. - * This value is simply a 16-bit number, no major/minor versions here. - */ -#define EEPROM_CALIB_VERSION_OFFSET (2*0xB6) /* 2 bytes */ - u16 calib_version; /* abs.ofs: 364 */ - u8 reserved13[2]; - u8 reserved14[96]; /* abs.ofs: 368 */ - -/* - * 4965 Txpower calibration data. - */ -#define EEPROM_IWL_CALIB_TXPOWER_OFFSET (2*0xE8) /* 48 bytes */ - struct iwl4965_eeprom_calib_info calib_info; /* abs.ofs: 464 */ - - u8 reserved16[140]; /* fill out to full 1024 byte block */ - - -} __attribute__ ((packed)); - -#define IWL_EEPROM_IMAGE_SIZE 1024 - -/* End of EEPROM */ #include "iwl-4965-commands.h" diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index a79e8c383a39..dc55ff294b73 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -38,6 +38,7 @@ #include #include +#include "iwl-eeprom.h" #include "iwl-core.h" #include "iwl-4965.h" #include "iwl-helpers.h" @@ -4824,10 +4825,23 @@ void iwl4965_hw_cancel_deferred_work(struct iwl4965_priv *priv) cancel_delayed_work(&priv->init_alive_start); } +static struct iwl_lib_ops iwl4965_lib = { + .eeprom_ops = { + .verify_signature = iwlcore_eeprom_verify_signature, + .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, + .release_semaphore = iwlcore_eeprom_release_semaphore, + }, +}; + +static struct iwl_ops iwl4965_ops = { + .lib = &iwl4965_lib, +}; + static struct iwl_cfg iwl4965_agn_cfg = { .name = "4965AGN", .fw_name = "iwlwifi-4965" IWL4965_UCODE_API ".ucode", .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, + .ops = &iwl4965_ops, }; struct pci_device_id iwl4965_hw_card_ids[] = { @@ -4836,35 +4850,4 @@ struct pci_device_id iwl4965_hw_card_ids[] = { {0} }; -/* - * The device's EEPROM semaphore prevents conflicts between driver and uCode - * when accessing the EEPROM; each access is a series of pulses to/from the - * EEPROM chip, not a single event, so even reads could conflict if they - * weren't arbitrated by the semaphore. - */ -int iwl4965_eeprom_acquire_semaphore(struct iwl4965_priv *priv) -{ - u16 count; - int rc; - - for (count = 0; count < EEPROM_SEM_RETRY_LIMIT; count++) { - /* Request semaphore */ - iwl4965_set_bit(priv, CSR_HW_IF_CONFIG_REG, - CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); - - /* See if we got it */ - rc = iwl4965_poll_bit(priv, CSR_HW_IF_CONFIG_REG, - CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, - CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, - EEPROM_SEM_TIMEOUT); - if (rc >= 0) { - IWL_DEBUG_IO("Acquired semaphore after %d tries.\n", - count+1); - return rc; - } - } - - return rc; -} - MODULE_DEVICE_TABLE(pci, iwl4965_hw_card_ids); diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index 6ce408137365..f4e395fcb807 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -40,6 +40,7 @@ extern struct pci_device_id iwl4965_hw_card_ids[]; #define DRV_NAME "iwl4965" +#include "iwl-eeprom.h" #include "iwl-4965-hw.h" #include "iwl-csr.h" #include "iwl-prph.h" @@ -640,7 +641,6 @@ extern u8 iwl4965_add_station_flags(struct iwl4965_priv *priv, const u8 *addr, extern int iwl4965_is_network_packet(struct iwl4965_priv *priv, struct ieee80211_hdr *header); extern int iwl4965_power_init_handle(struct iwl4965_priv *priv); -extern int iwl4965_eeprom_init(struct iwl4965_priv *priv); extern void iwl4965_handle_data_packet_monitor(struct iwl4965_priv *priv, struct iwl4965_rx_mem_buffer *rxb, void *data, short len, @@ -746,8 +746,6 @@ struct iwl4965_priv; /* * Forward declare iwl-4965.c functions for iwl-base.c */ -extern int iwl4965_eeprom_acquire_semaphore(struct iwl4965_priv *priv); - extern int iwl4965_tx_queue_update_wr_ptr(struct iwl4965_priv *priv, struct iwl4965_tx_queue *txq, u16 byte_cnt); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index b8383c83f18d..9ca539861db2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -31,6 +31,7 @@ #include #include "iwl-4965-debug.h" +#include "iwl-eeprom.h" #include "iwl-core.h" MODULE_DESCRIPTION("iwl core"); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index bdd32f891683..88fd49abdabd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -75,10 +75,20 @@ #define IWL_SKU_A 0x2 #define IWL_SKU_N 0x8 +struct iwl_lib_ops { + /* eeprom operations (as defined in iwl-eeprom.h) */ + struct iwl_eeprom_ops eeprom_ops; +}; + +struct iwl_ops { + const struct iwl_lib_ops *lib; +}; + struct iwl_cfg { const char *name; const char *fw_name; unsigned int sku; + const struct iwl_ops *ops; }; #endif /* __iwl_core_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index ce1c3f68fde0..d84a7f296d90 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -45,6 +45,7 @@ #include +#include "iwl-eeprom.h" #include "iwl-core.h" #include "iwl-4965.h" #include "iwl-helpers.h" @@ -1560,85 +1561,6 @@ static int iwl4965_send_beacon_cmd(struct iwl4965_priv *priv) return rc; } -/****************************************************************************** - * - * EEPROM related functions - * - ******************************************************************************/ - -static void get_eeprom_mac(struct iwl4965_priv *priv, u8 *mac) -{ - memcpy(mac, priv->eeprom.mac_address, 6); -} - -static inline void iwl4965_eeprom_release_semaphore(struct iwl4965_priv *priv) -{ - iwl4965_clear_bit(priv, CSR_HW_IF_CONFIG_REG, - CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); -} - -/** - * iwl4965_eeprom_init - read EEPROM contents - * - * Load the EEPROM contents from adapter into priv->eeprom - * - * NOTE: This routine uses the non-debug IO access functions. - */ -int iwl4965_eeprom_init(struct iwl4965_priv *priv) -{ - u16 *e = (u16 *)&priv->eeprom; - u32 gp = iwl4965_read32(priv, CSR_EEPROM_GP); - u32 r; - int sz = sizeof(priv->eeprom); - int rc; - int i; - u16 addr; - - /* The EEPROM structure has several padding buffers within it - * and when adding new EEPROM maps is subject to programmer errors - * which may be very difficult to identify without explicitly - * checking the resulting size of the eeprom map. */ - BUILD_BUG_ON(sizeof(priv->eeprom) != IWL_EEPROM_IMAGE_SIZE); - - if ((gp & CSR_EEPROM_GP_VALID_MSK) == CSR_EEPROM_GP_BAD_SIGNATURE) { - IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x", gp); - return -ENOENT; - } - - /* Make sure driver (instead of uCode) is allowed to read EEPROM */ - rc = iwl4965_eeprom_acquire_semaphore(priv); - if (rc < 0) { - IWL_ERROR("Failed to acquire EEPROM semaphore.\n"); - return -ENOENT; - } - - /* eeprom is an array of 16bit values */ - for (addr = 0; addr < sz; addr += sizeof(u16)) { - _iwl4965_write32(priv, CSR_EEPROM_REG, addr << 1); - _iwl4965_clear_bit(priv, CSR_EEPROM_REG, CSR_EEPROM_REG_BIT_CMD); - - for (i = 0; i < IWL_EEPROM_ACCESS_TIMEOUT; - i += IWL_EEPROM_ACCESS_DELAY) { - r = _iwl4965_read_direct32(priv, CSR_EEPROM_REG); - if (r & CSR_EEPROM_REG_READ_VALID_MSK) - break; - udelay(IWL_EEPROM_ACCESS_DELAY); - } - - if (!(r & CSR_EEPROM_REG_READ_VALID_MSK)) { - IWL_ERROR("Time out reading EEPROM[%d]", addr); - rc = -ETIMEDOUT; - goto done; - } - e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16)); - } - rc = 0; - -done: - iwl4965_eeprom_release_semaphore(priv); - return rc; -} - /****************************************************************************** * * Misc. internal state and helper functions @@ -8765,13 +8687,13 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e goto out_remove_sysfs; } /* Read the EEPROM */ - err = iwl4965_eeprom_init(priv); + err = iwl_eeprom_init(priv); if (err) { IWL_ERROR("Unable to init EEPROM\n"); goto out_remove_sysfs; } /* MAC Address location in EEPROM same for 3945/4965 */ - get_eeprom_mac(priv, priv->mac_addr); + iwl_eeprom_get_mac(priv, priv->mac_addr); IWL_DEBUG_INFO("MAC address: %s\n", print_mac(mac, priv->mac_addr)); SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr); -- cgit v1.2.1 From 0310ae721d1b7aaf10dd8b712a3a83c355786970 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Tue, 11 Mar 2008 16:17:19 -0700 Subject: iwlwifi: Fix endianity in debug print This patch fix debug print out endianity issue for bitmap Since u64 and le64 variables are casted to unsigned long long, after patch 'wireless: correct warnings from using '%llx' for type 'u64' also bitmaps need to be converted to native endianity Signed-off-by: Tomas Winkler Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index dc55ff294b73..3401f2a30cc5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -4263,7 +4263,7 @@ static void iwl4965_rx_reply_compressed_ba(struct iwl4965_priv *priv, "%d, scd_ssn = %d\n", ba_resp->tid, ba_resp->seq_ctl, - (unsigned long long)ba_resp->bitmap, + (unsigned long long)le64_to_cpu(ba_resp->bitmap), ba_resp->scd_flow, ba_resp->scd_ssn); IWL_DEBUG_TX_REPLY("DAT start_idx = %d, bitmap = 0x%llx \n", -- cgit v1.2.1 From 35cdeaf4103b9a5c8a86899a5ed12a86c6a12a37 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Tue, 11 Mar 2008 16:17:20 -0700 Subject: iwlwifi: change rate number to a constant This patch moves a number to an understandable define Signed-off-by: Tomas Winkler Signed-off-by: Ron Rindjunsky Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl4965-base.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index d84a7f296d90..b78ca7720bdf 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -5450,8 +5450,9 @@ static void iwl4965_init_hw_rates(struct iwl4965_priv *priv, /* * If CCK != 1M then set short preamble rate flag. */ - rates[i].flags |= (iwl4965_rates[i].plcp == 10) ? - 0 : IEEE80211_RATE_SHORT_PREAMBLE; + rates[i].flags |= + (iwl4965_rates[i].plcp == IWL_RATE_1M_PLCP) ? + 0 : IEEE80211_RATE_SHORT_PREAMBLE; } } } -- cgit v1.2.1 From 26c0f03f6b77c513cb7bc37b73a06819bdbb791b Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Tue, 11 Mar 2008 16:17:15 -0700 Subject: iwlwifi: fix bug to show hidden APs during scan Indirect scanning ('iwlist scan') should report information about hidden APs. When an AP is hidden it does not respond to active scanning, we thus have to use passive scanning to locate these APs. This fixes http://bughost.org/bugzilla/show_bug.cgi?id=1499 Signed-off-by: Reinette Chatre Tested-by: Bill Moss Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl3945-base.c | 21 +++++++++++++-------- drivers/net/wireless/iwlwifi/iwl4965-base.c | 21 +++++++++++++-------- 2 files changed, 26 insertions(+), 16 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index bf3925fdb9be..093b863ef904 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -6309,18 +6309,23 @@ static void iwl3945_bg_request_scan(struct work_struct *data) if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) scan->filter_flags = RXON_FILTER_PROMISC_MSK; - if (direct_mask) + if (direct_mask) { IWL_DEBUG_SCAN ("Initiating direct scan for %s.\n", iwl3945_escape_essid(priv->essid, priv->essid_len)); - else + scan->channel_count = + iwl3945_get_channels_for_scan( + priv, band, 1, /* active */ + direct_mask, + (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]); + } else { IWL_DEBUG_SCAN("Initiating indirect scan.\n"); - - scan->channel_count = - iwl3945_get_channels_for_scan( - priv, band, 1, /* active */ - direct_mask, - (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]); + scan->channel_count = + iwl3945_get_channels_for_scan( + priv, band, 0, /* passive */ + direct_mask, + (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]); + } cmd.len += le16_to_cpu(scan->tx_cmd.len) + scan->channel_count * sizeof(struct iwl3945_scan_channel); diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index b78ca7720bdf..0b7335181719 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -6744,18 +6744,23 @@ static void iwl4965_bg_request_scan(struct work_struct *data) if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) scan->filter_flags = RXON_FILTER_PROMISC_MSK; - if (direct_mask) + if (direct_mask) { IWL_DEBUG_SCAN ("Initiating direct scan for %s.\n", iwl4965_escape_essid(priv->essid, priv->essid_len)); - else + scan->channel_count = + iwl4965_get_channels_for_scan( + priv, band, 1, /* active */ + direct_mask, + (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]); + } else { IWL_DEBUG_SCAN("Initiating indirect scan.\n"); - - scan->channel_count = - iwl4965_get_channels_for_scan( - priv, band, 1, /* active */ - direct_mask, - (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]); + scan->channel_count = + iwl4965_get_channels_for_scan( + priv, band, 0, /* passive */ + direct_mask, + (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]); + } cmd.len += le16_to_cpu(scan->tx_cmd.len) + scan->channel_count * sizeof(struct iwl4965_scan_channel); -- cgit v1.2.1 From 835d3ac5e8cbe1fec2c02c7fc662586b30b1f5a8 Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Wed, 12 Mar 2008 16:05:40 +0100 Subject: libertas: convert CMD_MAC_CONTROL to a direct command convert CMD_MAC_CONTROL to a direct command Signed-off-by: Holger Schurig Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/cmd.c | 31 ++++++------------------------- drivers/net/wireless/libertas/cmdresp.c | 1 - drivers/net/wireless/libertas/hostcmd.h | 4 ++-- 3 files changed, 8 insertions(+), 28 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index 445c6dc09786..84dde09bfbc3 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -1200,24 +1200,6 @@ static void lbs_submit_command(struct lbs_private *priv, lbs_deb_leave(LBS_DEB_HOST); } -static int lbs_cmd_mac_control(struct lbs_private *priv, - struct cmd_ds_command *cmd) -{ - struct cmd_ds_mac_control *mac = &cmd->params.macctrl; - - lbs_deb_enter(LBS_DEB_CMD); - - cmd->command = cpu_to_le16(CMD_MAC_CONTROL); - cmd->size = cpu_to_le16(sizeof(struct cmd_ds_mac_control) + S_DS_GEN); - mac->action = cpu_to_le16(priv->currentpacketfilter); - - lbs_deb_cmd("MAC_CONTROL: action 0x%04x, size %d\n", - le16_to_cpu(mac->action), le16_to_cpu(cmd->size)); - - lbs_deb_leave(LBS_DEB_CMD); - return 0; -} - /** * This function inserts command node to cmdfreeq * after cleans it. Requires priv->driver_lock held. @@ -1307,12 +1289,15 @@ int lbs_set_radio_control(struct lbs_private *priv) int lbs_set_mac_packet_filter(struct lbs_private *priv) { int ret = 0; + struct cmd_ds_mac_control cmd; lbs_deb_enter(LBS_DEB_CMD); - /* Send MAC control command to station */ - ret = lbs_prepare_and_send_command(priv, - CMD_MAC_CONTROL, 0, 0, 0, NULL); + cmd.hdr.size = cpu_to_le16(sizeof(cmd)); + cmd.action = cpu_to_le16(priv->currentpacketfilter); + cmd.reserved = 0; + + ret = lbs_cmd_with_response(priv, CMD_MAC_CONTROL, &cmd); lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); return ret; @@ -1382,10 +1367,6 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, ret = lbs_cmd_802_11_ps_mode(priv, cmdptr, cmd_action); break; - case CMD_MAC_CONTROL: - ret = lbs_cmd_mac_control(priv, cmdptr); - break; - case CMD_802_11_ASSOCIATE: case CMD_802_11_REASSOCIATE: ret = lbs_cmd_80211_associate(priv, cmdptr, pdata_buf); diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c index 63aa884b18f2..5534a7b859da 100644 --- a/drivers/net/wireless/libertas/cmdresp.c +++ b/drivers/net/wireless/libertas/cmdresp.c @@ -394,7 +394,6 @@ static inline int handle_cmd_response(struct lbs_private *priv, break; case CMD_RET(CMD_MAC_MULTICAST_ADR): - case CMD_RET(CMD_MAC_CONTROL): case CMD_RET(CMD_802_11_RESET): case CMD_RET(CMD_802_11_AUTHENTICATE): case CMD_RET(CMD_802_11_BEACON_STOP): diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h index 56bc1aa2bb00..b5361b3393d9 100644 --- a/drivers/net/wireless/libertas/hostcmd.h +++ b/drivers/net/wireless/libertas/hostcmd.h @@ -211,8 +211,9 @@ struct cmd_ds_802_11_get_log { }; struct cmd_ds_mac_control { + struct cmd_header hdr; __le16 action; - __le16 reserved; + u16 reserved; }; struct cmd_ds_mac_multicast_adr { @@ -695,7 +696,6 @@ struct cmd_ds_command { /* command Body */ union { struct cmd_ds_802_11_ps_mode psmode; - struct cmd_ds_mac_control macctrl; struct cmd_ds_802_11_associate associate; struct cmd_ds_802_11_deauthenticate deauth; struct cmd_ds_802_11_ad_hoc_start ads; -- cgit v1.2.1 From d9e9778c2ac5bac02fc118e9a2954e4c70f88eb6 Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Wed, 12 Mar 2008 16:06:43 +0100 Subject: libertas: rename packetfilter to mac_control The CMD_MAC_CONTROL can be used for other things than just filtering packets, e.g. to enable and disable WMM. This uses the same term mac_control for the define, the function and the shadow value in struct lbs_private. Signed-off-by: Holger Schurig Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/assoc.c | 8 ++++---- drivers/net/wireless/libertas/cmd.c | 4 ++-- drivers/net/wireless/libertas/decl.h | 2 +- drivers/net/wireless/libertas/dev.h | 2 +- drivers/net/wireless/libertas/main.c | 29 ++++++++++++++--------------- 5 files changed, 22 insertions(+), 23 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c index 707b7ff592ec..54161f1e742a 100644 --- a/drivers/net/wireless/libertas/assoc.c +++ b/drivers/net/wireless/libertas/assoc.c @@ -268,11 +268,11 @@ static int assoc_helper_wep_keys(struct lbs_private *priv, /* enable/disable the MAC's WEP packet filter */ if (assoc_req->secinfo.wep_enabled) - priv->currentpacketfilter |= CMD_ACT_MAC_WEP_ENABLE; + priv->mac_control |= CMD_ACT_MAC_WEP_ENABLE; else - priv->currentpacketfilter &= ~CMD_ACT_MAC_WEP_ENABLE; + priv->mac_control &= ~CMD_ACT_MAC_WEP_ENABLE; - ret = lbs_set_mac_packet_filter(priv); + ret = lbs_set_mac_control(priv); if (ret) goto out; @@ -304,7 +304,7 @@ static int assoc_helper_secinfo(struct lbs_private *priv, memcpy(&priv->secinfo, &assoc_req->secinfo, sizeof(struct lbs_802_11_security)); - ret = lbs_set_mac_packet_filter(priv); + ret = lbs_set_mac_control(priv); if (ret) goto out; diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index 84dde09bfbc3..4fcf5e1d98aa 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -1286,7 +1286,7 @@ int lbs_set_radio_control(struct lbs_private *priv) return ret; } -int lbs_set_mac_packet_filter(struct lbs_private *priv) +int lbs_set_mac_control(struct lbs_private *priv) { int ret = 0; struct cmd_ds_mac_control cmd; @@ -1294,7 +1294,7 @@ int lbs_set_mac_packet_filter(struct lbs_private *priv) lbs_deb_enter(LBS_DEB_CMD); cmd.hdr.size = cpu_to_le16(sizeof(cmd)); - cmd.action = cpu_to_le16(priv->currentpacketfilter); + cmd.action = cpu_to_le16(priv->mac_control); cmd.reserved = 0; ret = lbs_cmd_with_response(priv, CMD_MAC_CONTROL, &cmd); diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h index 4e22341b4f3d..f0de2a1e918f 100644 --- a/drivers/net/wireless/libertas/decl.h +++ b/drivers/net/wireless/libertas/decl.h @@ -17,7 +17,7 @@ struct net_device; struct cmd_ctrl_node; struct cmd_ds_command; -int lbs_set_mac_packet_filter(struct lbs_private *priv); +int lbs_set_mac_control(struct lbs_private *priv); void lbs_send_tx_feedback(struct lbs_private *priv); diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index ff2c046ca73f..4122a3223432 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h @@ -252,7 +252,7 @@ struct lbs_private { struct sk_buff *currenttxskb; /** NIC Operation characteristics */ - u16 currentpacketfilter; + u16 mac_control; u32 connect_status; u32 mesh_connect_status; u16 regioncode; diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 2e5bac826c48..37cc05044cd7 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -581,45 +581,45 @@ static int lbs_copy_multicast_address(struct lbs_private *priv, static void lbs_set_multicast_list(struct net_device *dev) { struct lbs_private *priv = dev->priv; - int oldpacketfilter; + int old_mac_control; DECLARE_MAC_BUF(mac); lbs_deb_enter(LBS_DEB_NET); - oldpacketfilter = priv->currentpacketfilter; + old_mac_control = priv->mac_control; if (dev->flags & IFF_PROMISC) { lbs_deb_net("enable promiscuous mode\n"); - priv->currentpacketfilter |= + priv->mac_control |= CMD_ACT_MAC_PROMISCUOUS_ENABLE; - priv->currentpacketfilter &= + priv->mac_control &= ~(CMD_ACT_MAC_ALL_MULTICAST_ENABLE | CMD_ACT_MAC_MULTICAST_ENABLE); } else { /* Multicast */ - priv->currentpacketfilter &= + priv->mac_control &= ~CMD_ACT_MAC_PROMISCUOUS_ENABLE; if (dev->flags & IFF_ALLMULTI || dev->mc_count > MRVDRV_MAX_MULTICAST_LIST_SIZE) { lbs_deb_net( "enabling all multicast\n"); - priv->currentpacketfilter |= + priv->mac_control |= CMD_ACT_MAC_ALL_MULTICAST_ENABLE; - priv->currentpacketfilter &= + priv->mac_control &= ~CMD_ACT_MAC_MULTICAST_ENABLE; } else { - priv->currentpacketfilter &= + priv->mac_control &= ~CMD_ACT_MAC_ALL_MULTICAST_ENABLE; if (!dev->mc_count) { lbs_deb_net("no multicast addresses, " "disabling multicast\n"); - priv->currentpacketfilter &= + priv->mac_control &= ~CMD_ACT_MAC_MULTICAST_ENABLE; } else { int i; - priv->currentpacketfilter |= + priv->mac_control |= CMD_ACT_MAC_MULTICAST_ENABLE; priv->nr_of_multicastmacaddr = @@ -642,9 +642,8 @@ static void lbs_set_multicast_list(struct net_device *dev) } } - if (priv->currentpacketfilter != oldpacketfilter) { - lbs_set_mac_packet_filter(priv); - } + if (priv->mac_control != old_mac_control) + lbs_set_mac_control(priv); lbs_deb_leave(LBS_DEB_NET); } @@ -945,7 +944,7 @@ static int lbs_setup_firmware(struct lbs_private *priv) goto done; } - lbs_set_mac_packet_filter(priv); + lbs_set_mac_control(priv); ret = lbs_get_data_rate(priv); if (ret < 0) { @@ -1036,7 +1035,7 @@ static int lbs_init_adapter(struct lbs_private *priv) priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; priv->mode = IW_MODE_INFRA; priv->curbssparams.channel = DEFAULT_AD_HOC_CHANNEL; - priv->currentpacketfilter = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON; + priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON; priv->radioon = RADIO_ON; priv->auto_rate = 1; priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE; -- cgit v1.2.1 From 56ca84c61b667e23cdc6e5179df57b9baa0eddc3 Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Wed, 12 Mar 2008 17:06:09 +0100 Subject: libertas: remove some unused commands Neither CMD_802_11_PAIRWISE_TSC nor CMD_802_11_GROUP_TSC is used or documented. It might have something to do with TKIP sequence counters, but that's just an educated guess. Remove all occurences of them. CMD_CODE_DNLD is also neither used nor documented. Signed-off-by: Holger Schurig Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/cmd.c | 7 ------- drivers/net/wireless/libertas/host.h | 3 --- 2 files changed, 10 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index 4fcf5e1d98aa..62f9f3bdfdfb 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -1379,8 +1379,6 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, case CMD_802_11_AD_HOC_START: ret = lbs_cmd_80211_ad_hoc_start(priv, cmdptr, pdata_buf); break; - case CMD_CODE_DNLD: - break; case CMD_802_11_RESET: ret = lbs_cmd_802_11_reset(priv, cmdptr, cmd_action); @@ -1440,11 +1438,6 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, ret = lbs_cmd_80211_ad_hoc_stop(priv, cmdptr); break; - case CMD_802_11_PAIRWISE_TSC: - break; - case CMD_802_11_GROUP_TSC: - break; - case CMD_802_11_MAC_ADDRESS: ret = lbs_cmd_802_11_mac_address(priv, cmdptr, cmd_action); break; diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h index 1aa04076b1ac..aae878b042c0 100644 --- a/drivers/net/wireless/libertas/host.h +++ b/drivers/net/wireless/libertas/host.h @@ -33,7 +33,6 @@ #define CMD_RET_802_11_ASSOCIATE 0x8012 /* Command codes */ -#define CMD_CODE_DNLD 0x0002 #define CMD_GET_HW_SPEC 0x0003 #define CMD_EEPROM_UPDATE 0x0004 #define CMD_802_11_RESET 0x0005 @@ -68,8 +67,6 @@ #define CMD_802_11_AD_HOC_JOIN 0x002c #define CMD_802_11_QUERY_TKIP_REPLY_CNTRS 0x002e #define CMD_802_11_ENABLE_RSN 0x002f -#define CMD_802_11_PAIRWISE_TSC 0x0036 -#define CMD_802_11_GROUP_TSC 0x0037 #define CMD_802_11_SET_AFC 0x003c #define CMD_802_11_GET_AFC 0x003d #define CMD_802_11_AD_HOC_STOP 0x0040 -- cgit v1.2.1 From 8236e183fc53be2b5d81a4f547f9c5b645e10fe0 Mon Sep 17 00:00:00 2001 From: Max Stepanov Date: Wed, 12 Mar 2008 16:58:48 -0700 Subject: iwlwifi: Bug fix, CCMP with HW encryption with AGG This patch fixes a bug in security. Enables CCMP HW encryption with aggregations. Signed-off-by: Max Stepanov Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965-commands.h | 4 ++++ drivers/net/wireless/iwlwifi/iwl4965-base.c | 2 ++ 2 files changed, 6 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h index 35f592dc40c6..1025ffeb8fa8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h @@ -1045,6 +1045,10 @@ struct iwl4965_rx_mpdu_res_start { * MAC header) to DWORD boundary. */ #define TX_CMD_FLG_MH_PAD_MSK __constant_cpu_to_le32(1 << 20) +/* accelerate aggregation support + * 0 - no CCMP encryption; 1 - CCMP encryption */ +#define TX_CMD_FLG_AGG_CCMP_MSK __constant_cpu_to_le32(1 << 22) + /* HCCA-AP - disable duration overwriting. */ #define TX_CMD_FLG_DUR_MSK __constant_cpu_to_le32(1 << 25) diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 0b7335181719..d0cb36b9efe3 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -2427,6 +2427,8 @@ static void iwl4965_build_tx_cmd_hwcrypto(struct iwl4965_priv *priv, case ALG_CCMP: cmd->cmd.tx.sec_ctl = TX_CMD_SEC_CCM; memcpy(cmd->cmd.tx.key, keyinfo->key, keyinfo->keylen); + if (ctl->flags & IEEE80211_TXCTL_AMPDU) + cmd->cmd.tx.tx_flags |= TX_CMD_FLG_AGG_CCMP_MSK; IWL_DEBUG_TX("tx_cmd with aes hwcrypto\n"); break; -- cgit v1.2.1 From 0a6857e70d577237bb1cd1c991e68e7d3b6f7c90 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 12 Mar 2008 16:58:49 -0700 Subject: iwlwifi: rename iwl-4965-debug.h back to iwl-debug.h This patch removes iwl-4965-debug.h to iwl-debug.h It will be used by more NICs Signed-off-by: Tomas Winkler Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/Kconfig | 2 +- drivers/net/wireless/iwlwifi/iwl-4965-debug.h | 168 -------------------------- drivers/net/wireless/iwlwifi/iwl-4965-io.h | 36 +++--- drivers/net/wireless/iwlwifi/iwl-4965-rs.c | 4 +- drivers/net/wireless/iwlwifi/iwl-4965.c | 6 +- drivers/net/wireless/iwlwifi/iwl-4965.h | 4 +- drivers/net/wireless/iwlwifi/iwl-core.c | 8 +- drivers/net/wireless/iwlwifi/iwl-debug.h | 168 ++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-eeprom.c | 2 +- drivers/net/wireless/iwlwifi/iwl4965-base.c | 56 ++++----- 10 files changed, 227 insertions(+), 227 deletions(-) delete mode 100644 drivers/net/wireless/iwlwifi/iwl-4965-debug.h create mode 100644 drivers/net/wireless/iwlwifi/iwl-debug.h (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index 5b7c0160e1fa..acb807936131 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig @@ -50,7 +50,7 @@ config IWL4965_SENSITIVITY This option will enable sensitivity calibration for the iwl4965 driver. -config IWL4965_DEBUG +config IWLWIFI_DEBUG bool "Enable full debugging output in iwl4965 driver" depends on IWL4965 ---help--- diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-debug.h b/drivers/net/wireless/iwlwifi/iwl-4965-debug.h deleted file mode 100644 index df329481bb45..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-4965-debug.h +++ /dev/null @@ -1,168 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. - * - * Portions of this file are derived from the ipw3945 project. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * James P. Ketrenos - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - *****************************************************************************/ - -#ifndef __iwl4965_debug_h__ -#define __iwl4965_debug_h__ - -#ifdef CONFIG_IWL4965_DEBUG -extern u32 iwl4965_debug_level; -#define IWL_DEBUG(level, fmt, args...) \ -do { if (iwl4965_debug_level & (level)) \ - printk(KERN_ERR DRV_NAME": %c %s " fmt, \ - in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0) - -#define IWL_DEBUG_LIMIT(level, fmt, args...) \ -do { if ((iwl4965_debug_level & (level)) && net_ratelimit()) \ - printk(KERN_ERR DRV_NAME": %c %s " fmt, \ - in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0) - -static inline void iwl4965_print_hex_dump(int level, void *p, u32 len) -{ - if (!(iwl4965_debug_level & level)) - return; - - print_hex_dump(KERN_DEBUG, "iwl data: ", DUMP_PREFIX_OFFSET, 16, 1, - p, len, 1); -} -#else - -static inline void IWL_DEBUG(int level, const char *fmt, ...) -{ -} -static inline void IWL_DEBUG_LIMIT(int level, const char *fmt, ...) -{ -} -static inline void iwl4965_print_hex_dump(int level, void *p, u32 len) -{ -} -#endif /* CONFIG_IWL4965_DEBUG */ - - - -/* - * To use the debug system; - * - * If you are defining a new debug classification, simply add it to the #define - * list here in the form of: - * - * #define IWL_DL_xxxx VALUE - * - * shifting value to the left one bit from the previous entry. xxxx should be - * the name of the classification (for example, WEP) - * - * You then need to either add a IWL_xxxx_DEBUG() macro definition for your - * classification, or use IWL_DEBUG(IWL_DL_xxxx, ...) whenever you want - * to send output to that classification. - * - * To add your debug level to the list of levels seen when you perform - * - * % cat /proc/net/iwl/debug_level - * - * you simply need to add your entry to the iwl4965_debug_levels array. - * - * If you do not see debug_level in /proc/net/iwl then you do not have - * CONFIG_IWL4965_DEBUG defined in your kernel configuration - * - */ - -#define IWL_DL_INFO (1 << 0) -#define IWL_DL_MAC80211 (1 << 1) -#define IWL_DL_HOST_COMMAND (1 << 2) -#define IWL_DL_STATE (1 << 3) - -#define IWL_DL_RADIO (1 << 7) -#define IWL_DL_POWER (1 << 8) -#define IWL_DL_TEMP (1 << 9) - -#define IWL_DL_NOTIF (1 << 10) -#define IWL_DL_SCAN (1 << 11) -#define IWL_DL_ASSOC (1 << 12) -#define IWL_DL_DROP (1 << 13) - -#define IWL_DL_TXPOWER (1 << 14) - -#define IWL_DL_AP (1 << 15) - -#define IWL_DL_FW (1 << 16) -#define IWL_DL_RF_KILL (1 << 17) -#define IWL_DL_FW_ERRORS (1 << 18) - -#define IWL_DL_LED (1 << 19) - -#define IWL_DL_RATE (1 << 20) - -#define IWL_DL_CALIB (1 << 21) -#define IWL_DL_WEP (1 << 22) -#define IWL_DL_TX (1 << 23) -#define IWL_DL_RX (1 << 24) -#define IWL_DL_ISR (1 << 25) -#define IWL_DL_HT (1 << 26) -#define IWL_DL_IO (1 << 27) -#define IWL_DL_11H (1 << 28) - -#define IWL_DL_STATS (1 << 29) -#define IWL_DL_TX_REPLY (1 << 30) -#define IWL_DL_QOS (1 << 31) - -#define IWL_ERROR(f, a...) printk(KERN_ERR DRV_NAME ": " f, ## a) -#define IWL_WARNING(f, a...) printk(KERN_WARNING DRV_NAME ": " f, ## a) -#define IWL_DEBUG_INFO(f, a...) IWL_DEBUG(IWL_DL_INFO, f, ## a) - -#define IWL_DEBUG_MAC80211(f, a...) IWL_DEBUG(IWL_DL_MAC80211, f, ## a) -#define IWL_DEBUG_TEMP(f, a...) IWL_DEBUG(IWL_DL_TEMP, f, ## a) -#define IWL_DEBUG_SCAN(f, a...) IWL_DEBUG(IWL_DL_SCAN, f, ## a) -#define IWL_DEBUG_RX(f, a...) IWL_DEBUG(IWL_DL_RX, f, ## a) -#define IWL_DEBUG_TX(f, a...) IWL_DEBUG(IWL_DL_TX, f, ## a) -#define IWL_DEBUG_ISR(f, a...) IWL_DEBUG(IWL_DL_ISR, f, ## a) -#define IWL_DEBUG_LED(f, a...) IWL_DEBUG(IWL_DL_LED, f, ## a) -#define IWL_DEBUG_WEP(f, a...) IWL_DEBUG(IWL_DL_WEP, f, ## a) -#define IWL_DEBUG_HC(f, a...) IWL_DEBUG(IWL_DL_HOST_COMMAND, f, ## a) -#define IWL_DEBUG_CALIB(f, a...) IWL_DEBUG(IWL_DL_CALIB, f, ## a) -#define IWL_DEBUG_FW(f, a...) IWL_DEBUG(IWL_DL_FW, f, ## a) -#define IWL_DEBUG_RF_KILL(f, a...) IWL_DEBUG(IWL_DL_RF_KILL, f, ## a) -#define IWL_DEBUG_DROP(f, a...) IWL_DEBUG(IWL_DL_DROP, f, ## a) -#define IWL_DEBUG_DROP_LIMIT(f, a...) IWL_DEBUG_LIMIT(IWL_DL_DROP, f, ## a) -#define IWL_DEBUG_AP(f, a...) IWL_DEBUG(IWL_DL_AP, f, ## a) -#define IWL_DEBUG_TXPOWER(f, a...) IWL_DEBUG(IWL_DL_TXPOWER, f, ## a) -#define IWL_DEBUG_IO(f, a...) IWL_DEBUG(IWL_DL_IO, f, ## a) -#define IWL_DEBUG_RATE(f, a...) IWL_DEBUG(IWL_DL_RATE, f, ## a) -#define IWL_DEBUG_RATE_LIMIT(f, a...) IWL_DEBUG_LIMIT(IWL_DL_RATE, f, ## a) -#define IWL_DEBUG_NOTIF(f, a...) IWL_DEBUG(IWL_DL_NOTIF, f, ## a) -#define IWL_DEBUG_ASSOC(f, a...) IWL_DEBUG(IWL_DL_ASSOC | IWL_DL_INFO, f, ## a) -#define IWL_DEBUG_ASSOC_LIMIT(f, a...) \ - IWL_DEBUG_LIMIT(IWL_DL_ASSOC | IWL_DL_INFO, f, ## a) -#define IWL_DEBUG_HT(f, a...) IWL_DEBUG(IWL_DL_HT, f, ## a) -#define IWL_DEBUG_STATS(f, a...) IWL_DEBUG(IWL_DL_STATS, f, ## a) -#define IWL_DEBUG_STATS_LIMIT(f, a...) IWL_DEBUG_LIMIT(IWL_DL_STATS, f, ## a) -#define IWL_DEBUG_TX_REPLY(f, a...) IWL_DEBUG(IWL_DL_TX_REPLY, f, ## a) -#define IWL_DEBUG_QOS(f, a...) IWL_DEBUG(IWL_DL_QOS, f, ## a) -#define IWL_DEBUG_RADIO(f, a...) IWL_DEBUG(IWL_DL_RADIO, f, ## a) -#define IWL_DEBUG_POWER(f, a...) IWL_DEBUG(IWL_DL_POWER, f, ## a) -#define IWL_DEBUG_11H(f, a...) IWL_DEBUG(IWL_DL_11H, f, ## a) - -#endif diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-io.h b/drivers/net/wireless/iwlwifi/iwl-4965-io.h index 07fca8888f40..3accdfb33e56 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-io.h @@ -31,7 +31,7 @@ #include -#include "iwl-4965-debug.h" +#include "iwl-debug.h" /* * IO, register, and NIC memory access functions @@ -60,7 +60,7 @@ */ #define _iwl4965_write32(priv, ofs, val) writel((val), (priv)->hw_base + (ofs)) -#ifdef CONFIG_IWL4965_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUG static inline void __iwl4965_write32(const char *f, u32 l, struct iwl4965_priv *priv, u32 ofs, u32 val) { @@ -74,7 +74,7 @@ static inline void __iwl4965_write32(const char *f, u32 l, struct iwl4965_priv * #endif #define _iwl4965_read32(priv, ofs) readl((priv)->hw_base + (ofs)) -#ifdef CONFIG_IWL4965_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUG static inline u32 __iwl4965_read32(char *f, u32 l, struct iwl4965_priv *priv, u32 ofs) { IWL_DEBUG_IO("read_direct32(0x%08X) - %s %d\n", ofs, f, l); @@ -99,7 +99,7 @@ static inline int _iwl4965_poll_bit(struct iwl4965_priv *priv, u32 addr, return -ETIMEDOUT; } -#ifdef CONFIG_IWL4965_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUG static inline int __iwl4965_poll_bit(const char *f, u32 l, struct iwl4965_priv *priv, u32 addr, u32 bits, u32 mask, int timeout) @@ -120,7 +120,7 @@ static inline void _iwl4965_set_bit(struct iwl4965_priv *priv, u32 reg, u32 mask { _iwl4965_write32(priv, reg, _iwl4965_read32(priv, reg) | mask); } -#ifdef CONFIG_IWL4965_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUG static inline void __iwl4965_set_bit(const char *f, u32 l, struct iwl4965_priv *priv, u32 reg, u32 mask) { @@ -137,7 +137,7 @@ static inline void _iwl4965_clear_bit(struct iwl4965_priv *priv, u32 reg, u32 ma { _iwl4965_write32(priv, reg, _iwl4965_read32(priv, reg) & ~mask); } -#ifdef CONFIG_IWL4965_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUG static inline void __iwl4965_clear_bit(const char *f, u32 l, struct iwl4965_priv *priv, u32 reg, u32 mask) { @@ -155,7 +155,7 @@ static inline int _iwl4965_grab_nic_access(struct iwl4965_priv *priv) int ret; u32 gp_ctl; -#ifdef CONFIG_IWL4965_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUG if (atomic_read(&priv->restrict_refcnt)) return 0; #endif @@ -186,13 +186,13 @@ static inline int _iwl4965_grab_nic_access(struct iwl4965_priv *priv) return -EIO; } -#ifdef CONFIG_IWL4965_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUG atomic_inc(&priv->restrict_refcnt); #endif return 0; } -#ifdef CONFIG_IWL4965_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUG static inline int __iwl4965_grab_nic_access(const char *f, u32 l, struct iwl4965_priv *priv) { @@ -212,13 +212,13 @@ static inline int __iwl4965_grab_nic_access(const char *f, u32 l, static inline void _iwl4965_release_nic_access(struct iwl4965_priv *priv) { -#ifdef CONFIG_IWL4965_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUG if (atomic_dec_and_test(&priv->restrict_refcnt)) #endif _iwl4965_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); } -#ifdef CONFIG_IWL4965_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUG static inline void __iwl4965_release_nic_access(const char *f, u32 l, struct iwl4965_priv *priv) { @@ -239,7 +239,7 @@ static inline u32 _iwl4965_read_direct32(struct iwl4965_priv *priv, u32 reg) { return _iwl4965_read32(priv, reg); } -#ifdef CONFIG_IWL4965_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUG static inline u32 __iwl4965_read_direct32(const char *f, u32 l, struct iwl4965_priv *priv, u32 reg) { @@ -261,7 +261,7 @@ static inline void _iwl4965_write_direct32(struct iwl4965_priv *priv, { _iwl4965_write32(priv, reg, value); } -#ifdef CONFIG_IWL4965_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUG static void __iwl4965_write_direct32(u32 line, struct iwl4965_priv *priv, u32 reg, u32 value) { @@ -301,7 +301,7 @@ static inline int _iwl4965_poll_direct_bit(struct iwl4965_priv *priv, return -ETIMEDOUT; } -#ifdef CONFIG_IWL4965_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUG static inline int __iwl4965_poll_direct_bit(const char *f, u32 l, struct iwl4965_priv *priv, u32 addr, u32 mask, int timeout) @@ -327,7 +327,7 @@ static inline u32 _iwl4965_read_prph(struct iwl4965_priv *priv, u32 reg) _iwl4965_write_direct32(priv, HBUS_TARG_PRPH_RADDR, reg | (3 << 24)); return _iwl4965_read_direct32(priv, HBUS_TARG_PRPH_RDAT); } -#ifdef CONFIG_IWL4965_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUG static inline u32 __iwl4965_read_prph(u32 line, struct iwl4965_priv *priv, u32 reg) { if (!atomic_read(&priv->restrict_refcnt)) @@ -348,7 +348,7 @@ static inline void _iwl4965_write_prph(struct iwl4965_priv *priv, ((addr & 0x0000FFFF) | (3 << 24))); _iwl4965_write_direct32(priv, HBUS_TARG_PRPH_WDAT, val); } -#ifdef CONFIG_IWL4965_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUG static inline void __iwl4965_write_prph(u32 line, struct iwl4965_priv *priv, u32 addr, u32 val) { @@ -365,7 +365,7 @@ static inline void __iwl4965_write_prph(u32 line, struct iwl4965_priv *priv, #define _iwl4965_set_bits_prph(priv, reg, mask) \ _iwl4965_write_prph(priv, reg, (_iwl4965_read_prph(priv, reg) | mask)) -#ifdef CONFIG_IWL4965_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUG static inline void __iwl4965_set_bits_prph(u32 line, struct iwl4965_priv *priv, u32 reg, u32 mask) { @@ -383,7 +383,7 @@ static inline void __iwl4965_set_bits_prph(u32 line, struct iwl4965_priv *priv, #define _iwl4965_set_bits_mask_prph(priv, reg, bits, mask) \ _iwl4965_write_prph(priv, reg, ((_iwl4965_read_prph(priv, reg) & mask) | bits)) -#ifdef CONFIG_IWL4965_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUG static inline void __iwl4965_set_bits_mask_prph(u32 line, struct iwl4965_priv *priv, u32 reg, u32 bits, u32 mask) { diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c index 4b46226ff350..7733b23d582c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c @@ -244,7 +244,7 @@ static inline u8 iwl4965_rate_get_rate(u32 rate_n_flags) static int rs_send_lq_cmd(struct iwl4965_priv *priv, struct iwl4965_link_quality_cmd *lq, u8 flags) { -#ifdef CONFIG_IWL4965_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUG int i; #endif struct iwl4965_host_cmd cmd = { @@ -265,7 +265,7 @@ static int rs_send_lq_cmd(struct iwl4965_priv *priv, IWL_DEBUG_RATE("lq dta 0x%X 0x%X\n", lq->general_params.single_stream_ant_msk, lq->general_params.dual_stream_ant_msk); -#ifdef CONFIG_IWL4965_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUG for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) IWL_DEBUG_RATE("lq index %d 0x%X\n", i, lq->rs_table[i].rate_n_flags); diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 3401f2a30cc5..2896af28981a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -3583,7 +3583,7 @@ static void iwl4965_update_ps_mode(struct iwl4965_priv *priv, u16 ps_bit, u8 *ad } } } -#ifdef CONFIG_IWL4965_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUG /** * iwl4965_dbg_report_frame - dump frame to syslog during debug sessions @@ -3623,7 +3623,7 @@ static void iwl4965_dbg_report_frame(struct iwl4965_priv *priv, struct iwl4965_rx_frame_end *rx_end = IWL_RX_END(pkt); u8 *data = IWL_RX_DATA(pkt); - if (likely(!(iwl4965_debug_level & IWL_DL_RX))) + if (likely(!(iwl_debug_level & IWL_DL_RX))) return; /* MAC header */ @@ -3726,7 +3726,7 @@ static void iwl4965_dbg_report_frame(struct iwl4965_priv *priv, } } if (print_dump) - iwl4965_print_hex_dump(IWL_DL_RX, data, length); + iwl_print_hex_dump(IWL_DL_RX, data, length); } #else static inline void iwl4965_dbg_report_frame(struct iwl4965_priv *priv, diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index f4e395fcb807..4426d0f85564 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -44,7 +44,7 @@ extern struct pci_device_id iwl4965_hw_card_ids[]; #include "iwl-4965-hw.h" #include "iwl-csr.h" #include "iwl-prph.h" -#include "iwl-4965-debug.h" +#include "iwl-debug.h" /* Change firmware file name, using "-" and incrementing number, * *only* when uCode interface or architecture changes so that it @@ -1202,7 +1202,7 @@ struct iwl4965_priv { u32 pm_state[16]; #endif -#ifdef CONFIG_IWL4965_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUG /* debugging info */ u32 framecnt_to_us; atomic_t restrict_refcnt; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 9ca539861db2..4645d194773e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -30,7 +30,7 @@ #include #include -#include "iwl-4965-debug.h" +#include "iwl-debug.h" #include "iwl-eeprom.h" #include "iwl-core.h" @@ -39,7 +39,7 @@ MODULE_VERSION(IWLWIFI_VERSION); MODULE_AUTHOR(DRV_COPYRIGHT); MODULE_LICENSE("GPL/BSD"); -#ifdef CONFIG_IWL4965_DEBUG -u32 iwl4965_debug_level; -EXPORT_SYMBOL(iwl4965_debug_level); +#ifdef CONFIG_IWLWIFI_DEBUG +u32 iwl_debug_level; +EXPORT_SYMBOL(iwl_debug_level); #endif diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h new file mode 100644 index 000000000000..067700620e21 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -0,0 +1,168 @@ +/****************************************************************************** + * + * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. + * + * Portions of this file are derived from the ipw3945 project. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * James P. Ketrenos + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + *****************************************************************************/ + +#ifndef __iwl_debug_h__ +#define __iwl_debug_h__ + +#ifdef CONFIG_IWLWIFI_DEBUG +extern u32 iwl_debug_level; +#define IWL_DEBUG(level, fmt, args...) \ +do { if (iwl_debug_level & (level)) \ + printk(KERN_ERR DRV_NAME": %c %s " fmt, \ + in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0) + +#define IWL_DEBUG_LIMIT(level, fmt, args...) \ +do { if ((iwl_debug_level & (level)) && net_ratelimit()) \ + printk(KERN_ERR DRV_NAME": %c %s " fmt, \ + in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0) + +static inline void iwl_print_hex_dump(int level, void *p, u32 len) +{ + if (!(iwl_debug_level & level)) + return; + + print_hex_dump(KERN_DEBUG, "iwl data: ", DUMP_PREFIX_OFFSET, 16, 1, + p, len, 1); +} +#else + +static inline void IWL_DEBUG(int level, const char *fmt, ...) +{ +} +static inline void IWL_DEBUG_LIMIT(int level, const char *fmt, ...) +{ +} +static inline void iwl_print_hex_dump(int level, void *p, u32 len) +{ +} +#endif /* CONFIG_IWLWIFI_DEBUG */ + + + +/* + * To use the debug system; + * + * If you are defining a new debug classification, simply add it to the #define + * list here in the form of: + * + * #define IWL_DL_xxxx VALUE + * + * shifting value to the left one bit from the previous entry. xxxx should be + * the name of the classification (for example, WEP) + * + * You then need to either add a IWL_xxxx_DEBUG() macro definition for your + * classification, or use IWL_DEBUG(IWL_DL_xxxx, ...) whenever you want + * to send output to that classification. + * + * To add your debug level to the list of levels seen when you perform + * + * % cat /proc/net/iwl/debug_level + * + * you simply need to add your entry to the iwl_debug_levels array. + * + * If you do not see debug_level in /proc/net/iwl then you do not have + * CONFIG_IWLWIFI_DEBUG defined in your kernel configuration + * + */ + +#define IWL_DL_INFO (1 << 0) +#define IWL_DL_MAC80211 (1 << 1) +#define IWL_DL_HOST_COMMAND (1 << 2) +#define IWL_DL_STATE (1 << 3) + +#define IWL_DL_RADIO (1 << 7) +#define IWL_DL_POWER (1 << 8) +#define IWL_DL_TEMP (1 << 9) + +#define IWL_DL_NOTIF (1 << 10) +#define IWL_DL_SCAN (1 << 11) +#define IWL_DL_ASSOC (1 << 12) +#define IWL_DL_DROP (1 << 13) + +#define IWL_DL_TXPOWER (1 << 14) + +#define IWL_DL_AP (1 << 15) + +#define IWL_DL_FW (1 << 16) +#define IWL_DL_RF_KILL (1 << 17) +#define IWL_DL_FW_ERRORS (1 << 18) + +#define IWL_DL_LED (1 << 19) + +#define IWL_DL_RATE (1 << 20) + +#define IWL_DL_CALIB (1 << 21) +#define IWL_DL_WEP (1 << 22) +#define IWL_DL_TX (1 << 23) +#define IWL_DL_RX (1 << 24) +#define IWL_DL_ISR (1 << 25) +#define IWL_DL_HT (1 << 26) +#define IWL_DL_IO (1 << 27) +#define IWL_DL_11H (1 << 28) + +#define IWL_DL_STATS (1 << 29) +#define IWL_DL_TX_REPLY (1 << 30) +#define IWL_DL_QOS (1 << 31) + +#define IWL_ERROR(f, a...) printk(KERN_ERR DRV_NAME ": " f, ## a) +#define IWL_WARNING(f, a...) printk(KERN_WARNING DRV_NAME ": " f, ## a) +#define IWL_DEBUG_INFO(f, a...) IWL_DEBUG(IWL_DL_INFO, f, ## a) + +#define IWL_DEBUG_MAC80211(f, a...) IWL_DEBUG(IWL_DL_MAC80211, f, ## a) +#define IWL_DEBUG_TEMP(f, a...) IWL_DEBUG(IWL_DL_TEMP, f, ## a) +#define IWL_DEBUG_SCAN(f, a...) IWL_DEBUG(IWL_DL_SCAN, f, ## a) +#define IWL_DEBUG_RX(f, a...) IWL_DEBUG(IWL_DL_RX, f, ## a) +#define IWL_DEBUG_TX(f, a...) IWL_DEBUG(IWL_DL_TX, f, ## a) +#define IWL_DEBUG_ISR(f, a...) IWL_DEBUG(IWL_DL_ISR, f, ## a) +#define IWL_DEBUG_LED(f, a...) IWL_DEBUG(IWL_DL_LED, f, ## a) +#define IWL_DEBUG_WEP(f, a...) IWL_DEBUG(IWL_DL_WEP, f, ## a) +#define IWL_DEBUG_HC(f, a...) IWL_DEBUG(IWL_DL_HOST_COMMAND, f, ## a) +#define IWL_DEBUG_CALIB(f, a...) IWL_DEBUG(IWL_DL_CALIB, f, ## a) +#define IWL_DEBUG_FW(f, a...) IWL_DEBUG(IWL_DL_FW, f, ## a) +#define IWL_DEBUG_RF_KILL(f, a...) IWL_DEBUG(IWL_DL_RF_KILL, f, ## a) +#define IWL_DEBUG_DROP(f, a...) IWL_DEBUG(IWL_DL_DROP, f, ## a) +#define IWL_DEBUG_DROP_LIMIT(f, a...) IWL_DEBUG_LIMIT(IWL_DL_DROP, f, ## a) +#define IWL_DEBUG_AP(f, a...) IWL_DEBUG(IWL_DL_AP, f, ## a) +#define IWL_DEBUG_TXPOWER(f, a...) IWL_DEBUG(IWL_DL_TXPOWER, f, ## a) +#define IWL_DEBUG_IO(f, a...) IWL_DEBUG(IWL_DL_IO, f, ## a) +#define IWL_DEBUG_RATE(f, a...) IWL_DEBUG(IWL_DL_RATE, f, ## a) +#define IWL_DEBUG_RATE_LIMIT(f, a...) IWL_DEBUG_LIMIT(IWL_DL_RATE, f, ## a) +#define IWL_DEBUG_NOTIF(f, a...) IWL_DEBUG(IWL_DL_NOTIF, f, ## a) +#define IWL_DEBUG_ASSOC(f, a...) IWL_DEBUG(IWL_DL_ASSOC | IWL_DL_INFO, f, ## a) +#define IWL_DEBUG_ASSOC_LIMIT(f, a...) \ + IWL_DEBUG_LIMIT(IWL_DL_ASSOC | IWL_DL_INFO, f, ## a) +#define IWL_DEBUG_HT(f, a...) IWL_DEBUG(IWL_DL_HT, f, ## a) +#define IWL_DEBUG_STATS(f, a...) IWL_DEBUG(IWL_DL_STATS, f, ## a) +#define IWL_DEBUG_STATS_LIMIT(f, a...) IWL_DEBUG_LIMIT(IWL_DL_STATS, f, ## a) +#define IWL_DEBUG_TX_REPLY(f, a...) IWL_DEBUG(IWL_DL_TX_REPLY, f, ## a) +#define IWL_DEBUG_QOS(f, a...) IWL_DEBUG(IWL_DL_QOS, f, ## a) +#define IWL_DEBUG_RADIO(f, a...) IWL_DEBUG(IWL_DL_RADIO, f, ## a) +#define IWL_DEBUG_POWER(f, a...) IWL_DEBUG(IWL_DL_POWER, f, ## a) +#define IWL_DEBUG_11H(f, a...) IWL_DEBUG(IWL_DL_11H, f, ## a) + +#endif diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index 0064387dea91..4fd1b362d2ed 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -71,7 +71,7 @@ #include "iwl-4965-commands.h" #include "iwl-4965.h" #include "iwl-core.h" -#include "iwl-4965-debug.h" +#include "iwl-debug.h" #include "iwl-eeprom.h" #include "iwl-4965-io.h" diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index d0cb36b9efe3..e05bc902ee6e 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -76,7 +76,7 @@ int iwl4965_param_amsdu_size_8K; /* def: enable 8K amsdu size */ #define DRV_DESCRIPTION "Intel(R) Wireless WiFi Link 4965AGN driver for Linux" -#ifdef CONFIG_IWL4965_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUG #define VD "d" #else #define VD @@ -2578,7 +2578,7 @@ static int iwl4965_get_sta_id(struct iwl4965_priv *priv, IWL_DEBUG_DROP("Station %s not in station map. " "Defaulting to broadcast...\n", print_mac(mac, hdr->addr1)); - iwl4965_print_hex_dump(IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr)); + iwl_print_hex_dump(IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr)); return priv->hw_setting.bcast_sta_id; default: @@ -2634,7 +2634,7 @@ static int iwl4965_tx_skb(struct iwl4965_priv *priv, fc = le16_to_cpu(hdr->frame_control); -#ifdef CONFIG_IWL4965_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUG if (ieee80211_is_auth(fc)) IWL_DEBUG_TX("Sending AUTH frame\n"); else if (ieee80211_is_assoc_request(fc)) @@ -2792,10 +2792,10 @@ static int iwl4965_tx_skb(struct iwl4965_priv *priv, txq->need_update = 0; } - iwl4965_print_hex_dump(IWL_DL_TX, out_cmd->cmd.payload, + iwl_print_hex_dump(IWL_DL_TX, out_cmd->cmd.payload, sizeof(out_cmd->cmd.tx)); - iwl4965_print_hex_dump(IWL_DL_TX, (u8 *)out_cmd->cmd.tx.hdr, + iwl_print_hex_dump(IWL_DL_TX, (u8 *)out_cmd->cmd.tx.hdr, ieee80211_get_hdrlen(fc)); /* Set up entry for this TFD in Tx byte-count array */ @@ -3590,7 +3590,7 @@ static void iwl4965_rx_spectrum_measure_notif(struct iwl4965_priv *priv, static void iwl4965_rx_pm_sleep_notif(struct iwl4965_priv *priv, struct iwl4965_rx_mem_buffer *rxb) { -#ifdef CONFIG_IWL4965_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUG struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data; struct iwl4965_sleep_notification *sleep = &(pkt->u.sleep_notif); IWL_DEBUG_RX("sleep mode: %d, src: %d\n", @@ -3605,7 +3605,7 @@ static void iwl4965_rx_pm_debug_statistics_notif(struct iwl4965_priv *priv, IWL_DEBUG_RADIO("Dumping %d bytes of unhandled " "notification for %s:\n", le32_to_cpu(pkt->len), get_cmd_string(pkt->hdr.cmd)); - iwl4965_print_hex_dump(IWL_DL_RADIO, pkt->u.raw, le32_to_cpu(pkt->len)); + iwl_print_hex_dump(IWL_DL_RADIO, pkt->u.raw, le32_to_cpu(pkt->len)); } static void iwl4965_bg_beacon_update(struct work_struct *work) @@ -3636,7 +3636,7 @@ static void iwl4965_bg_beacon_update(struct work_struct *work) static void iwl4965_rx_beacon_notif(struct iwl4965_priv *priv, struct iwl4965_rx_mem_buffer *rxb) { -#ifdef CONFIG_IWL4965_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUG struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data; struct iwl4965_beacon_notif *beacon = &(pkt->u.beacon_status); u8 rate = iwl4965_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags); @@ -3659,7 +3659,7 @@ static void iwl4965_rx_beacon_notif(struct iwl4965_priv *priv, static void iwl4965_rx_reply_scan(struct iwl4965_priv *priv, struct iwl4965_rx_mem_buffer *rxb) { -#ifdef CONFIG_IWL4965_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUG struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data; struct iwl4965_scanreq_notification *notif = (struct iwl4965_scanreq_notification *)pkt->u.raw; @@ -4510,13 +4510,13 @@ static int iwl4965_tx_queue_update_write_ptr(struct iwl4965_priv *priv, return rc; } -#ifdef CONFIG_IWL4965_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUG static void iwl4965_print_rx_config_cmd(struct iwl4965_rxon_cmd *rxon) { DECLARE_MAC_BUF(mac); IWL_DEBUG_RADIO("RX CONFIG:\n"); - iwl4965_print_hex_dump(IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon)); + iwl_print_hex_dump(IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon)); IWL_DEBUG_RADIO("u16 channel: 0x%x\n", le16_to_cpu(rxon->channel)); IWL_DEBUG_RADIO("u32 flags: 0x%08X\n", le32_to_cpu(rxon->flags)); IWL_DEBUG_RADIO("u32 filter_flags: 0x%08x\n", @@ -4733,8 +4733,8 @@ static void iwl4965_irq_handle_error(struct iwl4965_priv *priv) /* Cancel currently queued command. */ clear_bit(STATUS_HCMD_ACTIVE, &priv->status); -#ifdef CONFIG_IWL4965_DEBUG - if (iwl4965_debug_level & IWL_DL_FW_ERRORS) { +#ifdef CONFIG_IWLWIFI_DEBUG + if (iwl_debug_level & IWL_DL_FW_ERRORS) { iwl4965_dump_nic_error_log(priv); iwl4965_dump_nic_event_log(priv); iwl4965_print_rx_config_cmd(&priv->staging_rxon); @@ -4782,7 +4782,7 @@ static void iwl4965_irq_tasklet(struct iwl4965_priv *priv) u32 inta, handled = 0; u32 inta_fh; unsigned long flags; -#ifdef CONFIG_IWL4965_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUG u32 inta_mask; #endif @@ -4800,8 +4800,8 @@ static void iwl4965_irq_tasklet(struct iwl4965_priv *priv) inta_fh = iwl4965_read32(priv, CSR_FH_INT_STATUS); iwl4965_write32(priv, CSR_FH_INT_STATUS, inta_fh); -#ifdef CONFIG_IWL4965_DEBUG - if (iwl4965_debug_level & IWL_DL_ISR) { +#ifdef CONFIG_IWLWIFI_DEBUG + if (iwl_debug_level & IWL_DL_ISR) { /* just for debug */ inta_mask = iwl4965_read32(priv, CSR_INT_MASK); IWL_DEBUG_ISR("inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", @@ -4834,8 +4834,8 @@ static void iwl4965_irq_tasklet(struct iwl4965_priv *priv) return; } -#ifdef CONFIG_IWL4965_DEBUG - if (iwl4965_debug_level & (IWL_DL_ISR)) { +#ifdef CONFIG_IWLWIFI_DEBUG + if (iwl_debug_level & (IWL_DL_ISR)) { /* NIC fires this, but we don't use it, redundant with WAKEUP */ if (inta & CSR_INT_BIT_SCD) IWL_DEBUG_ISR("Scheduler finished to transmit " @@ -4925,8 +4925,8 @@ static void iwl4965_irq_tasklet(struct iwl4965_priv *priv) /* Re-enable all interrupts */ iwl4965_enable_interrupts(priv); -#ifdef CONFIG_IWL4965_DEBUG - if (iwl4965_debug_level & (IWL_DL_ISR)) { +#ifdef CONFIG_IWLWIFI_DEBUG + if (iwl_debug_level & (IWL_DL_ISR)) { inta = iwl4965_read32(priv, CSR_INT); inta_mask = iwl4965_read32(priv, CSR_INT_MASK); inta_fh = iwl4965_read32(priv, CSR_FH_INT_STATUS); @@ -7916,7 +7916,7 @@ static int iwl4965_mac_conf_ht(struct ieee80211_hw *hw, * *****************************************************************************/ -#ifdef CONFIG_IWL4965_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUG /* * The following adds a new attribute to the sysfs representation @@ -7928,7 +7928,7 @@ static int iwl4965_mac_conf_ht(struct ieee80211_hw *hw, static ssize_t show_debug_level(struct device_driver *d, char *buf) { - return sprintf(buf, "0x%08X\n", iwl4965_debug_level); + return sprintf(buf, "0x%08X\n", iwl_debug_level); } static ssize_t store_debug_level(struct device_driver *d, const char *buf, size_t count) @@ -7941,7 +7941,7 @@ static ssize_t store_debug_level(struct device_driver *d, printk(KERN_INFO DRV_NAME ": %s is not in hex or decimal form.\n", buf); else - iwl4965_debug_level = val; + iwl_debug_level = val; return strnlen(buf, count); } @@ -7949,7 +7949,7 @@ static ssize_t store_debug_level(struct device_driver *d, static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO, show_debug_level, store_debug_level); -#endif /* CONFIG_IWL4965_DEBUG */ +#endif /* CONFIG_IWLWIFI_DEBUG */ static ssize_t show_rf_kill(struct device *d, struct device_attribute *attr, char *buf) @@ -8548,8 +8548,8 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e priv->pci_dev = pdev; priv->antenna = (enum iwl4965_antenna)iwl4965_param_antenna; -#ifdef CONFIG_IWL4965_DEBUG - iwl4965_debug_level = iwl4965_param_debug; +#ifdef CONFIG_IWLWIFI_DEBUG + iwl_debug_level = iwl4965_param_debug; atomic_set(&priv->restrict_refcnt, 0); #endif priv->retry_rate = 1; @@ -8878,7 +8878,7 @@ static int __init iwl4965_init(void) IWL_ERROR("Unable to initialize PCI module\n"); return ret; } -#ifdef CONFIG_IWL4965_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUG ret = driver_create_file(&iwl4965_driver.driver, &driver_attr_debug_level); if (ret) { IWL_ERROR("Unable to create driver sysfs file\n"); @@ -8892,7 +8892,7 @@ static int __init iwl4965_init(void) static void __exit iwl4965_exit(void) { -#ifdef CONFIG_IWL4965_DEBUG +#ifdef CONFIG_IWLWIFI_DEBUG driver_remove_file(&iwl4965_driver.driver, &driver_attr_debug_level); #endif pci_unregister_driver(&iwl4965_driver); -- cgit v1.2.1 From c79dd5b5bc5a65822cdc9d571032c469ad7577d5 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 12 Mar 2008 16:58:50 -0700 Subject: iwlwifi: rename struct iwl4965_priv to struct iwl_priv This patch renames iwl4965_priv to iwl_priv. iwl_priv will be shared by more hw. Signed-off-by: Tomas Winkler Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965-io.h | 58 ++-- drivers/net/wireless/iwlwifi/iwl-4965-rs.c | 42 +-- drivers/net/wireless/iwlwifi/iwl-4965.c | 178 ++++++------- drivers/net/wireless/iwlwifi/iwl-4965.h | 128 ++++----- drivers/net/wireless/iwlwifi/iwl-eeprom.c | 10 +- drivers/net/wireless/iwlwifi/iwl-eeprom.h | 18 +- drivers/net/wireless/iwlwifi/iwl4965-base.c | 396 ++++++++++++++-------------- 7 files changed, 415 insertions(+), 415 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-io.h b/drivers/net/wireless/iwlwifi/iwl-4965-io.h index 3accdfb33e56..fba7d03d4291 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-io.h @@ -61,7 +61,7 @@ #define _iwl4965_write32(priv, ofs, val) writel((val), (priv)->hw_base + (ofs)) #ifdef CONFIG_IWLWIFI_DEBUG -static inline void __iwl4965_write32(const char *f, u32 l, struct iwl4965_priv *priv, +static inline void __iwl4965_write32(const char *f, u32 l, struct iwl_priv *priv, u32 ofs, u32 val) { IWL_DEBUG_IO("write32(0x%08X, 0x%08X) - %s %d\n", ofs, val, f, l); @@ -75,7 +75,7 @@ static inline void __iwl4965_write32(const char *f, u32 l, struct iwl4965_priv * #define _iwl4965_read32(priv, ofs) readl((priv)->hw_base + (ofs)) #ifdef CONFIG_IWLWIFI_DEBUG -static inline u32 __iwl4965_read32(char *f, u32 l, struct iwl4965_priv *priv, u32 ofs) +static inline u32 __iwl4965_read32(char *f, u32 l, struct iwl_priv *priv, u32 ofs) { IWL_DEBUG_IO("read_direct32(0x%08X) - %s %d\n", ofs, f, l); return _iwl4965_read32(priv, ofs); @@ -85,7 +85,7 @@ static inline u32 __iwl4965_read32(char *f, u32 l, struct iwl4965_priv *priv, u3 #define iwl4965_read32(p, o) _iwl4965_read32(p, o) #endif -static inline int _iwl4965_poll_bit(struct iwl4965_priv *priv, u32 addr, +static inline int _iwl4965_poll_bit(struct iwl_priv *priv, u32 addr, u32 bits, u32 mask, int timeout) { int i = 0; @@ -101,7 +101,7 @@ static inline int _iwl4965_poll_bit(struct iwl4965_priv *priv, u32 addr, } #ifdef CONFIG_IWLWIFI_DEBUG static inline int __iwl4965_poll_bit(const char *f, u32 l, - struct iwl4965_priv *priv, u32 addr, + struct iwl_priv *priv, u32 addr, u32 bits, u32 mask, int timeout) { int ret = _iwl4965_poll_bit(priv, addr, bits, mask, timeout); @@ -116,13 +116,13 @@ static inline int __iwl4965_poll_bit(const char *f, u32 l, #define iwl4965_poll_bit(p, a, b, m, t) _iwl4965_poll_bit(p, a, b, m, t) #endif -static inline void _iwl4965_set_bit(struct iwl4965_priv *priv, u32 reg, u32 mask) +static inline void _iwl4965_set_bit(struct iwl_priv *priv, u32 reg, u32 mask) { _iwl4965_write32(priv, reg, _iwl4965_read32(priv, reg) | mask); } #ifdef CONFIG_IWLWIFI_DEBUG static inline void __iwl4965_set_bit(const char *f, u32 l, - struct iwl4965_priv *priv, u32 reg, u32 mask) + struct iwl_priv *priv, u32 reg, u32 mask) { u32 val = _iwl4965_read32(priv, reg) | mask; IWL_DEBUG_IO("set_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val); @@ -133,13 +133,13 @@ static inline void __iwl4965_set_bit(const char *f, u32 l, #define iwl4965_set_bit(p, r, m) _iwl4965_set_bit(p, r, m) #endif -static inline void _iwl4965_clear_bit(struct iwl4965_priv *priv, u32 reg, u32 mask) +static inline void _iwl4965_clear_bit(struct iwl_priv *priv, u32 reg, u32 mask) { _iwl4965_write32(priv, reg, _iwl4965_read32(priv, reg) & ~mask); } #ifdef CONFIG_IWLWIFI_DEBUG static inline void __iwl4965_clear_bit(const char *f, u32 l, - struct iwl4965_priv *priv, u32 reg, u32 mask) + struct iwl_priv *priv, u32 reg, u32 mask) { u32 val = _iwl4965_read32(priv, reg) & ~mask; IWL_DEBUG_IO("clear_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val); @@ -150,7 +150,7 @@ static inline void __iwl4965_clear_bit(const char *f, u32 l, #define iwl4965_clear_bit(p, r, m) _iwl4965_clear_bit(p, r, m) #endif -static inline int _iwl4965_grab_nic_access(struct iwl4965_priv *priv) +static inline int _iwl4965_grab_nic_access(struct iwl_priv *priv) { int ret; u32 gp_ctl; @@ -194,7 +194,7 @@ static inline int _iwl4965_grab_nic_access(struct iwl4965_priv *priv) #ifdef CONFIG_IWLWIFI_DEBUG static inline int __iwl4965_grab_nic_access(const char *f, u32 l, - struct iwl4965_priv *priv) + struct iwl_priv *priv) { if (atomic_read(&priv->restrict_refcnt)) IWL_DEBUG_INFO("Grabbing access while already held at " @@ -210,7 +210,7 @@ static inline int __iwl4965_grab_nic_access(const char *f, u32 l, _iwl4965_grab_nic_access(priv) #endif -static inline void _iwl4965_release_nic_access(struct iwl4965_priv *priv) +static inline void _iwl4965_release_nic_access(struct iwl_priv *priv) { #ifdef CONFIG_IWLWIFI_DEBUG if (atomic_dec_and_test(&priv->restrict_refcnt)) @@ -220,7 +220,7 @@ static inline void _iwl4965_release_nic_access(struct iwl4965_priv *priv) } #ifdef CONFIG_IWLWIFI_DEBUG static inline void __iwl4965_release_nic_access(const char *f, u32 l, - struct iwl4965_priv *priv) + struct iwl_priv *priv) { if (atomic_read(&priv->restrict_refcnt) <= 0) IWL_ERROR("Release unheld nic access at line %d.\n", l); @@ -235,13 +235,13 @@ static inline void __iwl4965_release_nic_access(const char *f, u32 l, _iwl4965_release_nic_access(priv) #endif -static inline u32 _iwl4965_read_direct32(struct iwl4965_priv *priv, u32 reg) +static inline u32 _iwl4965_read_direct32(struct iwl_priv *priv, u32 reg) { return _iwl4965_read32(priv, reg); } #ifdef CONFIG_IWLWIFI_DEBUG static inline u32 __iwl4965_read_direct32(const char *f, u32 l, - struct iwl4965_priv *priv, u32 reg) + struct iwl_priv *priv, u32 reg) { u32 value = _iwl4965_read_direct32(priv, reg); if (!atomic_read(&priv->restrict_refcnt)) @@ -256,14 +256,14 @@ static inline u32 __iwl4965_read_direct32(const char *f, u32 l, #define iwl4965_read_direct32 _iwl4965_read_direct32 #endif -static inline void _iwl4965_write_direct32(struct iwl4965_priv *priv, +static inline void _iwl4965_write_direct32(struct iwl_priv *priv, u32 reg, u32 value) { _iwl4965_write32(priv, reg, value); } #ifdef CONFIG_IWLWIFI_DEBUG static void __iwl4965_write_direct32(u32 line, - struct iwl4965_priv *priv, u32 reg, u32 value) + struct iwl_priv *priv, u32 reg, u32 value) { if (!atomic_read(&priv->restrict_refcnt)) IWL_ERROR("Nic access not held from line %d\n", line); @@ -275,7 +275,7 @@ static void __iwl4965_write_direct32(u32 line, #define iwl4965_write_direct32 _iwl4965_write_direct32 #endif -static inline void iwl4965_write_reg_buf(struct iwl4965_priv *priv, +static inline void iwl4965_write_reg_buf(struct iwl_priv *priv, u32 reg, u32 len, u32 *values) { u32 count = sizeof(u32); @@ -286,7 +286,7 @@ static inline void iwl4965_write_reg_buf(struct iwl4965_priv *priv, } } -static inline int _iwl4965_poll_direct_bit(struct iwl4965_priv *priv, +static inline int _iwl4965_poll_direct_bit(struct iwl_priv *priv, u32 addr, u32 mask, int timeout) { int i = 0; @@ -303,7 +303,7 @@ static inline int _iwl4965_poll_direct_bit(struct iwl4965_priv *priv, #ifdef CONFIG_IWLWIFI_DEBUG static inline int __iwl4965_poll_direct_bit(const char *f, u32 l, - struct iwl4965_priv *priv, + struct iwl_priv *priv, u32 addr, u32 mask, int timeout) { int ret = _iwl4965_poll_direct_bit(priv, addr, mask, timeout); @@ -322,13 +322,13 @@ static inline int __iwl4965_poll_direct_bit(const char *f, u32 l, #define iwl4965_poll_direct_bit _iwl4965_poll_direct_bit #endif -static inline u32 _iwl4965_read_prph(struct iwl4965_priv *priv, u32 reg) +static inline u32 _iwl4965_read_prph(struct iwl_priv *priv, u32 reg) { _iwl4965_write_direct32(priv, HBUS_TARG_PRPH_RADDR, reg | (3 << 24)); return _iwl4965_read_direct32(priv, HBUS_TARG_PRPH_RDAT); } #ifdef CONFIG_IWLWIFI_DEBUG -static inline u32 __iwl4965_read_prph(u32 line, struct iwl4965_priv *priv, u32 reg) +static inline u32 __iwl4965_read_prph(u32 line, struct iwl_priv *priv, u32 reg) { if (!atomic_read(&priv->restrict_refcnt)) IWL_ERROR("Nic access not held from line %d\n", line); @@ -341,7 +341,7 @@ static inline u32 __iwl4965_read_prph(u32 line, struct iwl4965_priv *priv, u32 r #define iwl4965_read_prph _iwl4965_read_prph #endif -static inline void _iwl4965_write_prph(struct iwl4965_priv *priv, +static inline void _iwl4965_write_prph(struct iwl_priv *priv, u32 addr, u32 val) { _iwl4965_write_direct32(priv, HBUS_TARG_PRPH_WADDR, @@ -349,7 +349,7 @@ static inline void _iwl4965_write_prph(struct iwl4965_priv *priv, _iwl4965_write_direct32(priv, HBUS_TARG_PRPH_WDAT, val); } #ifdef CONFIG_IWLWIFI_DEBUG -static inline void __iwl4965_write_prph(u32 line, struct iwl4965_priv *priv, +static inline void __iwl4965_write_prph(u32 line, struct iwl_priv *priv, u32 addr, u32 val) { if (!atomic_read(&priv->restrict_refcnt)) @@ -366,7 +366,7 @@ static inline void __iwl4965_write_prph(u32 line, struct iwl4965_priv *priv, #define _iwl4965_set_bits_prph(priv, reg, mask) \ _iwl4965_write_prph(priv, reg, (_iwl4965_read_prph(priv, reg) | mask)) #ifdef CONFIG_IWLWIFI_DEBUG -static inline void __iwl4965_set_bits_prph(u32 line, struct iwl4965_priv *priv, +static inline void __iwl4965_set_bits_prph(u32 line, struct iwl_priv *priv, u32 reg, u32 mask) { if (!atomic_read(&priv->restrict_refcnt)) @@ -385,7 +385,7 @@ static inline void __iwl4965_set_bits_prph(u32 line, struct iwl4965_priv *priv, #ifdef CONFIG_IWLWIFI_DEBUG static inline void __iwl4965_set_bits_mask_prph(u32 line, - struct iwl4965_priv *priv, u32 reg, u32 bits, u32 mask) + struct iwl_priv *priv, u32 reg, u32 bits, u32 mask) { if (!atomic_read(&priv->restrict_refcnt)) IWL_ERROR("Nic access not held from line %d\n", line); @@ -397,26 +397,26 @@ static inline void __iwl4965_set_bits_mask_prph(u32 line, #define iwl4965_set_bits_mask_prph _iwl4965_set_bits_mask_prph #endif -static inline void iwl4965_clear_bits_prph(struct iwl4965_priv +static inline void iwl4965_clear_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask) { u32 val = _iwl4965_read_prph(priv, reg); _iwl4965_write_prph(priv, reg, (val & ~mask)); } -static inline u32 iwl4965_read_targ_mem(struct iwl4965_priv *priv, u32 addr) +static inline u32 iwl4965_read_targ_mem(struct iwl_priv *priv, u32 addr) { iwl4965_write_direct32(priv, HBUS_TARG_MEM_RADDR, addr); return iwl4965_read_direct32(priv, HBUS_TARG_MEM_RDAT); } -static inline void iwl4965_write_targ_mem(struct iwl4965_priv *priv, u32 addr, u32 val) +static inline void iwl4965_write_targ_mem(struct iwl_priv *priv, u32 addr, u32 val) { iwl4965_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr); iwl4965_write_direct32(priv, HBUS_TARG_MEM_WDAT, val); } -static inline void iwl4965_write_targ_mem_buf(struct iwl4965_priv *priv, u32 addr, +static inline void iwl4965_write_targ_mem_buf(struct iwl_priv *priv, u32 addr, u32 len, u32 *values) { iwl4965_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr); diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c index 7733b23d582c..02990aeabab5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c @@ -162,11 +162,11 @@ struct iwl4965_lq_sta { struct dentry *rs_sta_dbgfs_tx_agg_tid_en_file; #endif struct iwl4965_rate dbg_fixed; - struct iwl4965_priv *drv; + struct iwl_priv *drv; #endif }; -static void rs_rate_scale_perform(struct iwl4965_priv *priv, +static void rs_rate_scale_perform(struct iwl_priv *priv, struct net_device *dev, struct ieee80211_hdr *hdr, struct sta_info *sta); @@ -229,7 +229,7 @@ static s32 expected_tpt_mimo40MHzSGI[IWL_RATE_COUNT] = { 0, 0, 0, 0, 131, 131, 191, 222, 242, 270, 284, 289, 293 }; -static int iwl4965_lq_sync_callback(struct iwl4965_priv *priv, +static int iwl4965_lq_sync_callback(struct iwl_priv *priv, struct iwl4965_cmd *cmd, struct sk_buff *skb) { /*We didn't cache the SKB; let the caller free it */ @@ -241,7 +241,7 @@ static inline u8 iwl4965_rate_get_rate(u32 rate_n_flags) return (u8)(rate_n_flags & 0xFF); } -static int rs_send_lq_cmd(struct iwl4965_priv *priv, +static int rs_send_lq_cmd(struct iwl_priv *priv, struct iwl4965_link_quality_cmd *lq, u8 flags) { #ifdef CONFIG_IWLWIFI_DEBUG @@ -388,7 +388,7 @@ static u32 rs_tl_get_load(struct iwl4965_lq_sta *lq_data, u8 tid) return tl->total; } -static void rs_tl_turn_on_agg_for_tid(struct iwl4965_priv *priv, +static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, struct iwl4965_lq_sta *lq_data, u8 tid, struct sta_info *sta) { @@ -407,7 +407,7 @@ static void rs_tl_turn_on_agg_for_tid(struct iwl4965_priv *priv, } } -static void rs_tl_turn_on_agg(struct iwl4965_priv *priv, u8 tid, +static void rs_tl_turn_on_agg(struct iwl_priv *priv, u8 tid, struct iwl4965_lq_sta *lq_data, struct sta_info *sta) { @@ -658,7 +658,7 @@ static inline void rs_toggle_antenna(struct iwl4965_rate *new_rate, } } -static inline u8 rs_use_green(struct iwl4965_priv *priv, +static inline u8 rs_use_green(struct iwl_priv *priv, struct ieee80211_conf *conf) { #ifdef CONFIG_IWL4965_HT @@ -821,7 +821,7 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, struct iwl4965_link_quality_cmd *table; struct sta_info *sta; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - struct iwl4965_priv *priv = (struct iwl4965_priv *)priv_rate; + struct iwl_priv *priv = (struct iwl_priv *)priv_rate; struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); struct ieee80211_hw *hw = local_to_hw(local); struct iwl4965_rate_scale_data *window = NULL; @@ -1128,7 +1128,7 @@ static void rs_get_expected_tpt_table(struct iwl4965_lq_sta *lq_sta, * to decrease to match "active" throughput. When moving from MIMO to SISO, * bit rate will typically need to increase, but not if performance was bad. */ -static s32 rs_get_best_rate(struct iwl4965_priv *priv, +static s32 rs_get_best_rate(struct iwl_priv *priv, struct iwl4965_lq_sta *lq_sta, struct iwl4965_scale_tbl_info *tbl, /* "search" */ u16 rate_mask, s8 index, s8 rate) @@ -1226,7 +1226,7 @@ static inline u8 rs_is_both_ant_supp(u8 valid_antenna) /* * Set up search table for MIMO */ -static int rs_switch_to_mimo(struct iwl4965_priv *priv, +static int rs_switch_to_mimo(struct iwl_priv *priv, struct iwl4965_lq_sta *lq_sta, struct ieee80211_conf *conf, struct sta_info *sta, @@ -1291,7 +1291,7 @@ static int rs_switch_to_mimo(struct iwl4965_priv *priv, /* * Set up search table for SISO */ -static int rs_switch_to_siso(struct iwl4965_priv *priv, +static int rs_switch_to_siso(struct iwl_priv *priv, struct iwl4965_lq_sta *lq_sta, struct ieee80211_conf *conf, struct sta_info *sta, @@ -1354,7 +1354,7 @@ static int rs_switch_to_siso(struct iwl4965_priv *priv, /* * Try to switch to new modulation mode from legacy */ -static int rs_move_legacy_other(struct iwl4965_priv *priv, +static int rs_move_legacy_other(struct iwl_priv *priv, struct iwl4965_lq_sta *lq_sta, struct ieee80211_conf *conf, struct sta_info *sta, @@ -1452,7 +1452,7 @@ static int rs_move_legacy_other(struct iwl4965_priv *priv, /* * Try to switch to new modulation mode from SISO */ -static int rs_move_siso_to_other(struct iwl4965_priv *priv, +static int rs_move_siso_to_other(struct iwl_priv *priv, struct iwl4965_lq_sta *lq_sta, struct ieee80211_conf *conf, struct sta_info *sta, @@ -1548,7 +1548,7 @@ static int rs_move_siso_to_other(struct iwl4965_priv *priv, /* * Try to switch to new modulation mode from MIMO */ -static int rs_move_mimo_to_other(struct iwl4965_priv *priv, +static int rs_move_mimo_to_other(struct iwl_priv *priv, struct iwl4965_lq_sta *lq_sta, struct ieee80211_conf *conf, struct sta_info *sta, @@ -1728,7 +1728,7 @@ static void rs_stay_in_table(struct iwl4965_lq_sta *lq_sta) /* * Do rate scaling and search for new modulation mode. */ -static void rs_rate_scale_perform(struct iwl4965_priv *priv, +static void rs_rate_scale_perform(struct iwl_priv *priv, struct net_device *dev, struct ieee80211_hdr *hdr, struct sta_info *sta) @@ -2148,7 +2148,7 @@ out: } -static void rs_initialize_lq(struct iwl4965_priv *priv, +static void rs_initialize_lq(struct iwl_priv *priv, struct ieee80211_conf *conf, struct sta_info *sta) { @@ -2213,7 +2213,7 @@ static void rs_get_rate(void *priv_rate, struct net_device *dev, struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct sta_info *sta; u16 fc; - struct iwl4965_priv *priv = (struct iwl4965_priv *)priv_rate; + struct iwl_priv *priv = (struct iwl_priv *)priv_rate; struct iwl4965_lq_sta *lq_sta; IWL_DEBUG_RATE_LIMIT("rate scale calculate new rate for skb\n"); @@ -2294,7 +2294,7 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, int i, j; struct ieee80211_conf *conf = &local->hw.conf; struct ieee80211_supported_band *sband; - struct iwl4965_priv *priv = (struct iwl4965_priv *)priv_rate; + struct iwl_priv *priv = (struct iwl_priv *)priv_rate; struct iwl4965_lq_sta *lq_sta = priv_sta; sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; @@ -2516,7 +2516,7 @@ static void rs_free(void *priv_rate) static void rs_clear(void *priv_rate) { - struct iwl4965_priv *priv = (struct iwl4965_priv *) priv_rate; + struct iwl_priv *priv = (struct iwl_priv *) priv_rate; IWL_DEBUG_RATE("enter\n"); @@ -2726,7 +2726,7 @@ static struct rate_control_ops rs_ops = { int iwl4965_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id) { struct ieee80211_local *local = hw_to_local(hw); - struct iwl4965_priv *priv = hw->priv; + struct iwl_priv *priv = hw->priv; struct iwl4965_lq_sta *lq_sta; struct sta_info *sta; int cnt = 0, i; @@ -2816,7 +2816,7 @@ int iwl4965_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id) void iwl4965_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) { - struct iwl4965_priv *priv = hw->priv; + struct iwl_priv *priv = hw->priv; priv->lq_mngr.lq_ready = 1; } diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 2896af28981a..7b0ad728f927 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -43,7 +43,7 @@ #include "iwl-4965.h" #include "iwl-helpers.h" -static void iwl4965_hw_card_show_info(struct iwl4965_priv *priv); +static void iwl4965_hw_card_show_info(struct iwl_priv *priv); #define IWL_DECLARE_RATE_INFO(r, s, ip, in, rp, rn, pp, np) \ [IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP, \ @@ -111,7 +111,7 @@ static int is_fat_channel(__le32 rxon_flags) (rxon_flags & RXON_FLG_CHANNEL_MODE_MIXED_MSK); } -static u8 is_single_stream(struct iwl4965_priv *priv) +static u8 is_single_stream(struct iwl_priv *priv) { #ifdef CONFIG_IWL4965_HT if (!priv->current_ht_config.is_ht || @@ -155,7 +155,7 @@ int iwl4965_hwrate_to_plcp_idx(u32 rate_n_flags) /** * translate ucode response to mac80211 tx status control values */ -void iwl4965_hwrate_to_tx_control(struct iwl4965_priv *priv, u32 rate_n_flags, +void iwl4965_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, struct ieee80211_tx_control *control) { int rate_index; @@ -188,7 +188,7 @@ void iwl4965_hwrate_to_tx_control(struct iwl4965_priv *priv, u32 rate_n_flags, * MIMO (dual stream) requires at least 2, but works better with 3. * This does not determine *which* chains to use, just how many. */ -static int iwl4965_get_rx_chain_counter(struct iwl4965_priv *priv, +static int iwl4965_get_rx_chain_counter(struct iwl_priv *priv, u8 *idle_state, u8 *rx_state) { u8 is_single = is_single_stream(priv); @@ -217,7 +217,7 @@ static int iwl4965_get_rx_chain_counter(struct iwl4965_priv *priv, return 0; } -int iwl4965_hw_rxq_stop(struct iwl4965_priv *priv) +int iwl4965_hw_rxq_stop(struct iwl_priv *priv) { int rc; unsigned long flags; @@ -242,7 +242,7 @@ int iwl4965_hw_rxq_stop(struct iwl4965_priv *priv) return 0; } -u8 iwl4965_hw_find_station(struct iwl4965_priv *priv, const u8 *addr) +u8 iwl4965_hw_find_station(struct iwl_priv *priv, const u8 *addr) { int i; int start = 0; @@ -274,7 +274,7 @@ u8 iwl4965_hw_find_station(struct iwl4965_priv *priv, const u8 *addr) return ret; } -static int iwl4965_nic_set_pwr_src(struct iwl4965_priv *priv, int pwr_max) +static int iwl4965_nic_set_pwr_src(struct iwl_priv *priv, int pwr_max) { int ret; unsigned long flags; @@ -307,7 +307,7 @@ static int iwl4965_nic_set_pwr_src(struct iwl4965_priv *priv, int pwr_max) return ret; } -static int iwl4965_rx_init(struct iwl4965_priv *priv, struct iwl4965_rx_queue *rxq) +static int iwl4965_rx_init(struct iwl_priv *priv, struct iwl4965_rx_queue *rxq) { int rc; unsigned long flags; @@ -360,7 +360,7 @@ static int iwl4965_rx_init(struct iwl4965_priv *priv, struct iwl4965_rx_queue *r } /* Tell 4965 where to find the "keep warm" buffer */ -static int iwl4965_kw_init(struct iwl4965_priv *priv) +static int iwl4965_kw_init(struct iwl_priv *priv) { unsigned long flags; int rc; @@ -378,7 +378,7 @@ out: return rc; } -static int iwl4965_kw_alloc(struct iwl4965_priv *priv) +static int iwl4965_kw_alloc(struct iwl_priv *priv) { struct pci_dev *dev = priv->pci_dev; struct iwl4965_kw *kw = &priv->kw; @@ -399,7 +399,7 @@ static int iwl4965_kw_alloc(struct iwl4965_priv *priv) * * Does not set up a command, or touch hardware. */ -int iwl4965_set_fat_chan_info(struct iwl4965_priv *priv, +int iwl4965_set_fat_chan_info(struct iwl_priv *priv, enum ieee80211_band band, u16 channel, const struct iwl4965_eeprom_channel *eeprom_ch, u8 fat_extension_channel) @@ -443,7 +443,7 @@ int iwl4965_set_fat_chan_info(struct iwl4965_priv *priv, /** * iwl4965_kw_free - Free the "keep warm" buffer */ -static void iwl4965_kw_free(struct iwl4965_priv *priv) +static void iwl4965_kw_free(struct iwl_priv *priv) { struct pci_dev *dev = priv->pci_dev; struct iwl4965_kw *kw = &priv->kw; @@ -461,7 +461,7 @@ static void iwl4965_kw_free(struct iwl4965_priv *priv) * @param priv * @return error code */ -static int iwl4965_txq_ctx_reset(struct iwl4965_priv *priv) +static int iwl4965_txq_ctx_reset(struct iwl_priv *priv) { int rc = 0; int txq_id, slots_num; @@ -523,7 +523,7 @@ static int iwl4965_txq_ctx_reset(struct iwl4965_priv *priv) return rc; } -int iwl4965_hw_nic_init(struct iwl4965_priv *priv) +int iwl4965_hw_nic_init(struct iwl_priv *priv) { int rc; unsigned long flags; @@ -668,7 +668,7 @@ int iwl4965_hw_nic_init(struct iwl4965_priv *priv) return 0; } -int iwl4965_hw_nic_stop_master(struct iwl4965_priv *priv) +int iwl4965_hw_nic_stop_master(struct iwl_priv *priv) { int rc = 0; u32 reg_val; @@ -704,7 +704,7 @@ int iwl4965_hw_nic_stop_master(struct iwl4965_priv *priv) /** * iwl4965_hw_txq_ctx_stop - Stop all Tx DMA channels, free Tx queue memory */ -void iwl4965_hw_txq_ctx_stop(struct iwl4965_priv *priv) +void iwl4965_hw_txq_ctx_stop(struct iwl_priv *priv) { int txq_id; @@ -732,7 +732,7 @@ void iwl4965_hw_txq_ctx_stop(struct iwl4965_priv *priv) iwl4965_hw_txq_ctx_free(priv); } -int iwl4965_hw_nic_reset(struct iwl4965_priv *priv) +int iwl4965_hw_nic_reset(struct iwl_priv *priv) { int rc = 0; unsigned long flags; @@ -793,7 +793,7 @@ int iwl4965_hw_nic_reset(struct iwl4965_priv *priv) */ static void iwl4965_bg_statistics_periodic(unsigned long data) { - struct iwl4965_priv *priv = (struct iwl4965_priv *)data; + struct iwl_priv *priv = (struct iwl_priv *)data; queue_work(priv->workqueue, &priv->statistics_work); } @@ -805,7 +805,7 @@ static void iwl4965_bg_statistics_periodic(unsigned long data) */ static void iwl4965_bg_statistics_work(struct work_struct *work) { - struct iwl4965_priv *priv = container_of(work, struct iwl4965_priv, + struct iwl_priv *priv = container_of(work, struct iwl_priv, statistics_work); if (test_bit(STATUS_EXIT_PENDING, &priv->status)) @@ -819,7 +819,7 @@ static void iwl4965_bg_statistics_work(struct work_struct *work) #define CT_LIMIT_CONST 259 #define TM_CT_KILL_THRESHOLD 110 -void iwl4965_rf_kill_ct_config(struct iwl4965_priv *priv) +void iwl4965_rf_kill_ct_config(struct iwl_priv *priv) { struct iwl4965_ct_kill_config cmd; u32 R1, R2, R3; @@ -865,7 +865,7 @@ void iwl4965_rf_kill_ct_config(struct iwl4965_priv *priv) * enough to receive all of our own network traffic, but not so * high that our DSP gets too busy trying to lock onto non-network * activity/noise. */ -static int iwl4965_sens_energy_cck(struct iwl4965_priv *priv, +static int iwl4965_sens_energy_cck(struct iwl_priv *priv, u32 norm_fa, u32 rx_enable_time, struct statistics_general_data *rx_info) @@ -1056,7 +1056,7 @@ static int iwl4965_sens_energy_cck(struct iwl4965_priv *priv, } -static int iwl4965_sens_auto_corr_ofdm(struct iwl4965_priv *priv, +static int iwl4965_sens_auto_corr_ofdm(struct iwl_priv *priv, u32 norm_fa, u32 rx_enable_time) { @@ -1121,7 +1121,7 @@ static int iwl4965_sens_auto_corr_ofdm(struct iwl4965_priv *priv, return 0; } -static int iwl4965_sensitivity_callback(struct iwl4965_priv *priv, +static int iwl4965_sensitivity_callback(struct iwl_priv *priv, struct iwl4965_cmd *cmd, struct sk_buff *skb) { /* We didn't cache the SKB; let the caller free it */ @@ -1129,7 +1129,7 @@ static int iwl4965_sensitivity_callback(struct iwl4965_priv *priv, } /* Prepare a SENSITIVITY_CMD, send to uCode if values have changed */ -static int iwl4965_sensitivity_write(struct iwl4965_priv *priv, u8 flags) +static int iwl4965_sensitivity_write(struct iwl_priv *priv, u8 flags) { int rc = 0; struct iwl4965_sensitivity_cmd cmd ; @@ -1206,7 +1206,7 @@ static int iwl4965_sensitivity_write(struct iwl4965_priv *priv, u8 flags) return 0; } -void iwl4965_init_sensitivity(struct iwl4965_priv *priv, u8 flags, u8 force) +void iwl4965_init_sensitivity(struct iwl_priv *priv, u8 flags, u8 force) { int rc = 0; int i; @@ -1264,7 +1264,7 @@ void iwl4965_init_sensitivity(struct iwl4965_priv *priv, u8 flags, u8 force) /* Reset differential Rx gains in NIC to prepare for chain noise calibration. * Called after every association, but this runs only once! * ... once chain noise is calibrated the first time, it's good forever. */ -void iwl4965_chain_noise_reset(struct iwl4965_priv *priv) +void iwl4965_chain_noise_reset(struct iwl_priv *priv) { struct iwl4965_chain_noise_data *data = NULL; int rc = 0; @@ -1293,7 +1293,7 @@ void iwl4965_chain_noise_reset(struct iwl4965_priv *priv) * 1) Which antennas are connected. * 2) Differential rx gain settings to balance the 3 receivers. */ -static void iwl4965_noise_calibration(struct iwl4965_priv *priv, +static void iwl4965_noise_calibration(struct iwl_priv *priv, struct iwl4965_notif_statistics *stat_resp) { struct iwl4965_chain_noise_data *data = NULL; @@ -1526,7 +1526,7 @@ static void iwl4965_noise_calibration(struct iwl4965_priv *priv, return; } -static void iwl4965_sensitivity_calibration(struct iwl4965_priv *priv, +static void iwl4965_sensitivity_calibration(struct iwl_priv *priv, struct iwl4965_notif_statistics *resp) { int rc = 0; @@ -1633,7 +1633,7 @@ static void iwl4965_sensitivity_calibration(struct iwl4965_priv *priv, static void iwl4965_bg_sensitivity_work(struct work_struct *work) { - struct iwl4965_priv *priv = container_of(work, struct iwl4965_priv, + struct iwl_priv *priv = container_of(work, struct iwl_priv, sensitivity_work); mutex_lock(&priv->mutex); @@ -1663,7 +1663,7 @@ static void iwl4965_bg_sensitivity_work(struct work_struct *work) static void iwl4965_bg_txpower_work(struct work_struct *work) { - struct iwl4965_priv *priv = container_of(work, struct iwl4965_priv, + struct iwl_priv *priv = container_of(work, struct iwl_priv, txpower_work); /* If a scan happened to start before we got here @@ -1691,7 +1691,7 @@ static void iwl4965_bg_txpower_work(struct work_struct *work) /* * Acquire priv->lock before calling this function ! */ -static void iwl4965_set_wr_ptrs(struct iwl4965_priv *priv, int txq_id, u32 index) +static void iwl4965_set_wr_ptrs(struct iwl_priv *priv, int txq_id, u32 index) { iwl4965_write_direct32(priv, HBUS_TARG_WRPTR, (index & 0xff) | (txq_id << 8)); @@ -1705,7 +1705,7 @@ static void iwl4965_set_wr_ptrs(struct iwl4965_priv *priv, int txq_id, u32 index * * NOTE: Acquire priv->lock before calling this function ! */ -static void iwl4965_tx_queue_set_status(struct iwl4965_priv *priv, +static void iwl4965_tx_queue_set_status(struct iwl_priv *priv, struct iwl4965_tx_queue *txq, int tx_fifo_id, int scd_retry) { @@ -1739,17 +1739,17 @@ static const u16 default_queue_to_tx_fifo[] = { IWL_TX_FIFO_HCCA_2 }; -static inline void iwl4965_txq_ctx_activate(struct iwl4965_priv *priv, int txq_id) +static inline void iwl4965_txq_ctx_activate(struct iwl_priv *priv, int txq_id) { set_bit(txq_id, &priv->txq_ctx_active_msk); } -static inline void iwl4965_txq_ctx_deactivate(struct iwl4965_priv *priv, int txq_id) +static inline void iwl4965_txq_ctx_deactivate(struct iwl_priv *priv, int txq_id) { clear_bit(txq_id, &priv->txq_ctx_active_msk); } -int iwl4965_alive_notify(struct iwl4965_priv *priv) +int iwl4965_alive_notify(struct iwl_priv *priv) { u32 a; int i = 0; @@ -1841,7 +1841,7 @@ int iwl4965_alive_notify(struct iwl4965_priv *priv) * * Called when initializing driver */ -int iwl4965_hw_set_hw_setting(struct iwl4965_priv *priv) +int iwl4965_hw_set_hw_setting(struct iwl_priv *priv) { /* Allocate area for Tx byte count tables and Rx queue status */ priv->hw_setting.shared_virt = @@ -1876,7 +1876,7 @@ int iwl4965_hw_set_hw_setting(struct iwl4965_priv *priv) * * Destroy all TX DMA queues and structures */ -void iwl4965_hw_txq_ctx_free(struct iwl4965_priv *priv) +void iwl4965_hw_txq_ctx_free(struct iwl_priv *priv) { int txq_id; @@ -1894,7 +1894,7 @@ void iwl4965_hw_txq_ctx_free(struct iwl4965_priv *priv) * Does NOT advance any TFD circular buffer read/write indexes * Does NOT free the TFD itself (which is within circular buffer) */ -int iwl4965_hw_txq_free_tfd(struct iwl4965_priv *priv, struct iwl4965_tx_queue *txq) +int iwl4965_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl4965_tx_queue *txq) { struct iwl4965_tfd_frame *bd_tmp = (struct iwl4965_tfd_frame *)&txq->bd[0]; struct iwl4965_tfd_frame *bd = &bd_tmp[txq->q.read_ptr]; @@ -1947,7 +1947,7 @@ int iwl4965_hw_txq_free_tfd(struct iwl4965_priv *priv, struct iwl4965_tx_queue * return 0; } -int iwl4965_hw_reg_set_txpower(struct iwl4965_priv *priv, s8 power) +int iwl4965_hw_reg_set_txpower(struct iwl_priv *priv, s8 power) { IWL_ERROR("TODO: Implement iwl4965_hw_reg_set_txpower!\n"); return -EINVAL; @@ -2003,7 +2003,7 @@ static s32 iwl4965_get_voltage_compensation(s32 eeprom_voltage, } static const struct iwl4965_channel_info * -iwl4965_get_channel_txpower_info(struct iwl4965_priv *priv, +iwl4965_get_channel_txpower_info(struct iwl_priv *priv, enum ieee80211_band band, u16 channel) { const struct iwl4965_channel_info *ch_info; @@ -2042,7 +2042,7 @@ static s32 iwl4965_get_tx_atten_grp(u16 channel) return -1; } -static u32 iwl4965_get_sub_band(const struct iwl4965_priv *priv, u32 channel) +static u32 iwl4965_get_sub_band(const struct iwl_priv *priv, u32 channel) { s32 b = -1; @@ -2078,7 +2078,7 @@ static s32 iwl4965_interpolate_value(s32 x, s32 x1, s32 y1, s32 x2, s32 y2) * differences in channel frequencies, which is proportional to differences * in channel number. */ -static int iwl4965_interpolate_chan(struct iwl4965_priv *priv, u32 channel, +static int iwl4965_interpolate_chan(struct iwl_priv *priv, u32 channel, struct iwl4965_eeprom_calib_ch_info *chan_info) { s32 s = -1; @@ -2411,7 +2411,7 @@ static const struct gain_entry gain_table[2][108] = { } }; -static int iwl4965_fill_txpower_tbl(struct iwl4965_priv *priv, u8 band, u16 channel, +static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel, u8 is_fat, u8 ctrl_chan_high, struct iwl4965_tx_power_db *tx_power_tbl) { @@ -2668,7 +2668,7 @@ static int iwl4965_fill_txpower_tbl(struct iwl4965_priv *priv, u8 band, u16 chan * Uses the active RXON for channel, band, and characteristics (fat, high) * The power limit is taken from priv->user_txpower_limit. */ -int iwl4965_hw_reg_send_txpower(struct iwl4965_priv *priv) +int iwl4965_hw_reg_send_txpower(struct iwl_priv *priv) { struct iwl4965_txpowertable_cmd cmd = { 0 }; int rc = 0; @@ -2705,7 +2705,7 @@ int iwl4965_hw_reg_send_txpower(struct iwl4965_priv *priv) return rc; } -int iwl4965_hw_channel_switch(struct iwl4965_priv *priv, u16 channel) +int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel) { int rc; u8 band = 0; @@ -2749,7 +2749,7 @@ int iwl4965_hw_channel_switch(struct iwl4965_priv *priv, u16 channel) #define RTS_HCCA_RETRY_LIMIT 3 #define RTS_DFAULT_RETRY_LIMIT 60 -void iwl4965_hw_build_tx_cmd_rate(struct iwl4965_priv *priv, +void iwl4965_hw_build_tx_cmd_rate(struct iwl_priv *priv, struct iwl4965_cmd *cmd, struct ieee80211_tx_control *ctrl, struct ieee80211_hdr *hdr, int sta_id, @@ -2816,19 +2816,19 @@ void iwl4965_hw_build_tx_cmd_rate(struct iwl4965_priv *priv, tx->rate_n_flags = iwl4965_hw_set_rate_n_flags(rate_plcp, rate_flags); } -int iwl4965_hw_get_rx_read(struct iwl4965_priv *priv) +int iwl4965_hw_get_rx_read(struct iwl_priv *priv) { struct iwl4965_shared *shared_data = priv->hw_setting.shared_virt; return IWL_GET_BITS(*shared_data, rb_closed_stts_rb_num); } -int iwl4965_hw_get_temperature(struct iwl4965_priv *priv) +int iwl4965_hw_get_temperature(struct iwl_priv *priv) { return priv->temperature; } -unsigned int iwl4965_hw_get_beacon_cmd(struct iwl4965_priv *priv, +unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv, struct iwl4965_frame *frame, u8 rate) { struct iwl4965_tx_beacon_cmd *tx_beacon_cmd; @@ -2867,7 +2867,7 @@ unsigned int iwl4965_hw_get_beacon_cmd(struct iwl4965_priv *priv, * 4965 supports up to 16 Tx queues in DRAM, mapped to up to 8 Tx DMA * channels supported in hardware. */ -int iwl4965_hw_tx_queue_init(struct iwl4965_priv *priv, struct iwl4965_tx_queue *txq) +int iwl4965_hw_tx_queue_init(struct iwl_priv *priv, struct iwl4965_tx_queue *txq) { int rc; unsigned long flags; @@ -2895,7 +2895,7 @@ int iwl4965_hw_tx_queue_init(struct iwl4965_priv *priv, struct iwl4965_tx_queue return 0; } -int iwl4965_hw_txq_attach_buf_to_tfd(struct iwl4965_priv *priv, void *ptr, +int iwl4965_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *ptr, dma_addr_t addr, u16 len) { int index, is_odd; @@ -2929,7 +2929,7 @@ int iwl4965_hw_txq_attach_buf_to_tfd(struct iwl4965_priv *priv, void *ptr, return 0; } -static void iwl4965_hw_card_show_info(struct iwl4965_priv *priv) +static void iwl4965_hw_card_show_info(struct iwl_priv *priv) { u16 hw_version = priv->eeprom.board_revision_4965; @@ -2947,7 +2947,7 @@ static void iwl4965_hw_card_show_info(struct iwl4965_priv *priv) /** * iwl4965_tx_queue_update_wr_ptr - Set up entry in Tx byte-count array */ -int iwl4965_tx_queue_update_wr_ptr(struct iwl4965_priv *priv, +int iwl4965_tx_queue_update_wr_ptr(struct iwl_priv *priv, struct iwl4965_tx_queue *txq, u16 byte_cnt) { int len; @@ -2978,7 +2978,7 @@ int iwl4965_tx_queue_update_wr_ptr(struct iwl4965_priv *priv, * Selects how many and which Rx receivers/antennas/chains to use. * This should not be used for scan command ... it puts data in wrong place. */ -void iwl4965_set_rxon_chain(struct iwl4965_priv *priv) +void iwl4965_set_rxon_chain(struct iwl_priv *priv) { u8 is_single = is_single_stream(priv); u8 idle_state, rx_state; @@ -3031,7 +3031,7 @@ static s32 sign_extend(u32 oper, int index) * * A return of <0 indicates bogus data in the statistics */ -int iwl4965_get_temperature(const struct iwl4965_priv *priv) +int iwl4965_get_temperature(const struct iwl_priv *priv) { s32 temperature; s32 vt; @@ -3099,7 +3099,7 @@ int iwl4965_get_temperature(const struct iwl4965_priv *priv) * Assumes caller will replace priv->last_temperature once calibration * executed. */ -static int iwl4965_is_temp_calib_needed(struct iwl4965_priv *priv) +static int iwl4965_is_temp_calib_needed(struct iwl_priv *priv) { int temp_diff; @@ -3132,7 +3132,7 @@ static int iwl4965_is_temp_calib_needed(struct iwl4965_priv *priv) /* Calculate noise level, based on measurements during network silence just * before arriving beacon. This measurement can be done only if we know * exactly when to expect beacons, therefore only when we're associated. */ -static void iwl4965_rx_calc_noise(struct iwl4965_priv *priv) +static void iwl4965_rx_calc_noise(struct iwl_priv *priv) { struct statistics_rx_non_phy *rx_info = &(priv->statistics.rx.general); @@ -3169,7 +3169,7 @@ static void iwl4965_rx_calc_noise(struct iwl4965_priv *priv) priv->last_rx_noise); } -void iwl4965_hw_rx_statistics(struct iwl4965_priv *priv, struct iwl4965_rx_mem_buffer *rxb) +void iwl4965_hw_rx_statistics(struct iwl_priv *priv, struct iwl4965_rx_mem_buffer *rxb) { struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data; int change; @@ -3233,7 +3233,7 @@ void iwl4965_hw_rx_statistics(struct iwl4965_priv *priv, struct iwl4965_rx_mem_b queue_work(priv->workqueue, &priv->txpower_work); } -static void iwl4965_add_radiotap(struct iwl4965_priv *priv, +static void iwl4965_add_radiotap(struct iwl_priv *priv, struct sk_buff *skb, struct iwl4965_rx_phy_res *rx_start, struct ieee80211_rx_status *stats, @@ -3337,7 +3337,7 @@ static void iwl4965_add_radiotap(struct iwl4965_priv *priv, stats->flag |= RX_FLAG_RADIOTAP; } -static void iwl4965_handle_data_packet(struct iwl4965_priv *priv, int is_data, +static void iwl4965_handle_data_packet(struct iwl_priv *priv, int is_data, int include_phy, struct iwl4965_rx_mem_buffer *rxb, struct ieee80211_rx_status *stats) @@ -3552,7 +3552,7 @@ void iwl4965_init_ht_hw_capab(struct ieee80211_ht_info *ht_info, } #endif /* CONFIG_IWL4965_HT */ -static void iwl4965_sta_modify_ps_wake(struct iwl4965_priv *priv, int sta_id) +static void iwl4965_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id) { unsigned long flags; @@ -3566,7 +3566,7 @@ static void iwl4965_sta_modify_ps_wake(struct iwl4965_priv *priv, int sta_id) iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, CMD_ASYNC); } -static void iwl4965_update_ps_mode(struct iwl4965_priv *priv, u16 ps_bit, u8 *addr) +static void iwl4965_update_ps_mode(struct iwl_priv *priv, u16 ps_bit, u8 *addr) { /* FIXME: need locking over ps_status ??? */ u8 sta_id = iwl4965_hw_find_station(priv, addr); @@ -3595,7 +3595,7 @@ static void iwl4965_update_ps_mode(struct iwl4965_priv *priv, u16 ps_bit, u8 *ad * TODO: This was originally written for 3945, need to audit for * proper operation with 4965. */ -static void iwl4965_dbg_report_frame(struct iwl4965_priv *priv, +static void iwl4965_dbg_report_frame(struct iwl_priv *priv, struct iwl4965_rx_packet *pkt, struct ieee80211_hdr *header, int group100) { @@ -3729,7 +3729,7 @@ static void iwl4965_dbg_report_frame(struct iwl4965_priv *priv, iwl_print_hex_dump(IWL_DL_RX, data, length); } #else -static inline void iwl4965_dbg_report_frame(struct iwl4965_priv *priv, +static inline void iwl4965_dbg_report_frame(struct iwl_priv *priv, struct iwl4965_rx_packet *pkt, struct ieee80211_hdr *header, int group100) @@ -3742,7 +3742,7 @@ static inline void iwl4965_dbg_report_frame(struct iwl4965_priv *priv, /* Called for REPLY_4965_RX (legacy ABG frames), or * REPLY_RX_MPDU_CMD (HT high-throughput N frames). */ -static void iwl4965_rx_reply_rx(struct iwl4965_priv *priv, +static void iwl4965_rx_reply_rx(struct iwl_priv *priv, struct iwl4965_rx_mem_buffer *rxb) { struct ieee80211_hdr *header; @@ -4004,7 +4004,7 @@ static void iwl4965_rx_reply_rx(struct iwl4965_priv *priv, /* Cache phy data (Rx signal strength, etc) for HT frame (REPLY_RX_PHY_CMD). * This will be used later in iwl4965_rx_reply_rx() for REPLY_RX_MPDU_CMD. */ -static void iwl4965_rx_reply_rx_phy(struct iwl4965_priv *priv, +static void iwl4965_rx_reply_rx_phy(struct iwl_priv *priv, struct iwl4965_rx_mem_buffer *rxb) { struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data; @@ -4013,7 +4013,7 @@ static void iwl4965_rx_reply_rx_phy(struct iwl4965_priv *priv, sizeof(struct iwl4965_rx_phy_res)); } -static void iwl4965_rx_missed_beacon_notif(struct iwl4965_priv *priv, +static void iwl4965_rx_missed_beacon_notif(struct iwl_priv *priv, struct iwl4965_rx_mem_buffer *rxb) { @@ -4040,7 +4040,7 @@ static void iwl4965_rx_missed_beacon_notif(struct iwl4965_priv *priv, /** * iwl4965_sta_modify_enable_tid_tx - Enable Tx for this TID in station table */ -static void iwl4965_sta_modify_enable_tid_tx(struct iwl4965_priv *priv, +static void iwl4965_sta_modify_enable_tid_tx(struct iwl_priv *priv, int sta_id, int tid) { unsigned long flags; @@ -4061,7 +4061,7 @@ static void iwl4965_sta_modify_enable_tid_tx(struct iwl4965_priv *priv, * Go through block-ack's bitmap of ACK'd frames, update driver's record of * ACK vs. not. This gets sent to mac80211, then to rate scaling algo. */ -static int iwl4965_tx_status_reply_compressed_ba(struct iwl4965_priv *priv, +static int iwl4965_tx_status_reply_compressed_ba(struct iwl_priv *priv, struct iwl4965_ht_agg *agg, struct iwl4965_compressed_ba_resp* ba_resp) @@ -4126,7 +4126,7 @@ static int iwl4965_tx_status_reply_compressed_ba(struct iwl4965_priv *priv, /** * iwl4965_tx_queue_stop_scheduler - Stop queue, but keep configuration */ -static void iwl4965_tx_queue_stop_scheduler(struct iwl4965_priv *priv, +static void iwl4965_tx_queue_stop_scheduler(struct iwl_priv *priv, u16 txq_id) { /* Simply stop the queue, but don't change any configuration; @@ -4141,7 +4141,7 @@ static void iwl4965_tx_queue_stop_scheduler(struct iwl4965_priv *priv, * txq_id must be greater than IWL_BACK_QUEUE_FIRST_ID * priv->lock must be held by the caller */ -static int iwl4965_tx_queue_agg_disable(struct iwl4965_priv *priv, u16 txq_id, +static int iwl4965_tx_queue_agg_disable(struct iwl_priv *priv, u16 txq_id, u16 ssn_idx, u8 tx_fifo) { int ret = 0; @@ -4174,7 +4174,7 @@ static int iwl4965_tx_queue_agg_disable(struct iwl4965_priv *priv, u16 txq_id, return 0; } -int iwl4965_check_empty_hw_queue(struct iwl4965_priv *priv, int sta_id, +int iwl4965_check_empty_hw_queue(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id) { struct iwl4965_queue *q = &priv->txq[txq_id].q; @@ -4224,7 +4224,7 @@ static inline int iwl4965_queue_dec_wrap(int index, int n_bd) * Handles block-acknowledge notification from device, which reports success * of frames sent via aggregation. */ -static void iwl4965_rx_reply_compressed_ba(struct iwl4965_priv *priv, +static void iwl4965_rx_reply_compressed_ba(struct iwl_priv *priv, struct iwl4965_rx_mem_buffer *rxb) { struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data; @@ -4292,7 +4292,7 @@ static void iwl4965_rx_reply_compressed_ba(struct iwl4965_priv *priv, /** * iwl4965_tx_queue_set_q2ratid - Map unique receiver/tid combination to a queue */ -static int iwl4965_tx_queue_set_q2ratid(struct iwl4965_priv *priv, u16 ra_tid, +static int iwl4965_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid, u16 txq_id) { u32 tbl_dw_addr; @@ -4323,7 +4323,7 @@ static int iwl4965_tx_queue_set_q2ratid(struct iwl4965_priv *priv, u16 ra_tid, * NOTE: txq_id must be greater than IWL_BACK_QUEUE_FIRST_ID, * i.e. it must be one of the higher queues used for aggregation */ -static int iwl4965_tx_queue_agg_enable(struct iwl4965_priv *priv, int txq_id, +static int iwl4965_tx_queue_agg_enable(struct iwl_priv *priv, int txq_id, int tx_fifo, int sta_id, int tid, u16 ssn_idx) { @@ -4400,7 +4400,7 @@ static int iwl4965_tx_queue_agg_enable(struct iwl4965_priv *priv, int txq_id, * calling this function (which runs REPLY_TX_LINK_QUALITY_CMD, * which requires station table entry to exist). */ -void iwl4965_add_station(struct iwl4965_priv *priv, const u8 *addr, int is_ap) +void iwl4965_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap) { int i, r; struct iwl4965_link_quality_cmd link_cmd = { @@ -4445,7 +4445,7 @@ void iwl4965_add_station(struct iwl4965_priv *priv, const u8 *addr, int is_ap) #ifdef CONFIG_IWL4965_HT -static u8 iwl4965_is_channel_extension(struct iwl4965_priv *priv, +static u8 iwl4965_is_channel_extension(struct iwl_priv *priv, enum ieee80211_band band, u16 channel, u8 extension_chan_offset) { @@ -4465,7 +4465,7 @@ static u8 iwl4965_is_channel_extension(struct iwl4965_priv *priv, return 0; } -static u8 iwl4965_is_fat_tx_allowed(struct iwl4965_priv *priv, +static u8 iwl4965_is_fat_tx_allowed(struct iwl_priv *priv, struct ieee80211_ht_info *sta_ht_inf) { struct iwl_ht_info *iwl_ht_conf = &priv->current_ht_config; @@ -4486,7 +4486,7 @@ static u8 iwl4965_is_fat_tx_allowed(struct iwl4965_priv *priv, iwl_ht_conf->extension_chan_offset)); } -void iwl4965_set_rxon_ht(struct iwl4965_priv *priv, struct iwl_ht_info *ht_info) +void iwl4965_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info) { struct iwl4965_rxon_cmd *rxon = &priv->staging_rxon; u32 val; @@ -4540,7 +4540,7 @@ void iwl4965_set_rxon_ht(struct iwl4965_priv *priv, struct iwl_ht_info *ht_info) return; } -void iwl4965_set_ht_add_station(struct iwl4965_priv *priv, u8 index, +void iwl4965_set_ht_add_station(struct iwl_priv *priv, u8 index, struct ieee80211_ht_info *sta_ht_inf) { __le32 sta_flags; @@ -4585,7 +4585,7 @@ void iwl4965_set_ht_add_station(struct iwl4965_priv *priv, u8 index, return; } -static void iwl4965_sta_modify_add_ba_tid(struct iwl4965_priv *priv, +static void iwl4965_sta_modify_add_ba_tid(struct iwl_priv *priv, int sta_id, int tid, u16 ssn) { unsigned long flags; @@ -4601,7 +4601,7 @@ static void iwl4965_sta_modify_add_ba_tid(struct iwl4965_priv *priv, iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, CMD_ASYNC); } -static void iwl4965_sta_modify_del_ba_tid(struct iwl4965_priv *priv, +static void iwl4965_sta_modify_del_ba_tid(struct iwl_priv *priv, int sta_id, int tid) { unsigned long flags; @@ -4622,7 +4622,7 @@ static void iwl4965_sta_modify_del_ba_tid(struct iwl4965_priv *priv, * Should never return anything < 7, because they should already * be in use as EDCA AC (0-3), Command (4), HCCA (5, 6). */ -static int iwl4965_txq_ctx_activate_free(struct iwl4965_priv *priv) +static int iwl4965_txq_ctx_activate_free(struct iwl_priv *priv) { int txq_id; @@ -4635,7 +4635,7 @@ static int iwl4965_txq_ctx_activate_free(struct iwl4965_priv *priv) static int iwl4965_mac_ht_tx_agg_start(struct ieee80211_hw *hw, const u8 *da, u16 tid, u16 *start_seq_num) { - struct iwl4965_priv *priv = hw->priv; + struct iwl_priv *priv = hw->priv; int sta_id; int tx_fifo; int txq_id; @@ -4695,7 +4695,7 @@ static int iwl4965_mac_ht_tx_agg_stop(struct ieee80211_hw *hw, const u8 *da, u16 tid) { - struct iwl4965_priv *priv = hw->priv; + struct iwl_priv *priv = hw->priv; int tx_fifo_id, txq_id, sta_id, ssn = -1; struct iwl4965_tid_data *tid_data; int ret, write_ptr, read_ptr; @@ -4756,7 +4756,7 @@ int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw, enum ieee80211_ampdu_mlme_action action, const u8 *addr, u16 tid, u16 *ssn) { - struct iwl4965_priv *priv = hw->priv; + struct iwl_priv *priv = hw->priv; int sta_id; DECLARE_MAC_BUF(mac); @@ -4789,7 +4789,7 @@ int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw, #endif /* CONFIG_IWL4965_HT */ /* Set up 4965-specific Rx frame reply handlers */ -void iwl4965_hw_rx_handler_setup(struct iwl4965_priv *priv) +void iwl4965_hw_rx_handler_setup(struct iwl_priv *priv) { /* Legacy Rx frames */ priv->rx_handlers[REPLY_4965_RX] = iwl4965_rx_reply_rx; @@ -4806,7 +4806,7 @@ void iwl4965_hw_rx_handler_setup(struct iwl4965_priv *priv) #endif /* CONFIG_IWL4965_HT */ } -void iwl4965_hw_setup_deferred_work(struct iwl4965_priv *priv) +void iwl4965_hw_setup_deferred_work(struct iwl_priv *priv) { INIT_WORK(&priv->txpower_work, iwl4965_bg_txpower_work); INIT_WORK(&priv->statistics_work, iwl4965_bg_statistics_work); @@ -4818,7 +4818,7 @@ void iwl4965_hw_setup_deferred_work(struct iwl4965_priv *priv) priv->statistics_periodic.function = iwl4965_bg_statistics_periodic; } -void iwl4965_hw_cancel_deferred_work(struct iwl4965_priv *priv) +void iwl4965_hw_cancel_deferred_work(struct iwl_priv *priv) { del_timer_sync(&priv->statistics_periodic); diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index 4426d0f85564..60353b2645d4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -315,13 +315,13 @@ enum { }; struct iwl4965_cmd; -struct iwl4965_priv; +struct iwl_priv; struct iwl4965_cmd_meta { struct iwl4965_cmd_meta *source; union { struct sk_buff *skb; - int (*callback)(struct iwl4965_priv *priv, + int (*callback)(struct iwl_priv *priv, struct iwl4965_cmd *cmd, struct sk_buff *skb); } __attribute__ ((packed)) u; @@ -634,40 +634,40 @@ struct iwl4965_driver_hw_info { * *****************************************************************************/ struct iwl4965_addsta_cmd; -extern int iwl4965_send_add_station(struct iwl4965_priv *priv, +extern int iwl4965_send_add_station(struct iwl_priv *priv, struct iwl4965_addsta_cmd *sta, u8 flags); -extern u8 iwl4965_add_station_flags(struct iwl4965_priv *priv, const u8 *addr, +extern u8 iwl4965_add_station_flags(struct iwl_priv *priv, const u8 *addr, int is_ap, u8 flags, void *ht_data); -extern int iwl4965_is_network_packet(struct iwl4965_priv *priv, +extern int iwl4965_is_network_packet(struct iwl_priv *priv, struct ieee80211_hdr *header); -extern int iwl4965_power_init_handle(struct iwl4965_priv *priv); -extern void iwl4965_handle_data_packet_monitor(struct iwl4965_priv *priv, +extern int iwl4965_power_init_handle(struct iwl_priv *priv); +extern void iwl4965_handle_data_packet_monitor(struct iwl_priv *priv, struct iwl4965_rx_mem_buffer *rxb, void *data, short len, struct ieee80211_rx_status *stats, u16 phy_flags); -extern int iwl4965_is_duplicate_packet(struct iwl4965_priv *priv, +extern int iwl4965_is_duplicate_packet(struct iwl_priv *priv, struct ieee80211_hdr *header); -extern int iwl4965_rx_queue_alloc(struct iwl4965_priv *priv); -extern void iwl4965_rx_queue_reset(struct iwl4965_priv *priv, +extern int iwl4965_rx_queue_alloc(struct iwl_priv *priv); +extern void iwl4965_rx_queue_reset(struct iwl_priv *priv, struct iwl4965_rx_queue *rxq); extern int iwl4965_calc_db_from_ratio(int sig_ratio); extern int iwl4965_calc_sig_qual(int rssi_dbm, int noise_dbm); -extern int iwl4965_tx_queue_init(struct iwl4965_priv *priv, +extern int iwl4965_tx_queue_init(struct iwl_priv *priv, struct iwl4965_tx_queue *txq, int count, u32 id); extern void iwl4965_rx_replenish(void *data); -extern void iwl4965_tx_queue_free(struct iwl4965_priv *priv, struct iwl4965_tx_queue *txq); -extern int iwl4965_send_cmd_pdu(struct iwl4965_priv *priv, u8 id, u16 len, +extern void iwl4965_tx_queue_free(struct iwl_priv *priv, struct iwl4965_tx_queue *txq); +extern int iwl4965_send_cmd_pdu(struct iwl_priv *priv, u8 id, u16 len, const void *data); -extern int __must_check iwl4965_send_cmd(struct iwl4965_priv *priv, +extern int __must_check iwl4965_send_cmd(struct iwl_priv *priv, struct iwl4965_host_cmd *cmd); -extern unsigned int iwl4965_fill_beacon_frame(struct iwl4965_priv *priv, +extern unsigned int iwl4965_fill_beacon_frame(struct iwl_priv *priv, struct ieee80211_hdr *hdr, const u8 *dest, int left); -extern int iwl4965_rx_queue_update_write_ptr(struct iwl4965_priv *priv, +extern int iwl4965_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl4965_rx_queue *q); -extern int iwl4965_send_statistics_request(struct iwl4965_priv *priv); -extern void iwl4965_set_decrypted_flag(struct iwl4965_priv *priv, struct sk_buff *skb, +extern int iwl4965_send_statistics_request(struct iwl_priv *priv); +extern void iwl4965_set_decrypted_flag(struct iwl_priv *priv, struct sk_buff *skb, u32 decrypt_res, struct ieee80211_rx_status *stats); extern __le16 *ieee80211_get_qos_ctrl(struct ieee80211_hdr *hdr); @@ -678,7 +678,7 @@ extern const u8 iwl4965_broadcast_addr[ETH_ALEN]; * Currently used by iwl-3945-rs... look at restructuring so that it doesn't * call this... todo... fix that. */ -extern u8 iwl4965_sync_station(struct iwl4965_priv *priv, int sta_id, +extern u8 iwl4965_sync_station(struct iwl_priv *priv, int sta_id, u16 tx_rate, u8 flags); /****************************************************************************** @@ -697,36 +697,36 @@ extern u8 iwl4965_sync_station(struct iwl4965_priv *priv, int sta_id, * iwl4965_mac_ <-- mac80211 callback * ****************************************************************************/ -extern void iwl4965_hw_rx_handler_setup(struct iwl4965_priv *priv); -extern void iwl4965_hw_setup_deferred_work(struct iwl4965_priv *priv); -extern void iwl4965_hw_cancel_deferred_work(struct iwl4965_priv *priv); -extern int iwl4965_hw_rxq_stop(struct iwl4965_priv *priv); -extern int iwl4965_hw_set_hw_setting(struct iwl4965_priv *priv); -extern int iwl4965_hw_nic_init(struct iwl4965_priv *priv); -extern int iwl4965_hw_nic_stop_master(struct iwl4965_priv *priv); -extern void iwl4965_hw_txq_ctx_free(struct iwl4965_priv *priv); -extern void iwl4965_hw_txq_ctx_stop(struct iwl4965_priv *priv); -extern int iwl4965_hw_nic_reset(struct iwl4965_priv *priv); -extern int iwl4965_hw_txq_attach_buf_to_tfd(struct iwl4965_priv *priv, void *tfd, +extern void iwl4965_hw_rx_handler_setup(struct iwl_priv *priv); +extern void iwl4965_hw_setup_deferred_work(struct iwl_priv *priv); +extern void iwl4965_hw_cancel_deferred_work(struct iwl_priv *priv); +extern int iwl4965_hw_rxq_stop(struct iwl_priv *priv); +extern int iwl4965_hw_set_hw_setting(struct iwl_priv *priv); +extern int iwl4965_hw_nic_init(struct iwl_priv *priv); +extern int iwl4965_hw_nic_stop_master(struct iwl_priv *priv); +extern void iwl4965_hw_txq_ctx_free(struct iwl_priv *priv); +extern void iwl4965_hw_txq_ctx_stop(struct iwl_priv *priv); +extern int iwl4965_hw_nic_reset(struct iwl_priv *priv); +extern int iwl4965_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *tfd, dma_addr_t addr, u16 len); -extern int iwl4965_hw_txq_free_tfd(struct iwl4965_priv *priv, struct iwl4965_tx_queue *txq); -extern int iwl4965_hw_get_temperature(struct iwl4965_priv *priv); -extern int iwl4965_hw_tx_queue_init(struct iwl4965_priv *priv, +extern int iwl4965_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl4965_tx_queue *txq); +extern int iwl4965_hw_get_temperature(struct iwl_priv *priv); +extern int iwl4965_hw_tx_queue_init(struct iwl_priv *priv, struct iwl4965_tx_queue *txq); -extern unsigned int iwl4965_hw_get_beacon_cmd(struct iwl4965_priv *priv, +extern unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv, struct iwl4965_frame *frame, u8 rate); -extern int iwl4965_hw_get_rx_read(struct iwl4965_priv *priv); -extern void iwl4965_hw_build_tx_cmd_rate(struct iwl4965_priv *priv, +extern int iwl4965_hw_get_rx_read(struct iwl_priv *priv); +extern void iwl4965_hw_build_tx_cmd_rate(struct iwl_priv *priv, struct iwl4965_cmd *cmd, struct ieee80211_tx_control *ctrl, struct ieee80211_hdr *hdr, int sta_id, int tx_id); -extern int iwl4965_hw_reg_send_txpower(struct iwl4965_priv *priv); -extern int iwl4965_hw_reg_set_txpower(struct iwl4965_priv *priv, s8 power); -extern void iwl4965_hw_rx_statistics(struct iwl4965_priv *priv, +extern int iwl4965_hw_reg_send_txpower(struct iwl_priv *priv); +extern int iwl4965_hw_reg_set_txpower(struct iwl_priv *priv, s8 power); +extern void iwl4965_hw_rx_statistics(struct iwl_priv *priv, struct iwl4965_rx_mem_buffer *rxb); -extern void iwl4965_disable_events(struct iwl4965_priv *priv); -extern int iwl4965_get_temperature(const struct iwl4965_priv *priv); +extern void iwl4965_disable_events(struct iwl_priv *priv); +extern int iwl4965_get_temperature(const struct iwl_priv *priv); /** * iwl4965_hw_find_station - Find station id for a given BSSID @@ -736,48 +736,48 @@ extern int iwl4965_get_temperature(const struct iwl4965_priv *priv); * not yet been merged into a single common layer for managing the * station tables. */ -extern u8 iwl4965_hw_find_station(struct iwl4965_priv *priv, const u8 *bssid); +extern u8 iwl4965_hw_find_station(struct iwl_priv *priv, const u8 *bssid); -extern int iwl4965_hw_channel_switch(struct iwl4965_priv *priv, u16 channel); -extern int iwl4965_tx_queue_reclaim(struct iwl4965_priv *priv, int txq_id, int index); +extern int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel); +extern int iwl4965_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index); extern int iwl4965_queue_space(const struct iwl4965_queue *q); -struct iwl4965_priv; +struct iwl_priv; /* * Forward declare iwl-4965.c functions for iwl-base.c */ -extern int iwl4965_tx_queue_update_wr_ptr(struct iwl4965_priv *priv, +extern int iwl4965_tx_queue_update_wr_ptr(struct iwl_priv *priv, struct iwl4965_tx_queue *txq, u16 byte_cnt); -extern void iwl4965_add_station(struct iwl4965_priv *priv, const u8 *addr, +extern void iwl4965_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap); -extern void iwl4965_set_rxon_chain(struct iwl4965_priv *priv); -extern int iwl4965_alive_notify(struct iwl4965_priv *priv); -extern void iwl4965_update_rate_scaling(struct iwl4965_priv *priv, u8 mode); -extern void iwl4965_chain_noise_reset(struct iwl4965_priv *priv); -extern void iwl4965_init_sensitivity(struct iwl4965_priv *priv, u8 flags, +extern void iwl4965_set_rxon_chain(struct iwl_priv *priv); +extern int iwl4965_alive_notify(struct iwl_priv *priv); +extern void iwl4965_update_rate_scaling(struct iwl_priv *priv, u8 mode); +extern void iwl4965_chain_noise_reset(struct iwl_priv *priv); +extern void iwl4965_init_sensitivity(struct iwl_priv *priv, u8 flags, u8 force); -extern int iwl4965_set_fat_chan_info(struct iwl4965_priv *priv, +extern int iwl4965_set_fat_chan_info(struct iwl_priv *priv, enum ieee80211_band band, u16 channel, const struct iwl4965_eeprom_channel *eeprom_ch, u8 fat_extension_channel); -extern void iwl4965_rf_kill_ct_config(struct iwl4965_priv *priv); -extern void iwl4965_hwrate_to_tx_control(struct iwl4965_priv *priv, +extern void iwl4965_rf_kill_ct_config(struct iwl_priv *priv); +extern void iwl4965_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, struct ieee80211_tx_control *control); #ifdef CONFIG_IWL4965_HT void iwl4965_init_ht_hw_capab(struct ieee80211_ht_info *ht_info, enum ieee80211_band band); -void iwl4965_set_rxon_ht(struct iwl4965_priv *priv, +void iwl4965_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info); -void iwl4965_set_ht_add_station(struct iwl4965_priv *priv, u8 index, +void iwl4965_set_ht_add_station(struct iwl_priv *priv, u8 index, struct ieee80211_ht_info *sta_ht_inf); int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw, enum ieee80211_ampdu_mlme_action action, const u8 *addr, u16 tid, u16 *ssn); -int iwl4965_check_empty_hw_queue(struct iwl4965_priv *priv, int sta_id, +int iwl4965_check_empty_hw_queue(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id); #else static inline void iwl4965_init_ht_hw_capab(struct ieee80211_ht_info *ht_info, @@ -966,7 +966,7 @@ enum { #endif -struct iwl4965_priv { +struct iwl_priv { /* ieee device used by generic ieee processing code */ struct ieee80211_hw *hw; @@ -982,7 +982,7 @@ struct iwl4965_priv { int alloc_rxb_skb; bool add_radiotap; - void (*rx_handlers[REPLY_MAX])(struct iwl4965_priv *priv, + void (*rx_handlers[REPLY_MAX])(struct iwl_priv *priv, struct iwl4965_rx_mem_buffer *rxb); struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; @@ -1214,9 +1214,9 @@ struct iwl4965_priv { #endif struct work_struct statistics_work; struct timer_list statistics_periodic; -}; /*iwl4965_priv */ +}; /*iwl_priv */ -static inline int iwl4965_is_associated(struct iwl4965_priv *priv) +static inline int iwl4965_is_associated(struct iwl_priv *priv) { return (priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0; } @@ -1259,9 +1259,9 @@ static inline int is_channel_ibss(const struct iwl4965_channel_info *ch) } extern const struct iwl4965_channel_info *iwl4965_get_channel_info( - const struct iwl4965_priv *priv, enum ieee80211_band band, u16 channel); + const struct iwl_priv *priv, enum ieee80211_band band, u16 channel); -/* Requires full declaration of iwl4965_priv before including */ +/* Requires full declaration of iwl_priv before including */ #include "iwl-4965-io.h" #endif /* __iwl4965_4965_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index 4fd1b362d2ed..ccacd489ae80 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -81,7 +81,7 @@ * ******************************************************************************/ -int iwlcore_eeprom_verify_signature(struct iwl4965_priv *priv) +int iwlcore_eeprom_verify_signature(struct iwl_priv *priv) { u32 gp = iwl4965_read32(priv, CSR_EEPROM_GP); if ((gp & CSR_EEPROM_GP_VALID_MSK) == CSR_EEPROM_GP_BAD_SIGNATURE) { @@ -98,7 +98,7 @@ EXPORT_SYMBOL(iwlcore_eeprom_verify_signature); * EEPROM chip, not a single event, so even reads could conflict if they * weren't arbitrated by the semaphore. */ -int iwlcore_eeprom_acquire_semaphore(struct iwl4965_priv *priv) +int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv) { u16 count; int ret; @@ -124,7 +124,7 @@ int iwlcore_eeprom_acquire_semaphore(struct iwl4965_priv *priv) } EXPORT_SYMBOL(iwlcore_eeprom_acquire_semaphore); -void iwlcore_eeprom_release_semaphore(struct iwl4965_priv *priv) +void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv) { iwl4965_clear_bit(priv, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); @@ -140,7 +140,7 @@ EXPORT_SYMBOL(iwlcore_eeprom_release_semaphore); * * NOTE: This routine uses the non-debug IO access functions. */ -int iwl_eeprom_init(struct iwl4965_priv *priv) +int iwl_eeprom_init(struct iwl_priv *priv) { u16 *e = (u16 *)&priv->eeprom; u32 gp = iwl4965_read32(priv, CSR_EEPROM_GP); @@ -197,7 +197,7 @@ done: EXPORT_SYMBOL(iwl_eeprom_init); -void iwl_eeprom_get_mac(const struct iwl4965_priv *priv, u8 *mac) +void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac) { memcpy(mac, priv->eeprom.mac_address, 6); } diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h index 7827566dcc8b..ad486fe7a96c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h @@ -63,7 +63,7 @@ #ifndef __iwl_eeprom_h__ #define __iwl_eeprom_h__ -struct iwl4965_priv; +struct iwl_priv; /* * EEPROM access time values: @@ -383,17 +383,17 @@ struct iwl4965_eeprom { /* End of EEPROM */ struct iwl_eeprom_ops { - int (*verify_signature) (struct iwl4965_priv *priv); - int (*acquire_semaphore) (struct iwl4965_priv *priv); - void (*release_semaphore) (struct iwl4965_priv *priv); + int (*verify_signature) (struct iwl_priv *priv); + int (*acquire_semaphore) (struct iwl_priv *priv); + void (*release_semaphore) (struct iwl_priv *priv); }; -void iwl_eeprom_get_mac(const struct iwl4965_priv *priv, u8 *mac); -int iwl_eeprom_init(struct iwl4965_priv *priv); +void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac); +int iwl_eeprom_init(struct iwl_priv *priv); -int iwlcore_eeprom_verify_signature(struct iwl4965_priv *priv); -int iwlcore_eeprom_acquire_semaphore(struct iwl4965_priv *priv); -void iwlcore_eeprom_release_semaphore(struct iwl4965_priv *priv); +int iwlcore_eeprom_verify_signature(struct iwl_priv *priv); +int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv); +void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv); #endif /* __iwl_eeprom_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index e05bc902ee6e..4e899ce81b32 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -50,7 +50,7 @@ #include "iwl-4965.h" #include "iwl-helpers.h" -static int iwl4965_tx_queue_update_write_ptr(struct iwl4965_priv *priv, +static int iwl4965_tx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl4965_tx_queue *txq); /****************************************************************************** @@ -107,7 +107,7 @@ __le16 *ieee80211_get_qos_ctrl(struct ieee80211_hdr *hdr) } static const struct ieee80211_supported_band *iwl4965_get_hw_mode( - struct iwl4965_priv *priv, enum ieee80211_band band) + struct iwl_priv *priv, enum ieee80211_band band) { return priv->hw->wiphy->bands[band]; } @@ -216,7 +216,7 @@ static inline u8 get_cmd_index(struct iwl4965_queue *q, u32 index, int is_huge) /** * iwl4965_queue_init - Initialize queue's high/low-water and read/write indexes */ -static int iwl4965_queue_init(struct iwl4965_priv *priv, struct iwl4965_queue *q, +static int iwl4965_queue_init(struct iwl_priv *priv, struct iwl4965_queue *q, int count, int slots_num, u32 id) { q->n_bd = count; @@ -247,7 +247,7 @@ static int iwl4965_queue_init(struct iwl4965_priv *priv, struct iwl4965_queue *q /** * iwl4965_tx_queue_alloc - Alloc driver data and TFD CB for one Tx/cmd queue */ -static int iwl4965_tx_queue_alloc(struct iwl4965_priv *priv, +static int iwl4965_tx_queue_alloc(struct iwl_priv *priv, struct iwl4965_tx_queue *txq, u32 id) { struct pci_dev *dev = priv->pci_dev; @@ -292,7 +292,7 @@ static int iwl4965_tx_queue_alloc(struct iwl4965_priv *priv, /** * iwl4965_tx_queue_init - Allocate and initialize one tx/cmd queue */ -int iwl4965_tx_queue_init(struct iwl4965_priv *priv, +int iwl4965_tx_queue_init(struct iwl_priv *priv, struct iwl4965_tx_queue *txq, int slots_num, u32 txq_id) { struct pci_dev *dev = priv->pci_dev; @@ -344,7 +344,7 @@ int iwl4965_tx_queue_init(struct iwl4965_priv *priv, * Free all buffers. * 0-fill, but do not free "txq" descriptor structure. */ -void iwl4965_tx_queue_free(struct iwl4965_priv *priv, struct iwl4965_tx_queue *txq) +void iwl4965_tx_queue_free(struct iwl_priv *priv, struct iwl4965_tx_queue *txq) { struct iwl4965_queue *q = &txq->q; struct pci_dev *dev = priv->pci_dev; @@ -395,7 +395,7 @@ const u8 iwl4965_broadcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF * * NOTE: This does not remove station from device's station table. */ -static u8 iwl4965_remove_station(struct iwl4965_priv *priv, const u8 *addr, int is_ap) +static u8 iwl4965_remove_station(struct iwl_priv *priv, const u8 *addr, int is_ap) { int index = IWL_INVALID_STATION; int i; @@ -437,7 +437,7 @@ out: * * NOTE: This does not clear or otherwise alter the device's station table. */ -static void iwl4965_clear_stations_table(struct iwl4965_priv *priv) +static void iwl4965_clear_stations_table(struct iwl_priv *priv) { unsigned long flags; @@ -452,7 +452,7 @@ static void iwl4965_clear_stations_table(struct iwl4965_priv *priv) /** * iwl4965_add_station_flags - Add station to tables in driver and device */ -u8 iwl4965_add_station_flags(struct iwl4965_priv *priv, const u8 *addr, +u8 iwl4965_add_station_flags(struct iwl_priv *priv, const u8 *addr, int is_ap, u8 flags, void *ht_data) { int i; @@ -524,7 +524,7 @@ u8 iwl4965_add_station_flags(struct iwl4965_priv *priv, const u8 *addr, /*************** DRIVER STATUS FUNCTIONS *****/ -static inline int iwl4965_is_ready(struct iwl4965_priv *priv) +static inline int iwl4965_is_ready(struct iwl_priv *priv) { /* The adapter is 'ready' if READY and GEO_CONFIGURED bits are * set but EXIT_PENDING is not */ @@ -533,23 +533,23 @@ static inline int iwl4965_is_ready(struct iwl4965_priv *priv) !test_bit(STATUS_EXIT_PENDING, &priv->status); } -static inline int iwl4965_is_alive(struct iwl4965_priv *priv) +static inline int iwl4965_is_alive(struct iwl_priv *priv) { return test_bit(STATUS_ALIVE, &priv->status); } -static inline int iwl4965_is_init(struct iwl4965_priv *priv) +static inline int iwl4965_is_init(struct iwl_priv *priv) { return test_bit(STATUS_INIT, &priv->status); } -static inline int iwl4965_is_rfkill(struct iwl4965_priv *priv) +static inline int iwl4965_is_rfkill(struct iwl_priv *priv) { return test_bit(STATUS_RF_KILL_HW, &priv->status) || test_bit(STATUS_RF_KILL_SW, &priv->status); } -static inline int iwl4965_is_ready_rf(struct iwl4965_priv *priv) +static inline int iwl4965_is_ready_rf(struct iwl_priv *priv) { if (iwl4965_is_rfkill(priv)) @@ -628,7 +628,7 @@ static const char *get_cmd_string(u8 cmd) * failed. On success, it turns the index (> 0) of command in the * command queue. */ -static int iwl4965_enqueue_hcmd(struct iwl4965_priv *priv, struct iwl4965_host_cmd *cmd) +static int iwl4965_enqueue_hcmd(struct iwl_priv *priv, struct iwl4965_host_cmd *cmd) { struct iwl4965_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM]; struct iwl4965_queue *q = &txq->q; @@ -703,7 +703,7 @@ static int iwl4965_enqueue_hcmd(struct iwl4965_priv *priv, struct iwl4965_host_c return ret ? ret : idx; } -static int iwl4965_send_cmd_async(struct iwl4965_priv *priv, struct iwl4965_host_cmd *cmd) +static int iwl4965_send_cmd_async(struct iwl_priv *priv, struct iwl4965_host_cmd *cmd) { int ret; @@ -727,7 +727,7 @@ static int iwl4965_send_cmd_async(struct iwl4965_priv *priv, struct iwl4965_host return 0; } -static int iwl4965_send_cmd_sync(struct iwl4965_priv *priv, struct iwl4965_host_cmd *cmd) +static int iwl4965_send_cmd_sync(struct iwl_priv *priv, struct iwl4965_host_cmd *cmd) { int cmd_idx; int ret; @@ -815,7 +815,7 @@ out: return ret; } -int iwl4965_send_cmd(struct iwl4965_priv *priv, struct iwl4965_host_cmd *cmd) +int iwl4965_send_cmd(struct iwl_priv *priv, struct iwl4965_host_cmd *cmd) { if (cmd->meta.flags & CMD_ASYNC) return iwl4965_send_cmd_async(priv, cmd); @@ -823,7 +823,7 @@ int iwl4965_send_cmd(struct iwl4965_priv *priv, struct iwl4965_host_cmd *cmd) return iwl4965_send_cmd_sync(priv, cmd); } -int iwl4965_send_cmd_pdu(struct iwl4965_priv *priv, u8 id, u16 len, const void *data) +int iwl4965_send_cmd_pdu(struct iwl_priv *priv, u8 id, u16 len, const void *data) { struct iwl4965_host_cmd cmd = { .id = id, @@ -834,7 +834,7 @@ int iwl4965_send_cmd_pdu(struct iwl4965_priv *priv, u8 id, u16 len, const void * return iwl4965_send_cmd_sync(priv, &cmd); } -static int __must_check iwl4965_send_cmd_u32(struct iwl4965_priv *priv, u8 id, u32 val) +static int __must_check iwl4965_send_cmd_u32(struct iwl_priv *priv, u8 id, u32 val) { struct iwl4965_host_cmd cmd = { .id = id, @@ -845,7 +845,7 @@ static int __must_check iwl4965_send_cmd_u32(struct iwl4965_priv *priv, u8 id, u return iwl4965_send_cmd_sync(priv, &cmd); } -int iwl4965_send_statistics_request(struct iwl4965_priv *priv) +int iwl4965_send_statistics_request(struct iwl_priv *priv) { return iwl4965_send_cmd_u32(priv, REPLY_STATISTICS_CMD, 0); } @@ -856,7 +856,7 @@ int iwl4965_send_statistics_request(struct iwl4965_priv *priv) * there is only one AP station with id= IWL_AP_ID * NOTE: mutex must be held before calling this fnction */ -static int iwl4965_rxon_add_station(struct iwl4965_priv *priv, +static int iwl4965_rxon_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap) { u8 sta_id; @@ -892,7 +892,7 @@ static int iwl4965_rxon_add_station(struct iwl4965_priv *priv, * NOTE: Does not commit to the hardware; it sets appropriate bit fields * in the staging RXON flag structure based on the phymode */ -static int iwl4965_set_rxon_channel(struct iwl4965_priv *priv, +static int iwl4965_set_rxon_channel(struct iwl_priv *priv, enum ieee80211_band band, u16 channel) { @@ -1000,7 +1000,7 @@ static int iwl4965_check_rxon_cmd(struct iwl4965_rxon_cmd *rxon) * or is clearing the RXON_FILTER_ASSOC_MSK, then return 1 to indicate that * a new tune (full RXON command, rather than RXON_ASSOC cmd) is required. */ -static int iwl4965_full_rxon_required(struct iwl4965_priv *priv) +static int iwl4965_full_rxon_required(struct iwl_priv *priv) { /* These items are only settable from the full RXON command */ @@ -1040,7 +1040,7 @@ static int iwl4965_full_rxon_required(struct iwl4965_priv *priv) return 0; } -static int iwl4965_send_rxon_assoc(struct iwl4965_priv *priv) +static int iwl4965_send_rxon_assoc(struct iwl_priv *priv) { int rc = 0; struct iwl4965_rx_packet *res = NULL; @@ -1102,7 +1102,7 @@ static int iwl4965_send_rxon_assoc(struct iwl4965_priv *priv) * function correctly transitions out of the RXON_ASSOC_MSK state if * a HW tune is required based on the RXON structure changes. */ -static int iwl4965_commit_rxon(struct iwl4965_priv *priv) +static int iwl4965_commit_rxon(struct iwl_priv *priv) { /* cast away the const for active_rxon in this function */ struct iwl4965_rxon_cmd *active_rxon = (void *)&priv->active_rxon; @@ -1230,7 +1230,7 @@ static int iwl4965_commit_rxon(struct iwl4965_priv *priv) return 0; } -static int iwl4965_send_bt_config(struct iwl4965_priv *priv) +static int iwl4965_send_bt_config(struct iwl_priv *priv) { struct iwl4965_bt_cmd bt_cmd = { .flags = 3, @@ -1244,7 +1244,7 @@ static int iwl4965_send_bt_config(struct iwl4965_priv *priv) sizeof(struct iwl4965_bt_cmd), &bt_cmd); } -static int iwl4965_send_scan_abort(struct iwl4965_priv *priv) +static int iwl4965_send_scan_abort(struct iwl_priv *priv) { int rc = 0; struct iwl4965_rx_packet *res; @@ -1285,7 +1285,7 @@ static int iwl4965_send_scan_abort(struct iwl4965_priv *priv) return rc; } -static int iwl4965_card_state_sync_callback(struct iwl4965_priv *priv, +static int iwl4965_card_state_sync_callback(struct iwl_priv *priv, struct iwl4965_cmd *cmd, struct sk_buff *skb) { @@ -1302,7 +1302,7 @@ static int iwl4965_card_state_sync_callback(struct iwl4965_priv *priv, * When in the 'halt' state, the card is shut down and must be fully * restarted to come back on. */ -static int iwl4965_send_card_state(struct iwl4965_priv *priv, u32 flags, u8 meta_flag) +static int iwl4965_send_card_state(struct iwl_priv *priv, u32 flags, u8 meta_flag) { struct iwl4965_host_cmd cmd = { .id = REPLY_CARD_STATE_CMD, @@ -1317,7 +1317,7 @@ static int iwl4965_send_card_state(struct iwl4965_priv *priv, u32 flags, u8 meta return iwl4965_send_cmd(priv, &cmd); } -static int iwl4965_add_sta_sync_callback(struct iwl4965_priv *priv, +static int iwl4965_add_sta_sync_callback(struct iwl_priv *priv, struct iwl4965_cmd *cmd, struct sk_buff *skb) { struct iwl4965_rx_packet *res = NULL; @@ -1345,7 +1345,7 @@ static int iwl4965_add_sta_sync_callback(struct iwl4965_priv *priv, return 1; } -int iwl4965_send_add_station(struct iwl4965_priv *priv, +int iwl4965_send_add_station(struct iwl_priv *priv, struct iwl4965_addsta_cmd *sta, u8 flags) { struct iwl4965_rx_packet *res = NULL; @@ -1392,7 +1392,7 @@ int iwl4965_send_add_station(struct iwl4965_priv *priv, return rc; } -static int iwl4965_update_sta_key_info(struct iwl4965_priv *priv, +static int iwl4965_update_sta_key_info(struct iwl_priv *priv, struct ieee80211_key_conf *keyconf, u8 sta_id) { @@ -1430,7 +1430,7 @@ static int iwl4965_update_sta_key_info(struct iwl4965_priv *priv, return 0; } -static int iwl4965_clear_sta_key_info(struct iwl4965_priv *priv, u8 sta_id) +static int iwl4965_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id) { unsigned long flags; @@ -1447,7 +1447,7 @@ static int iwl4965_clear_sta_key_info(struct iwl4965_priv *priv, u8 sta_id) return 0; } -static void iwl4965_clear_free_frames(struct iwl4965_priv *priv) +static void iwl4965_clear_free_frames(struct iwl_priv *priv) { struct list_head *element; @@ -1468,7 +1468,7 @@ static void iwl4965_clear_free_frames(struct iwl4965_priv *priv) } } -static struct iwl4965_frame *iwl4965_get_free_frame(struct iwl4965_priv *priv) +static struct iwl4965_frame *iwl4965_get_free_frame(struct iwl_priv *priv) { struct iwl4965_frame *frame; struct list_head *element; @@ -1488,13 +1488,13 @@ static struct iwl4965_frame *iwl4965_get_free_frame(struct iwl4965_priv *priv) return list_entry(element, struct iwl4965_frame, list); } -static void iwl4965_free_frame(struct iwl4965_priv *priv, struct iwl4965_frame *frame) +static void iwl4965_free_frame(struct iwl_priv *priv, struct iwl4965_frame *frame) { memset(frame, 0, sizeof(*frame)); list_add(&frame->list, &priv->free_frames); } -unsigned int iwl4965_fill_beacon_frame(struct iwl4965_priv *priv, +unsigned int iwl4965_fill_beacon_frame(struct iwl_priv *priv, struct ieee80211_hdr *hdr, const u8 *dest, int left) { @@ -1525,7 +1525,7 @@ static u8 iwl4965_rate_get_lowest_plcp(int rate_mask) return IWL_RATE_INVALID; } -static int iwl4965_send_beacon_cmd(struct iwl4965_priv *priv) +static int iwl4965_send_beacon_cmd(struct iwl_priv *priv) { struct iwl4965_frame *frame; unsigned int frame_size; @@ -1567,7 +1567,7 @@ static int iwl4965_send_beacon_cmd(struct iwl4965_priv *priv) * ******************************************************************************/ -static void iwl4965_unset_hw_setting(struct iwl4965_priv *priv) +static void iwl4965_unset_hw_setting(struct iwl_priv *priv) { if (priv->hw_setting.shared_virt) pci_free_consistent(priv->pci_dev, @@ -1608,7 +1608,7 @@ static u16 iwl4965_supported_rate_to_ie(u8 *ie, u16 supported_rate, /** * iwl4965_fill_probe_req - fill in all required fields and IE for probe request */ -static u16 iwl4965_fill_probe_req(struct iwl4965_priv *priv, +static u16 iwl4965_fill_probe_req(struct iwl_priv *priv, enum ieee80211_band band, struct ieee80211_mgmt *frame, int left, int is_direct) @@ -1726,7 +1726,7 @@ static u16 iwl4965_fill_probe_req(struct iwl4965_priv *priv, /* * QoS support */ -static int iwl4965_send_qos_params_command(struct iwl4965_priv *priv, +static int iwl4965_send_qos_params_command(struct iwl_priv *priv, struct iwl4965_qosparam_cmd *qos) { @@ -1734,7 +1734,7 @@ static int iwl4965_send_qos_params_command(struct iwl4965_priv *priv, sizeof(struct iwl4965_qosparam_cmd), qos); } -static void iwl4965_reset_qos(struct iwl4965_priv *priv) +static void iwl4965_reset_qos(struct iwl_priv *priv) { u16 cw_min = 15; u16 cw_max = 1023; @@ -1821,7 +1821,7 @@ static void iwl4965_reset_qos(struct iwl4965_priv *priv) spin_unlock_irqrestore(&priv->lock, flags); } -static void iwl4965_activate_qos(struct iwl4965_priv *priv, u8 force) +static void iwl4965_activate_qos(struct iwl_priv *priv, u8 force) { unsigned long flags; @@ -1899,7 +1899,7 @@ static struct iwl4965_power_vec_entry range_1[IWL_POWER_AC] = { SLP_VEC(4, 7, 10, 10, 0xFF)}, 0} }; -int iwl4965_power_init_handle(struct iwl4965_priv *priv) +int iwl4965_power_init_handle(struct iwl_priv *priv) { int rc = 0, i; struct iwl4965_power_mgr *pow_data; @@ -1938,7 +1938,7 @@ int iwl4965_power_init_handle(struct iwl4965_priv *priv) return rc; } -static int iwl4965_update_power_cmd(struct iwl4965_priv *priv, +static int iwl4965_update_power_cmd(struct iwl_priv *priv, struct iwl4965_powertable_cmd *cmd, u32 mode) { int rc = 0, i; @@ -2002,7 +2002,7 @@ static int iwl4965_update_power_cmd(struct iwl4965_priv *priv, return rc; } -static int iwl4965_send_power_mode(struct iwl4965_priv *priv, u32 mode) +static int iwl4965_send_power_mode(struct iwl_priv *priv, u32 mode) { u32 uninitialized_var(final_mode); int rc; @@ -2037,7 +2037,7 @@ static int iwl4965_send_power_mode(struct iwl4965_priv *priv, u32 mode) return rc; } -int iwl4965_is_network_packet(struct iwl4965_priv *priv, struct ieee80211_hdr *header) +int iwl4965_is_network_packet(struct iwl_priv *priv, struct ieee80211_hdr *header) { /* Filter incoming packets to determine if they are targeted toward * this network, discarding packets coming from ourselves */ @@ -2098,7 +2098,7 @@ static const char *iwl4965_get_tx_fail_reason(u32 status) * * NOTE: priv->mutex is not required before calling this function */ -static int iwl4965_scan_cancel(struct iwl4965_priv *priv) +static int iwl4965_scan_cancel(struct iwl_priv *priv) { if (!test_bit(STATUS_SCAN_HW, &priv->status)) { clear_bit(STATUS_SCANNING, &priv->status); @@ -2126,7 +2126,7 @@ static int iwl4965_scan_cancel(struct iwl4965_priv *priv) * * NOTE: priv->mutex must be held before calling this function */ -static int iwl4965_scan_cancel_timeout(struct iwl4965_priv *priv, unsigned long ms) +static int iwl4965_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms) { unsigned long now = jiffies; int ret; @@ -2145,7 +2145,7 @@ static int iwl4965_scan_cancel_timeout(struct iwl4965_priv *priv, unsigned long return ret; } -static void iwl4965_sequence_reset(struct iwl4965_priv *priv) +static void iwl4965_sequence_reset(struct iwl_priv *priv) { /* Reset ieee stats */ @@ -2175,7 +2175,7 @@ static __le16 iwl4965_adjust_beacon_interval(u16 beacon_val) return cpu_to_le16(new_val); } -static void iwl4965_setup_rxon_timing(struct iwl4965_priv *priv) +static void iwl4965_setup_rxon_timing(struct iwl_priv *priv) { u64 interval_tm_unit; u64 tsf, result; @@ -2231,7 +2231,7 @@ static void iwl4965_setup_rxon_timing(struct iwl4965_priv *priv) le16_to_cpu(priv->rxon_timing.atim_window)); } -static int iwl4965_scan_initiate(struct iwl4965_priv *priv) +static int iwl4965_scan_initiate(struct iwl_priv *priv) { if (priv->iw_mode == IEEE80211_IF_TYPE_AP) { IWL_ERROR("APs don't scan.\n"); @@ -2265,7 +2265,7 @@ static int iwl4965_scan_initiate(struct iwl4965_priv *priv) return 0; } -static int iwl4965_set_rxon_hwcrypto(struct iwl4965_priv *priv, int hw_decrypt) +static int iwl4965_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt) { struct iwl4965_rxon_cmd *rxon = &priv->staging_rxon; @@ -2277,7 +2277,7 @@ static int iwl4965_set_rxon_hwcrypto(struct iwl4965_priv *priv, int hw_decrypt) return 0; } -static void iwl4965_set_flags_for_phymode(struct iwl4965_priv *priv, +static void iwl4965_set_flags_for_phymode(struct iwl_priv *priv, enum ieee80211_band band) { if (band == IEEE80211_BAND_5GHZ) { @@ -2304,7 +2304,7 @@ static void iwl4965_set_flags_for_phymode(struct iwl4965_priv *priv, /* * initialize rxon structure with default values from eeprom */ -static void iwl4965_connection_init_rx_config(struct iwl4965_priv *priv) +static void iwl4965_connection_init_rx_config(struct iwl_priv *priv) { const struct iwl4965_channel_info *ch_info; @@ -2376,7 +2376,7 @@ static void iwl4965_connection_init_rx_config(struct iwl4965_priv *priv) iwl4965_set_rxon_chain(priv); } -static int iwl4965_set_mode(struct iwl4965_priv *priv, int mode) +static int iwl4965_set_mode(struct iwl_priv *priv, int mode) { if (mode == IEEE80211_IF_TYPE_IBSS) { const struct iwl4965_channel_info *ch_info; @@ -2415,7 +2415,7 @@ static int iwl4965_set_mode(struct iwl4965_priv *priv, int mode) return 0; } -static void iwl4965_build_tx_cmd_hwcrypto(struct iwl4965_priv *priv, +static void iwl4965_build_tx_cmd_hwcrypto(struct iwl_priv *priv, struct ieee80211_tx_control *ctl, struct iwl4965_cmd *cmd, struct sk_buff *skb_frag, @@ -2466,7 +2466,7 @@ static void iwl4965_build_tx_cmd_hwcrypto(struct iwl4965_priv *priv, /* * handle build REPLY_TX command notification. */ -static void iwl4965_build_tx_cmd_basic(struct iwl4965_priv *priv, +static void iwl4965_build_tx_cmd_basic(struct iwl_priv *priv, struct iwl4965_cmd *cmd, struct ieee80211_tx_control *ctrl, struct ieee80211_hdr *hdr, @@ -2535,7 +2535,7 @@ static void iwl4965_build_tx_cmd_basic(struct iwl4965_priv *priv, * * If new IBSS station, create new entry in station table */ -static int iwl4965_get_sta_id(struct iwl4965_priv *priv, +static int iwl4965_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) { int sta_id; @@ -2590,7 +2590,7 @@ static int iwl4965_get_sta_id(struct iwl4965_priv *priv, /* * start REPLY_TX command process */ -static int iwl4965_tx_skb(struct iwl4965_priv *priv, +static int iwl4965_tx_skb(struct iwl_priv *priv, struct sk_buff *skb, struct ieee80211_tx_control *ctl) { struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; @@ -2829,7 +2829,7 @@ drop: return -1; } -static void iwl4965_set_rate(struct iwl4965_priv *priv) +static void iwl4965_set_rate(struct iwl_priv *priv) { const struct ieee80211_supported_band *hw = NULL; struct ieee80211_rate *rate; @@ -2876,7 +2876,7 @@ static void iwl4965_set_rate(struct iwl4965_priv *priv) (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; } -static void iwl4965_radio_kill_sw(struct iwl4965_priv *priv, int disable_radio) +static void iwl4965_radio_kill_sw(struct iwl_priv *priv, int disable_radio) { unsigned long flags; @@ -2925,7 +2925,7 @@ static void iwl4965_radio_kill_sw(struct iwl4965_priv *priv, int disable_radio) return; } -void iwl4965_set_decrypted_flag(struct iwl4965_priv *priv, struct sk_buff *skb, +void iwl4965_set_decrypted_flag(struct iwl_priv *priv, struct sk_buff *skb, u32 decrypt_res, struct ieee80211_rx_status *stats) { u16 fc = @@ -2960,7 +2960,7 @@ void iwl4965_set_decrypted_flag(struct iwl4965_priv *priv, struct sk_buff *skb, #define IWL_PACKET_RETRY_TIME HZ -int iwl4965_is_duplicate_packet(struct iwl4965_priv *priv, struct ieee80211_hdr *header) +int iwl4965_is_duplicate_packet(struct iwl_priv *priv, struct ieee80211_hdr *header) { u16 sc = le16_to_cpu(header->seq_ctrl); u16 seq = (sc & IEEE80211_SCTL_SEQ) >> 4; @@ -3077,7 +3077,7 @@ static __le32 iwl4965_add_beacon_time(u32 base, u32 addon, u32 beacon_interval) return cpu_to_le32(res); } -static int iwl4965_get_measurement(struct iwl4965_priv *priv, +static int iwl4965_get_measurement(struct iwl_priv *priv, struct ieee80211_measurement_params *params, u8 type) { @@ -3157,7 +3157,7 @@ static int iwl4965_get_measurement(struct iwl4965_priv *priv, } #endif -static void iwl4965_txstatus_to_ieee(struct iwl4965_priv *priv, +static void iwl4965_txstatus_to_ieee(struct iwl_priv *priv, struct iwl4965_tx_info *tx_sta) { @@ -3183,7 +3183,7 @@ static void iwl4965_txstatus_to_ieee(struct iwl4965_priv *priv, * need to be reclaimed. As result, some free space forms. If there is * enough free space (> low mark), wake the stack that feeds us. */ -int iwl4965_tx_queue_reclaim(struct iwl4965_priv *priv, int txq_id, int index) +int iwl4965_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) { struct iwl4965_tx_queue *txq = &priv->txq[txq_id]; struct iwl4965_queue *q = &txq->q; @@ -3234,7 +3234,7 @@ static int iwl4965_is_tx_success(u32 status) ******************************************************************************/ #ifdef CONFIG_IWL4965_HT -static inline int iwl4965_get_ra_sta_id(struct iwl4965_priv *priv, +static inline int iwl4965_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) { if (priv->iw_mode == IEEE80211_IF_TYPE_STA) @@ -3246,7 +3246,7 @@ static inline int iwl4965_get_ra_sta_id(struct iwl4965_priv *priv, } static struct ieee80211_hdr *iwl4965_tx_queue_get_hdr( - struct iwl4965_priv *priv, int txq_id, int idx) + struct iwl_priv *priv, int txq_id, int idx) { if (priv->txq[txq_id].txb[idx].skb[0]) return (struct ieee80211_hdr *)priv->txq[txq_id]. @@ -3265,7 +3265,7 @@ static inline u32 iwl4965_get_scd_ssn(struct iwl4965_tx_resp *tx_resp) /** * iwl4965_tx_status_reply_tx - Handle Tx rspnse for frames in aggregation queue */ -static int iwl4965_tx_status_reply_tx(struct iwl4965_priv *priv, +static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv, struct iwl4965_ht_agg *agg, struct iwl4965_tx_resp_agg *tx_resp, u16 start_idx) @@ -3386,7 +3386,7 @@ static int iwl4965_tx_status_reply_tx(struct iwl4965_priv *priv, /** * iwl4965_rx_reply_tx - Handle standard (non-aggregation) Tx response */ -static void iwl4965_rx_reply_tx(struct iwl4965_priv *priv, +static void iwl4965_rx_reply_tx(struct iwl_priv *priv, struct iwl4965_rx_mem_buffer *rxb) { struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data; @@ -3497,7 +3497,7 @@ static void iwl4965_rx_reply_tx(struct iwl4965_priv *priv, } -static void iwl4965_rx_reply_alive(struct iwl4965_priv *priv, +static void iwl4965_rx_reply_alive(struct iwl_priv *priv, struct iwl4965_rx_mem_buffer *rxb) { struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data; @@ -3533,7 +3533,7 @@ static void iwl4965_rx_reply_alive(struct iwl4965_priv *priv, IWL_WARNING("uCode did not respond OK.\n"); } -static void iwl4965_rx_reply_add_sta(struct iwl4965_priv *priv, +static void iwl4965_rx_reply_add_sta(struct iwl_priv *priv, struct iwl4965_rx_mem_buffer *rxb) { struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data; @@ -3542,7 +3542,7 @@ static void iwl4965_rx_reply_add_sta(struct iwl4965_priv *priv, return; } -static void iwl4965_rx_reply_error(struct iwl4965_priv *priv, +static void iwl4965_rx_reply_error(struct iwl_priv *priv, struct iwl4965_rx_mem_buffer *rxb) { struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data; @@ -3558,7 +3558,7 @@ static void iwl4965_rx_reply_error(struct iwl4965_priv *priv, #define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x -static void iwl4965_rx_csa(struct iwl4965_priv *priv, struct iwl4965_rx_mem_buffer *rxb) +static void iwl4965_rx_csa(struct iwl_priv *priv, struct iwl4965_rx_mem_buffer *rxb) { struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data; struct iwl4965_rxon_cmd *rxon = (void *)&priv->active_rxon; @@ -3569,7 +3569,7 @@ static void iwl4965_rx_csa(struct iwl4965_priv *priv, struct iwl4965_rx_mem_buff priv->staging_rxon.channel = csa->channel; } -static void iwl4965_rx_spectrum_measure_notif(struct iwl4965_priv *priv, +static void iwl4965_rx_spectrum_measure_notif(struct iwl_priv *priv, struct iwl4965_rx_mem_buffer *rxb) { #ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT @@ -3587,7 +3587,7 @@ static void iwl4965_rx_spectrum_measure_notif(struct iwl4965_priv *priv, #endif } -static void iwl4965_rx_pm_sleep_notif(struct iwl4965_priv *priv, +static void iwl4965_rx_pm_sleep_notif(struct iwl_priv *priv, struct iwl4965_rx_mem_buffer *rxb) { #ifdef CONFIG_IWLWIFI_DEBUG @@ -3598,7 +3598,7 @@ static void iwl4965_rx_pm_sleep_notif(struct iwl4965_priv *priv, #endif } -static void iwl4965_rx_pm_debug_statistics_notif(struct iwl4965_priv *priv, +static void iwl4965_rx_pm_debug_statistics_notif(struct iwl_priv *priv, struct iwl4965_rx_mem_buffer *rxb) { struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data; @@ -3610,8 +3610,8 @@ static void iwl4965_rx_pm_debug_statistics_notif(struct iwl4965_priv *priv, static void iwl4965_bg_beacon_update(struct work_struct *work) { - struct iwl4965_priv *priv = - container_of(work, struct iwl4965_priv, beacon_update); + struct iwl_priv *priv = + container_of(work, struct iwl_priv, beacon_update); struct sk_buff *beacon; /* Pull updated AP beacon from mac80211. will fail if not in AP mode */ @@ -3633,7 +3633,7 @@ static void iwl4965_bg_beacon_update(struct work_struct *work) iwl4965_send_beacon_cmd(priv); } -static void iwl4965_rx_beacon_notif(struct iwl4965_priv *priv, +static void iwl4965_rx_beacon_notif(struct iwl_priv *priv, struct iwl4965_rx_mem_buffer *rxb) { #ifdef CONFIG_IWLWIFI_DEBUG @@ -3656,7 +3656,7 @@ static void iwl4965_rx_beacon_notif(struct iwl4965_priv *priv, } /* Service response to REPLY_SCAN_CMD (0x80) */ -static void iwl4965_rx_reply_scan(struct iwl4965_priv *priv, +static void iwl4965_rx_reply_scan(struct iwl_priv *priv, struct iwl4965_rx_mem_buffer *rxb) { #ifdef CONFIG_IWLWIFI_DEBUG @@ -3669,7 +3669,7 @@ static void iwl4965_rx_reply_scan(struct iwl4965_priv *priv, } /* Service SCAN_START_NOTIFICATION (0x82) */ -static void iwl4965_rx_scan_start_notif(struct iwl4965_priv *priv, +static void iwl4965_rx_scan_start_notif(struct iwl_priv *priv, struct iwl4965_rx_mem_buffer *rxb) { struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data; @@ -3686,7 +3686,7 @@ static void iwl4965_rx_scan_start_notif(struct iwl4965_priv *priv, } /* Service SCAN_RESULTS_NOTIFICATION (0x83) */ -static void iwl4965_rx_scan_results_notif(struct iwl4965_priv *priv, +static void iwl4965_rx_scan_results_notif(struct iwl_priv *priv, struct iwl4965_rx_mem_buffer *rxb) { struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data; @@ -3711,7 +3711,7 @@ static void iwl4965_rx_scan_results_notif(struct iwl4965_priv *priv, } /* Service SCAN_COMPLETE_NOTIFICATION (0x84) */ -static void iwl4965_rx_scan_complete_notif(struct iwl4965_priv *priv, +static void iwl4965_rx_scan_complete_notif(struct iwl_priv *priv, struct iwl4965_rx_mem_buffer *rxb) { struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data; @@ -3769,7 +3769,7 @@ reschedule: /* Handle notification from uCode that card's power state is changing * due to software, hardware, or critical temperature RFKILL */ -static void iwl4965_rx_card_state_notif(struct iwl4965_priv *priv, +static void iwl4965_rx_card_state_notif(struct iwl_priv *priv, struct iwl4965_rx_mem_buffer *rxb) { struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data; @@ -3847,7 +3847,7 @@ static void iwl4965_rx_card_state_notif(struct iwl4965_priv *priv, * This function chains into the hardware specific files for them to setup * any hardware specific handlers as well. */ -static void iwl4965_setup_rx_handlers(struct iwl4965_priv *priv) +static void iwl4965_setup_rx_handlers(struct iwl_priv *priv) { priv->rx_handlers[REPLY_ALIVE] = iwl4965_rx_reply_alive; priv->rx_handlers[REPLY_ADD_STA] = iwl4965_rx_reply_add_sta; @@ -3889,7 +3889,7 @@ static void iwl4965_setup_rx_handlers(struct iwl4965_priv *priv) * will be executed. The attached skb (if present) will only be freed * if the callback returns 1 */ -static void iwl4965_tx_cmd_complete(struct iwl4965_priv *priv, +static void iwl4965_tx_cmd_complete(struct iwl_priv *priv, struct iwl4965_rx_mem_buffer *rxb) { struct iwl4965_rx_packet *pkt = (struct iwl4965_rx_packet *)rxb->skb->data; @@ -4012,7 +4012,7 @@ static int iwl4965_rx_queue_space(const struct iwl4965_rx_queue *q) /** * iwl4965_rx_queue_update_write_ptr - Update the write pointer for the RX queue */ -int iwl4965_rx_queue_update_write_ptr(struct iwl4965_priv *priv, struct iwl4965_rx_queue *q) +int iwl4965_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl4965_rx_queue *q) { u32 reg = 0; int rc = 0; @@ -4058,7 +4058,7 @@ int iwl4965_rx_queue_update_write_ptr(struct iwl4965_priv *priv, struct iwl4965_ /** * iwl4965_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr */ -static inline __le32 iwl4965_dma_addr2rbd_ptr(struct iwl4965_priv *priv, +static inline __le32 iwl4965_dma_addr2rbd_ptr(struct iwl_priv *priv, dma_addr_t dma_addr) { return cpu_to_le32((u32)(dma_addr >> 8)); @@ -4076,7 +4076,7 @@ static inline __le32 iwl4965_dma_addr2rbd_ptr(struct iwl4965_priv *priv, * also updates the memory address in the firmware to reference the new * target buffer. */ -static int iwl4965_rx_queue_restock(struct iwl4965_priv *priv) +static int iwl4965_rx_queue_restock(struct iwl_priv *priv) { struct iwl4965_rx_queue *rxq = &priv->rxq; struct list_head *element; @@ -4128,7 +4128,7 @@ static int iwl4965_rx_queue_restock(struct iwl4965_priv *priv) * Also restock the Rx queue via iwl4965_rx_queue_restock. * This is called as a scheduled work item (except for during initialization) */ -static void iwl4965_rx_allocate(struct iwl4965_priv *priv) +static void iwl4965_rx_allocate(struct iwl_priv *priv) { struct iwl4965_rx_queue *rxq = &priv->rxq; struct list_head *element; @@ -4170,7 +4170,7 @@ static void iwl4965_rx_allocate(struct iwl4965_priv *priv) */ static void __iwl4965_rx_replenish(void *data) { - struct iwl4965_priv *priv = data; + struct iwl_priv *priv = data; iwl4965_rx_allocate(priv); iwl4965_rx_queue_restock(priv); @@ -4179,7 +4179,7 @@ static void __iwl4965_rx_replenish(void *data) void iwl4965_rx_replenish(void *data) { - struct iwl4965_priv *priv = data; + struct iwl_priv *priv = data; unsigned long flags; iwl4965_rx_allocate(priv); @@ -4194,7 +4194,7 @@ void iwl4965_rx_replenish(void *data) * This free routine walks the list of POOL entries and if SKB is set to * non NULL it is unmapped and freed */ -static void iwl4965_rx_queue_free(struct iwl4965_priv *priv, struct iwl4965_rx_queue *rxq) +static void iwl4965_rx_queue_free(struct iwl_priv *priv, struct iwl4965_rx_queue *rxq) { int i; for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) { @@ -4212,7 +4212,7 @@ static void iwl4965_rx_queue_free(struct iwl4965_priv *priv, struct iwl4965_rx_q rxq->bd = NULL; } -int iwl4965_rx_queue_alloc(struct iwl4965_priv *priv) +int iwl4965_rx_queue_alloc(struct iwl_priv *priv) { struct iwl4965_rx_queue *rxq = &priv->rxq; struct pci_dev *dev = priv->pci_dev; @@ -4239,7 +4239,7 @@ int iwl4965_rx_queue_alloc(struct iwl4965_priv *priv) return 0; } -void iwl4965_rx_queue_reset(struct iwl4965_priv *priv, struct iwl4965_rx_queue *rxq) +void iwl4965_rx_queue_reset(struct iwl_priv *priv, struct iwl4965_rx_queue *rxq) { unsigned long flags; int i; @@ -4354,7 +4354,7 @@ int iwl4965_calc_sig_qual(int rssi_dbm, int noise_dbm) * the appropriate handlers, including command responses, * frame-received notifications, and other notifications. */ -static void iwl4965_rx_handle(struct iwl4965_priv *priv) +static void iwl4965_rx_handle(struct iwl_priv *priv) { struct iwl4965_rx_mem_buffer *rxb; struct iwl4965_rx_packet *pkt; @@ -4467,7 +4467,7 @@ static void iwl4965_rx_handle(struct iwl4965_priv *priv) /** * iwl4965_tx_queue_update_write_ptr - Send new write index to hardware */ -static int iwl4965_tx_queue_update_write_ptr(struct iwl4965_priv *priv, +static int iwl4965_tx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl4965_tx_queue *txq) { u32 reg = 0; @@ -4533,14 +4533,14 @@ static void iwl4965_print_rx_config_cmd(struct iwl4965_rxon_cmd *rxon) } #endif -static void iwl4965_enable_interrupts(struct iwl4965_priv *priv) +static void iwl4965_enable_interrupts(struct iwl_priv *priv) { IWL_DEBUG_ISR("Enabling interrupts\n"); set_bit(STATUS_INT_ENABLED, &priv->status); iwl4965_write32(priv, CSR_INT_MASK, CSR_INI_SET_MASK); } -static inline void iwl4965_disable_interrupts(struct iwl4965_priv *priv) +static inline void iwl4965_disable_interrupts(struct iwl_priv *priv) { clear_bit(STATUS_INT_ENABLED, &priv->status); @@ -4577,7 +4577,7 @@ static const char *desc_lookup(int i) #define ERROR_START_OFFSET (1 * sizeof(u32)) #define ERROR_ELEM_SIZE (7 * sizeof(u32)) -static void iwl4965_dump_nic_error_log(struct iwl4965_priv *priv) +static void iwl4965_dump_nic_error_log(struct iwl_priv *priv) { u32 data2, line; u32 desc, time, count, base, data1; @@ -4632,7 +4632,7 @@ static void iwl4965_dump_nic_error_log(struct iwl4965_priv *priv) * * NOTE: Must be called with iwl4965_grab_nic_access() already obtained! */ -static void iwl4965_print_event_log(struct iwl4965_priv *priv, u32 start_idx, +static void iwl4965_print_event_log(struct iwl_priv *priv, u32 start_idx, u32 num_events, u32 mode) { u32 i; @@ -4670,7 +4670,7 @@ static void iwl4965_print_event_log(struct iwl4965_priv *priv, u32 start_idx, } } -static void iwl4965_dump_nic_event_log(struct iwl4965_priv *priv) +static void iwl4965_dump_nic_event_log(struct iwl_priv *priv) { int rc; u32 base; /* SRAM byte address of event log header */ @@ -4725,7 +4725,7 @@ static void iwl4965_dump_nic_event_log(struct iwl4965_priv *priv) /** * iwl4965_irq_handle_error - called for HW or SW error interrupt from card */ -static void iwl4965_irq_handle_error(struct iwl4965_priv *priv) +static void iwl4965_irq_handle_error(struct iwl_priv *priv) { /* Set the FW error flag -- cleared on iwl4965_down */ set_bit(STATUS_FW_ERROR, &priv->status); @@ -4760,7 +4760,7 @@ static void iwl4965_irq_handle_error(struct iwl4965_priv *priv) } } -static void iwl4965_error_recovery(struct iwl4965_priv *priv) +static void iwl4965_error_recovery(struct iwl_priv *priv) { unsigned long flags; @@ -4777,7 +4777,7 @@ static void iwl4965_error_recovery(struct iwl4965_priv *priv) spin_unlock_irqrestore(&priv->lock, flags); } -static void iwl4965_irq_tasklet(struct iwl4965_priv *priv) +static void iwl4965_irq_tasklet(struct iwl_priv *priv) { u32 inta, handled = 0; u32 inta_fh; @@ -4939,7 +4939,7 @@ static void iwl4965_irq_tasklet(struct iwl4965_priv *priv) static irqreturn_t iwl4965_isr(int irq, void *data) { - struct iwl4965_priv *priv = data; + struct iwl_priv *priv = data; u32 inta, inta_mask; u32 inta_fh; if (!priv) @@ -4999,7 +4999,7 @@ static irqreturn_t iwl4965_isr(int irq, void *data) * EEPROM contents to the specific channel number supported for each * band. * - * For example, iwl4965_priv->eeprom.band_3_channels[4] from the band_3 + * For example, iwl_priv->eeprom.band_3_channels[4] from the band_3 * definition below maps to physical channel 42 in the 5.2GHz spectrum. * The specific geography and calibration information for that channel * is contained in the eeprom map itself. @@ -5054,7 +5054,7 @@ static u8 iwl4965_eeprom_band_7[] = { /* 5.2 FAT channel */ 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157 }; -static void iwl4965_init_band_reference(const struct iwl4965_priv *priv, +static void iwl4965_init_band_reference(const struct iwl_priv *priv, int band, int *eeprom_ch_count, const struct iwl4965_eeprom_channel @@ -5108,7 +5108,7 @@ static void iwl4965_init_band_reference(const struct iwl4965_priv *priv, * * Based on band and channel number. */ -const struct iwl4965_channel_info *iwl4965_get_channel_info(const struct iwl4965_priv *priv, +const struct iwl4965_channel_info *iwl4965_get_channel_info(const struct iwl_priv *priv, enum ieee80211_band band, u16 channel) { int i; @@ -5137,7 +5137,7 @@ const struct iwl4965_channel_info *iwl4965_get_channel_info(const struct iwl4965 /** * iwl4965_init_channel_map - Set up driver's info for all possible channels */ -static int iwl4965_init_channel_map(struct iwl4965_priv *priv) +static int iwl4965_init_channel_map(struct iwl_priv *priv) { int eeprom_ch_count = 0; const u8 *eeprom_ch_index = NULL; @@ -5289,7 +5289,7 @@ static int iwl4965_init_channel_map(struct iwl4965_priv *priv) /* * iwl4965_free_channel_map - undo allocations in iwl4965_init_channel_map */ -static void iwl4965_free_channel_map(struct iwl4965_priv *priv) +static void iwl4965_free_channel_map(struct iwl_priv *priv) { kfree(priv->channel_info); priv->channel_count = 0; @@ -5318,7 +5318,7 @@ static void iwl4965_free_channel_map(struct iwl4965_priv *priv) #define IWL_PASSIVE_DWELL_BASE (100) #define IWL_CHANNEL_TUNE_TIME 5 -static inline u16 iwl4965_get_active_dwell_time(struct iwl4965_priv *priv, +static inline u16 iwl4965_get_active_dwell_time(struct iwl_priv *priv, enum ieee80211_band band) { if (band == IEEE80211_BAND_5GHZ) @@ -5327,7 +5327,7 @@ static inline u16 iwl4965_get_active_dwell_time(struct iwl4965_priv *priv, return IWL_ACTIVE_DWELL_TIME_24; } -static u16 iwl4965_get_passive_dwell_time(struct iwl4965_priv *priv, +static u16 iwl4965_get_passive_dwell_time(struct iwl_priv *priv, enum ieee80211_band band) { u16 active = iwl4965_get_active_dwell_time(priv, band); @@ -5351,7 +5351,7 @@ static u16 iwl4965_get_passive_dwell_time(struct iwl4965_priv *priv, return passive; } -static int iwl4965_get_channels_for_scan(struct iwl4965_priv *priv, +static int iwl4965_get_channels_for_scan(struct iwl_priv *priv, enum ieee80211_band band, u8 is_active, u8 direct_mask, struct iwl4965_scan_channel *scan_ch) @@ -5438,7 +5438,7 @@ static int iwl4965_get_channels_for_scan(struct iwl4965_priv *priv, return added; } -static void iwl4965_init_hw_rates(struct iwl4965_priv *priv, +static void iwl4965_init_hw_rates(struct iwl_priv *priv, struct ieee80211_rate *rates) { int i; @@ -5462,7 +5462,7 @@ static void iwl4965_init_hw_rates(struct iwl4965_priv *priv, /** * iwl4965_init_geos - Initialize mac80211's geo/channel info based from eeprom */ -static int iwl4965_init_geos(struct iwl4965_priv *priv) +static int iwl4965_init_geos(struct iwl_priv *priv) { struct iwl4965_channel_info *ch; struct ieee80211_supported_band *sband; @@ -5584,7 +5584,7 @@ static int iwl4965_init_geos(struct iwl4965_priv *priv) /* * iwl4965_free_geos - undo allocations in iwl4965_init_geos */ -static void iwl4965_free_geos(struct iwl4965_priv *priv) +static void iwl4965_free_geos(struct iwl_priv *priv) { kfree(priv->ieee_channels); kfree(priv->ieee_rates); @@ -5597,7 +5597,7 @@ static void iwl4965_free_geos(struct iwl4965_priv *priv) * ******************************************************************************/ -static void iwl4965_dealloc_ucode_pci(struct iwl4965_priv *priv) +static void iwl4965_dealloc_ucode_pci(struct iwl_priv *priv) { iwl_free_fw_desc(priv->pci_dev, &priv->ucode_code); iwl_free_fw_desc(priv->pci_dev, &priv->ucode_data); @@ -5611,7 +5611,7 @@ static void iwl4965_dealloc_ucode_pci(struct iwl4965_priv *priv) * iwl4965_verify_inst_full - verify runtime uCode image in card vs. host, * looking at all data. */ -static int iwl4965_verify_inst_full(struct iwl4965_priv *priv, __le32 *image, +static int iwl4965_verify_inst_full(struct iwl_priv *priv, __le32 *image, u32 len) { u32 val; @@ -5659,7 +5659,7 @@ static int iwl4965_verify_inst_full(struct iwl4965_priv *priv, __le32 *image, * using sample data 100 bytes apart. If these sample points are good, * it's a pretty good bet that everything between them is good, too. */ -static int iwl4965_verify_inst_sparse(struct iwl4965_priv *priv, __le32 *image, u32 len) +static int iwl4965_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 len) { u32 val; int rc = 0; @@ -5702,7 +5702,7 @@ static int iwl4965_verify_inst_sparse(struct iwl4965_priv *priv, __le32 *image, * iwl4965_verify_ucode - determine which instruction image is in SRAM, * and verify its contents */ -static int iwl4965_verify_ucode(struct iwl4965_priv *priv) +static int iwl4965_verify_ucode(struct iwl_priv *priv) { __le32 *image; u32 len; @@ -5749,7 +5749,7 @@ static int iwl4965_verify_ucode(struct iwl4965_priv *priv) /* check contents of special bootstrap uCode SRAM */ -static int iwl4965_verify_bsm(struct iwl4965_priv *priv) +static int iwl4965_verify_bsm(struct iwl_priv *priv) { __le32 *image = priv->ucode_boot.v_addr; u32 len = priv->ucode_boot.len; @@ -5811,7 +5811,7 @@ static int iwl4965_verify_bsm(struct iwl4965_priv *priv) * the runtime uCode instructions and the backup data cache into SRAM, * and re-launches the runtime uCode from where it left off. */ -static int iwl4965_load_bsm(struct iwl4965_priv *priv) +static int iwl4965_load_bsm(struct iwl_priv *priv) { __le32 *image = priv->ucode_boot.v_addr; u32 len = priv->ucode_boot.len; @@ -5897,7 +5897,7 @@ static int iwl4965_load_bsm(struct iwl4965_priv *priv) return 0; } -static void iwl4965_nic_start(struct iwl4965_priv *priv) +static void iwl4965_nic_start(struct iwl_priv *priv) { /* Remove all resets to allow NIC to operate */ iwl4965_write32(priv, CSR_RESET, 0); @@ -5909,7 +5909,7 @@ static void iwl4965_nic_start(struct iwl4965_priv *priv) * * Copy into buffers for card to fetch via bus-mastering */ -static int iwl4965_read_ucode(struct iwl4965_priv *priv) +static int iwl4965_read_ucode(struct iwl_priv *priv) { struct iwl4965_ucode *ucode; int ret; @@ -6110,7 +6110,7 @@ static int iwl4965_read_ucode(struct iwl4965_priv *priv) * We need to replace them to load runtime uCode inst and data, * and to save runtime data when powering down. */ -static int iwl4965_set_ucode_ptrs(struct iwl4965_priv *priv) +static int iwl4965_set_ucode_ptrs(struct iwl_priv *priv) { dma_addr_t pinst; dma_addr_t pdata; @@ -6159,7 +6159,7 @@ static int iwl4965_set_ucode_ptrs(struct iwl4965_priv *priv) * * Tell "initialize" uCode to go ahead and load the runtime uCode. */ -static void iwl4965_init_alive_start(struct iwl4965_priv *priv) +static void iwl4965_init_alive_start(struct iwl_priv *priv) { /* Check alive response for "valid" sign from uCode */ if (priv->card_alive_init.is_valid != UCODE_VALID_OK) { @@ -6204,7 +6204,7 @@ static void iwl4965_init_alive_start(struct iwl4965_priv *priv) * from protocol/runtime uCode (initialization uCode's * Alive gets handled by iwl4965_init_alive_start()). */ -static void iwl4965_alive_start(struct iwl4965_priv *priv) +static void iwl4965_alive_start(struct iwl_priv *priv) { int rc = 0; @@ -6289,9 +6289,9 @@ static void iwl4965_alive_start(struct iwl4965_priv *priv) queue_work(priv->workqueue, &priv->restart); } -static void iwl4965_cancel_deferred_work(struct iwl4965_priv *priv); +static void iwl4965_cancel_deferred_work(struct iwl_priv *priv); -static void __iwl4965_down(struct iwl4965_priv *priv) +static void __iwl4965_down(struct iwl_priv *priv) { unsigned long flags; int exit_pending = test_bit(STATUS_EXIT_PENDING, &priv->status); @@ -6383,7 +6383,7 @@ static void __iwl4965_down(struct iwl4965_priv *priv) iwl4965_clear_free_frames(priv); } -static void iwl4965_down(struct iwl4965_priv *priv) +static void iwl4965_down(struct iwl_priv *priv) { mutex_lock(&priv->mutex); __iwl4965_down(priv); @@ -6394,7 +6394,7 @@ static void iwl4965_down(struct iwl4965_priv *priv) #define MAX_HW_RESTARTS 5 -static int __iwl4965_up(struct iwl4965_priv *priv) +static int __iwl4965_up(struct iwl_priv *priv) { int rc, i; @@ -6497,8 +6497,8 @@ static int __iwl4965_up(struct iwl4965_priv *priv) static void iwl4965_bg_init_alive_start(struct work_struct *data) { - struct iwl4965_priv *priv = - container_of(data, struct iwl4965_priv, init_alive_start.work); + struct iwl_priv *priv = + container_of(data, struct iwl_priv, init_alive_start.work); if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; @@ -6510,8 +6510,8 @@ static void iwl4965_bg_init_alive_start(struct work_struct *data) static void iwl4965_bg_alive_start(struct work_struct *data) { - struct iwl4965_priv *priv = - container_of(data, struct iwl4965_priv, alive_start.work); + struct iwl_priv *priv = + container_of(data, struct iwl_priv, alive_start.work); if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; @@ -6523,7 +6523,7 @@ static void iwl4965_bg_alive_start(struct work_struct *data) static void iwl4965_bg_rf_kill(struct work_struct *work) { - struct iwl4965_priv *priv = container_of(work, struct iwl4965_priv, rf_kill); + struct iwl_priv *priv = container_of(work, struct iwl_priv, rf_kill); wake_up_interruptible(&priv->wait_command_queue); @@ -6555,8 +6555,8 @@ static void iwl4965_bg_rf_kill(struct work_struct *work) static void iwl4965_bg_scan_check(struct work_struct *data) { - struct iwl4965_priv *priv = - container_of(data, struct iwl4965_priv, scan_check.work); + struct iwl_priv *priv = + container_of(data, struct iwl_priv, scan_check.work); if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; @@ -6576,8 +6576,8 @@ static void iwl4965_bg_scan_check(struct work_struct *data) static void iwl4965_bg_request_scan(struct work_struct *data) { - struct iwl4965_priv *priv = - container_of(data, struct iwl4965_priv, request_scan); + struct iwl_priv *priv = + container_of(data, struct iwl_priv, request_scan); struct iwl4965_host_cmd cmd = { .id = REPLY_SCAN_CMD, .len = sizeof(struct iwl4965_scan_cmd), @@ -6788,7 +6788,7 @@ static void iwl4965_bg_request_scan(struct work_struct *data) static void iwl4965_bg_up(struct work_struct *data) { - struct iwl4965_priv *priv = container_of(data, struct iwl4965_priv, up); + struct iwl_priv *priv = container_of(data, struct iwl_priv, up); if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; @@ -6800,7 +6800,7 @@ static void iwl4965_bg_up(struct work_struct *data) static void iwl4965_bg_restart(struct work_struct *data) { - struct iwl4965_priv *priv = container_of(data, struct iwl4965_priv, restart); + struct iwl_priv *priv = container_of(data, struct iwl_priv, restart); if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; @@ -6811,8 +6811,8 @@ static void iwl4965_bg_restart(struct work_struct *data) static void iwl4965_bg_rx_replenish(struct work_struct *data) { - struct iwl4965_priv *priv = - container_of(data, struct iwl4965_priv, rx_replenish); + struct iwl_priv *priv = + container_of(data, struct iwl_priv, rx_replenish); if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; @@ -6826,7 +6826,7 @@ static void iwl4965_bg_rx_replenish(struct work_struct *data) static void iwl4965_bg_post_associate(struct work_struct *data) { - struct iwl4965_priv *priv = container_of(data, struct iwl4965_priv, + struct iwl_priv *priv = container_of(data, struct iwl_priv, post_associate.work); int rc = 0; @@ -6940,7 +6940,7 @@ static void iwl4965_bg_post_associate(struct work_struct *data) static void iwl4965_bg_abort_scan(struct work_struct *work) { - struct iwl4965_priv *priv = container_of(work, struct iwl4965_priv, abort_scan); + struct iwl_priv *priv = container_of(work, struct iwl_priv, abort_scan); if (!iwl4965_is_ready(priv)) return; @@ -6957,8 +6957,8 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co static void iwl4965_bg_scan_completed(struct work_struct *work) { - struct iwl4965_priv *priv = - container_of(work, struct iwl4965_priv, scan_completed); + struct iwl_priv *priv = + container_of(work, struct iwl_priv, scan_completed); IWL_DEBUG(IWL_DL_INFO | IWL_DL_SCAN, "SCAN complete scan\n"); @@ -6987,7 +6987,7 @@ static void iwl4965_bg_scan_completed(struct work_struct *work) static int iwl4965_mac_start(struct ieee80211_hw *hw) { - struct iwl4965_priv *priv = hw->priv; + struct iwl_priv *priv = hw->priv; int ret; IWL_DEBUG_MAC80211("enter\n"); @@ -7064,7 +7064,7 @@ out_disable_msi: static void iwl4965_mac_stop(struct ieee80211_hw *hw) { - struct iwl4965_priv *priv = hw->priv; + struct iwl_priv *priv = hw->priv; IWL_DEBUG_MAC80211("enter\n"); @@ -7099,7 +7099,7 @@ static void iwl4965_mac_stop(struct ieee80211_hw *hw) static int iwl4965_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb, struct ieee80211_tx_control *ctl) { - struct iwl4965_priv *priv = hw->priv; + struct iwl_priv *priv = hw->priv; IWL_DEBUG_MAC80211("enter\n"); @@ -7121,7 +7121,7 @@ static int iwl4965_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb, static int iwl4965_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_if_init_conf *conf) { - struct iwl4965_priv *priv = hw->priv; + struct iwl_priv *priv = hw->priv; unsigned long flags; DECLARE_MAC_BUF(mac); @@ -7162,7 +7162,7 @@ static int iwl4965_mac_add_interface(struct ieee80211_hw *hw, */ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) { - struct iwl4965_priv *priv = hw->priv; + struct iwl_priv *priv = hw->priv; const struct iwl4965_channel_info *ch_info; unsigned long flags; int ret = 0; @@ -7257,7 +7257,7 @@ out: return ret; } -static void iwl4965_config_ap(struct iwl4965_priv *priv) +static void iwl4965_config_ap(struct iwl_priv *priv) { int rc = 0; @@ -7321,7 +7321,7 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_if_conf *conf) { - struct iwl4965_priv *priv = hw->priv; + struct iwl_priv *priv = hw->priv; DECLARE_MAC_BUF(mac); unsigned long flags; int rc; @@ -7439,7 +7439,7 @@ static void iwl4965_configure_filter(struct ieee80211_hw *hw, static void iwl4965_mac_remove_interface(struct ieee80211_hw *hw, struct ieee80211_if_init_conf *conf) { - struct iwl4965_priv *priv = hw->priv; + struct iwl_priv *priv = hw->priv; IWL_DEBUG_MAC80211("enter\n"); @@ -7468,7 +7468,7 @@ static void iwl4965_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_bss_conf *bss_conf, u32 changes) { - struct iwl4965_priv *priv = hw->priv; + struct iwl_priv *priv = hw->priv; if (changes & BSS_CHANGED_ERP_PREAMBLE) { if (bss_conf->use_short_preamble) @@ -7499,7 +7499,7 @@ static int iwl4965_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len) { int rc = 0; unsigned long flags; - struct iwl4965_priv *priv = hw->priv; + struct iwl_priv *priv = hw->priv; IWL_DEBUG_MAC80211("enter\n"); @@ -7556,7 +7556,7 @@ static int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, const u8 *local_addr, const u8 *addr, struct ieee80211_key_conf *key) { - struct iwl4965_priv *priv = hw->priv; + struct iwl_priv *priv = hw->priv; DECLARE_MAC_BUF(mac); int rc = 0; u8 sta_id; @@ -7615,7 +7615,7 @@ static int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, static int iwl4965_mac_conf_tx(struct ieee80211_hw *hw, int queue, const struct ieee80211_tx_queue_params *params) { - struct iwl4965_priv *priv = hw->priv; + struct iwl_priv *priv = hw->priv; unsigned long flags; int q; @@ -7666,7 +7666,7 @@ static int iwl4965_mac_conf_tx(struct ieee80211_hw *hw, int queue, static int iwl4965_mac_get_tx_stats(struct ieee80211_hw *hw, struct ieee80211_tx_queue_stats *stats) { - struct iwl4965_priv *priv = hw->priv; + struct iwl_priv *priv = hw->priv; int i, avail; struct iwl4965_tx_queue *txq; struct iwl4965_queue *q; @@ -7717,7 +7717,7 @@ static u64 iwl4965_mac_get_tsf(struct ieee80211_hw *hw) static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw) { - struct iwl4965_priv *priv = hw->priv; + struct iwl_priv *priv = hw->priv; unsigned long flags; mutex_lock(&priv->mutex); @@ -7789,7 +7789,7 @@ static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw) static int iwl4965_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, struct ieee80211_tx_control *control) { - struct iwl4965_priv *priv = hw->priv; + struct iwl_priv *priv = hw->priv; unsigned long flags; mutex_lock(&priv->mutex); @@ -7831,7 +7831,7 @@ static int iwl4965_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk #ifdef CONFIG_IWL4965_HT static void iwl4965_ht_info_fill(struct ieee80211_conf *conf, - struct iwl4965_priv *priv) + struct iwl_priv *priv) { struct iwl_ht_info *iwl_conf = &priv->current_ht_config; struct ieee80211_ht_info *ht_conf = &conf->ht_conf; @@ -7885,7 +7885,7 @@ static void iwl4965_ht_info_fill(struct ieee80211_conf *conf, static int iwl4965_mac_conf_ht(struct ieee80211_hw *hw, struct ieee80211_conf *conf) { - struct iwl4965_priv *priv = hw->priv; + struct iwl_priv *priv = hw->priv; IWL_DEBUG_MAC80211("enter: \n"); @@ -7960,7 +7960,7 @@ static ssize_t show_rf_kill(struct device *d, * 2 - HW based RF kill active * 3 - Both HW and SW based RF kill active */ - struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data; + struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; int val = (test_bit(STATUS_RF_KILL_SW, &priv->status) ? 0x1 : 0x0) | (test_bit(STATUS_RF_KILL_HW, &priv->status) ? 0x2 : 0x0); @@ -7971,7 +7971,7 @@ static ssize_t store_rf_kill(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { - struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data; + struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; mutex_lock(&priv->mutex); iwl4965_radio_kill_sw(priv, buf[0] == '1'); @@ -7985,7 +7985,7 @@ static DEVICE_ATTR(rf_kill, S_IWUSR | S_IRUGO, show_rf_kill, store_rf_kill); static ssize_t show_temperature(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data; + struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; if (!iwl4965_is_alive(priv)) return -EAGAIN; @@ -7999,7 +7999,7 @@ static ssize_t show_rs_window(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl4965_priv *priv = d->driver_data; + struct iwl_priv *priv = d->driver_data; return iwl4965_fill_rs_info(priv->hw, buf, IWL_AP_ID); } static DEVICE_ATTR(rs_window, S_IRUGO, show_rs_window, NULL); @@ -8007,7 +8007,7 @@ static DEVICE_ATTR(rs_window, S_IRUGO, show_rs_window, NULL); static ssize_t show_tx_power(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data; + struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; return sprintf(buf, "%d\n", priv->user_txpower_limit); } @@ -8015,7 +8015,7 @@ static ssize_t store_tx_power(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { - struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data; + struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; char *p = (char *)buf; u32 val; @@ -8034,7 +8034,7 @@ static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power); static ssize_t show_flags(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data; + struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; return sprintf(buf, "0x%04X\n", priv->active_rxon.flags); } @@ -8043,7 +8043,7 @@ static ssize_t store_flags(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { - struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data; + struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; u32 flags = simple_strtoul(buf, NULL, 0); mutex_lock(&priv->mutex); @@ -8068,7 +8068,7 @@ static DEVICE_ATTR(flags, S_IWUSR | S_IRUGO, show_flags, store_flags); static ssize_t show_filter_flags(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data; + struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; return sprintf(buf, "0x%04X\n", le32_to_cpu(priv->active_rxon.filter_flags)); @@ -8078,7 +8078,7 @@ static ssize_t store_filter_flags(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { - struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data; + struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; u32 filter_flags = simple_strtoul(buf, NULL, 0); mutex_lock(&priv->mutex); @@ -8107,7 +8107,7 @@ static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags, static ssize_t show_measurement(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl4965_priv *priv = dev_get_drvdata(d); + struct iwl_priv *priv = dev_get_drvdata(d); struct iwl4965_spectrum_notification measure_report; u32 size = sizeof(measure_report), len = 0, ofs = 0; u8 *data = (u8 *) & measure_report; @@ -8140,7 +8140,7 @@ static ssize_t store_measurement(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { - struct iwl4965_priv *priv = dev_get_drvdata(d); + struct iwl_priv *priv = dev_get_drvdata(d); struct ieee80211_measurement_params params = { .channel = le16_to_cpu(priv->active_rxon.channel), .start_time = cpu_to_le64(priv->last_tsf), @@ -8179,7 +8179,7 @@ static ssize_t store_retry_rate(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { - struct iwl4965_priv *priv = dev_get_drvdata(d); + struct iwl_priv *priv = dev_get_drvdata(d); priv->retry_rate = simple_strtoul(buf, NULL, 0); if (priv->retry_rate <= 0) @@ -8191,7 +8191,7 @@ static ssize_t store_retry_rate(struct device *d, static ssize_t show_retry_rate(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl4965_priv *priv = dev_get_drvdata(d); + struct iwl_priv *priv = dev_get_drvdata(d); return sprintf(buf, "%d", priv->retry_rate); } @@ -8202,7 +8202,7 @@ static ssize_t store_power_level(struct device *d, struct device_attribute *attr, const char *buf, size_t count) { - struct iwl4965_priv *priv = dev_get_drvdata(d); + struct iwl_priv *priv = dev_get_drvdata(d); int rc; int mode; @@ -8256,7 +8256,7 @@ static const s32 period_duration[] = { static ssize_t show_power_level(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl4965_priv *priv = dev_get_drvdata(d); + struct iwl_priv *priv = dev_get_drvdata(d); int level = IWL_POWER_LEVEL(priv->power_mode); char *p = buf; @@ -8300,7 +8300,7 @@ static DEVICE_ATTR(channels, S_IRUSR, show_channels, NULL); static ssize_t show_statistics(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl4965_priv *priv = dev_get_drvdata(d); + struct iwl_priv *priv = dev_get_drvdata(d); u32 size = sizeof(struct iwl4965_notif_statistics); u32 len = 0, ofs = 0; u8 *data = (u8 *) & priv->statistics; @@ -8338,7 +8338,7 @@ static DEVICE_ATTR(statistics, S_IRUGO, show_statistics, NULL); static ssize_t show_antenna(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl4965_priv *priv = dev_get_drvdata(d); + struct iwl_priv *priv = dev_get_drvdata(d); if (!iwl4965_is_alive(priv)) return -EAGAIN; @@ -8351,7 +8351,7 @@ static ssize_t store_antenna(struct device *d, const char *buf, size_t count) { int ant; - struct iwl4965_priv *priv = dev_get_drvdata(d); + struct iwl_priv *priv = dev_get_drvdata(d); if (count == 0) return 0; @@ -8376,7 +8376,7 @@ static DEVICE_ATTR(antenna, S_IWUSR | S_IRUGO, show_antenna, store_antenna); static ssize_t show_status(struct device *d, struct device_attribute *attr, char *buf) { - struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data; + struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; if (!iwl4965_is_alive(priv)) return -EAGAIN; return sprintf(buf, "0x%08x\n", (int)priv->status); @@ -8391,7 +8391,7 @@ static ssize_t dump_error_log(struct device *d, char *p = (char *)buf; if (p[0] == '1') - iwl4965_dump_nic_error_log((struct iwl4965_priv *)d->driver_data); + iwl4965_dump_nic_error_log((struct iwl_priv *)d->driver_data); return strnlen(buf, count); } @@ -8405,7 +8405,7 @@ static ssize_t dump_event_log(struct device *d, char *p = (char *)buf; if (p[0] == '1') - iwl4965_dump_nic_event_log((struct iwl4965_priv *)d->driver_data); + iwl4965_dump_nic_event_log((struct iwl_priv *)d->driver_data); return strnlen(buf, count); } @@ -8418,7 +8418,7 @@ static DEVICE_ATTR(dump_events, S_IWUSR, NULL, dump_event_log); * *****************************************************************************/ -static void iwl4965_setup_deferred_work(struct iwl4965_priv *priv) +static void iwl4965_setup_deferred_work(struct iwl_priv *priv) { priv->workqueue = create_workqueue(DRV_NAME); @@ -8443,7 +8443,7 @@ static void iwl4965_setup_deferred_work(struct iwl4965_priv *priv) iwl4965_irq_tasklet, (unsigned long)priv); } -static void iwl4965_cancel_deferred_work(struct iwl4965_priv *priv) +static void iwl4965_cancel_deferred_work(struct iwl_priv *priv) { iwl4965_hw_cancel_deferred_work(priv); @@ -8508,7 +8508,7 @@ static struct ieee80211_ops iwl4965_hw_ops = { static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { int err = 0; - struct iwl4965_priv *priv; + struct iwl_priv *priv; struct ieee80211_hw *hw; struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); int i; @@ -8531,7 +8531,7 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e /* mac80211 allocates memory for this device instance, including * space for this driver's private structure */ - hw = ieee80211_alloc_hw(sizeof(struct iwl4965_priv), &iwl4965_hw_ops); + hw = ieee80211_alloc_hw(sizeof(struct iwl_priv), &iwl4965_hw_ops); if (hw == NULL) { IWL_ERROR("Can not allocate network device\n"); err = -ENOMEM; @@ -8758,7 +8758,7 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e static void iwl4965_pci_remove(struct pci_dev *pdev) { - struct iwl4965_priv *priv = pci_get_drvdata(pdev); + struct iwl_priv *priv = pci_get_drvdata(pdev); struct list_head *p, *q; int i; @@ -8822,7 +8822,7 @@ static void iwl4965_pci_remove(struct pci_dev *pdev) static int iwl4965_pci_suspend(struct pci_dev *pdev, pm_message_t state) { - struct iwl4965_priv *priv = pci_get_drvdata(pdev); + struct iwl_priv *priv = pci_get_drvdata(pdev); if (priv->is_open) { set_bit(STATUS_IN_SUSPEND, &priv->status); @@ -8837,7 +8837,7 @@ static int iwl4965_pci_suspend(struct pci_dev *pdev, pm_message_t state) static int iwl4965_pci_resume(struct pci_dev *pdev) { - struct iwl4965_priv *priv = pci_get_drvdata(pdev); + struct iwl_priv *priv = pci_get_drvdata(pdev); pci_set_power_state(pdev, PCI_D0); -- cgit v1.2.1 From 19758bef09abe9d2a14575ffb6f686947e97fcb1 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 12 Mar 2008 16:58:51 -0700 Subject: iwlwifi: Add TX/RX statistcs to driver This patch supports collecting of TX and RX statistics in the driver. Signed-off-by: Tomas Winkler Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965.c | 9 +++++++++ drivers/net/wireless/iwlwifi/iwl-4965.h | 6 ++++++ drivers/net/wireless/iwlwifi/iwl4965-base.c | 10 +++++++++- 3 files changed, 24 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 7b0ad728f927..b2ea4d4f3f31 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -3337,6 +3337,14 @@ static void iwl4965_add_radiotap(struct iwl_priv *priv, stats->flag |= RX_FLAG_RADIOTAP; } +static void iwl_update_rx_stats(struct iwl_priv *priv, u16 fc, u16 len) +{ + /* 0 - mgmt, 1 - cnt, 2 - data */ + int idx = (fc & IEEE80211_FCTL_FTYPE) >> 2; + priv->rx_stats[idx].cnt++; + priv->rx_stats[idx].bytes += len; +} + static void iwl4965_handle_data_packet(struct iwl_priv *priv, int is_data, int include_phy, struct iwl4965_rx_mem_buffer *rxb, @@ -3406,6 +3414,7 @@ static void iwl4965_handle_data_packet(struct iwl_priv *priv, int is_data, if (priv->add_radiotap) iwl4965_add_radiotap(priv, rxb->skb, rx_start, stats, ampdu_status); + iwl_update_rx_stats(priv, le16_to_cpu(hdr->frame_control), len); ieee80211_rx_irqsafe(priv->hw, rxb->skb, stats); priv->alloc_rxb_skb--; rxb->skb = NULL; diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index 60353b2645d4..aded6010ce20 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -1107,6 +1107,12 @@ struct iwl_priv { int last_rx_rssi; /* From Rx packet statisitics */ int last_rx_noise; /* From beacon statistics */ + /* counts mgmt, ctl, and data packets */ + struct traffic_stats { + u32 cnt; + u64 bytes; + } tx_stats[3], rx_stats[3]; + struct iwl4965_power_mgr power_data; struct iwl4965_notif_statistics statistics; diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 4e899ce81b32..4f6ed6942065 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -2529,7 +2529,13 @@ static void iwl4965_build_tx_cmd_basic(struct iwl_priv *priv, cmd->cmd.tx.tx_flags = tx_flags; cmd->cmd.tx.next_frame_len = 0; } - +static void iwl_update_tx_stats(struct iwl_priv *priv, u16 fc, u16 len) +{ + /* 0 - mgmt, 1 - cnt, 2 - data */ + int idx = (fc & IEEE80211_FCTL_FTYPE) >> 2; + priv->tx_stats[idx].cnt++; + priv->tx_stats[idx].bytes += len; +} /** * iwl4965_get_sta_id - Find station's index within station table * @@ -2776,6 +2782,8 @@ static int iwl4965_tx_skb(struct iwl_priv *priv, /* set is_hcca to 0; it probably will never be implemented */ iwl4965_hw_build_tx_cmd_rate(priv, out_cmd, ctl, hdr, sta_id, 0); + iwl_update_tx_stats(priv, fc, len); + scratch_phys = txcmd_phys + sizeof(struct iwl4965_cmd_header) + offsetof(struct iwl4965_tx_cmd, scratch); out_cmd->cmd.tx.dram_lsb_ptr = cpu_to_le32(scratch_phys); -- cgit v1.2.1 From 712b6cf57a53da608a682b5f782c5785bda76001 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Wed, 12 Mar 2008 16:58:52 -0700 Subject: iwlwifi: Add debugfs to iwl core This patch adds debugfs support to iwl core currently only iwl4965 is supported Signed-off-by: Tomas Winkler Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/Kconfig | 6 + drivers/net/wireless/iwlwifi/Makefile | 4 + drivers/net/wireless/iwlwifi/iwl-4965.h | 6 +- drivers/net/wireless/iwlwifi/iwl-core.c | 3 +- drivers/net/wireless/iwlwifi/iwl-debug.h | 31 ++- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 319 ++++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl4965-base.c | 14 +- 7 files changed, 377 insertions(+), 6 deletions(-) create mode 100644 drivers/net/wireless/iwlwifi/iwl-debugfs.c (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index acb807936131..1ab14ed33f58 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig @@ -76,6 +76,12 @@ config IWLWIFI_DEBUG as the debug information can assist others in helping you resolve any problems you may encounter. +config IWLWIFI_DEBUGFS + bool "Iwlwifi debugfs support" + depends on IWLCORE && IWLWIFI_DEBUG && MAC80211_DEBUGFS + ---help--- + Enable creation of debugfs files for the iwlwifi drivers. + config IWL3945 tristate "Intel PRO/Wireless 3945ABG/BG Network Connection" depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 59d9c90d3610..86ac1fc60bbb 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile @@ -1,6 +1,10 @@ obj-$(CONFIG_IWLCORE) += iwlcore.o iwlcore-objs = iwl-core.o iwl-eeprom.o +ifeq ($(CONFIG_IWLWIFI_DEBUGFS),y) + iwlcore-objs += iwl-debugfs.o +endif + obj-$(CONFIG_IWL3945) += iwl3945.o iwl3945-objs = iwl3945-base.o iwl-3945.o iwl-3945-rs.o diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index aded6010ce20..cec62ba803b5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -1212,7 +1212,11 @@ struct iwl_priv { /* debugging info */ u32 framecnt_to_us; atomic_t restrict_refcnt; -#endif +#ifdef CONFIG_IWLWIFI_DEBUGFS + /* debugfs */ + struct iwl_debugfs *dbgfs; +#endif /* CONFIG_IWLWIFI_DEBUGFS */ +#endif /* CONFIG_IWLWIFI_DEBUG */ struct work_struct txpower_work; #ifdef CONFIG_IWL4965_SENSITIVITY diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 4645d194773e..3a9fc905e6bc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -30,6 +30,7 @@ #include #include +struct iwl_priv; /* FIXME: remove */ #include "iwl-debug.h" #include "iwl-eeprom.h" #include "iwl-core.h" @@ -37,7 +38,7 @@ MODULE_DESCRIPTION("iwl core"); MODULE_VERSION(IWLWIFI_VERSION); MODULE_AUTHOR(DRV_COPYRIGHT); -MODULE_LICENSE("GPL/BSD"); +MODULE_LICENSE("GPL"); #ifdef CONFIG_IWLWIFI_DEBUG u32 iwl_debug_level; diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index 067700620e21..c60724c21db8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -49,8 +49,27 @@ static inline void iwl_print_hex_dump(int level, void *p, u32 len) print_hex_dump(KERN_DEBUG, "iwl data: ", DUMP_PREFIX_OFFSET, 16, 1, p, len, 1); } -#else +#ifdef CONFIG_IWLWIFI_DEBUGFS +struct iwl_debugfs { + const char *name; + struct dentry *dir_drv; + struct dentry *dir_data; + struct dir_data_files{ + struct dentry *file_sram; + struct dentry *file_stations; + struct dentry *file_rx_statistics; + struct dentry *file_tx_statistics; + } dbgfs_data_files; + u32 sram_offset; + u32 sram_len; +}; + +int iwl_dbgfs_register(struct iwl_priv *priv, const char *name); +void iwl_dbgfs_unregister(struct iwl_priv *priv); +#endif + +#else static inline void IWL_DEBUG(int level, const char *fmt, ...) { } @@ -64,6 +83,16 @@ static inline void iwl_print_hex_dump(int level, void *p, u32 len) +#ifndef CONFIG_IWLWIFI_DEBUGFS +static inline int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) +{ + return 0; +} +static inline void iwl_dbgfs_unregister(struct iwl_priv *priv) +{ +} +#endif /* CONFIG_IWLWIFI_DEBUGFS */ + /* * To use the debug system; * diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c new file mode 100644 index 000000000000..c659bd3bc346 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -0,0 +1,319 @@ +/****************************************************************************** + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, + * USA + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * Contact Information: + * Tomas Winkler + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + *****************************************************************************/ + +#include +#include +#include + +#include +#include + + +#include "iwl-4965.h" +#include "iwl-debug.h" +#include "iwl-4965-io.h" + + +/* create and remove of files */ +#define DEBUGFS_ADD_DIR(name, parent) do { \ + dbgfs->dir_##name = debugfs_create_dir(#name, parent); \ + if (!(dbgfs->dir_##name)) \ + goto err; \ +} while (0) + +#define DEBUGFS_ADD_FILE(name, parent) do { \ + dbgfs->dbgfs_##parent##_files.file_##name = \ + debugfs_create_file(#name, 0644, dbgfs->dir_##parent, priv, \ + &iwl_dbgfs_##name##_ops); \ + if (!(dbgfs->dbgfs_##parent##_files.file_##name)) \ + goto err; \ +} while (0) + +#define DEBUGFS_REMOVE(name) do { \ + debugfs_remove(name); \ + name = NULL; \ +} while (0); + +/* file operation */ +#define DEBUGFS_READ_FUNC(name) \ +static ssize_t iwl_dbgfs_##name##_read(struct file *file, \ + char __user *user_buf, \ + size_t count, loff_t *ppos); + +#define DEBUGFS_WRITE_FUNC(name) \ +static ssize_t iwl_dbgfs_##name##_write(struct file *file, \ + const char __user *user_buf, \ + size_t count, loff_t *ppos); + + +static int iwl_dbgfs_open_file_generic(struct inode *inode, struct file *file) +{ + file->private_data = inode->i_private; + return 0; +} + +#define DEBUGFS_READ_FILE_OPS(name) \ + DEBUGFS_READ_FUNC(name); \ +static const struct file_operations iwl_dbgfs_##name##_ops = { \ + .read = iwl_dbgfs_##name##_read, \ + .open = iwl_dbgfs_open_file_generic, \ +}; + +#define DEBUGFS_READ_WRITE_FILE_OPS(name) \ + DEBUGFS_READ_FUNC(name); \ + DEBUGFS_WRITE_FUNC(name); \ +static const struct file_operations iwl_dbgfs_##name##_ops = { \ + .write = iwl_dbgfs_##name##_write, \ + .read = iwl_dbgfs_##name##_read, \ + .open = iwl_dbgfs_open_file_generic, \ +}; + + +static ssize_t iwl_dbgfs_tx_statistics_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) { + + struct iwl_priv *priv = (struct iwl_priv *)file->private_data; + char buf[256]; + int pos = 0; + + pos += sprintf(buf+pos, "mgmt: %u\n", priv->tx_stats[0].cnt); + pos += sprintf(buf+pos, "ctrl: %u\n", priv->tx_stats[1].cnt); + pos += sprintf(buf+pos, "data: %u\n", priv->tx_stats[2].cnt); + + return simple_read_from_buffer(user_buf, count, ppos, buf, pos); +} + +static ssize_t iwl_dbgfs_rx_statistics_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) { + + struct iwl_priv *priv = (struct iwl_priv *)file->private_data; + char buf[256]; + int pos = 0; + + pos += sprintf(buf+pos, "mgmt: %u\n", priv->rx_stats[0].cnt); + pos += sprintf(buf+pos, "ctrl: %u\n", priv->rx_stats[1].cnt); + pos += sprintf(buf+pos, "data: %u\n", priv->rx_stats[2].cnt); + + return simple_read_from_buffer(user_buf, count, ppos, buf, pos); +} + +#define BYTE1_MASK 0x000000ff; +#define BYTE2_MASK 0x0000ffff; +#define BYTE3_MASK 0x00ffffff; +static ssize_t iwl_dbgfs_sram_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + u32 val; + char buf[1024]; + ssize_t ret; + int i; + int pos = 0; + struct iwl_priv *priv = (struct iwl_priv *)file->private_data; + + printk(KERN_DEBUG "offset is: 0x%x\tlen is: 0x%x\n", + priv->dbgfs->sram_offset, priv->dbgfs->sram_len); + + iwl4965_grab_nic_access(priv); + for (i = priv->dbgfs->sram_len; i > 0; i -= 4) { + val = iwl4965_read_targ_mem(priv, priv->dbgfs->sram_offset + \ + priv->dbgfs->sram_len - i); + if (i < 4) { + switch (i) { + case 1: + val &= BYTE1_MASK; + break; + case 2: + val &= BYTE2_MASK; + break; + case 3: + val &= BYTE3_MASK; + break; + } + } + pos += sprintf(buf+pos, "0x%08x ", val); + } + pos += sprintf(buf+pos, "\n"); + iwl4965_release_nic_access(priv); + + ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); + return ret; +} + +static ssize_t iwl_dbgfs_sram_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct iwl_priv *priv = file->private_data; + char buf[64]; + int buf_size; + u32 offset, len; + + memset(buf, 0, sizeof(buf)); + buf_size = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, buf_size)) + return -EFAULT; + + if (sscanf(buf, "%x,%x", &offset, &len) == 2) { + priv->dbgfs->sram_offset = offset; + priv->dbgfs->sram_len = len; + } else { + priv->dbgfs->sram_offset = 0; + priv->dbgfs->sram_len = 0; + } + + return count; +} + +static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct iwl_priv *priv = (struct iwl_priv *)file->private_data; + struct iwl4965_station_entry *station; + int max_sta = priv->hw_setting.max_stations; + char *buf; + int i, j, pos = 0; + ssize_t ret; + /* Add 30 for initial string */ + const size_t bufsz = 30 + sizeof(char) * 500 * (priv->num_stations); + DECLARE_MAC_BUF(mac); + + buf = kmalloc(bufsz, GFP_KERNEL); + if(!buf) + return -ENOMEM; + + pos += sprintf(buf+pos, "num of stations: %d\n\n", + priv->num_stations); + + for (i = 0; i < max_sta; i++) { + station = &priv->stations[i]; + if (station->used) { + pos += sprintf(buf+pos, "station %d:\ngeneral data:\n", + i+1); + print_mac(mac, station->sta.sta.addr); + pos += sprintf(buf+pos, "id: %u\n", + station->sta.sta.sta_id); + pos += sprintf(buf+pos, "mode: %u\n", + station->sta.mode); + pos += sprintf(buf+pos, "flags: 0x%x\n", + station->sta.station_flags_msk); + pos += sprintf(buf+pos, "ps_status: %u\n", + station->ps_status); + + pos += sprintf(buf+pos, "tid data:\n"); + + pos += sprintf(buf+pos, "seq_num\t\ttxq_id\t"); + pos += sprintf(buf+pos, "frame_count\twait_for_ba\t"); + pos += sprintf(buf+pos, "start_idx\tbitmap0\t"); + pos += sprintf(buf+pos, "bitmap1\trate_n_flags\n"); + + for (j = 0; j < MAX_TID_COUNT; j++) { + pos += sprintf(buf+pos, "[%d]:\t\t%u\t", + j, station->tid[j].seq_number); + pos += sprintf(buf+pos, "%u\t\t%u\t\t%u\t\t", + station->tid[j].agg.txq_id, + station->tid[j].agg.frame_count, + station->tid[j].agg.wait_for_ba); + pos += sprintf(buf+pos, "%u\t%llu\t%u\n", + station->tid[j].agg.start_idx, + station->tid[j].agg.bitmap, + station->tid[j].agg.rate_n_flags); + } + pos += sprintf(buf+pos, "\n"); + } + } + + ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); + kfree(buf); + return ret; +} + + +DEBUGFS_READ_WRITE_FILE_OPS(sram); +DEBUGFS_READ_FILE_OPS(stations); +DEBUGFS_READ_FILE_OPS(rx_statistics); +DEBUGFS_READ_FILE_OPS(tx_statistics); + +/* + * Create the debugfs files and directories + * + */ +int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) +{ + struct iwl_debugfs *dbgfs; + + dbgfs = kzalloc(sizeof(struct iwl_debugfs), GFP_KERNEL); + if (!dbgfs) { + goto err; + } + + priv->dbgfs = dbgfs; + dbgfs->name = name; + dbgfs->dir_drv = debugfs_create_dir(name, NULL); + if (!dbgfs->dir_drv || IS_ERR(dbgfs->dir_drv)){ + goto err; + } + + DEBUGFS_ADD_DIR(data, dbgfs->dir_drv); + DEBUGFS_ADD_FILE(sram, data); + DEBUGFS_ADD_FILE(stations, data); + DEBUGFS_ADD_FILE(rx_statistics, data); + DEBUGFS_ADD_FILE(tx_statistics, data); + + return 0; + +err: + IWL_ERROR("Can't open the debugfs directory\n"); + iwl_dbgfs_unregister(priv); + return -ENOENT; +} +EXPORT_SYMBOL(iwl_dbgfs_register); + +/** + * Remove the debugfs files and directories + * + */ +void iwl_dbgfs_unregister(struct iwl_priv *priv) +{ + if (!(priv->dbgfs)) + return; + + DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_rx_statistics); + DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_tx_statistics); + DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sram); + DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_stations); + DEBUGFS_REMOVE(priv->dbgfs->dir_data); + DEBUGFS_REMOVE(priv->dbgfs->dir_drv); + kfree(priv->dbgfs); + priv->dbgfs = NULL; +} +EXPORT_SYMBOL(iwl_dbgfs_unregister); + + diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 4f6ed6942065..396940e701e5 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -8690,6 +8690,11 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e goto out_release_irq; } + err = iwl_dbgfs_register(priv, DRV_NAME); + if (err) { + IWL_ERROR("failed to create debugfs files\n"); + goto out_remove_sysfs; + } /* nic init */ iwl4965_set_bit(priv, CSR_GIO_CHICKEN_BITS, CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); @@ -8700,13 +8705,13 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); if (err < 0) { IWL_DEBUG_INFO("Failed to init the card\n"); - goto out_remove_sysfs; + goto out_remove_dbgfs; } /* Read the EEPROM */ err = iwl_eeprom_init(priv); if (err) { IWL_ERROR("Unable to init EEPROM\n"); - goto out_remove_sysfs; + goto out_remove_dbgfs; } /* MAC Address location in EEPROM same for 3945/4965 */ iwl_eeprom_get_mac(priv, priv->mac_addr); @@ -8716,7 +8721,7 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e err = iwl4965_init_channel_map(priv); if (err) { IWL_ERROR("initializing regulatory failed: %d\n", err); - goto out_remove_sysfs; + goto out_remove_dbgfs; } err = iwl4965_init_geos(priv); @@ -8743,6 +8748,8 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e iwl4965_free_geos(priv); out_free_channel_map: iwl4965_free_channel_map(priv); + out_remove_dbgfs: + iwl_dbgfs_unregister(priv); out_remove_sysfs: sysfs_remove_group(&pdev->dev.kobj, &iwl4965_attribute_group); @@ -8787,6 +8794,7 @@ static void iwl4965_pci_remove(struct pci_dev *pdev) } } + iwl_dbgfs_unregister(priv); sysfs_remove_group(&pdev->dev.kobj, &iwl4965_attribute_group); iwl4965_dealloc_ucode_pci(priv); -- cgit v1.2.1 From 8db4a2b986befabd2ad25c269e40444f06a6bda3 Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Wed, 19 Mar 2008 10:11:00 +0100 Subject: libertas: make a handy lbs_cmd_async() command This uses a static lbs_cmd_async_callback function, which is a noop. Just setting the callback argument to __lbs_cmd_async() to NULL won't work, because then the cmdnode wouldn't be released. This also makes __lbs_cmd_async() a static method, which is now only used by lbs_cmd() and lbs_cmd_async(). Signed-off-by: Holger Schurig Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/cmd.c | 84 ++++++++++++++++++++++++------------- drivers/net/wireless/libertas/cmd.h | 9 ++-- 2 files changed, 57 insertions(+), 36 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index 62f9f3bdfdfb..be461c5c42ae 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -19,6 +19,46 @@ static void lbs_set_cmd_ctrl_node(struct lbs_private *priv, void *pdata_buf); +/** + * @brief Simple callback that copies response back into command + * + * @param priv A pointer to struct lbs_private structure + * @param extra A pointer to the original command structure for which + * 'resp' is a response + * @param resp A pointer to the command response + * + * @return 0 on success, error on failure + */ +int lbs_cmd_copyback(struct lbs_private *priv, unsigned long extra, + struct cmd_header *resp) +{ + struct cmd_header *buf = (void *)extra; + uint16_t copy_len; + + copy_len = min(le16_to_cpu(buf->size), le16_to_cpu(resp->size)); + memcpy(buf, resp, copy_len); + return 0; +} +EXPORT_SYMBOL_GPL(lbs_cmd_copyback); + +/** + * @brief Simple callback that ignores the result. Use this if + * you just want to send a command to the hardware, but don't + * care for the result. + * + * @param priv ignored + * @param extra ignored + * @param resp ignored + * + * @return 0 for success + */ +static int lbs_cmd_async_callback(struct lbs_private *priv, unsigned long extra, + struct cmd_header *resp) +{ + return 0; +} + + /** * @brief Checks whether a command is allowed in Power Save mode * @@ -1242,7 +1282,7 @@ void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd, cmd->cmdwaitqwoken = 1; wake_up_interruptible(&cmd->cmdwait_q); - if (!cmd->callback) + if (!cmd->callback || cmd->callback == lbs_cmd_async_callback) __lbs_cleanup_and_insert_cmd(priv, cmd); priv->cur_cmd = NULL; } @@ -2018,32 +2058,10 @@ void lbs_ps_confirm_sleep(struct lbs_private *priv, u16 psmode) } -/** - * @brief Simple callback that copies response back into command - * - * @param priv A pointer to struct lbs_private structure - * @param extra A pointer to the original command structure for which - * 'resp' is a response - * @param resp A pointer to the command response - * - * @return 0 on success, error on failure - */ -int lbs_cmd_copyback(struct lbs_private *priv, unsigned long extra, - struct cmd_header *resp) -{ - struct cmd_header *buf = (void *)extra; - uint16_t copy_len; - - copy_len = min(le16_to_cpu(buf->size), le16_to_cpu(resp->size)); - memcpy(buf, resp, copy_len); - return 0; -} -EXPORT_SYMBOL_GPL(lbs_cmd_copyback); - -struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv, uint16_t command, - struct cmd_header *in_cmd, int in_cmd_size, - int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *), - unsigned long callback_arg) +static struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv, + uint16_t command, struct cmd_header *in_cmd, int in_cmd_size, + int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *), + unsigned long callback_arg) { struct cmd_ctrl_node *cmdnode; @@ -2080,9 +2098,6 @@ struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv, uint16_t command lbs_deb_host("PREP_CMD: command 0x%04x\n", command); - /* here was the big old switch() statement, which is now obsolete, - * because the caller of lbs_cmd() sets up all of *cmd for us. */ - cmdnode->cmdwaitqwoken = 0; lbs_queue_cmd(priv, cmdnode); wake_up_interruptible(&priv->waitq); @@ -2092,6 +2107,15 @@ struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv, uint16_t command return cmdnode; } +void lbs_cmd_async(struct lbs_private *priv, uint16_t command, + struct cmd_header *in_cmd, int in_cmd_size) +{ + lbs_deb_enter(LBS_DEB_CMD); + __lbs_cmd_async(priv, command, in_cmd, in_cmd_size, + lbs_cmd_async_callback, 0); + lbs_deb_leave(LBS_DEB_CMD); +} + int __lbs_cmd(struct lbs_private *priv, uint16_t command, struct cmd_header *in_cmd, int in_cmd_size, int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *), diff --git a/drivers/net/wireless/libertas/cmd.h b/drivers/net/wireless/libertas/cmd.h index d250e6bc0609..3dfc2d43c224 100644 --- a/drivers/net/wireless/libertas/cmd.h +++ b/drivers/net/wireless/libertas/cmd.h @@ -18,12 +18,9 @@ #define lbs_cmd_with_response(priv, cmdnr, cmd) \ lbs_cmd(priv, cmdnr, cmd, lbs_cmd_copyback, (unsigned long) (cmd)) -/* __lbs_cmd() will free the cmdnode and return success/failure. - __lbs_cmd_async() requires that the callback free the cmdnode */ -struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv, uint16_t command, - struct cmd_header *in_cmd, int in_cmd_size, - int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *), - unsigned long callback_arg); +void lbs_cmd_async(struct lbs_private *priv, uint16_t command, + struct cmd_header *in_cmd, int in_cmd_size); + int __lbs_cmd(struct lbs_private *priv, uint16_t command, struct cmd_header *in_cmd, int in_cmd_size, int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *), -- cgit v1.2.1 From c97329e21fc487ebf251c920d46537ff5fb4d8a7 Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Tue, 18 Mar 2008 11:20:21 +0100 Subject: libertas: fix scheduling while atomic bug in CMD_MAC_CONTROL The old code incorrectly used lbs_cmd_with_response() and now uses lbs_cmd_async(). While there I noticed that there is no real useful return values for asynchronous command functions, so I made the function "void". Signed-off-by: Holger Schurig Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/assoc.c | 8 ++------ drivers/net/wireless/libertas/cmd.c | 9 ++++----- drivers/net/wireless/libertas/decl.h | 2 +- 3 files changed, 7 insertions(+), 12 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c index 54161f1e742a..fcea2a124a56 100644 --- a/drivers/net/wireless/libertas/assoc.c +++ b/drivers/net/wireless/libertas/assoc.c @@ -272,9 +272,7 @@ static int assoc_helper_wep_keys(struct lbs_private *priv, else priv->mac_control &= ~CMD_ACT_MAC_WEP_ENABLE; - ret = lbs_set_mac_control(priv); - if (ret) - goto out; + lbs_set_mac_control(priv); mutex_lock(&priv->lock); @@ -304,9 +302,7 @@ static int assoc_helper_secinfo(struct lbs_private *priv, memcpy(&priv->secinfo, &assoc_req->secinfo, sizeof(struct lbs_802_11_security)); - ret = lbs_set_mac_control(priv); - if (ret) - goto out; + lbs_set_mac_control(priv); /* If RSN is already enabled, don't try to enable it again, since * ENABLE_RSN resets internal state machines and will clobber the diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index be461c5c42ae..be8a170b633f 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -1326,9 +1326,8 @@ int lbs_set_radio_control(struct lbs_private *priv) return ret; } -int lbs_set_mac_control(struct lbs_private *priv) +void lbs_set_mac_control(struct lbs_private *priv) { - int ret = 0; struct cmd_ds_mac_control cmd; lbs_deb_enter(LBS_DEB_CMD); @@ -1337,10 +1336,10 @@ int lbs_set_mac_control(struct lbs_private *priv) cmd.action = cpu_to_le16(priv->mac_control); cmd.reserved = 0; - ret = lbs_cmd_with_response(priv, CMD_MAC_CONTROL, &cmd); + lbs_cmd_async(priv, CMD_MAC_CONTROL, + &cmd.hdr, sizeof(cmd)); - lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); - return ret; + lbs_deb_leave(LBS_DEB_CMD); } /** diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h index f0de2a1e918f..989fb77e66dc 100644 --- a/drivers/net/wireless/libertas/decl.h +++ b/drivers/net/wireless/libertas/decl.h @@ -17,7 +17,7 @@ struct net_device; struct cmd_ctrl_node; struct cmd_ds_command; -int lbs_set_mac_control(struct lbs_private *priv); +void lbs_set_mac_control(struct lbs_private *priv); void lbs_send_tx_feedback(struct lbs_private *priv); -- cgit v1.2.1 From c49c3b77c8c611f562ca4e201d88d3e69465f928 Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Mon, 17 Mar 2008 12:45:58 +0100 Subject: libertas: convert GET_LOG to a direct command Now uses __lbs_cmd() to get the "log" (it's actually more a snapshot of various counters, not a sequential log). Besides the "mechanical" convertion the patch add the following logical changes: * Removes the priv->logmsg variable, it was only used in one place anyway, also don't blindly get the counters when associating. Getting the counters then the user asks via WEXT for them is good enought. * don't set wstats.discard.fragment with log.rxfrag, because the latter is a counter for successfully received packets, not for fragmented packets. Signed-off-by: Holger Schurig Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/assoc.c | 4 ---- drivers/net/wireless/libertas/cmd.c | 16 ---------------- drivers/net/wireless/libertas/cmdresp.c | 18 ------------------ drivers/net/wireless/libertas/dev.h | 2 -- drivers/net/wireless/libertas/hostcmd.h | 3 ++- drivers/net/wireless/libertas/wext.c | 14 ++++++++------ 6 files changed, 10 insertions(+), 47 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c index fcea2a124a56..95d98203eb4e 100644 --- a/drivers/net/wireless/libertas/assoc.c +++ b/drivers/net/wireless/libertas/assoc.c @@ -624,10 +624,6 @@ void lbs_association_worker(struct work_struct *work) lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0, CMD_OPTION_WAITFORRSP, 0, NULL); - - lbs_prepare_and_send_command(priv, - CMD_802_11_GET_LOG, - 0, CMD_OPTION_WAITFORRSP, 0, NULL); } else { ret = -1; } diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index be8a170b633f..5e35788946f1 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -494,18 +494,6 @@ static int lbs_cmd_802_11_reset(struct lbs_private *priv, return 0; } -static int lbs_cmd_802_11_get_log(struct lbs_private *priv, - struct cmd_ds_command *cmd) -{ - lbs_deb_enter(LBS_DEB_CMD); - cmd->command = cpu_to_le16(CMD_802_11_GET_LOG); - cmd->size = - cpu_to_le16(sizeof(struct cmd_ds_802_11_get_log) + S_DS_GEN); - - lbs_deb_leave(LBS_DEB_CMD); - return 0; -} - static int lbs_cmd_802_11_get_stat(struct lbs_private *priv, struct cmd_ds_command *cmd) { @@ -1423,10 +1411,6 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, ret = lbs_cmd_802_11_reset(priv, cmdptr, cmd_action); break; - case CMD_802_11_GET_LOG: - ret = lbs_cmd_802_11_get_log(priv, cmdptr); - break; - case CMD_802_11_AUTHENTICATE: ret = lbs_cmd_80211_authenticate(priv, cmdptr, pdata_buf); break; diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c index 5534a7b859da..240feeb1b49b 100644 --- a/drivers/net/wireless/libertas/cmdresp.c +++ b/drivers/net/wireless/libertas/cmdresp.c @@ -303,20 +303,6 @@ static int lbs_ret_802_11_eeprom_access(struct lbs_private *priv, return 0; } -static int lbs_ret_get_log(struct lbs_private *priv, - struct cmd_ds_command *resp) -{ - struct cmd_ds_802_11_get_log *logmessage = &resp->params.glog; - - lbs_deb_enter(LBS_DEB_CMD); - - /* Stored little-endian */ - memcpy(&priv->logmsg, logmessage, sizeof(struct cmd_ds_802_11_get_log)); - - lbs_deb_leave(LBS_DEB_CMD); - return 0; -} - static int lbs_ret_802_11_bcn_ctrl(struct lbs_private * priv, struct cmd_ds_command *resp) { @@ -352,10 +338,6 @@ static inline int handle_cmd_response(struct lbs_private *priv, ret = lbs_ret_reg_access(priv, respcmd, resp); break; - case CMD_RET(CMD_802_11_GET_LOG): - ret = lbs_ret_get_log(priv, resp); - break; - case CMD_RET_802_11_ASSOCIATE: case CMD_RET(CMD_802_11_ASSOCIATE): case CMD_RET(CMD_802_11_REASSOCIATE): diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index 4122a3223432..17e02bed6bfa 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h @@ -323,8 +323,6 @@ struct lbs_private { u8 *prdeeprom; struct lbs_offset_value offsetvalue; - struct cmd_ds_802_11_get_log logmsg; - u32 monitormode; u8 fw_ready; }; diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h index b5361b3393d9..acbcd56831cb 100644 --- a/drivers/net/wireless/libertas/hostcmd.h +++ b/drivers/net/wireless/libertas/hostcmd.h @@ -195,6 +195,8 @@ struct cmd_ds_802_11_scan_rsp { }; struct cmd_ds_802_11_get_log { + struct cmd_header hdr; + __le32 mcasttxframe; __le32 failed; __le32 retry; @@ -701,7 +703,6 @@ struct cmd_ds_command { struct cmd_ds_802_11_ad_hoc_start ads; struct cmd_ds_802_11_reset reset; struct cmd_ds_802_11_ad_hoc_result result; - struct cmd_ds_802_11_get_log glog; struct cmd_ds_802_11_authenticate auth; struct cmd_ds_802_11_get_stat gstat; struct cmd_ds_802_3_get_stat gstat_8023; diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c index cded4bb69164..5ccb4e0c8d64 100644 --- a/drivers/net/wireless/libertas/wext.c +++ b/drivers/net/wireless/libertas/wext.c @@ -820,6 +820,7 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev) int stats_valid = 0; u8 rssi; u32 tx_retries; + struct cmd_ds_802_11_get_log log; lbs_deb_enter(LBS_DEB_WEXT); @@ -863,7 +864,11 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev) /* Quality by TX errors */ priv->wstats.discard.retries = priv->stats.tx_errors; - tx_retries = le32_to_cpu(priv->logmsg.retry); + memset(&log, 0, sizeof(log)); + log.hdr.size = cpu_to_le16(sizeof(log)); + lbs_cmd_with_response(priv, CMD_802_11_GET_LOG, &log); + + tx_retries = le32_to_cpu(log.retry); if (tx_retries > 75) tx_qual = (90 - tx_retries) * POOR / 15; @@ -879,10 +884,9 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev) (PERFECT - VERY_GOOD) / 50 + VERY_GOOD; quality = min(quality, tx_qual); - priv->wstats.discard.code = le32_to_cpu(priv->logmsg.wepundecryptable); - priv->wstats.discard.fragment = le32_to_cpu(priv->logmsg.rxfrag); + priv->wstats.discard.code = le32_to_cpu(log.wepundecryptable); priv->wstats.discard.retries = tx_retries; - priv->wstats.discard.misc = le32_to_cpu(priv->logmsg.ackfailure); + priv->wstats.discard.misc = le32_to_cpu(log.ackfailure); /* Calculate quality */ priv->wstats.qual.qual = min_t(u8, quality, 100); @@ -892,8 +896,6 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev) /* update stats asynchronously for future calls */ lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0, 0, 0, NULL); - lbs_prepare_and_send_command(priv, CMD_802_11_GET_LOG, 0, - 0, 0, NULL); out: if (!stats_valid) { priv->wstats.miss.beacon = 0; -- cgit v1.2.1 From d4ff0ef635b222d5f66dad65e9364d702e5f94e0 Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Wed, 19 Mar 2008 14:25:18 +0100 Subject: libertas: misc power saving adjusts * firmware for the CF card supports power saving * the driver currenly only accept "iwconfig ethX power on|off", so I fixed what the range wext ioctl reports. * initialize value/flags in lbs_get_power() * get rid of unused parameter psmode in lbs_ps_confirm_sleep() * some minor debug output tweaks Signed-off-by: Holger Schurig Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/cmd.c | 10 ++-------- drivers/net/wireless/libertas/cmdresp.c | 18 +++++++++--------- drivers/net/wireless/libertas/decl.h | 2 +- drivers/net/wireless/libertas/if_cs.c | 3 +++ drivers/net/wireless/libertas/main.c | 2 +- drivers/net/wireless/libertas/wext.c | 24 +++++++----------------- 6 files changed, 23 insertions(+), 36 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index 5e35788946f1..733110a03b56 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -1927,10 +1927,6 @@ static int sendconfirmsleep(struct lbs_private *priv, u8 *cmdptr, u16 size) int ret = 0; lbs_deb_enter(LBS_DEB_HOST); - - lbs_deb_host("SEND_SLEEPC_CMD: before download, cmd size %d\n", - size); - lbs_deb_hex(LBS_DEB_HOST, "sleep confirm command", cmdptr, size); ret = priv->hw_host_to_card(priv, MVMS_CMD, cmdptr, size); @@ -1953,8 +1949,6 @@ static int sendconfirmsleep(struct lbs_private *priv, u8 *cmdptr, u16 size) priv->intcounter); } spin_unlock_irqrestore(&priv->driver_lock, flags); - - lbs_deb_host("SEND_SLEEPC_CMD: sent confirm sleep\n"); } lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret); @@ -2006,10 +2000,10 @@ void lbs_ps_wakeup(struct lbs_private *priv, int wait_option) * @param psmode Power Saving mode * @return n/a */ -void lbs_ps_confirm_sleep(struct lbs_private *priv, u16 psmode) +void lbs_ps_confirm_sleep(struct lbs_private *priv) { unsigned long flags =0; - u8 allowed = 1; + int allowed = 1; lbs_deb_enter(LBS_DEB_HOST); diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c index 240feeb1b49b..45de4316bdd7 100644 --- a/drivers/net/wireless/libertas/cmdresp.c +++ b/drivers/net/wireless/libertas/cmdresp.c @@ -656,11 +656,9 @@ int lbs_process_event(struct lbs_private *priv) eventcause = priv->eventcause >> SBI_EVENT_CAUSE_SHIFT; spin_unlock_irq(&priv->driver_lock); - lbs_deb_cmd("event cause %d\n", eventcause); - switch (eventcause) { case MACREG_INT_CODE_LINK_SENSED: - lbs_deb_cmd("EVENT: MACREG_INT_CODE_LINK_SENSED\n"); + lbs_deb_cmd("EVENT: link sensed\n"); break; case MACREG_INT_CODE_DEAUTHENTICATED: @@ -679,7 +677,7 @@ int lbs_process_event(struct lbs_private *priv) break; case MACREG_INT_CODE_PS_SLEEP: - lbs_deb_cmd("EVENT: sleep\n"); + lbs_deb_cmd("EVENT: ps sleep\n"); /* handle unexpected PS SLEEP event */ if (priv->psstate == PS_STATE_FULL_POWER) { @@ -689,17 +687,17 @@ int lbs_process_event(struct lbs_private *priv) } priv->psstate = PS_STATE_PRE_SLEEP; - lbs_ps_confirm_sleep(priv, (u16) priv->psmode); + lbs_ps_confirm_sleep(priv); break; case MACREG_INT_CODE_HOST_AWAKE: - lbs_deb_cmd("EVENT: HOST_AWAKE\n"); + lbs_deb_cmd("EVENT: host awake\n"); lbs_send_confirmwake(priv); break; case MACREG_INT_CODE_PS_AWAKE: - lbs_deb_cmd("EVENT: awake\n"); + lbs_deb_cmd("EVENT: ps awake\n"); /* handle unexpected PS AWAKE event */ if (priv->psstate == PS_STATE_FULL_POWER) { lbs_deb_cmd( @@ -730,14 +728,16 @@ int lbs_process_event(struct lbs_private *priv) lbs_deb_cmd("EVENT: MULTICAST MIC ERROR\n"); handle_mic_failureevent(priv, MACREG_INT_CODE_MIC_ERR_MULTICAST); break; + case MACREG_INT_CODE_MIB_CHANGED: + lbs_deb_cmd("EVENT: MIB CHANGED\n"); + break; case MACREG_INT_CODE_INIT_DONE: + lbs_deb_cmd("EVENT: INIT DONE\n"); break; - case MACREG_INT_CODE_ADHOC_BCN_LOST: lbs_deb_cmd("EVENT: ADHOC beacon lost\n"); break; - case MACREG_INT_CODE_RSSI_LOW: lbs_pr_alert("EVENT: rssi low\n"); break; diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h index 989fb77e66dc..f0a0de9c6f5a 100644 --- a/drivers/net/wireless/libertas/decl.h +++ b/drivers/net/wireless/libertas/decl.h @@ -49,7 +49,7 @@ int lbs_set_regiontable(struct lbs_private *priv, u8 region, u8 band); int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *); void lbs_ps_sleep(struct lbs_private *priv, int wait_option); -void lbs_ps_confirm_sleep(struct lbs_private *priv, u16 psmode); +void lbs_ps_confirm_sleep(struct lbs_private *priv); void lbs_ps_wakeup(struct lbs_private *priv, int wait_option); struct chan_freq_power *lbs_find_cfp_by_band_and_channel( diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c index 5a9cadb97503..d17746582160 100644 --- a/drivers/net/wireless/libertas/if_cs.c +++ b/drivers/net/wireless/libertas/if_cs.c @@ -882,6 +882,9 @@ static int if_cs_probe(struct pcmcia_device *p_dev) goto out3; } + /* The firmware for the CF card supports powersave */ + priv->ps_supported = 1; + ret = 0; goto out; diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 37cc05044cd7..449e84f89ae7 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -803,7 +803,7 @@ static int lbs_thread(void *data) lbs_deb_thread("main_thread: PRE_SLEEP--intcounter=%d currenttxskb=%p dnld_sent=%d cur_cmd=%p, confirm now\n", priv->intcounter, priv->currenttxskb, priv->dnld_sent, priv->cur_cmd); - lbs_ps_confirm_sleep(priv, (u16) priv->psmode); + lbs_ps_confirm_sleep(priv); } else { /* workaround for firmware sending * deauth/linkloss event immediately diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c index 5ccb4e0c8d64..c039db648fac 100644 --- a/drivers/net/wireless/libertas/wext.c +++ b/drivers/net/wireless/libertas/wext.c @@ -656,13 +656,10 @@ static int lbs_get_range(struct net_device *dev, struct iw_request_info *info, range->num_encoding_sizes = 2; range->max_encoding_tokens = 4; - range->min_pmp = 1000000; - range->max_pmp = 120000000; - range->min_pmt = 1000; - range->max_pmt = 1000000; - range->pmp_flags = IW_POWER_PERIOD; - range->pmt_flags = IW_POWER_TIMEOUT; - range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R; + /* + * Right now we support only "iwconfig ethX power on|off" + */ + range->pm_capa = IW_POWER_ON; /* * Minimum version we recommend @@ -784,21 +781,14 @@ static int lbs_get_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra) { struct lbs_private *priv = dev->priv; - int mode; lbs_deb_enter(LBS_DEB_WEXT); - mode = priv->psmode; - - if ((vwrq->disabled = (mode == LBS802_11POWERMODECAM)) - || priv->connect_status == LBS_DISCONNECTED) - { - goto out; - } - vwrq->value = 0; + vwrq->flags = 0; + vwrq->disabled = priv->psmode == LBS802_11POWERMODECAM + || priv->connect_status == LBS_DISCONNECTED; -out: lbs_deb_leave(LBS_DEB_WEXT); return 0; } -- cgit v1.2.1 From e98a88dd33b7188ce84533e128101dd9630ae592 Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Wed, 19 Mar 2008 14:25:58 +0100 Subject: libertas: remove lots of unused stuff This removes many unused function parameters as well as some not-implemented functions, e.g. CMD_802_11_GET_STATS. The silly lbs_set_cmd_ctrl_node() function is now also gone. Signed-off-by: Holger Schurig Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/11d.c | 16 +++--- drivers/net/wireless/libertas/11d.h | 5 +- drivers/net/wireless/libertas/cmd.c | 99 +++++++-------------------------- drivers/net/wireless/libertas/cmdresp.c | 29 ++-------- drivers/net/wireless/libertas/debugfs.c | 6 +- drivers/net/wireless/libertas/decl.h | 1 - drivers/net/wireless/libertas/join.c | 9 +-- drivers/net/wireless/libertas/join.h | 9 +-- drivers/net/wireless/libertas/main.c | 4 +- drivers/net/wireless/libertas/wext.c | 2 +- 10 files changed, 46 insertions(+), 134 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/libertas/11d.c b/drivers/net/wireless/libertas/11d.c index 5e10ce0d351c..4bc46a60ae2f 100644 --- a/drivers/net/wireless/libertas/11d.c +++ b/drivers/net/wireless/libertas/11d.c @@ -79,7 +79,7 @@ static u8 *lbs_code_2_region(u8 code) * @param nrchan number of channels * @return the nrchan-th chan number */ -static u8 lbs_get_chan_11d(u8 band, u8 firstchan, u8 nrchan, u8 *chan) +static u8 lbs_get_chan_11d(u8 firstchan, u8 nrchan, u8 *chan) /*find the nrchan-th chan after the firstchan*/ { u8 i; @@ -134,7 +134,7 @@ static u8 lbs_channel_known_11d(u8 chan, return 0; } -u32 lbs_chan_2_freq(u8 chan, u8 band) +u32 lbs_chan_2_freq(u8 chan) { struct chan_freq_power *cf; u16 i; @@ -264,7 +264,7 @@ static void lbs_generate_parsed_region_chan_11d(struct region_channel *region_ch * @param chan chan * @return TRUE;FALSE */ -static u8 lbs_region_chan_supported_11d(u8 region, u8 band, u8 chan) +static u8 lbs_region_chan_supported_11d(u8 region, u8 chan) { struct chan_freq_power *cfp; int cfp_no; @@ -273,7 +273,7 @@ static u8 lbs_region_chan_supported_11d(u8 region, u8 band, u8 chan) lbs_deb_enter(LBS_DEB_11D); - cfp = lbs_get_region_cfp_table(region, band, &cfp_no); + cfp = lbs_get_region_cfp_table(region, &cfp_no); if (cfp == NULL) return 0; @@ -367,7 +367,7 @@ static int parse_domain_info_11d(struct ieeetypes_countryinfofullset* for (i = 0; idx < MAX_NO_OF_CHAN && i < nrchan; i++) { /*step4: channel is supported? */ - if (!lbs_get_chan_11d(band, firstchan, i, &curchan)) { + if (!lbs_get_chan_11d(firstchan, i, &curchan)) { /* Chan is not found in UN table */ lbs_deb_11d("chan is not supported: %d \n", i); break; @@ -375,8 +375,7 @@ static int parse_domain_info_11d(struct ieeetypes_countryinfofullset* lastchan = curchan; - if (lbs_region_chan_supported_11d - (region, band, curchan)) { + if (lbs_region_chan_supported_11d(region, curchan)) { /*step5: Check if curchan is supported by mrvl in region */ parsed_region_chan->chanpwr[idx].chan = curchan; parsed_region_chan->chanpwr[idx].pwr = @@ -554,8 +553,7 @@ done: * @param resp pointer to command response buffer * @return 0; -1 */ -int lbs_ret_802_11d_domain_info(struct lbs_private *priv, - struct cmd_ds_command *resp) +int lbs_ret_802_11d_domain_info(struct cmd_ds_command *resp) { struct cmd_ds_802_11d_domain_info *domaininfo = &resp->params.domaininforesp; struct mrvlietypes_domainparamset *domain = &domaininfo->domain; diff --git a/drivers/net/wireless/libertas/11d.h b/drivers/net/wireless/libertas/11d.h index 811eea2cfba3..4f4f47f0f878 100644 --- a/drivers/net/wireless/libertas/11d.h +++ b/drivers/net/wireless/libertas/11d.h @@ -83,7 +83,7 @@ struct lbs_private; u8 lbs_get_scan_type_11d(u8 chan, struct parsed_region_chan_11d *parsed_region_chan); -u32 lbs_chan_2_freq(u8 chan, u8 band); +u32 lbs_chan_2_freq(u8 chan); void lbs_init_11d(struct lbs_private *priv); @@ -93,8 +93,7 @@ int lbs_cmd_802_11d_domain_info(struct lbs_private *priv, struct cmd_ds_command *cmd, u16 cmdno, u16 cmdOption); -int lbs_ret_802_11d_domain_info(struct lbs_private *priv, - struct cmd_ds_command *resp); +int lbs_ret_802_11d_domain_info(struct cmd_ds_command *resp); struct bss_descriptor; int lbs_parse_dnld_countryinfo_11d(struct lbs_private *priv, diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index 733110a03b56..59801f103e66 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -14,9 +14,6 @@ #include "cmd.h" static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv); -static void lbs_set_cmd_ctrl_node(struct lbs_private *priv, - struct cmd_ctrl_node *ptempnode, - void *pdata_buf); /** @@ -183,8 +180,7 @@ int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria) } EXPORT_SYMBOL_GPL(lbs_host_sleep_cfg); -static int lbs_cmd_802_11_ps_mode(struct lbs_private *priv, - struct cmd_ds_command *cmd, +static int lbs_cmd_802_11_ps_mode(struct cmd_ds_command *cmd, u16 cmd_action) { struct cmd_ds_802_11_ps_mode *psm = &cmd->params.psmode; @@ -479,8 +475,7 @@ int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action, return ret; } -static int lbs_cmd_802_11_reset(struct lbs_private *priv, - struct cmd_ds_command *cmd, int cmd_action) +static int lbs_cmd_802_11_reset(struct cmd_ds_command *cmd, int cmd_action) { struct cmd_ds_802_11_reset *reset = &cmd->params.reset; @@ -494,18 +489,6 @@ static int lbs_cmd_802_11_reset(struct lbs_private *priv, return 0; } -static int lbs_cmd_802_11_get_stat(struct lbs_private *priv, - struct cmd_ds_command *cmd) -{ - lbs_deb_enter(LBS_DEB_CMD); - cmd->command = cpu_to_le16(CMD_802_11_GET_STAT); - cmd->size = - cpu_to_le16(sizeof(struct cmd_ds_802_11_get_stat) + S_DS_GEN); - - lbs_deb_leave(LBS_DEB_CMD); - return 0; -} - static int lbs_cmd_802_11_snmp_mib(struct lbs_private *priv, struct cmd_ds_command *cmd, int cmd_action, @@ -626,8 +609,7 @@ static int lbs_cmd_802_11_snmp_mib(struct lbs_private *priv, return 0; } -static int lbs_cmd_802_11_rf_tx_power(struct lbs_private *priv, - struct cmd_ds_command *cmd, +static int lbs_cmd_802_11_rf_tx_power(struct cmd_ds_command *cmd, u16 cmd_action, void *pdata_buf) { @@ -670,8 +652,7 @@ static int lbs_cmd_802_11_rf_tx_power(struct lbs_private *priv, return 0; } -static int lbs_cmd_802_11_monitor_mode(struct lbs_private *priv, - struct cmd_ds_command *cmd, +static int lbs_cmd_802_11_monitor_mode(struct cmd_ds_command *cmd, u16 cmd_action, void *pdata_buf) { struct cmd_ds_802_11_monitor_mode *monitor = &cmd->params.monitor; @@ -898,8 +879,7 @@ static int lbs_cmd_802_11_rssi(struct lbs_private *priv, return 0; } -static int lbs_cmd_reg_access(struct lbs_private *priv, - struct cmd_ds_command *cmdptr, +static int lbs_cmd_reg_access(struct cmd_ds_command *cmdptr, u8 cmd_action, void *pdata_buf) { struct lbs_offset_value *offval; @@ -996,9 +976,8 @@ static int lbs_cmd_802_11_mac_address(struct lbs_private *priv, return 0; } -static int lbs_cmd_802_11_eeprom_access(struct lbs_private *priv, - struct cmd_ds_command *cmd, - int cmd_action, void *pdata_buf) +static int lbs_cmd_802_11_eeprom_access(struct cmd_ds_command *cmd, + void *pdata_buf) { struct lbs_ioctl_regrdwr *ea = pdata_buf; @@ -1018,8 +997,7 @@ static int lbs_cmd_802_11_eeprom_access(struct lbs_private *priv, return 0; } -static int lbs_cmd_bt_access(struct lbs_private *priv, - struct cmd_ds_command *cmd, +static int lbs_cmd_bt_access(struct cmd_ds_command *cmd, u16 cmd_action, void *pdata_buf) { struct cmd_ds_bt_access *bt_access = &cmd->params.bt; @@ -1056,8 +1034,7 @@ static int lbs_cmd_bt_access(struct lbs_private *priv, return 0; } -static int lbs_cmd_fwt_access(struct lbs_private *priv, - struct cmd_ds_command *cmd, +static int lbs_cmd_fwt_access(struct cmd_ds_command *cmd, u16 cmd_action, void *pdata_buf) { struct cmd_ds_fwt_access *fwt_access = &cmd->params.fwt; @@ -1376,7 +1353,8 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, goto done; } - lbs_set_cmd_ctrl_node(priv, cmdnode, pdata_buf); + cmdnode->callback = NULL; + cmdnode->callback_arg = (unsigned long)pdata_buf; cmdptr = (struct cmd_ds_command *)cmdnode->cmdbuf; @@ -1391,7 +1369,7 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, switch (cmd_no) { case CMD_802_11_PS_MODE: - ret = lbs_cmd_802_11_ps_mode(priv, cmdptr, cmd_action); + ret = lbs_cmd_802_11_ps_mode(cmdptr, cmd_action); break; case CMD_802_11_ASSOCIATE: @@ -1408,17 +1386,13 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, break; case CMD_802_11_RESET: - ret = lbs_cmd_802_11_reset(priv, cmdptr, cmd_action); + ret = lbs_cmd_802_11_reset(cmdptr, cmd_action); break; case CMD_802_11_AUTHENTICATE: ret = lbs_cmd_80211_authenticate(priv, cmdptr, pdata_buf); break; - case CMD_802_11_GET_STAT: - ret = lbs_cmd_802_11_get_stat(priv, cmdptr); - break; - case CMD_802_11_SNMP_MIB: ret = lbs_cmd_802_11_snmp_mib(priv, cmdptr, cmd_action, cmd_oid, pdata_buf); @@ -1427,12 +1401,12 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, case CMD_MAC_REG_ACCESS: case CMD_BBP_REG_ACCESS: case CMD_RF_REG_ACCESS: - ret = lbs_cmd_reg_access(priv, cmdptr, cmd_action, pdata_buf); + ret = lbs_cmd_reg_access(cmdptr, cmd_action, pdata_buf); break; case CMD_802_11_RF_TX_POWER: - ret = lbs_cmd_802_11_rf_tx_power(priv, cmdptr, - cmd_action, pdata_buf); + ret = lbs_cmd_802_11_rf_tx_power(cmdptr, + cmd_action, pdata_buf); break; case CMD_802_11_RATE_ADAPT_RATESET: @@ -1445,7 +1419,7 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, break; case CMD_802_11_MONITOR_MODE: - ret = lbs_cmd_802_11_monitor_mode(priv, cmdptr, + ret = lbs_cmd_802_11_monitor_mode(cmdptr, cmd_action, pdata_buf); break; @@ -1458,7 +1432,7 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, break; case CMD_802_11_AD_HOC_STOP: - ret = lbs_cmd_80211_ad_hoc_stop(priv, cmdptr); + ret = lbs_cmd_80211_ad_hoc_stop(cmdptr); break; case CMD_802_11_MAC_ADDRESS: @@ -1466,8 +1440,7 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, break; case CMD_802_11_EEPROM_ACCESS: - ret = lbs_cmd_802_11_eeprom_access(priv, cmdptr, - cmd_action, pdata_buf); + ret = lbs_cmd_802_11_eeprom_access(cmdptr, pdata_buf); break; case CMD_802_11_SET_AFC: @@ -1534,11 +1507,11 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, ret = 0; break; case CMD_BT_ACCESS: - ret = lbs_cmd_bt_access(priv, cmdptr, cmd_action, pdata_buf); + ret = lbs_cmd_bt_access(cmdptr, cmd_action, pdata_buf); break; case CMD_FWT_ACCESS: - ret = lbs_cmd_fwt_access(priv, cmdptr, cmd_action, pdata_buf); + ret = lbs_cmd_fwt_access(cmdptr, cmd_action, pdata_buf); break; case CMD_GET_TSF: @@ -1710,36 +1683,6 @@ static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv) return tempnode; } -/** - * @brief This function cleans command node. - * - * @param ptempnode A pointer to cmdCtrlNode structure - * @return n/a - */ - -/** - * @brief This function initializes the command node. - * - * @param priv A pointer to struct lbs_private structure - * @param ptempnode A pointer to cmd_ctrl_node structure - * @param pdata_buf A pointer to informaion buffer - * @return 0 or -1 - */ -static void lbs_set_cmd_ctrl_node(struct lbs_private *priv, - struct cmd_ctrl_node *ptempnode, - void *pdata_buf) -{ - lbs_deb_enter(LBS_DEB_HOST); - - if (!ptempnode) - return; - - ptempnode->callback = NULL; - ptempnode->callback_arg = (unsigned long)pdata_buf; - - lbs_deb_leave(LBS_DEB_HOST); -} - /** * @brief This function executes next command in command * pending queue. It will put fimware back to PS mode diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c index 45de4316bdd7..888f92d8afc9 100644 --- a/drivers/net/wireless/libertas/cmdresp.c +++ b/drivers/net/wireless/libertas/cmdresp.c @@ -146,22 +146,6 @@ static int lbs_ret_reg_access(struct lbs_private *priv, return ret; } -static int lbs_ret_802_11_stat(struct lbs_private *priv, - struct cmd_ds_command *resp) -{ - lbs_deb_enter(LBS_DEB_CMD); -/* currently priv->wlan802_11Stat is unused - - struct cmd_ds_802_11_get_stat *p11Stat = &resp->params.gstat; - - // TODO Convert it to Big endian befor copy - memcpy(&priv->wlan802_11Stat, - p11Stat, sizeof(struct cmd_ds_802_11_get_stat)); -*/ - lbs_deb_leave(LBS_DEB_CMD); - return 0; -} - static int lbs_ret_802_11_snmp_mib(struct lbs_private *priv, struct cmd_ds_command *resp) { @@ -321,7 +305,6 @@ static int lbs_ret_802_11_bcn_ctrl(struct lbs_private * priv, } static inline int handle_cmd_response(struct lbs_private *priv, - unsigned long dummy, struct cmd_header *cmd_response) { struct cmd_ds_command *resp = (struct cmd_ds_command *) cmd_response; @@ -346,7 +329,7 @@ static inline int handle_cmd_response(struct lbs_private *priv, case CMD_RET(CMD_802_11_DISASSOCIATE): case CMD_RET(CMD_802_11_DEAUTHENTICATE): - ret = lbs_ret_80211_disassociate(priv, resp); + ret = lbs_ret_80211_disassociate(priv); break; case CMD_RET(CMD_802_11_AD_HOC_START): @@ -354,10 +337,6 @@ static inline int handle_cmd_response(struct lbs_private *priv, ret = lbs_ret_80211_ad_hoc_start(priv, resp); break; - case CMD_RET(CMD_802_11_GET_STAT): - ret = lbs_ret_802_11_stat(priv, resp); - break; - case CMD_RET(CMD_802_11_SNMP_MIB): ret = lbs_ret_802_11_snmp_mib(priv, resp); break; @@ -394,7 +373,7 @@ static inline int handle_cmd_response(struct lbs_private *priv, break; case CMD_RET(CMD_802_11_AD_HOC_STOP): - ret = lbs_ret_80211_ad_hoc_stop(priv, resp); + ret = lbs_ret_80211_ad_hoc_stop(priv); break; case CMD_RET(CMD_802_11_EEPROM_ACCESS): @@ -402,7 +381,7 @@ static inline int handle_cmd_response(struct lbs_private *priv, break; case CMD_RET(CMD_802_11D_DOMAIN_INFO): - ret = lbs_ret_802_11d_domain_info(priv, resp); + ret = lbs_ret_802_11d_domain_info(resp); break; case CMD_RET(CMD_802_11_TPC_CFG): @@ -605,7 +584,7 @@ int lbs_process_rx_command(struct lbs_private *priv) ret = priv->cur_cmd->callback(priv, priv->cur_cmd->callback_arg, resp); } else - ret = handle_cmd_response(priv, 0, resp); + ret = handle_cmd_response(priv, resp); spin_lock_irqsave(&priv->driver_lock, flags); diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c index 8f88786b036f..6d7c0d9b677b 100644 --- a/drivers/net/wireless/libertas/debugfs.c +++ b/drivers/net/wireless/libertas/debugfs.c @@ -19,7 +19,7 @@ static char *szStates[] = { }; #ifdef PROC_DEBUG -static void lbs_debug_init(struct lbs_private *priv, struct net_device *dev); +static void lbs_debug_init(struct lbs_private *priv); #endif static int open_file_generic(struct inode *inode, struct file *file) @@ -778,7 +778,7 @@ void lbs_debugfs_init_one(struct lbs_private *priv, struct net_device *dev) } #ifdef PROC_DEBUG - lbs_debug_init(priv, dev); + lbs_debug_init(priv); #endif exit: return; @@ -952,7 +952,7 @@ static struct file_operations lbs_debug_fops = { * @param dev pointer net_device * @return N/A */ -static void lbs_debug_init(struct lbs_private *priv, struct net_device *dev) +static void lbs_debug_init(struct lbs_private *priv) { int i; diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h index f0a0de9c6f5a..cadc59d7f77f 100644 --- a/drivers/net/wireless/libertas/decl.h +++ b/drivers/net/wireless/libertas/decl.h @@ -63,7 +63,6 @@ void lbs_send_iwevcustom_event(struct lbs_private *priv, s8 *str); /* main.c */ struct chan_freq_power *lbs_get_region_cfp_table(u8 region, - u8 band, int *cfp_no); struct lbs_private *lbs_add_card(void *card, struct device *dmdev); int lbs_remove_card(struct lbs_private *priv); diff --git a/drivers/net/wireless/libertas/join.c b/drivers/net/wireless/libertas/join.c index 56e64a697c37..3e5026ff2ffa 100644 --- a/drivers/net/wireless/libertas/join.c +++ b/drivers/net/wireless/libertas/join.c @@ -561,8 +561,7 @@ done: return ret; } -int lbs_cmd_80211_ad_hoc_stop(struct lbs_private *priv, - struct cmd_ds_command *cmd) +int lbs_cmd_80211_ad_hoc_stop(struct cmd_ds_command *cmd) { cmd->command = cpu_to_le16(CMD_802_11_AD_HOC_STOP); cmd->size = cpu_to_le16(S_DS_GEN); @@ -773,8 +772,7 @@ done: return ret; } -int lbs_ret_80211_disassociate(struct lbs_private *priv, - struct cmd_ds_command *resp) +int lbs_ret_80211_disassociate(struct lbs_private *priv) { lbs_deb_enter(LBS_DEB_JOIN); @@ -863,8 +861,7 @@ done: return ret; } -int lbs_ret_80211_ad_hoc_stop(struct lbs_private *priv, - struct cmd_ds_command *resp) +int lbs_ret_80211_ad_hoc_stop(struct lbs_private *priv) { lbs_deb_enter(LBS_DEB_JOIN); diff --git a/drivers/net/wireless/libertas/join.h b/drivers/net/wireless/libertas/join.h index 792c64fe3514..bfc3a10a2f39 100644 --- a/drivers/net/wireless/libertas/join.h +++ b/drivers/net/wireless/libertas/join.h @@ -18,8 +18,7 @@ int lbs_cmd_80211_authenticate(struct lbs_private *priv, int lbs_cmd_80211_ad_hoc_join(struct lbs_private *priv, struct cmd_ds_command *cmd, void *pdata_buf); -int lbs_cmd_80211_ad_hoc_stop(struct lbs_private *priv, - struct cmd_ds_command *cmd); +int lbs_cmd_80211_ad_hoc_stop(struct cmd_ds_command *cmd); int lbs_cmd_80211_ad_hoc_start(struct lbs_private *priv, struct cmd_ds_command *cmd, void *pdata_buf); @@ -31,10 +30,8 @@ int lbs_cmd_80211_associate(struct lbs_private *priv, int lbs_ret_80211_ad_hoc_start(struct lbs_private *priv, struct cmd_ds_command *resp); -int lbs_ret_80211_ad_hoc_stop(struct lbs_private *priv, - struct cmd_ds_command *resp); -int lbs_ret_80211_disassociate(struct lbs_private *priv, - struct cmd_ds_command *resp); +int lbs_ret_80211_ad_hoc_stop(struct lbs_private *priv); +int lbs_ret_80211_disassociate(struct lbs_private *priv); int lbs_ret_80211_associate(struct lbs_private *priv, struct cmd_ds_command *resp); diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 449e84f89ae7..1eb0cb0a82b7 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -1391,7 +1391,7 @@ static void lbs_remove_mesh(struct lbs_private *priv) * @param cfp_no A pointer to CFP number * @return A pointer to CFP */ -struct chan_freq_power *lbs_get_region_cfp_table(u8 region, u8 band, int *cfp_no) +struct chan_freq_power *lbs_get_region_cfp_table(u8 region, int *cfp_no) { int i, end; @@ -1425,7 +1425,7 @@ int lbs_set_regiontable(struct lbs_private *priv, u8 region, u8 band) memset(priv->region_channel, 0, sizeof(priv->region_channel)); - cfp = lbs_get_region_cfp_table(region, band, &cfp_no); + cfp = lbs_get_region_cfp_table(region, &cfp_no); if (cfp != NULL) { priv->region_channel[i].nrcfp = cfp_no; priv->region_channel[i].CFP = cfp; diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c index c039db648fac..738142e802d4 100644 --- a/drivers/net/wireless/libertas/wext.c +++ b/drivers/net/wireless/libertas/wext.c @@ -605,7 +605,7 @@ static int lbs_get_range(struct net_device *dev, struct iw_request_info *info, lbs_deb_wext("chan_no %d\n", chan_no); range->freq[range->num_frequency].i = (long)chan_no; range->freq[range->num_frequency].m = - (long)lbs_chan_2_freq(chan_no, band) * 100000; + (long)lbs_chan_2_freq(chan_no) * 100000; range->freq[range->num_frequency].e = 1; range->num_frequency++; } -- cgit v1.2.1 From ff829ae01644c10722132a45981615be962c4a5c Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Wed, 19 Mar 2008 17:08:32 +0100 Subject: libertas: store rssi as an u32 Don't store an (hardware base) u8 value in bss_descriptor, but just an unsigned int (RSSI is really unsigned). Compilers generate more efficent code for ints than for bytes. Signed-off-by: Holger Schurig Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/debugfs.c | 2 +- drivers/net/wireless/libertas/scan.c | 4 ++-- drivers/net/wireless/libertas/scan.h | 7 +------ 3 files changed, 4 insertions(+), 9 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c index 6d7c0d9b677b..7072e26b42d9 100644 --- a/drivers/net/wireless/libertas/debugfs.c +++ b/drivers/net/wireless/libertas/debugfs.c @@ -78,7 +78,7 @@ static ssize_t lbs_getscantable(struct file *file, char __user *userbuf, u16 spectrum_mgmt = (iter_bss->capability & WLAN_CAPABILITY_SPECTRUM_MGMT); pos += snprintf(buf+pos, len-pos, - "%02u| %03d | %04ld | %s |", + "%02u| %03d | %04d | %s |", numscansdone, iter_bss->channel, iter_bss->rssi, print_mac(mac, iter_bss->bssid)); pos += snprintf(buf+pos, len-pos, " %04x-", iter_bss->capability); diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c index 0598541451d8..3825b7979fc4 100644 --- a/drivers/net/wireless/libertas/scan.c +++ b/drivers/net/wireless/libertas/scan.c @@ -602,7 +602,7 @@ static int lbs_scan_networks(struct lbs_private *priv, int full_scan) lbs_deb_scan("scan table:\n"); list_for_each_entry(iter, &priv->network_list, list) lbs_deb_scan("%02d: BSSID %s, RSSI %d, SSID '%s'\n", - i++, print_mac(mac, iter->bssid), (int)iter->rssi, + i++, print_mac(mac, iter->bssid), iter->rssi, escape_essid(iter->ssid, iter->ssid_len)); mutex_unlock(&priv->lock); #endif @@ -948,7 +948,7 @@ struct bss_descriptor *lbs_find_ssid_in_list(struct lbs_private *priv, uint8_t *bssid, uint8_t mode, int channel) { - uint8_t bestrssi = 0; + u32 bestrssi = 0; struct bss_descriptor * iter_bss = NULL; struct bss_descriptor * found_bss = NULL; struct bss_descriptor * tmp_oldest = NULL; diff --git a/drivers/net/wireless/libertas/scan.h b/drivers/net/wireless/libertas/scan.h index c50c8b74714b..b50cf1415e04 100644 --- a/drivers/net/wireless/libertas/scan.h +++ b/drivers/net/wireless/libertas/scan.h @@ -34,14 +34,9 @@ struct bss_descriptor { u8 ssid_len; u16 capability; - - /* receive signal strength in dBm */ - long rssi; - + u32 rssi; u32 channel; - u16 beaconperiod; - u32 atimwindow; /* IW_MODE_AUTO, IW_MODE_ADHOC, IW_MODE_INFRA */ -- cgit v1.2.1 From 99f7d39bb020a06c98cd42641b6193b761f763ca Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Fri, 14 Mar 2008 10:38:45 -0700 Subject: iwlwifi: remove macros containing offsets from eeprom struct A user needing to access these fields can use offsetof() for access. The comments still contain the offset to assist with debugging. Signed-off-by: Reinette Chatre CC: Michael Buesch Signed-off-by: Assaf Krauss Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-hw.h | 32 ------------------------------ drivers/net/wireless/iwlwifi/iwl-eeprom.h | 32 ------------------------------ 2 files changed, 64 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h index 1ca6fa494e4b..368da9852aab 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h @@ -198,43 +198,27 @@ struct iwl3945_eeprom_temperature_corr { */ struct iwl3945_eeprom { u8 reserved0[16]; -#define EEPROM_DEVICE_ID (2*0x08) /* 2 bytes */ u16 device_id; /* abs.ofs: 16 */ u8 reserved1[2]; -#define EEPROM_PMC (2*0x0A) /* 2 bytes */ u16 pmc; /* abs.ofs: 20 */ u8 reserved2[20]; -#define EEPROM_MAC_ADDRESS (2*0x15) /* 6 bytes */ u8 mac_address[6]; /* abs.ofs: 42 */ u8 reserved3[58]; -#define EEPROM_BOARD_REVISION (2*0x35) /* 2 bytes */ u16 board_revision; /* abs.ofs: 106 */ u8 reserved4[11]; -#define EEPROM_BOARD_PBA_NUMBER (2*0x3B+1) /* 9 bytes */ u8 board_pba_number[9]; /* abs.ofs: 119 */ u8 reserved5[8]; -#define EEPROM_VERSION (2*0x44) /* 2 bytes */ u16 version; /* abs.ofs: 136 */ -#define EEPROM_SKU_CAP (2*0x45) /* 1 bytes */ u8 sku_cap; /* abs.ofs: 138 */ -#define EEPROM_LEDS_MODE (2*0x45+1) /* 1 bytes */ u8 leds_mode; /* abs.ofs: 139 */ -#define EEPROM_OEM_MODE (2*0x46) /* 2 bytes */ u16 oem_mode; -#define EEPROM_WOWLAN_MODE (2*0x47) /* 2 bytes */ u16 wowlan_mode; /* abs.ofs: 142 */ -#define EEPROM_LEDS_TIME_INTERVAL (2*0x48) /* 2 bytes */ u16 leds_time_interval; /* abs.ofs: 144 */ -#define EEPROM_LEDS_OFF_TIME (2*0x49) /* 1 bytes */ u8 leds_off_time; /* abs.ofs: 146 */ -#define EEPROM_LEDS_ON_TIME (2*0x49+1) /* 1 bytes */ u8 leds_on_time; /* abs.ofs: 147 */ -#define EEPROM_ALMGOR_M_VERSION (2*0x4A) /* 1 bytes */ u8 almgor_m_version; /* abs.ofs: 148 */ -#define EEPROM_ANTENNA_SWITCH_TYPE (2*0x4A+1) /* 1 bytes */ u8 antenna_switch_type; /* abs.ofs: 149 */ u8 reserved6[42]; -#define EEPROM_REGULATORY_SKU_ID (2*0x60) /* 4 bytes */ u8 sku_id[4]; /* abs.ofs: 192 */ /* @@ -249,9 +233,7 @@ struct iwl3945_eeprom { * * 2.4 GHz channels 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 */ -#define EEPROM_REGULATORY_BAND_1 (2*0x62) /* 2 bytes */ u16 band_1_count; /* abs.ofs: 196 */ -#define EEPROM_REGULATORY_BAND_1_CHANNELS (2*0x63) /* 28 bytes */ struct iwl3945_eeprom_channel band_1_channels[14]; /* abs.ofs: 196 */ /* @@ -259,36 +241,28 @@ struct iwl3945_eeprom { * 5.0 GHz channels 7, 8, 11, 12, 16 * (4915-5080MHz) (none of these is ever supported) */ -#define EEPROM_REGULATORY_BAND_2 (2*0x71) /* 2 bytes */ u16 band_2_count; /* abs.ofs: 226 */ -#define EEPROM_REGULATORY_BAND_2_CHANNELS (2*0x72) /* 26 bytes */ struct iwl3945_eeprom_channel band_2_channels[13]; /* abs.ofs: 228 */ /* * 5.2 GHz channels 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64 * (5170-5320MHz) */ -#define EEPROM_REGULATORY_BAND_3 (2*0x7F) /* 2 bytes */ u16 band_3_count; /* abs.ofs: 254 */ -#define EEPROM_REGULATORY_BAND_3_CHANNELS (2*0x80) /* 24 bytes */ struct iwl3945_eeprom_channel band_3_channels[12]; /* abs.ofs: 256 */ /* * 5.5 GHz channels 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 * (5500-5700MHz) */ -#define EEPROM_REGULATORY_BAND_4 (2*0x8C) /* 2 bytes */ u16 band_4_count; /* abs.ofs: 280 */ -#define EEPROM_REGULATORY_BAND_4_CHANNELS (2*0x8D) /* 22 bytes */ struct iwl3945_eeprom_channel band_4_channels[11]; /* abs.ofs: 282 */ /* * 5.7 GHz channels 145, 149, 153, 157, 161, 165 * (5725-5825MHz) */ -#define EEPROM_REGULATORY_BAND_5 (2*0x98) /* 2 bytes */ u16 band_5_count; /* abs.ofs: 304 */ -#define EEPROM_REGULATORY_BAND_5_CHANNELS (2*0x99) /* 12 bytes */ struct iwl3945_eeprom_channel band_5_channels[6]; /* abs.ofs: 306 */ u8 reserved9[194]; @@ -296,15 +270,9 @@ struct iwl3945_eeprom { /* * 3945 Txpower calibration data. */ -#define EEPROM_TXPOWER_CALIB_GROUP0 0x200 -#define EEPROM_TXPOWER_CALIB_GROUP1 0x240 -#define EEPROM_TXPOWER_CALIB_GROUP2 0x280 -#define EEPROM_TXPOWER_CALIB_GROUP3 0x2c0 -#define EEPROM_TXPOWER_CALIB_GROUP4 0x300 #define IWL_NUM_TX_CALIB_GROUPS 5 struct iwl3945_eeprom_txpower_group groups[IWL_NUM_TX_CALIB_GROUPS]; /* abs.ofs: 512 */ -#define EEPROM_CALIB_TEMPERATURE_CORRECT 0x340 struct iwl3945_eeprom_temperature_corr corrections; /* abs.ofs: 832 */ u8 reserved16[172]; /* fill out to full 1024 byte block */ } __attribute__ ((packed)); diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h index ad486fe7a96c..404c700c7c18 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h @@ -228,49 +228,31 @@ struct iwl4965_eeprom_calib_info { */ struct iwl4965_eeprom { u8 reserved0[16]; -#define EEPROM_DEVICE_ID (2*0x08) /* 2 bytes */ u16 device_id; /* abs.ofs: 16 */ u8 reserved1[2]; -#define EEPROM_PMC (2*0x0A) /* 2 bytes */ u16 pmc; /* abs.ofs: 20 */ u8 reserved2[20]; -#define EEPROM_MAC_ADDRESS (2*0x15) /* 6 bytes */ u8 mac_address[6]; /* abs.ofs: 42 */ u8 reserved3[58]; -#define EEPROM_BOARD_REVISION (2*0x35) /* 2 bytes */ u16 board_revision; /* abs.ofs: 106 */ u8 reserved4[11]; -#define EEPROM_BOARD_PBA_NUMBER (2*0x3B+1) /* 9 bytes */ u8 board_pba_number[9]; /* abs.ofs: 119 */ u8 reserved5[8]; -#define EEPROM_VERSION (2*0x44) /* 2 bytes */ u16 version; /* abs.ofs: 136 */ -#define EEPROM_SKU_CAP (2*0x45) /* 1 bytes */ u8 sku_cap; /* abs.ofs: 138 */ -#define EEPROM_LEDS_MODE (2*0x45+1) /* 1 bytes */ u8 leds_mode; /* abs.ofs: 139 */ -#define EEPROM_OEM_MODE (2*0x46) /* 2 bytes */ u16 oem_mode; -#define EEPROM_WOWLAN_MODE (2*0x47) /* 2 bytes */ u16 wowlan_mode; /* abs.ofs: 142 */ -#define EEPROM_LEDS_TIME_INTERVAL (2*0x48) /* 2 bytes */ u16 leds_time_interval; /* abs.ofs: 144 */ -#define EEPROM_LEDS_OFF_TIME (2*0x49) /* 1 bytes */ u8 leds_off_time; /* abs.ofs: 146 */ -#define EEPROM_LEDS_ON_TIME (2*0x49+1) /* 1 bytes */ u8 leds_on_time; /* abs.ofs: 147 */ -#define EEPROM_ALMGOR_M_VERSION (2*0x4A) /* 1 bytes */ u8 almgor_m_version; /* abs.ofs: 148 */ -#define EEPROM_ANTENNA_SWITCH_TYPE (2*0x4A+1) /* 1 bytes */ u8 antenna_switch_type; /* abs.ofs: 149 */ u8 reserved6[8]; -#define EEPROM_4965_BOARD_REVISION (2*0x4F) /* 2 bytes */ u16 board_revision_4965; /* abs.ofs: 158 */ u8 reserved7[13]; -#define EEPROM_4965_BOARD_PBA (2*0x56+1) /* 9 bytes */ u8 board_pba_number_4965[9]; /* abs.ofs: 173 */ u8 reserved8[10]; -#define EEPROM_REGULATORY_SKU_ID (2*0x60) /* 4 bytes */ u8 sku_id[4]; /* abs.ofs: 192 */ /* @@ -285,9 +267,7 @@ struct iwl4965_eeprom { * * 2.4 GHz channels 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 */ -#define EEPROM_REGULATORY_BAND_1 (2*0x62) /* 2 bytes */ u16 band_1_count; /* abs.ofs: 196 */ -#define EEPROM_REGULATORY_BAND_1_CHANNELS (2*0x63) /* 28 bytes */ struct iwl4965_eeprom_channel band_1_channels[14]; /* abs.ofs: 196 */ /* @@ -295,36 +275,28 @@ struct iwl4965_eeprom { * 5.0 GHz channels 7, 8, 11, 12, 16 * (4915-5080MHz) (none of these is ever supported) */ -#define EEPROM_REGULATORY_BAND_2 (2*0x71) /* 2 bytes */ u16 band_2_count; /* abs.ofs: 226 */ -#define EEPROM_REGULATORY_BAND_2_CHANNELS (2*0x72) /* 26 bytes */ struct iwl4965_eeprom_channel band_2_channels[13]; /* abs.ofs: 228 */ /* * 5.2 GHz channels 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64 * (5170-5320MHz) */ -#define EEPROM_REGULATORY_BAND_3 (2*0x7F) /* 2 bytes */ u16 band_3_count; /* abs.ofs: 254 */ -#define EEPROM_REGULATORY_BAND_3_CHANNELS (2*0x80) /* 24 bytes */ struct iwl4965_eeprom_channel band_3_channels[12]; /* abs.ofs: 256 */ /* * 5.5 GHz channels 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 * (5500-5700MHz) */ -#define EEPROM_REGULATORY_BAND_4 (2*0x8C) /* 2 bytes */ u16 band_4_count; /* abs.ofs: 280 */ -#define EEPROM_REGULATORY_BAND_4_CHANNELS (2*0x8D) /* 22 bytes */ struct iwl4965_eeprom_channel band_4_channels[11]; /* abs.ofs: 282 */ /* * 5.7 GHz channels 145, 149, 153, 157, 161, 165 * (5725-5825MHz) */ -#define EEPROM_REGULATORY_BAND_5 (2*0x98) /* 2 bytes */ u16 band_5_count; /* abs.ofs: 304 */ -#define EEPROM_REGULATORY_BAND_5_CHANNELS (2*0x99) /* 12 bytes */ struct iwl4965_eeprom_channel band_5_channels[6]; /* abs.ofs: 306 */ u8 reserved10[2]; @@ -345,7 +317,6 @@ struct iwl4965_eeprom { * * NOTE: 4965 does not support FAT channels on 2.4 GHz. */ -#define EEPROM_REGULATORY_BAND_24_FAT_CHANNELS (2*0xA0) /* 14 bytes */ struct iwl4965_eeprom_channel band_24_channels[7]; /* abs.ofs: 320 */ u8 reserved11[2]; @@ -353,7 +324,6 @@ struct iwl4965_eeprom { * 5.2 GHz FAT channels 36 (40), 44 (48), 52 (56), 60 (64), * 100 (104), 108 (112), 116 (120), 124 (128), 132 (136), 149 (153), 157 (161) */ -#define EEPROM_REGULATORY_BAND_52_FAT_CHANNELS (2*0xA8) /* 22 bytes */ struct iwl4965_eeprom_channel band_52_channels[11]; /* abs.ofs: 336 */ u8 reserved12[6]; @@ -362,7 +332,6 @@ struct iwl4965_eeprom { * Driver does not work with txpower calibration version < 5. * This value is simply a 16-bit number, no major/minor versions here. */ -#define EEPROM_CALIB_VERSION_OFFSET (2*0xB6) /* 2 bytes */ u16 calib_version; /* abs.ofs: 364 */ u8 reserved13[2]; u8 reserved14[96]; /* abs.ofs: 368 */ @@ -370,7 +339,6 @@ struct iwl4965_eeprom { /* * 4965 Txpower calibration data. */ -#define EEPROM_IWL_CALIB_TXPOWER_OFFSET (2*0xE8) /* 48 bytes */ struct iwl4965_eeprom_calib_info calib_info; /* abs.ofs: 464 */ u8 reserved16[140]; /* fill out to full 1024 byte block */ -- cgit v1.2.1 From 316c30d9dddc1bd5b586a6cf9808018746372cc9 Mon Sep 17 00:00:00 2001 From: Assaf Krauss Date: Fri, 14 Mar 2008 10:38:46 -0700 Subject: iwlwifi: Re-ordering probe flow (4965) This patch re-orders the iwl4965_pci_probe function. Signed-off-by: Assaf Krauss Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965.c | 19 ++- drivers/net/wireless/iwlwifi/iwl4965-base.c | 252 +++++++++++++++------------- 2 files changed, 151 insertions(+), 120 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index b2ea4d4f3f31..3d30cba0ad45 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -1843,14 +1843,26 @@ int iwl4965_alive_notify(struct iwl_priv *priv) */ int iwl4965_hw_set_hw_setting(struct iwl_priv *priv) { + int ret = 0; + + if ((iwl4965_param_queues_num > IWL_MAX_NUM_QUEUES) || + (iwl4965_param_queues_num < IWL_MIN_NUM_QUEUES)) { + IWL_ERROR("invalid queues_num, should be between %d and %d\n", + IWL_MIN_NUM_QUEUES, IWL_MAX_NUM_QUEUES); + ret = -EINVAL; + goto out; + } + /* Allocate area for Tx byte count tables and Rx queue status */ priv->hw_setting.shared_virt = pci_alloc_consistent(priv->pci_dev, sizeof(struct iwl4965_shared), &priv->hw_setting.shared_phys); - if (!priv->hw_setting.shared_virt) - return -1; + if (!priv->hw_setting.shared_virt) { + ret = -ENOMEM; + goto out; + } memset(priv->hw_setting.shared_virt, 0, sizeof(struct iwl4965_shared)); @@ -1868,7 +1880,8 @@ int iwl4965_hw_set_hw_setting(struct iwl_priv *priv) priv->hw_setting.tx_ant_num = 2; - return 0; +out: + return ret; } /** diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 396940e701e5..a2ee34e40b20 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -8522,6 +8522,10 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e int i; DECLARE_MAC_BUF(mac); + /************************ + * 1. Allocating HW data + ************************/ + /* Disabling hardware scan means that mac80211 will perform scans * "the hard way", rather than using device's scan. */ if (iwl4965_param_disable_hw_scan) { @@ -8529,14 +8533,6 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e iwl4965_hw_ops.hw_scan = NULL; } - if ((iwl4965_param_queues_num > IWL_MAX_NUM_QUEUES) || - (iwl4965_param_queues_num < IWL_MIN_NUM_QUEUES)) { - IWL_ERROR("invalid queues_num, should be between %d and %d\n", - IWL_MIN_NUM_QUEUES, IWL_MAX_NUM_QUEUES); - err = -EINVAL; - goto out; - } - /* mac80211 allocates memory for this device instance, including * space for this driver's private structure */ hw = ieee80211_alloc_hw(sizeof(struct iwl_priv), &iwl4965_hw_ops); @@ -8547,22 +8543,101 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e } SET_IEEE80211_DEV(hw, &pdev->dev); - hw->rate_control_algorithm = "iwl-4965-rs"; - IWL_DEBUG_INFO("*** LOAD DRIVER ***\n"); priv = hw->priv; priv->hw = hw; priv->cfg = cfg; priv->pci_dev = pdev; - priv->antenna = (enum iwl4965_antenna)iwl4965_param_antenna; + #ifdef CONFIG_IWLWIFI_DEBUG iwl_debug_level = iwl4965_param_debug; atomic_set(&priv->restrict_refcnt, 0); #endif - priv->retry_rate = 1; - priv->ibss_beacon = NULL; + /************************** + * 2. Initializing PCI bus + **************************/ + if (pci_enable_device(pdev)) { + err = -ENODEV; + goto out_ieee80211_free_hw; + } + + pci_set_master(pdev); + + err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); + if (!err) + err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); + if (err) { + printk(KERN_WARNING DRV_NAME + ": No suitable DMA available.\n"); + goto out_pci_disable_device; + } + + err = pci_request_regions(pdev, DRV_NAME); + if (err) + goto out_pci_disable_device; + + pci_set_drvdata(pdev, priv); + + /* We disable the RETRY_TIMEOUT register (0x41) to keep + * PCI Tx retries from interfering with C3 CPU state */ + pci_write_config_byte(pdev, 0x41, 0x00); + + /*********************** + * 3. Read REV register + ***********************/ + priv->hw_base = pci_iomap(pdev, 0, 0); + if (!priv->hw_base) { + err = -ENODEV; + goto out_pci_release_regions; + } + + IWL_DEBUG_INFO("pci_resource_len = 0x%08llx\n", + (unsigned long long) pci_resource_len(pdev, 0)); + IWL_DEBUG_INFO("pci_resource_base = %p\n", priv->hw_base); + + printk(KERN_INFO DRV_NAME + ": Detected Intel Wireless WiFi Link %s\n", priv->cfg->name); + + /***************** + * 4. Read EEPROM + *****************/ + /* nic init */ + iwl4965_set_bit(priv, CSR_GIO_CHICKEN_BITS, + CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); + + iwl4965_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); + err = iwl4965_poll_bit(priv, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, + CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); + if (err < 0) { + IWL_DEBUG_INFO("Failed to init the card\n"); + goto out_iounmap; + } + /* Read the EEPROM */ + err = iwl_eeprom_init(priv); + if (err) { + IWL_ERROR("Unable to init EEPROM\n"); + goto out_iounmap; + } + /* MAC Address location in EEPROM same for 3945/4965 */ + iwl_eeprom_get_mac(priv, priv->mac_addr); + IWL_DEBUG_INFO("MAC address: %s\n", print_mac(mac, priv->mac_addr)); + SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr); + + /************************ + * 5. Setup HW constants + ************************/ + /* Device-specific setup */ + if (iwl4965_hw_set_hw_setting(priv)) { + IWL_ERROR("failed to set hw settings\n"); + goto out_iounmap; + } + + /******************* + * 6. Setup hw/priv + *******************/ /* Tell mac80211 and its clients (e.g. Wireless Extensions) * the range of signal quality values that we'll provide. @@ -8583,6 +8658,11 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e hw->queues = 16; #endif /* CONFIG_IWL4965_HT */ + hw->rate_control_algorithm = "iwl-4965-rs"; + priv->antenna = (enum iwl4965_antenna)iwl4965_param_antenna; + priv->retry_rate = 1; + priv->ibss_beacon = NULL; + spin_lock_init(&priv->lock); spin_lock_init(&priv->power_data.lock); spin_lock_init(&priv->sta_lock); @@ -8595,12 +8675,6 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e INIT_LIST_HEAD(&priv->free_frames); mutex_init(&priv->mutex); - if (pci_enable_device(pdev)) { - err = -ENODEV; - goto out_ieee80211_free_hw; - } - - pci_set_master(pdev); /* Clear the driver's (not device's) station table */ iwl4965_clear_stations_table(priv); @@ -8610,44 +8684,8 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e priv->ieee_rates = NULL; priv->band = IEEE80211_BAND_2GHZ; - err = pci_set_dma_mask(pdev, DMA_32BIT_MASK); - if (!err) - err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); - if (err) { - printk(KERN_WARNING DRV_NAME ": No suitable DMA available.\n"); - goto out_pci_disable_device; - } - - pci_set_drvdata(pdev, priv); - err = pci_request_regions(pdev, DRV_NAME); - if (err) - goto out_pci_disable_device; - - /* We disable the RETRY_TIMEOUT register (0x41) to keep - * PCI Tx retries from interfering with C3 CPU state */ - pci_write_config_byte(pdev, 0x41, 0x00); - - priv->hw_base = pci_iomap(pdev, 0, 0); - if (!priv->hw_base) { - err = -ENODEV; - goto out_pci_release_regions; - } - - IWL_DEBUG_INFO("pci_resource_len = 0x%08llx\n", - (unsigned long long) pci_resource_len(pdev, 0)); - IWL_DEBUG_INFO("pci_resource_base = %p\n", priv->hw_base); - - /* Initialize module parameter values here */ - - /* Disable radio (SW RF KILL) via parameter when loading driver */ - if (iwl4965_param_disable) { - set_bit(STATUS_RF_KILL_SW, &priv->status); - IWL_DEBUG_INFO("Radio disabled.\n"); - } - priv->iw_mode = IEEE80211_IF_TYPE_STA; - priv->ps_mode = 0; priv->use_ant_b_for_management_frame = 1; /* start with ant B */ priv->valid_antenna = 0x7; /* assume all 3 connected */ priv->ps_mode = IWL_MIMO_PS_NONE; @@ -8655,73 +8693,22 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e /* Choose which receivers/antennas to use */ iwl4965_set_rxon_chain(priv); - - printk(KERN_INFO DRV_NAME - ": Detected Intel Wireless WiFi Link %s\n", priv->cfg->name); - - /* Device-specific setup */ - if (iwl4965_hw_set_hw_setting(priv)) { - IWL_ERROR("failed to set hw settings\n"); - goto out_iounmap; - } - - if (iwl4965_param_qos_enable) - priv->qos_data.qos_enable = 1; - iwl4965_reset_qos(priv); priv->qos_data.qos_active = 0; priv->qos_data.qos_cap.val = 0; iwl4965_set_rxon_channel(priv, IEEE80211_BAND_2GHZ, 6); - iwl4965_setup_deferred_work(priv); - iwl4965_setup_rx_handlers(priv); priv->rates_mask = IWL_RATES_MASK; /* If power management is turned on, default to AC mode */ priv->power_mode = IWL_POWER_AC; priv->user_txpower_limit = IWL_DEFAULT_TX_POWER; - iwl4965_disable_interrupts(priv); - - err = sysfs_create_group(&pdev->dev.kobj, &iwl4965_attribute_group); - if (err) { - IWL_ERROR("failed to create sysfs device attributes\n"); - goto out_release_irq; - } - - err = iwl_dbgfs_register(priv, DRV_NAME); - if (err) { - IWL_ERROR("failed to create debugfs files\n"); - goto out_remove_sysfs; - } - /* nic init */ - iwl4965_set_bit(priv, CSR_GIO_CHICKEN_BITS, - CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); - - iwl4965_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); - err = iwl4965_poll_bit(priv, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, - CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); - if (err < 0) { - IWL_DEBUG_INFO("Failed to init the card\n"); - goto out_remove_dbgfs; - } - /* Read the EEPROM */ - err = iwl_eeprom_init(priv); - if (err) { - IWL_ERROR("Unable to init EEPROM\n"); - goto out_remove_dbgfs; - } - /* MAC Address location in EEPROM same for 3945/4965 */ - iwl_eeprom_get_mac(priv, priv->mac_addr); - IWL_DEBUG_INFO("MAC address: %s\n", print_mac(mac, priv->mac_addr)); - SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr); - err = iwl4965_init_channel_map(priv); if (err) { IWL_ERROR("initializing regulatory failed: %d\n", err); - goto out_remove_dbgfs; + goto out_unset_hw_settings; } err = iwl4965_init_geos(priv); @@ -8739,32 +8726,63 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e priv->hw->conf.beacon_int = 100; priv->mac80211_registered = 1; + + /********************************** + * 7. Initialize module parameters + **********************************/ + + /* Disable radio (SW RF KILL) via parameter when loading driver */ + if (iwl4965_param_disable) { + set_bit(STATUS_RF_KILL_SW, &priv->status); + IWL_DEBUG_INFO("Radio disabled.\n"); + } + + if (iwl4965_param_qos_enable) + priv->qos_data.qos_enable = 1; + + /******************** + * 8. Setup services + ********************/ + iwl4965_disable_interrupts(priv); + + err = sysfs_create_group(&pdev->dev.kobj, &iwl4965_attribute_group); + if (err) { + IWL_ERROR("failed to create sysfs device attributes\n"); + goto out_free_geos; + } + + err = iwl_dbgfs_register(priv, DRV_NAME); + if (err) { + IWL_ERROR("failed to create debugfs files\n"); + goto out_remove_sysfs; + } + + iwl4965_setup_deferred_work(priv); + iwl4965_setup_rx_handlers(priv); + + /******************** + * 9. Conclude + ********************/ pci_save_state(pdev); pci_disable_device(pdev); return 0; + out_remove_sysfs: + sysfs_remove_group(&pdev->dev.kobj, &iwl4965_attribute_group); out_free_geos: iwl4965_free_geos(priv); out_free_channel_map: iwl4965_free_channel_map(priv); - out_remove_dbgfs: - iwl_dbgfs_unregister(priv); - out_remove_sysfs: - sysfs_remove_group(&pdev->dev.kobj, &iwl4965_attribute_group); - - out_release_irq: - destroy_workqueue(priv->workqueue); - priv->workqueue = NULL; + out_unset_hw_settings: iwl4965_unset_hw_setting(priv); - out_iounmap: pci_iounmap(pdev, priv->hw_base); out_pci_release_regions: pci_release_regions(pdev); + pci_set_drvdata(pdev, NULL); out_pci_disable_device: pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); out_ieee80211_free_hw: ieee80211_free_hw(priv->hw); out: -- cgit v1.2.1 From 00acbc91354f7c548ce12a9ebb7fd25c4c3861ae Mon Sep 17 00:00:00 2001 From: Assaf Krauss Date: Fri, 14 Mar 2008 10:38:47 -0700 Subject: iwlwifi: Packing all 4965 parameters This patch defines a package struct for iwlwifi parameters, and uses a single instance of this struct to group all iwl4965 module parameters together. Signed-off-by: Assaf Krauss Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965.c | 14 ++++----- drivers/net/wireless/iwlwifi/iwl-4965.h | 4 +-- drivers/net/wireless/iwlwifi/iwl-core.h | 12 ++++++++ drivers/net/wireless/iwlwifi/iwl4965-base.c | 45 ++++++++++++++--------------- 4 files changed, 42 insertions(+), 33 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 3d30cba0ad45..2e54dae95751 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -320,7 +320,7 @@ static int iwl4965_rx_init(struct iwl_priv *priv, struct iwl4965_rx_queue *rxq) return rc; } - if (iwl4965_param_amsdu_size_8K) + if (iwl4965_mod_params.amsdu_size_8K) rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K; else rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K; @@ -1845,8 +1845,8 @@ int iwl4965_hw_set_hw_setting(struct iwl_priv *priv) { int ret = 0; - if ((iwl4965_param_queues_num > IWL_MAX_NUM_QUEUES) || - (iwl4965_param_queues_num < IWL_MIN_NUM_QUEUES)) { + if ((iwl4965_mod_params.num_of_queues > IWL_MAX_NUM_QUEUES) || + (iwl4965_mod_params.num_of_queues < IWL_MIN_NUM_QUEUES)) { IWL_ERROR("invalid queues_num, should be between %d and %d\n", IWL_MIN_NUM_QUEUES, IWL_MAX_NUM_QUEUES); ret = -EINVAL; @@ -1866,11 +1866,11 @@ int iwl4965_hw_set_hw_setting(struct iwl_priv *priv) memset(priv->hw_setting.shared_virt, 0, sizeof(struct iwl4965_shared)); - priv->hw_setting.max_txq_num = iwl4965_param_queues_num; + priv->hw_setting.max_txq_num = iwl4965_mod_params.num_of_queues; priv->hw_setting.tx_cmd_len = sizeof(struct iwl4965_tx_cmd); priv->hw_setting.max_rxq_size = RX_QUEUE_SIZE; priv->hw_setting.max_rxq_log = RX_QUEUE_SIZE_LOG; - if (iwl4965_param_amsdu_size_8K) + if (iwl4965_mod_params.amsdu_size_8K) priv->hw_setting.rx_buf_size = IWL_RX_BUF_SIZE_8K; else priv->hw_setting.rx_buf_size = IWL_RX_BUF_SIZE_4K; @@ -3421,7 +3421,7 @@ static void iwl4965_handle_data_packet(struct iwl_priv *priv, int is_data, stats->flag = 0; hdr = (struct ieee80211_hdr *)rxb->skb->data; - if (iwl4965_param_hwcrypto) + if (iwl4965_mod_params.hw_crypto) iwl4965_set_decrypted_flag(priv, rxb->skb, ampdu_status, stats); if (priv->add_radiotap) @@ -3561,7 +3561,7 @@ void iwl4965_init_ht_hw_capab(struct ieee80211_ht_info *ht_info, ht_info->cap |= (u16)IEEE80211_HT_CAP_SGI_20; ht_info->cap |= (u16)(IEEE80211_HT_CAP_MIMO_PS & (IWL_MIMO_PS_NONE << 2)); - if (iwl4965_param_amsdu_size_8K) { + if (iwl4965_mod_params.amsdu_size_8K) { printk(KERN_DEBUG "iwl4965 in A-MSDU 8K support mode\n"); ht_info->cap |= (u16)IEEE80211_HT_CAP_MAX_AMSDU; } diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index cec62ba803b5..1480e1b698a4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -67,9 +67,7 @@ extern struct pci_device_id iwl4965_hw_card_ids[]; #define IWL_NOISE_MEAS_NOT_AVAILABLE (-127) /* Module parameters accessible from iwl-*.c */ -extern int iwl4965_param_hwcrypto; -extern int iwl4965_param_queues_num; -extern int iwl4965_param_amsdu_size_8K; +extern struct iwl_mod_params iwl4965_mod_params; enum iwl4965_antenna { IWL_ANTENNA_DIVERSITY, diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 88fd49abdabd..fb4ce081807b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -84,11 +84,23 @@ struct iwl_ops { const struct iwl_lib_ops *lib; }; +struct iwl_mod_params { + int disable; /* def: 0 = enable radio */ + int hw_crypto; /* def: 0 = using software encryption */ + int debug; /* def: 0 = minimal debug log messages */ + int disable_hw_scan; /* def: 0 = use h/w scan */ + int num_of_queues; /* def: HW dependent */ + int enable_qos; /* def: 1 = use quality of service */ + int amsdu_size_8K; /* def: 1 = enable 8K amsdu size */ + int antenna; /* def: 0 = both antennas (use diversity) */ +}; + struct iwl_cfg { const char *name; const char *fw_name; unsigned int sku; const struct iwl_ops *ops; + const struct iwl_mod_params *mod_params; }; #endif /* __iwl_core_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index a2ee34e40b20..465918cf77f1 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -60,14 +60,12 @@ static int iwl4965_tx_queue_update_write_ptr(struct iwl_priv *priv, ******************************************************************************/ /* module parameters */ -static int iwl4965_param_disable_hw_scan; /* def: 0 = use 4965's h/w scan */ -static int iwl4965_param_debug; /* def: 0 = minimal debug log messages */ -static int iwl4965_param_disable; /* def: enable radio */ -static int iwl4965_param_antenna; /* def: 0 = both antennas (use diversity) */ -int iwl4965_param_hwcrypto; /* def: using software encryption */ -static int iwl4965_param_qos_enable = 1; /* def: 1 = use quality of service */ -int iwl4965_param_queues_num = IWL_MAX_NUM_QUEUES; /* def: 16 Tx queues */ -int iwl4965_param_amsdu_size_8K; /* def: enable 8K amsdu size */ +struct iwl_mod_params iwl4965_mod_params = { + .num_of_queues = IWL_MAX_NUM_QUEUES, + .enable_qos = 1, + .amsdu_size_8K = 1, + /* the rest are 0 by default */ +}; /* * module name, copyright, version, etc. @@ -7186,7 +7184,7 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co goto out; } - if (unlikely(!iwl4965_param_disable_hw_scan && + if (unlikely(!iwl4965_mod_params.disable_hw_scan && test_bit(STATUS_SCANNING, &priv->status))) { IWL_DEBUG_MAC80211("leave - scanning\n"); set_bit(STATUS_CONF_PENDING, &priv->status); @@ -7571,7 +7569,7 @@ static int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, IWL_DEBUG_MAC80211("enter\n"); - if (!iwl4965_param_hwcrypto) { + if (!iwl4965_mod_params.hw_crypto) { IWL_DEBUG_MAC80211("leave - hwcrypto disabled\n"); return -EOPNOTSUPP; } @@ -8528,7 +8526,7 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e /* Disabling hardware scan means that mac80211 will perform scans * "the hard way", rather than using device's scan. */ - if (iwl4965_param_disable_hw_scan) { + if (iwl4965_mod_params.disable_hw_scan) { IWL_DEBUG_INFO("Disabling hw_scan\n"); iwl4965_hw_ops.hw_scan = NULL; } @@ -8551,7 +8549,7 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e priv->pci_dev = pdev; #ifdef CONFIG_IWLWIFI_DEBUG - iwl_debug_level = iwl4965_param_debug; + iwl_debug_level = iwl4965_mod_params.debug; atomic_set(&priv->restrict_refcnt, 0); #endif @@ -8659,7 +8657,7 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e #endif /* CONFIG_IWL4965_HT */ hw->rate_control_algorithm = "iwl-4965-rs"; - priv->antenna = (enum iwl4965_antenna)iwl4965_param_antenna; + priv->antenna = (enum iwl4965_antenna)iwl4965_mod_params.antenna; priv->retry_rate = 1; priv->ibss_beacon = NULL; @@ -8732,12 +8730,12 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e **********************************/ /* Disable radio (SW RF KILL) via parameter when loading driver */ - if (iwl4965_param_disable) { + if (iwl4965_mod_params.disable) { set_bit(STATUS_RF_KILL_SW, &priv->status); IWL_DEBUG_INFO("Radio disabled.\n"); } - if (iwl4965_param_qos_enable) + if (iwl4965_mod_params.enable_qos) priv->qos_data.qos_enable = 1; /******************** @@ -8932,25 +8930,26 @@ static void __exit iwl4965_exit(void) pci_unregister_driver(&iwl4965_driver); } -module_param_named(antenna, iwl4965_param_antenna, int, 0444); +module_param_named(antenna, iwl4965_mod_params.antenna, int, 0444); MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); -module_param_named(disable, iwl4965_param_disable, int, 0444); +module_param_named(disable, iwl4965_mod_params.disable, int, 0444); MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])"); -module_param_named(hwcrypto, iwl4965_param_hwcrypto, int, 0444); +module_param_named(hwcrypto, iwl4965_mod_params.hw_crypto, int, 0444); MODULE_PARM_DESC(hwcrypto, "using hardware crypto engine (default 0 [software])\n"); -module_param_named(debug, iwl4965_param_debug, int, 0444); +module_param_named(debug, iwl4965_mod_params.debug, int, 0444); MODULE_PARM_DESC(debug, "debug output mask"); -module_param_named(disable_hw_scan, iwl4965_param_disable_hw_scan, int, 0444); +module_param_named( + disable_hw_scan, iwl4965_mod_params.disable_hw_scan, int, 0444); MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)"); -module_param_named(queues_num, iwl4965_param_queues_num, int, 0444); +module_param_named(queues_num, iwl4965_mod_params.num_of_queues, int, 0444); MODULE_PARM_DESC(queues_num, "number of hw queues."); /* QoS */ -module_param_named(qos_enable, iwl4965_param_qos_enable, int, 0444); +module_param_named(qos_enable, iwl4965_mod_params.enable_qos, int, 0444); MODULE_PARM_DESC(qos_enable, "enable all QoS functionality"); -module_param_named(amsdu_size_8K, iwl4965_param_amsdu_size_8K, int, 0444); +module_param_named(amsdu_size_8K, iwl4965_mod_params.amsdu_size_8K, int, 0444); MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size"); module_exit(iwl4965_exit); -- cgit v1.2.1 From 1d0a082d38decb62ceb3e26a4bb1a3ca78843a23 Mon Sep 17 00:00:00 2001 From: Assaf Krauss Date: Fri, 14 Mar 2008 10:38:48 -0700 Subject: iwlwifi: Probe Flow - Performing allocation in a separate function Performing allocation in a separate function (previously handled in 'probe') Signed-off-by: Assaf Krauss Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-core.c | 27 +++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-core.h | 7 +++++++ drivers/net/wireless/iwlwifi/iwl4965-base.c | 13 +++++-------- 3 files changed, 39 insertions(+), 8 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 3a9fc905e6bc..244318af53fc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -29,12 +29,15 @@ #include #include #include +#include struct iwl_priv; /* FIXME: remove */ #include "iwl-debug.h" #include "iwl-eeprom.h" #include "iwl-core.h" +#include "iwl-4965.h" /* FIXME: remove */ + MODULE_DESCRIPTION("iwl core"); MODULE_VERSION(IWLWIFI_VERSION); MODULE_AUTHOR(DRV_COPYRIGHT); @@ -44,3 +47,27 @@ MODULE_LICENSE("GPL"); u32 iwl_debug_level; EXPORT_SYMBOL(iwl_debug_level); #endif + +/* This function both allocates and initializes hw and priv. */ +struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg, + struct ieee80211_ops *hw_ops) +{ + struct iwl_priv *priv; + + /* mac80211 allocates memory for this device instance, including + * space for this driver's private structure */ + struct ieee80211_hw *hw = + ieee80211_alloc_hw(sizeof(struct iwl_priv), hw_ops); + if (hw == NULL) { + IWL_ERROR("Can not allocate network device\n"); + goto out; + } + + priv = hw->priv; + priv->hw = hw; + +out: + return hw; +} +EXPORT_SYMBOL(iwl_alloc_all); + diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index fb4ce081807b..33bef1fecf4d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -103,4 +103,11 @@ struct iwl_cfg { const struct iwl_mod_params *mod_params; }; +/*************************** + * L i b * + ***************************/ + +struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg, + struct ieee80211_ops *hw_ops); + #endif /* __iwl_core_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 465918cf77f1..a8fa1bfa570b 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -8531,21 +8531,18 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e iwl4965_hw_ops.hw_scan = NULL; } - /* mac80211 allocates memory for this device instance, including - * space for this driver's private structure */ - hw = ieee80211_alloc_hw(sizeof(struct iwl_priv), &iwl4965_hw_ops); - if (hw == NULL) { - IWL_ERROR("Can not allocate network device\n"); + hw = iwl_alloc_all(cfg, &iwl4965_hw_ops); + if (!hw) { err = -ENOMEM; goto out; } + priv = hw->priv; + /* At this point both hw and priv are allocated. */ + SET_IEEE80211_DEV(hw, &pdev->dev); IWL_DEBUG_INFO("*** LOAD DRIVER ***\n"); - priv = hw->priv; - priv->hw = hw; priv->cfg = cfg; - priv->pci_dev = pdev; #ifdef CONFIG_IWLWIFI_DEBUG -- cgit v1.2.1 From bf85ea4fbecab278c63f02fd102b33cc6cb21eb9 Mon Sep 17 00:00:00 2001 From: Assaf Krauss Date: Fri, 14 Mar 2008 10:38:49 -0700 Subject: iwlwifi: Probe Flow - Extracting hw and priv init 1. Extracting hw and priv initialization from probe function. 2. Moving some initialization functions to core module. Signed-off-by: Assaf Krauss Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965.c | 144 ++++--- drivers/net/wireless/iwlwifi/iwl-4965.h | 27 +- drivers/net/wireless/iwlwifi/iwl-core.c | 178 +++++++++ drivers/net/wireless/iwlwifi/iwl-core.h | 10 + drivers/net/wireless/iwlwifi/iwl-eeprom.c | 356 +++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-eeprom.h | 8 + drivers/net/wireless/iwlwifi/iwl4965-base.c | 577 ++-------------------------- 7 files changed, 677 insertions(+), 623 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 2e54dae95751..8b2d04ed43d6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -105,6 +105,90 @@ static const u16 default_tid_to_tx_fifo[] = { #endif /*CONFIG_IWL4965_HT */ +static int iwl4965_init_drv(struct iwl_priv *priv) +{ + int ret; + int i; + + priv->antenna = (enum iwl4965_antenna)iwl4965_mod_params.antenna; + priv->retry_rate = 1; + priv->ibss_beacon = NULL; + + spin_lock_init(&priv->lock); + spin_lock_init(&priv->power_data.lock); + spin_lock_init(&priv->sta_lock); + spin_lock_init(&priv->hcmd_lock); + spin_lock_init(&priv->lq_mngr.lock); + + for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++) + INIT_LIST_HEAD(&priv->ibss_mac_hash[i]); + + INIT_LIST_HEAD(&priv->free_frames); + + mutex_init(&priv->mutex); + + /* Clear the driver's (not device's) station table */ + iwlcore_clear_stations_table(priv); + + priv->data_retry_limit = -1; + priv->ieee_channels = NULL; + priv->ieee_rates = NULL; + priv->band = IEEE80211_BAND_2GHZ; + + priv->iw_mode = IEEE80211_IF_TYPE_STA; + + priv->use_ant_b_for_management_frame = 1; /* start with ant B */ + priv->valid_antenna = 0x7; /* assume all 3 connected */ + priv->ps_mode = IWL_MIMO_PS_NONE; + + /* Choose which receivers/antennas to use */ + iwl4965_set_rxon_chain(priv); + + iwlcore_reset_qos(priv); + + priv->qos_data.qos_active = 0; + priv->qos_data.qos_cap.val = 0; + + iwlcore_set_rxon_channel(priv, IEEE80211_BAND_2GHZ, 6); + + priv->rates_mask = IWL_RATES_MASK; + /* If power management is turned on, default to AC mode */ + priv->power_mode = IWL_POWER_AC; + priv->user_txpower_limit = IWL_DEFAULT_TX_POWER; + + ret = iwl_init_channel_map(priv); + if (ret) { + IWL_ERROR("initializing regulatory failed: %d\n", ret); + goto err; + } + + ret = iwl4965_init_geos(priv); + if (ret) { + IWL_ERROR("initializing geos failed: %d\n", ret); + goto err_free_channel_map; + } + + iwl4965_rate_control_register(priv->hw); + ret = ieee80211_register_hw(priv->hw); + if (ret) { + IWL_ERROR("Failed to register network device (error %d)\n", + ret); + goto err_free_geos; + } + + priv->hw->conf.beacon_int = 100; + priv->mac80211_registered = 1; + + return 0; + +err_free_geos: + iwl4965_free_geos(priv); +err_free_channel_map: + iwl_free_channel_map(priv); +err: + return ret; +} + static int is_fat_channel(__le32 rxon_flags) { return (rxon_flags & RXON_FLG_CHANNEL_MODE_PURE_40_MSK) || @@ -391,55 +475,6 @@ static int iwl4965_kw_alloc(struct iwl_priv *priv) return 0; } -#define CHECK_AND_PRINT(x) ((eeprom_ch->flags & EEPROM_CHANNEL_##x) \ - ? # x " " : "") - -/** - * iwl4965_set_fat_chan_info - Copy fat channel info into driver's priv. - * - * Does not set up a command, or touch hardware. - */ -int iwl4965_set_fat_chan_info(struct iwl_priv *priv, - enum ieee80211_band band, u16 channel, - const struct iwl4965_eeprom_channel *eeprom_ch, - u8 fat_extension_channel) -{ - struct iwl4965_channel_info *ch_info; - - ch_info = (struct iwl4965_channel_info *) - iwl4965_get_channel_info(priv, band, channel); - - if (!is_channel_valid(ch_info)) - return -1; - - IWL_DEBUG_INFO("FAT Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x" - " %ddBm): Ad-Hoc %ssupported\n", - ch_info->channel, - is_channel_a_band(ch_info) ? - "5.2" : "2.4", - CHECK_AND_PRINT(IBSS), - CHECK_AND_PRINT(ACTIVE), - CHECK_AND_PRINT(RADAR), - CHECK_AND_PRINT(WIDE), - CHECK_AND_PRINT(NARROW), - CHECK_AND_PRINT(DFS), - eeprom_ch->flags, - eeprom_ch->max_power_avg, - ((eeprom_ch->flags & EEPROM_CHANNEL_IBSS) - && !(eeprom_ch->flags & EEPROM_CHANNEL_RADAR)) ? - "" : "not "); - - ch_info->fat_eeprom = *eeprom_ch; - ch_info->fat_max_power_avg = eeprom_ch->max_power_avg; - ch_info->fat_curr_txpow = eeprom_ch->max_power_avg; - ch_info->fat_min_power = 0; - ch_info->fat_scan_power = eeprom_ch->max_power_avg; - ch_info->fat_flags = eeprom_ch->flags; - ch_info->fat_extension_channel = fat_extension_channel; - - return 0; -} - /** * iwl4965_kw_free - Free the "keep warm" buffer */ @@ -2015,11 +2050,11 @@ static s32 iwl4965_get_voltage_compensation(s32 eeprom_voltage, return comp; } -static const struct iwl4965_channel_info * +static const struct iwl_channel_info * iwl4965_get_channel_txpower_info(struct iwl_priv *priv, enum ieee80211_band band, u16 channel) { - const struct iwl4965_channel_info *ch_info; + const struct iwl_channel_info *ch_info; ch_info = iwl4965_get_channel_info(priv, band, channel); @@ -2438,7 +2473,7 @@ static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel, s32 txatten_grp = CALIB_CH_GROUP_MAX; int i; int c; - const struct iwl4965_channel_info *ch_info = NULL; + const struct iwl_channel_info *ch_info = NULL; struct iwl4965_eeprom_calib_ch_info ch_eeprom_info; const struct iwl4965_eeprom_calib_measure *measurement; s16 voltage; @@ -2725,7 +2760,7 @@ int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel) u8 is_fat = 0; u8 ctrl_chan_high = 0; struct iwl4965_channel_switch_cmd cmd = { 0 }; - const struct iwl4965_channel_info *ch_info; + const struct iwl_channel_info *ch_info; band = priv->band == IEEE80211_BAND_2GHZ; @@ -4471,7 +4506,7 @@ static u8 iwl4965_is_channel_extension(struct iwl_priv *priv, enum ieee80211_band band, u16 channel, u8 extension_chan_offset) { - const struct iwl4965_channel_info *ch_info; + const struct iwl_channel_info *ch_info; ch_info = iwl4965_get_channel_info(priv, band, channel); if (!is_channel_valid(ch_info)) @@ -4848,6 +4883,7 @@ void iwl4965_hw_cancel_deferred_work(struct iwl_priv *priv) } static struct iwl_lib_ops iwl4965_lib = { + .init_drv = iwl4965_init_drv, .eeprom_ops = { .verify_signature = iwlcore_eeprom_verify_signature, .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index 1480e1b698a4..7baed4db2f3f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -197,7 +197,7 @@ enum { */ #define IWL4965_MAX_RATE (33) -struct iwl4965_channel_info { +struct iwl_channel_info { struct iwl4965_channel_tgd_info tgd; struct iwl4965_channel_tgh_info tgh; struct iwl4965_eeprom_channel eeprom; /* EEPROM regulatory limit */ @@ -669,6 +669,8 @@ extern void iwl4965_set_decrypted_flag(struct iwl_priv *priv, struct sk_buff *sk u32 decrypt_res, struct ieee80211_rx_status *stats); extern __le16 *ieee80211_get_qos_ctrl(struct ieee80211_hdr *hdr); +int iwl4965_init_geos(struct iwl_priv *priv); +void iwl4965_free_geos(struct iwl_priv *priv); extern const u8 iwl4965_broadcast_addr[ETH_ALEN]; @@ -755,11 +757,6 @@ extern void iwl4965_update_rate_scaling(struct iwl_priv *priv, u8 mode); extern void iwl4965_chain_noise_reset(struct iwl_priv *priv); extern void iwl4965_init_sensitivity(struct iwl_priv *priv, u8 flags, u8 force); -extern int iwl4965_set_fat_chan_info(struct iwl_priv *priv, - enum ieee80211_band band, - u16 channel, - const struct iwl4965_eeprom_channel *eeprom_ch, - u8 fat_extension_channel); extern void iwl4965_rf_kill_ct_config(struct iwl_priv *priv); extern void iwl4965_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, @@ -995,7 +992,7 @@ struct iwl_priv { /* we allocate array of iwl4965_channel_info for NIC's valid channels. * Access via channel # using indirect index array */ - struct iwl4965_channel_info *channel_info; /* channel info array */ + struct iwl_channel_info *channel_info; /* channel info array */ u8 channel_count; /* # of channels */ /* each calibration channel group in the EEPROM has a derived @@ -1229,44 +1226,44 @@ static inline int iwl4965_is_associated(struct iwl_priv *priv) return (priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0; } -static inline int is_channel_valid(const struct iwl4965_channel_info *ch_info) +static inline int is_channel_valid(const struct iwl_channel_info *ch_info) { if (ch_info == NULL) return 0; return (ch_info->flags & EEPROM_CHANNEL_VALID) ? 1 : 0; } -static inline int is_channel_narrow(const struct iwl4965_channel_info *ch_info) +static inline int is_channel_narrow(const struct iwl_channel_info *ch_info) { return (ch_info->flags & EEPROM_CHANNEL_NARROW) ? 1 : 0; } -static inline int is_channel_radar(const struct iwl4965_channel_info *ch_info) +static inline int is_channel_radar(const struct iwl_channel_info *ch_info) { return (ch_info->flags & EEPROM_CHANNEL_RADAR) ? 1 : 0; } -static inline u8 is_channel_a_band(const struct iwl4965_channel_info *ch_info) +static inline u8 is_channel_a_band(const struct iwl_channel_info *ch_info) { return ch_info->band == IEEE80211_BAND_5GHZ; } -static inline u8 is_channel_bg_band(const struct iwl4965_channel_info *ch_info) +static inline u8 is_channel_bg_band(const struct iwl_channel_info *ch_info) { return ch_info->band == IEEE80211_BAND_2GHZ; } -static inline int is_channel_passive(const struct iwl4965_channel_info *ch) +static inline int is_channel_passive(const struct iwl_channel_info *ch) { return (!(ch->flags & EEPROM_CHANNEL_ACTIVE)) ? 1 : 0; } -static inline int is_channel_ibss(const struct iwl4965_channel_info *ch) +static inline int is_channel_ibss(const struct iwl_channel_info *ch) { return ((ch->flags & EEPROM_CHANNEL_IBSS)) ? 1 : 0; } -extern const struct iwl4965_channel_info *iwl4965_get_channel_info( +extern const struct iwl_channel_info *iwl4965_get_channel_info( const struct iwl_priv *priv, enum ieee80211_band band, u16 channel); /* Requires full declaration of iwl_priv before including */ diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 244318af53fc..0e9c3b3d98ce 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -71,3 +71,181 @@ out: } EXPORT_SYMBOL(iwl_alloc_all); +/** + * iwlcore_clear_stations_table - Clear the driver's station table + * + * NOTE: This does not clear or otherwise alter the device's station table. + */ +void iwlcore_clear_stations_table(struct iwl_priv *priv) +{ + unsigned long flags; + + spin_lock_irqsave(&priv->sta_lock, flags); + + priv->num_stations = 0; + memset(priv->stations, 0, sizeof(priv->stations)); + + spin_unlock_irqrestore(&priv->sta_lock, flags); +} +EXPORT_SYMBOL(iwlcore_clear_stations_table); + +void iwlcore_reset_qos(struct iwl_priv *priv) +{ + u16 cw_min = 15; + u16 cw_max = 1023; + u8 aifs = 2; + u8 is_legacy = 0; + unsigned long flags; + int i; + + spin_lock_irqsave(&priv->lock, flags); + priv->qos_data.qos_active = 0; + + if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS) { + if (priv->qos_data.qos_enable) + priv->qos_data.qos_active = 1; + if (!(priv->active_rate & 0xfff0)) { + cw_min = 31; + is_legacy = 1; + } + } else if (priv->iw_mode == IEEE80211_IF_TYPE_AP) { + if (priv->qos_data.qos_enable) + priv->qos_data.qos_active = 1; + } else if (!(priv->staging_rxon.flags & RXON_FLG_SHORT_SLOT_MSK)) { + cw_min = 31; + is_legacy = 1; + } + + if (priv->qos_data.qos_active) + aifs = 3; + + priv->qos_data.def_qos_parm.ac[0].cw_min = cpu_to_le16(cw_min); + priv->qos_data.def_qos_parm.ac[0].cw_max = cpu_to_le16(cw_max); + priv->qos_data.def_qos_parm.ac[0].aifsn = aifs; + priv->qos_data.def_qos_parm.ac[0].edca_txop = 0; + priv->qos_data.def_qos_parm.ac[0].reserved1 = 0; + + if (priv->qos_data.qos_active) { + i = 1; + priv->qos_data.def_qos_parm.ac[i].cw_min = cpu_to_le16(cw_min); + priv->qos_data.def_qos_parm.ac[i].cw_max = cpu_to_le16(cw_max); + priv->qos_data.def_qos_parm.ac[i].aifsn = 7; + priv->qos_data.def_qos_parm.ac[i].edca_txop = 0; + priv->qos_data.def_qos_parm.ac[i].reserved1 = 0; + + i = 2; + priv->qos_data.def_qos_parm.ac[i].cw_min = + cpu_to_le16((cw_min + 1) / 2 - 1); + priv->qos_data.def_qos_parm.ac[i].cw_max = + cpu_to_le16(cw_max); + priv->qos_data.def_qos_parm.ac[i].aifsn = 2; + if (is_legacy) + priv->qos_data.def_qos_parm.ac[i].edca_txop = + cpu_to_le16(6016); + else + priv->qos_data.def_qos_parm.ac[i].edca_txop = + cpu_to_le16(3008); + priv->qos_data.def_qos_parm.ac[i].reserved1 = 0; + + i = 3; + priv->qos_data.def_qos_parm.ac[i].cw_min = + cpu_to_le16((cw_min + 1) / 4 - 1); + priv->qos_data.def_qos_parm.ac[i].cw_max = + cpu_to_le16((cw_max + 1) / 2 - 1); + priv->qos_data.def_qos_parm.ac[i].aifsn = 2; + priv->qos_data.def_qos_parm.ac[i].reserved1 = 0; + if (is_legacy) + priv->qos_data.def_qos_parm.ac[i].edca_txop = + cpu_to_le16(3264); + else + priv->qos_data.def_qos_parm.ac[i].edca_txop = + cpu_to_le16(1504); + } else { + for (i = 1; i < 4; i++) { + priv->qos_data.def_qos_parm.ac[i].cw_min = + cpu_to_le16(cw_min); + priv->qos_data.def_qos_parm.ac[i].cw_max = + cpu_to_le16(cw_max); + priv->qos_data.def_qos_parm.ac[i].aifsn = aifs; + priv->qos_data.def_qos_parm.ac[i].edca_txop = 0; + priv->qos_data.def_qos_parm.ac[i].reserved1 = 0; + } + } + IWL_DEBUG_QOS("set QoS to default \n"); + + spin_unlock_irqrestore(&priv->lock, flags); +} +EXPORT_SYMBOL(iwlcore_reset_qos); + +/** + * iwlcore_set_rxon_channel - Set the phymode and channel values in staging RXON + * @phymode: MODE_IEEE80211A sets to 5.2GHz; all else set to 2.4GHz + * @channel: Any channel valid for the requested phymode + + * In addition to setting the staging RXON, priv->phymode is also set. + * + * NOTE: Does not commit to the hardware; it sets appropriate bit fields + * in the staging RXON flag structure based on the phymode + */ +int iwlcore_set_rxon_channel(struct iwl_priv *priv, + enum ieee80211_band band, + u16 channel) +{ + if (!iwl4965_get_channel_info(priv, band, channel)) { + IWL_DEBUG_INFO("Could not set channel to %d [%d]\n", + channel, band); + return -EINVAL; + } + + if ((le16_to_cpu(priv->staging_rxon.channel) == channel) && + (priv->band == band)) + return 0; + + priv->staging_rxon.channel = cpu_to_le16(channel); + if (band == IEEE80211_BAND_5GHZ) + priv->staging_rxon.flags &= ~RXON_FLG_BAND_24G_MSK; + else + priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK; + + priv->band = band; + + IWL_DEBUG_INFO("Staging channel set to %d [%d]\n", channel, band); + + return 0; +} +EXPORT_SYMBOL(iwlcore_set_rxon_channel); + +static void iwlcore_init_hw(struct iwl_priv *priv) +{ + struct ieee80211_hw *hw = priv->hw; + hw->rate_control_algorithm = "iwl-4965-rs"; + + /* Tell mac80211 and its clients (e.g. Wireless Extensions) + * the range of signal quality values that we'll provide. + * Negative values for level/noise indicate that we'll provide dBm. + * For WE, at least, non-0 values here *enable* display of values + * in app (iwconfig). */ + hw->max_rssi = -20; /* signal level, negative indicates dBm */ + hw->max_noise = -20; /* noise level, negative indicates dBm */ + hw->max_signal = 100; /* link quality indication (%) */ + + /* Tell mac80211 our Tx characteristics */ + hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE; + + /* Default value; 4 EDCA QOS priorities */ + hw->queues = 4; +#ifdef CONFIG_IWL4965_HT + /* Enhanced value; more queues, to support 11n aggregation */ + hw->queues = 16; +#endif /* CONFIG_IWL4965_HT */ +} + +int iwl_setup(struct iwl_priv *priv) +{ + int ret = 0; + iwlcore_init_hw(priv); + ret = priv->cfg->ops->lib->init_drv(priv); + return ret; +} +EXPORT_SYMBOL(iwl_setup); + diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 33bef1fecf4d..4dde4d628a80 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -76,6 +76,8 @@ #define IWL_SKU_N 0x8 struct iwl_lib_ops { + /* iwlwifi driver (priv) init */ + int (*init_drv)(struct iwl_priv *priv); /* eeprom operations (as defined in iwl-eeprom.h) */ struct iwl_eeprom_ops eeprom_ops; }; @@ -110,4 +112,12 @@ struct iwl_cfg { struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg, struct ieee80211_ops *hw_ops); +void iwlcore_clear_stations_table(struct iwl_priv *priv); +void iwlcore_reset_qos(struct iwl_priv *priv); +int iwlcore_set_rxon_channel(struct iwl_priv *priv, + enum ieee80211_band band, + u16 channel); + +int iwl_setup(struct iwl_priv *priv); + #endif /* __iwl_core_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index ccacd489ae80..32ebec35f2af 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -75,6 +75,67 @@ #include "iwl-eeprom.h" #include "iwl-4965-io.h" +/************************** EEPROM BANDS **************************** + * + * The iwl_eeprom_band definitions below provide the mapping from the + * EEPROM contents to the specific channel number supported for each + * band. + * + * For example, iwl_priv->eeprom.band_3_channels[4] from the band_3 + * definition below maps to physical channel 42 in the 5.2GHz spectrum. + * The specific geography and calibration information for that channel + * is contained in the eeprom map itself. + * + * During init, we copy the eeprom information and channel map + * information into priv->channel_info_24/52 and priv->channel_map_24/52 + * + * channel_map_24/52 provides the index in the channel_info array for a + * given channel. We have to have two separate maps as there is channel + * overlap with the 2.4GHz and 5.2GHz spectrum as seen in band_1 and + * band_2 + * + * A value of 0xff stored in the channel_map indicates that the channel + * is not supported by the hardware at all. + * + * A value of 0xfe in the channel_map indicates that the channel is not + * valid for Tx with the current hardware. This means that + * while the system can tune and receive on a given channel, it may not + * be able to associate or transmit any frames on that + * channel. There is no corresponding channel information for that + * entry. + * + *********************************************************************/ + +/* 2.4 GHz */ +const u8 iwl_eeprom_band_1[14] = { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 +}; + +/* 5.2 GHz bands */ +static const u8 iwl_eeprom_band_2[] = { /* 4915-5080MHz */ + 183, 184, 185, 187, 188, 189, 192, 196, 7, 8, 11, 12, 16 +}; + +static const u8 iwl_eeprom_band_3[] = { /* 5170-5320MHz */ + 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64 +}; + +static const u8 iwl_eeprom_band_4[] = { /* 5500-5700MHz */ + 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 +}; + +static const u8 iwl_eeprom_band_5[] = { /* 5725-5825MHz */ + 145, 149, 153, 157, 161, 165 +}; + +static const u8 iwl_eeprom_band_6[] = { /* 2.4 FAT channel */ + 1, 2, 3, 4, 5, 6, 7 +}; + +static const u8 iwl_eeprom_band_7[] = { /* 5.2 FAT channel */ + 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157 +}; + /****************************************************************************** * * EEPROM related functions @@ -203,3 +264,298 @@ void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac) } EXPORT_SYMBOL(iwl_eeprom_get_mac); +static void iwl_init_band_reference(const struct iwl_priv *priv, + int band, + int *eeprom_ch_count, + const struct iwl4965_eeprom_channel + **eeprom_ch_info, + const u8 **eeprom_ch_index) +{ + switch (band) { + case 1: /* 2.4GHz band */ + *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_1); + *eeprom_ch_info = priv->eeprom.band_1_channels; + *eeprom_ch_index = iwl_eeprom_band_1; + break; + case 2: /* 4.9GHz band */ + *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_2); + *eeprom_ch_info = priv->eeprom.band_2_channels; + *eeprom_ch_index = iwl_eeprom_band_2; + break; + case 3: /* 5.2GHz band */ + *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_3); + *eeprom_ch_info = priv->eeprom.band_3_channels; + *eeprom_ch_index = iwl_eeprom_band_3; + break; + case 4: /* 5.5GHz band */ + *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_4); + *eeprom_ch_info = priv->eeprom.band_4_channels; + *eeprom_ch_index = iwl_eeprom_band_4; + break; + case 5: /* 5.7GHz band */ + *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_5); + *eeprom_ch_info = priv->eeprom.band_5_channels; + *eeprom_ch_index = iwl_eeprom_band_5; + break; + case 6: /* 2.4GHz FAT channels */ + *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_6); + *eeprom_ch_info = priv->eeprom.band_24_channels; + *eeprom_ch_index = iwl_eeprom_band_6; + break; + case 7: /* 5 GHz FAT channels */ + *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_7); + *eeprom_ch_info = priv->eeprom.band_52_channels; + *eeprom_ch_index = iwl_eeprom_band_7; + break; + default: + BUG(); + return; + } +} + +#define CHECK_AND_PRINT(x) ((eeprom_ch->flags & EEPROM_CHANNEL_##x) \ + ? # x " " : "") + +/** + * iwl4965_set_fat_chan_info - Copy fat channel info into driver's priv. + * + * Does not set up a command, or touch hardware. + */ +static int iwl4965_set_fat_chan_info(struct iwl_priv *priv, + enum ieee80211_band band, u16 channel, + const struct iwl4965_eeprom_channel *eeprom_ch, + u8 fat_extension_channel) +{ + struct iwl_channel_info *ch_info; + + ch_info = (struct iwl_channel_info *) + iwl4965_get_channel_info(priv, band, channel); + + if (!is_channel_valid(ch_info)) + return -1; + + IWL_DEBUG_INFO("FAT Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x" + " %ddBm): Ad-Hoc %ssupported\n", + ch_info->channel, + is_channel_a_band(ch_info) ? + "5.2" : "2.4", + CHECK_AND_PRINT(IBSS), + CHECK_AND_PRINT(ACTIVE), + CHECK_AND_PRINT(RADAR), + CHECK_AND_PRINT(WIDE), + CHECK_AND_PRINT(NARROW), + CHECK_AND_PRINT(DFS), + eeprom_ch->flags, + eeprom_ch->max_power_avg, + ((eeprom_ch->flags & EEPROM_CHANNEL_IBSS) + && !(eeprom_ch->flags & EEPROM_CHANNEL_RADAR)) ? + "" : "not "); + + ch_info->fat_eeprom = *eeprom_ch; + ch_info->fat_max_power_avg = eeprom_ch->max_power_avg; + ch_info->fat_curr_txpow = eeprom_ch->max_power_avg; + ch_info->fat_min_power = 0; + ch_info->fat_scan_power = eeprom_ch->max_power_avg; + ch_info->fat_flags = eeprom_ch->flags; + ch_info->fat_extension_channel = fat_extension_channel; + + return 0; +} + +#define CHECK_AND_PRINT_I(x) ((eeprom_ch_info[ch].flags & EEPROM_CHANNEL_##x) \ + ? # x " " : "") + +/** + * iwl_init_channel_map - Set up driver's info for all possible channels + */ +int iwl_init_channel_map(struct iwl_priv *priv) +{ + int eeprom_ch_count = 0; + const u8 *eeprom_ch_index = NULL; + const struct iwl4965_eeprom_channel *eeprom_ch_info = NULL; + int band, ch; + struct iwl_channel_info *ch_info; + + if (priv->channel_count) { + IWL_DEBUG_INFO("Channel map already initialized.\n"); + return 0; + } + + if (priv->eeprom.version < 0x2f) { + IWL_WARNING("Unsupported EEPROM version: 0x%04X\n", + priv->eeprom.version); + return -EINVAL; + } + + IWL_DEBUG_INFO("Initializing regulatory info from EEPROM\n"); + + priv->channel_count = + ARRAY_SIZE(iwl_eeprom_band_1) + + ARRAY_SIZE(iwl_eeprom_band_2) + + ARRAY_SIZE(iwl_eeprom_band_3) + + ARRAY_SIZE(iwl_eeprom_band_4) + + ARRAY_SIZE(iwl_eeprom_band_5); + + IWL_DEBUG_INFO("Parsing data for %d channels.\n", priv->channel_count); + + priv->channel_info = kzalloc(sizeof(struct iwl_channel_info) * + priv->channel_count, GFP_KERNEL); + if (!priv->channel_info) { + IWL_ERROR("Could not allocate channel_info\n"); + priv->channel_count = 0; + return -ENOMEM; + } + + ch_info = priv->channel_info; + + /* Loop through the 5 EEPROM bands adding them in order to the + * channel map we maintain (that contains additional information than + * what just in the EEPROM) */ + for (band = 1; band <= 5; band++) { + + iwl_init_band_reference(priv, band, &eeprom_ch_count, + &eeprom_ch_info, &eeprom_ch_index); + + /* Loop through each band adding each of the channels */ + for (ch = 0; ch < eeprom_ch_count; ch++) { + ch_info->channel = eeprom_ch_index[ch]; + ch_info->band = (band == 1) ? IEEE80211_BAND_2GHZ : + IEEE80211_BAND_5GHZ; + + /* permanently store EEPROM's channel regulatory flags + * and max power in channel info database. */ + ch_info->eeprom = eeprom_ch_info[ch]; + + /* Copy the run-time flags so they are there even on + * invalid channels */ + ch_info->flags = eeprom_ch_info[ch].flags; + + if (!(is_channel_valid(ch_info))) { + IWL_DEBUG_INFO("Ch. %d Flags %x [%sGHz] - " + "No traffic\n", + ch_info->channel, + ch_info->flags, + is_channel_a_band(ch_info) ? + "5.2" : "2.4"); + ch_info++; + continue; + } + + /* Initialize regulatory-based run-time data */ + ch_info->max_power_avg = ch_info->curr_txpow = + eeprom_ch_info[ch].max_power_avg; + ch_info->scan_power = eeprom_ch_info[ch].max_power_avg; + ch_info->min_power = 0; + + IWL_DEBUG_INFO("Ch. %d [%sGHz] %s%s%s%s%s%s%s(0x%02x" + " %ddBm): Ad-Hoc %ssupported\n", + ch_info->channel, + is_channel_a_band(ch_info) ? + "5.2" : "2.4", + CHECK_AND_PRINT_I(VALID), + CHECK_AND_PRINT_I(IBSS), + CHECK_AND_PRINT_I(ACTIVE), + CHECK_AND_PRINT_I(RADAR), + CHECK_AND_PRINT_I(WIDE), + CHECK_AND_PRINT_I(NARROW), + CHECK_AND_PRINT_I(DFS), + eeprom_ch_info[ch].flags, + eeprom_ch_info[ch].max_power_avg, + ((eeprom_ch_info[ch]. + flags & EEPROM_CHANNEL_IBSS) + && !(eeprom_ch_info[ch]. + flags & EEPROM_CHANNEL_RADAR)) + ? "" : "not "); + + /* Set the user_txpower_limit to the highest power + * supported by any channel */ + if (eeprom_ch_info[ch].max_power_avg > + priv->user_txpower_limit) + priv->user_txpower_limit = + eeprom_ch_info[ch].max_power_avg; + + ch_info++; + } + } + + /* Two additional EEPROM bands for 2.4 and 5 GHz FAT channels */ + for (band = 6; band <= 7; band++) { + enum ieee80211_band ieeeband; + u8 fat_extension_chan; + + iwl_init_band_reference(priv, band, &eeprom_ch_count, + &eeprom_ch_info, &eeprom_ch_index); + + /* EEPROM band 6 is 2.4, band 7 is 5 GHz */ + ieeeband = + (band == 6) ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; + + /* Loop through each band adding each of the channels */ + for (ch = 0; ch < eeprom_ch_count; ch++) { + + if ((band == 6) && + ((eeprom_ch_index[ch] == 5) || + (eeprom_ch_index[ch] == 6) || + (eeprom_ch_index[ch] == 7))) + fat_extension_chan = HT_IE_EXT_CHANNEL_MAX; + else + fat_extension_chan = HT_IE_EXT_CHANNEL_ABOVE; + + /* Set up driver's info for lower half */ + iwl4965_set_fat_chan_info(priv, ieeeband, + eeprom_ch_index[ch], + &(eeprom_ch_info[ch]), + fat_extension_chan); + + /* Set up driver's info for upper half */ + iwl4965_set_fat_chan_info(priv, ieeeband, + (eeprom_ch_index[ch] + 4), + &(eeprom_ch_info[ch]), + HT_IE_EXT_CHANNEL_BELOW); + } + } + + return 0; +} +EXPORT_SYMBOL(iwl_init_channel_map); + +/* + * iwl_free_channel_map - undo allocations in iwl4965_init_channel_map + */ +void iwl_free_channel_map(struct iwl_priv *priv) +{ + kfree(priv->channel_info); + priv->channel_count = 0; +} +EXPORT_SYMBOL(iwl_free_channel_map); + +/** + * iwl_get_channel_info - Find driver's private channel info + * + * Based on band and channel number. + */ +const struct iwl_channel_info *iwl4965_get_channel_info( + const struct iwl_priv *priv, + enum ieee80211_band band, u16 channel) +{ + int i; + + switch (band) { + case IEEE80211_BAND_5GHZ: + for (i = 14; i < priv->channel_count; i++) { + if (priv->channel_info[i].channel == channel) + return &priv->channel_info[i]; + } + break; + case IEEE80211_BAND_2GHZ: + if (channel >= 1 && channel <= 14) + return &priv->channel_info[channel - 1]; + break; + default: + BUG(); + } + + return NULL; +} +EXPORT_SYMBOL(iwl4965_get_channel_info); + diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h index 404c700c7c18..8a583947b2c7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h @@ -137,6 +137,8 @@ struct iwl4965_eeprom_channel { * Look for this in calib_version member of struct iwl4965_eeprom. */ #define EEPROM_TX_POWER_VERSION_NEW (5) +/* 2.4 GHz */ +extern const u8 iwl_eeprom_band_1[14]; /* * 4965 factory calibration data for one txpower level, on one channel, @@ -364,4 +366,10 @@ int iwlcore_eeprom_verify_signature(struct iwl_priv *priv); int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv); void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv); +int iwl_init_channel_map(struct iwl_priv *priv); +void iwl_free_channel_map(struct iwl_priv *priv); +const struct iwl_channel_info *iwl4965_get_channel_info( + const struct iwl_priv *priv, + enum ieee80211_band band, u16 channel); + #endif /* __iwl_eeprom_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index a8fa1bfa570b..9cf1f204666d 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -430,23 +430,6 @@ out: } #endif -/** - * iwl4965_clear_stations_table - Clear the driver's station table - * - * NOTE: This does not clear or otherwise alter the device's station table. - */ -static void iwl4965_clear_stations_table(struct iwl_priv *priv) -{ - unsigned long flags; - - spin_lock_irqsave(&priv->sta_lock, flags); - - priv->num_stations = 0; - memset(priv->stations, 0, sizeof(priv->stations)); - - spin_unlock_irqrestore(&priv->sta_lock, flags); -} - /** * iwl4965_add_station_flags - Add station to tables in driver and device */ @@ -880,43 +863,6 @@ static int iwl4965_rxon_add_station(struct iwl_priv *priv, return sta_id; } -/** - * iwl4965_set_rxon_channel - Set the phymode and channel values in staging RXON - * @phymode: MODE_IEEE80211A sets to 5.2GHz; all else set to 2.4GHz - * @channel: Any channel valid for the requested phymode - - * In addition to setting the staging RXON, priv->phymode is also set. - * - * NOTE: Does not commit to the hardware; it sets appropriate bit fields - * in the staging RXON flag structure based on the phymode - */ -static int iwl4965_set_rxon_channel(struct iwl_priv *priv, - enum ieee80211_band band, - u16 channel) -{ - if (!iwl4965_get_channel_info(priv, band, channel)) { - IWL_DEBUG_INFO("Could not set channel to %d [%d]\n", - channel, band); - return -EINVAL; - } - - if ((le16_to_cpu(priv->staging_rxon.channel) == channel) && - (priv->band == band)) - return 0; - - priv->staging_rxon.channel = cpu_to_le16(channel); - if (band == IEEE80211_BAND_5GHZ) - priv->staging_rxon.flags &= ~RXON_FLG_BAND_24G_MSK; - else - priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK; - - priv->band = band; - - IWL_DEBUG_INFO("Staging channel set to %d [%d]\n", channel, band); - - return 0; -} - /** * iwl4965_check_rxon_cmd - validate RXON structure is valid * @@ -1186,7 +1132,7 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv) return rc; } - iwl4965_clear_stations_table(priv); + iwlcore_clear_stations_table(priv); #ifdef CONFIG_IWL4965_SENSITIVITY if (!priv->error_recovering) @@ -1732,93 +1678,6 @@ static int iwl4965_send_qos_params_command(struct iwl_priv *priv, sizeof(struct iwl4965_qosparam_cmd), qos); } -static void iwl4965_reset_qos(struct iwl_priv *priv) -{ - u16 cw_min = 15; - u16 cw_max = 1023; - u8 aifs = 2; - u8 is_legacy = 0; - unsigned long flags; - int i; - - spin_lock_irqsave(&priv->lock, flags); - priv->qos_data.qos_active = 0; - - if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS) { - if (priv->qos_data.qos_enable) - priv->qos_data.qos_active = 1; - if (!(priv->active_rate & 0xfff0)) { - cw_min = 31; - is_legacy = 1; - } - } else if (priv->iw_mode == IEEE80211_IF_TYPE_AP) { - if (priv->qos_data.qos_enable) - priv->qos_data.qos_active = 1; - } else if (!(priv->staging_rxon.flags & RXON_FLG_SHORT_SLOT_MSK)) { - cw_min = 31; - is_legacy = 1; - } - - if (priv->qos_data.qos_active) - aifs = 3; - - priv->qos_data.def_qos_parm.ac[0].cw_min = cpu_to_le16(cw_min); - priv->qos_data.def_qos_parm.ac[0].cw_max = cpu_to_le16(cw_max); - priv->qos_data.def_qos_parm.ac[0].aifsn = aifs; - priv->qos_data.def_qos_parm.ac[0].edca_txop = 0; - priv->qos_data.def_qos_parm.ac[0].reserved1 = 0; - - if (priv->qos_data.qos_active) { - i = 1; - priv->qos_data.def_qos_parm.ac[i].cw_min = cpu_to_le16(cw_min); - priv->qos_data.def_qos_parm.ac[i].cw_max = cpu_to_le16(cw_max); - priv->qos_data.def_qos_parm.ac[i].aifsn = 7; - priv->qos_data.def_qos_parm.ac[i].edca_txop = 0; - priv->qos_data.def_qos_parm.ac[i].reserved1 = 0; - - i = 2; - priv->qos_data.def_qos_parm.ac[i].cw_min = - cpu_to_le16((cw_min + 1) / 2 - 1); - priv->qos_data.def_qos_parm.ac[i].cw_max = - cpu_to_le16(cw_max); - priv->qos_data.def_qos_parm.ac[i].aifsn = 2; - if (is_legacy) - priv->qos_data.def_qos_parm.ac[i].edca_txop = - cpu_to_le16(6016); - else - priv->qos_data.def_qos_parm.ac[i].edca_txop = - cpu_to_le16(3008); - priv->qos_data.def_qos_parm.ac[i].reserved1 = 0; - - i = 3; - priv->qos_data.def_qos_parm.ac[i].cw_min = - cpu_to_le16((cw_min + 1) / 4 - 1); - priv->qos_data.def_qos_parm.ac[i].cw_max = - cpu_to_le16((cw_max + 1) / 2 - 1); - priv->qos_data.def_qos_parm.ac[i].aifsn = 2; - priv->qos_data.def_qos_parm.ac[i].reserved1 = 0; - if (is_legacy) - priv->qos_data.def_qos_parm.ac[i].edca_txop = - cpu_to_le16(3264); - else - priv->qos_data.def_qos_parm.ac[i].edca_txop = - cpu_to_le16(1504); - } else { - for (i = 1; i < 4; i++) { - priv->qos_data.def_qos_parm.ac[i].cw_min = - cpu_to_le16(cw_min); - priv->qos_data.def_qos_parm.ac[i].cw_max = - cpu_to_le16(cw_max); - priv->qos_data.def_qos_parm.ac[i].aifsn = aifs; - priv->qos_data.def_qos_parm.ac[i].edca_txop = 0; - priv->qos_data.def_qos_parm.ac[i].reserved1 = 0; - } - } - IWL_DEBUG_QOS("set QoS to default \n"); - - spin_unlock_irqrestore(&priv->lock, flags); -} - static void iwl4965_activate_qos(struct iwl_priv *priv, u8 force) { unsigned long flags; @@ -2304,7 +2163,7 @@ static void iwl4965_set_flags_for_phymode(struct iwl_priv *priv, */ static void iwl4965_connection_init_rx_config(struct iwl_priv *priv) { - const struct iwl4965_channel_info *ch_info; + const struct iwl_channel_info *ch_info; memset(&priv->staging_rxon, 0, sizeof(priv->staging_rxon)); @@ -2377,7 +2236,7 @@ static void iwl4965_connection_init_rx_config(struct iwl_priv *priv) static int iwl4965_set_mode(struct iwl_priv *priv, int mode) { if (mode == IEEE80211_IF_TYPE_IBSS) { - const struct iwl4965_channel_info *ch_info; + const struct iwl_channel_info *ch_info; ch_info = iwl4965_get_channel_info(priv, priv->band, @@ -2395,7 +2254,7 @@ static int iwl4965_set_mode(struct iwl_priv *priv, int mode) iwl4965_connection_init_rx_config(priv); memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN); - iwl4965_clear_stations_table(priv); + iwlcore_clear_stations_table(priv); /* dont commit rxon if rf-kill is on*/ if (!iwl4965_is_ready_rf(priv)) @@ -4999,308 +4858,6 @@ static irqreturn_t iwl4965_isr(int irq, void *data) return IRQ_NONE; } -/************************** EEPROM BANDS **************************** - * - * The iwl4965_eeprom_band definitions below provide the mapping from the - * EEPROM contents to the specific channel number supported for each - * band. - * - * For example, iwl_priv->eeprom.band_3_channels[4] from the band_3 - * definition below maps to physical channel 42 in the 5.2GHz spectrum. - * The specific geography and calibration information for that channel - * is contained in the eeprom map itself. - * - * During init, we copy the eeprom information and channel map - * information into priv->channel_info_24/52 and priv->channel_map_24/52 - * - * channel_map_24/52 provides the index in the channel_info array for a - * given channel. We have to have two separate maps as there is channel - * overlap with the 2.4GHz and 5.2GHz spectrum as seen in band_1 and - * band_2 - * - * A value of 0xff stored in the channel_map indicates that the channel - * is not supported by the hardware at all. - * - * A value of 0xfe in the channel_map indicates that the channel is not - * valid for Tx with the current hardware. This means that - * while the system can tune and receive on a given channel, it may not - * be able to associate or transmit any frames on that - * channel. There is no corresponding channel information for that - * entry. - * - *********************************************************************/ - -/* 2.4 GHz */ -static const u8 iwl4965_eeprom_band_1[14] = { - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 -}; - -/* 5.2 GHz bands */ -static const u8 iwl4965_eeprom_band_2[] = { /* 4915-5080MHz */ - 183, 184, 185, 187, 188, 189, 192, 196, 7, 8, 11, 12, 16 -}; - -static const u8 iwl4965_eeprom_band_3[] = { /* 5170-5320MHz */ - 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64 -}; - -static const u8 iwl4965_eeprom_band_4[] = { /* 5500-5700MHz */ - 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 -}; - -static const u8 iwl4965_eeprom_band_5[] = { /* 5725-5825MHz */ - 145, 149, 153, 157, 161, 165 -}; - -static u8 iwl4965_eeprom_band_6[] = { /* 2.4 FAT channel */ - 1, 2, 3, 4, 5, 6, 7 -}; - -static u8 iwl4965_eeprom_band_7[] = { /* 5.2 FAT channel */ - 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157 -}; - -static void iwl4965_init_band_reference(const struct iwl_priv *priv, - int band, - int *eeprom_ch_count, - const struct iwl4965_eeprom_channel - **eeprom_ch_info, - const u8 **eeprom_ch_index) -{ - switch (band) { - case 1: /* 2.4GHz band */ - *eeprom_ch_count = ARRAY_SIZE(iwl4965_eeprom_band_1); - *eeprom_ch_info = priv->eeprom.band_1_channels; - *eeprom_ch_index = iwl4965_eeprom_band_1; - break; - case 2: /* 4.9GHz band */ - *eeprom_ch_count = ARRAY_SIZE(iwl4965_eeprom_band_2); - *eeprom_ch_info = priv->eeprom.band_2_channels; - *eeprom_ch_index = iwl4965_eeprom_band_2; - break; - case 3: /* 5.2GHz band */ - *eeprom_ch_count = ARRAY_SIZE(iwl4965_eeprom_band_3); - *eeprom_ch_info = priv->eeprom.band_3_channels; - *eeprom_ch_index = iwl4965_eeprom_band_3; - break; - case 4: /* 5.5GHz band */ - *eeprom_ch_count = ARRAY_SIZE(iwl4965_eeprom_band_4); - *eeprom_ch_info = priv->eeprom.band_4_channels; - *eeprom_ch_index = iwl4965_eeprom_band_4; - break; - case 5: /* 5.7GHz band */ - *eeprom_ch_count = ARRAY_SIZE(iwl4965_eeprom_band_5); - *eeprom_ch_info = priv->eeprom.band_5_channels; - *eeprom_ch_index = iwl4965_eeprom_band_5; - break; - case 6: /* 2.4GHz FAT channels */ - *eeprom_ch_count = ARRAY_SIZE(iwl4965_eeprom_band_6); - *eeprom_ch_info = priv->eeprom.band_24_channels; - *eeprom_ch_index = iwl4965_eeprom_band_6; - break; - case 7: /* 5 GHz FAT channels */ - *eeprom_ch_count = ARRAY_SIZE(iwl4965_eeprom_band_7); - *eeprom_ch_info = priv->eeprom.band_52_channels; - *eeprom_ch_index = iwl4965_eeprom_band_7; - break; - default: - BUG(); - return; - } -} - -/** - * iwl4965_get_channel_info - Find driver's private channel info - * - * Based on band and channel number. - */ -const struct iwl4965_channel_info *iwl4965_get_channel_info(const struct iwl_priv *priv, - enum ieee80211_band band, u16 channel) -{ - int i; - - switch (band) { - case IEEE80211_BAND_5GHZ: - for (i = 14; i < priv->channel_count; i++) { - if (priv->channel_info[i].channel == channel) - return &priv->channel_info[i]; - } - break; - case IEEE80211_BAND_2GHZ: - if (channel >= 1 && channel <= 14) - return &priv->channel_info[channel - 1]; - break; - default: - BUG(); - } - - return NULL; -} - -#define CHECK_AND_PRINT(x) ((eeprom_ch_info[ch].flags & EEPROM_CHANNEL_##x) \ - ? # x " " : "") - -/** - * iwl4965_init_channel_map - Set up driver's info for all possible channels - */ -static int iwl4965_init_channel_map(struct iwl_priv *priv) -{ - int eeprom_ch_count = 0; - const u8 *eeprom_ch_index = NULL; - const struct iwl4965_eeprom_channel *eeprom_ch_info = NULL; - int band, ch; - struct iwl4965_channel_info *ch_info; - - if (priv->channel_count) { - IWL_DEBUG_INFO("Channel map already initialized.\n"); - return 0; - } - - if (priv->eeprom.version < 0x2f) { - IWL_WARNING("Unsupported EEPROM version: 0x%04X\n", - priv->eeprom.version); - return -EINVAL; - } - - IWL_DEBUG_INFO("Initializing regulatory info from EEPROM\n"); - - priv->channel_count = - ARRAY_SIZE(iwl4965_eeprom_band_1) + - ARRAY_SIZE(iwl4965_eeprom_band_2) + - ARRAY_SIZE(iwl4965_eeprom_band_3) + - ARRAY_SIZE(iwl4965_eeprom_band_4) + - ARRAY_SIZE(iwl4965_eeprom_band_5); - - IWL_DEBUG_INFO("Parsing data for %d channels.\n", priv->channel_count); - - priv->channel_info = kzalloc(sizeof(struct iwl4965_channel_info) * - priv->channel_count, GFP_KERNEL); - if (!priv->channel_info) { - IWL_ERROR("Could not allocate channel_info\n"); - priv->channel_count = 0; - return -ENOMEM; - } - - ch_info = priv->channel_info; - - /* Loop through the 5 EEPROM bands adding them in order to the - * channel map we maintain (that contains additional information than - * what just in the EEPROM) */ - for (band = 1; band <= 5; band++) { - - iwl4965_init_band_reference(priv, band, &eeprom_ch_count, - &eeprom_ch_info, &eeprom_ch_index); - - /* Loop through each band adding each of the channels */ - for (ch = 0; ch < eeprom_ch_count; ch++) { - ch_info->channel = eeprom_ch_index[ch]; - ch_info->band = (band == 1) ? IEEE80211_BAND_2GHZ : - IEEE80211_BAND_5GHZ; - - /* permanently store EEPROM's channel regulatory flags - * and max power in channel info database. */ - ch_info->eeprom = eeprom_ch_info[ch]; - - /* Copy the run-time flags so they are there even on - * invalid channels */ - ch_info->flags = eeprom_ch_info[ch].flags; - - if (!(is_channel_valid(ch_info))) { - IWL_DEBUG_INFO("Ch. %d Flags %x [%sGHz] - " - "No traffic\n", - ch_info->channel, - ch_info->flags, - is_channel_a_band(ch_info) ? - "5.2" : "2.4"); - ch_info++; - continue; - } - - /* Initialize regulatory-based run-time data */ - ch_info->max_power_avg = ch_info->curr_txpow = - eeprom_ch_info[ch].max_power_avg; - ch_info->scan_power = eeprom_ch_info[ch].max_power_avg; - ch_info->min_power = 0; - - IWL_DEBUG_INFO("Ch. %d [%sGHz] %s%s%s%s%s%s%s(0x%02x" - " %ddBm): Ad-Hoc %ssupported\n", - ch_info->channel, - is_channel_a_band(ch_info) ? - "5.2" : "2.4", - CHECK_AND_PRINT(VALID), - CHECK_AND_PRINT(IBSS), - CHECK_AND_PRINT(ACTIVE), - CHECK_AND_PRINT(RADAR), - CHECK_AND_PRINT(WIDE), - CHECK_AND_PRINT(NARROW), - CHECK_AND_PRINT(DFS), - eeprom_ch_info[ch].flags, - eeprom_ch_info[ch].max_power_avg, - ((eeprom_ch_info[ch]. - flags & EEPROM_CHANNEL_IBSS) - && !(eeprom_ch_info[ch]. - flags & EEPROM_CHANNEL_RADAR)) - ? "" : "not "); - - /* Set the user_txpower_limit to the highest power - * supported by any channel */ - if (eeprom_ch_info[ch].max_power_avg > - priv->user_txpower_limit) - priv->user_txpower_limit = - eeprom_ch_info[ch].max_power_avg; - - ch_info++; - } - } - - /* Two additional EEPROM bands for 2.4 and 5 GHz FAT channels */ - for (band = 6; band <= 7; band++) { - enum ieee80211_band ieeeband; - u8 fat_extension_chan; - - iwl4965_init_band_reference(priv, band, &eeprom_ch_count, - &eeprom_ch_info, &eeprom_ch_index); - - /* EEPROM band 6 is 2.4, band 7 is 5 GHz */ - ieeeband = (band == 6) ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; - - /* Loop through each band adding each of the channels */ - for (ch = 0; ch < eeprom_ch_count; ch++) { - - if ((band == 6) && - ((eeprom_ch_index[ch] == 5) || - (eeprom_ch_index[ch] == 6) || - (eeprom_ch_index[ch] == 7))) - fat_extension_chan = HT_IE_EXT_CHANNEL_MAX; - else - fat_extension_chan = HT_IE_EXT_CHANNEL_ABOVE; - - /* Set up driver's info for lower half */ - iwl4965_set_fat_chan_info(priv, ieeeband, - eeprom_ch_index[ch], - &(eeprom_ch_info[ch]), - fat_extension_chan); - - /* Set up driver's info for upper half */ - iwl4965_set_fat_chan_info(priv, ieeeband, - (eeprom_ch_index[ch] + 4), - &(eeprom_ch_info[ch]), - HT_IE_EXT_CHANNEL_BELOW); - } - } - - return 0; -} - -/* - * iwl4965_free_channel_map - undo allocations in iwl4965_init_channel_map - */ -static void iwl4965_free_channel_map(struct iwl_priv *priv) -{ - kfree(priv->channel_info); - priv->channel_count = 0; -} - /* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after * sending probe req. This should be set long enough to hear probe responses * from more than one AP. */ @@ -5364,7 +4921,7 @@ static int iwl4965_get_channels_for_scan(struct iwl_priv *priv, { const struct ieee80211_channel *channels = NULL; const struct ieee80211_supported_band *sband; - const struct iwl4965_channel_info *ch_info; + const struct iwl_channel_info *ch_info; u16 passive_dwell = 0; u16 active_dwell = 0; int added, i; @@ -5468,9 +5025,9 @@ static void iwl4965_init_hw_rates(struct iwl_priv *priv, /** * iwl4965_init_geos - Initialize mac80211's geo/channel info based from eeprom */ -static int iwl4965_init_geos(struct iwl_priv *priv) +int iwl4965_init_geos(struct iwl_priv *priv) { - struct iwl4965_channel_info *ch; + struct iwl_channel_info *ch; struct ieee80211_supported_band *sband; struct ieee80211_channel *channels; struct ieee80211_channel *geo_ch; @@ -5498,7 +5055,7 @@ static int iwl4965_init_geos(struct iwl_priv *priv) /* 5.2GHz channels start after the 2.4GHz channels */ sband = &priv->bands[IEEE80211_BAND_5GHZ]; - sband->channels = &channels[ARRAY_SIZE(iwl4965_eeprom_band_1)]; + sband->channels = &channels[ARRAY_SIZE(iwl_eeprom_band_1)]; /* just OFDM */ sband->bitrates = &rates[IWL_FIRST_OFDM_RATE]; sband->n_bitrates = IWL_RATE_COUNT - IWL_FIRST_OFDM_RATE; @@ -5590,7 +5147,7 @@ static int iwl4965_init_geos(struct iwl_priv *priv) /* * iwl4965_free_geos - undo allocations in iwl4965_init_geos */ -static void iwl4965_free_geos(struct iwl_priv *priv) +void iwl4965_free_geos(struct iwl_priv *priv) { kfree(priv->ieee_channels); kfree(priv->ieee_rates); @@ -6233,7 +5790,7 @@ static void iwl4965_alive_start(struct iwl_priv *priv) goto restart; } - iwl4965_clear_stations_table(priv); + iwlcore_clear_stations_table(priv); rc = iwl4965_alive_notify(priv); if (rc) { @@ -6310,7 +5867,7 @@ static void __iwl4965_down(struct iwl_priv *priv) if (!exit_pending) set_bit(STATUS_EXIT_PENDING, &priv->status); - iwl4965_clear_stations_table(priv); + iwlcore_clear_stations_table(priv); /* Unblock any waiting calls */ wake_up_interruptible_all(&priv->wait_command_queue); @@ -6465,7 +6022,7 @@ static int __iwl4965_up(struct iwl_priv *priv) for (i = 0; i < MAX_HW_RESTARTS; i++) { - iwl4965_clear_stations_table(priv); + iwlcore_clear_stations_table(priv); /* load bootstrap state machine, * load bootstrap program into processor's memory, @@ -6911,7 +6468,7 @@ static void iwl4965_bg_post_associate(struct work_struct *data) case IEEE80211_IF_TYPE_IBSS: /* clear out the station table */ - iwl4965_clear_stations_table(priv); + iwlcore_clear_stations_table(priv); iwl4965_rxon_add_station(priv, iwl4965_broadcast_addr, 0); iwl4965_rxon_add_station(priv, priv->bssid, 0); @@ -7169,7 +6726,7 @@ static int iwl4965_mac_add_interface(struct ieee80211_hw *hw, static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) { struct iwl_priv *priv = hw->priv; - const struct iwl4965_channel_info *ch_info; + const struct iwl_channel_info *ch_info; unsigned long flags; int ret = 0; @@ -7215,7 +6772,7 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co priv->staging_rxon.flags = 0; #endif /* CONFIG_IWL4965_HT */ - iwl4965_set_rxon_channel(priv, conf->channel->band, + iwlcore_set_rxon_channel(priv, conf->channel->band, ieee80211_frequency_to_channel(conf->channel->center_freq)); iwl4965_set_flags_for_phymode(priv, conf->channel->band); @@ -7736,7 +7293,7 @@ static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw) spin_unlock_irqrestore(&priv->lock, flags); #endif /* CONFIG_IWL4965_HT */ - iwl4965_reset_qos(priv); + iwlcore_reset_qos(priv); cancel_delayed_work(&priv->post_associate); @@ -7825,7 +7382,7 @@ static int iwl4965_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk IWL_DEBUG_MAC80211("leave\n"); spin_unlock_irqrestore(&priv->lock, flags); - iwl4965_reset_qos(priv); + iwlcore_reset_qos(priv); queue_work(priv->workqueue, &priv->post_associate.work); @@ -8517,7 +8074,6 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e struct iwl_priv *priv; struct ieee80211_hw *hw; struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); - int i; DECLARE_MAC_BUF(mac); /************************ @@ -8634,93 +8190,10 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e * 6. Setup hw/priv *******************/ - /* Tell mac80211 and its clients (e.g. Wireless Extensions) - * the range of signal quality values that we'll provide. - * Negative values for level/noise indicate that we'll provide dBm. - * For WE, at least, non-0 values here *enable* display of values - * in app (iwconfig). */ - hw->max_rssi = -20; /* signal level, negative indicates dBm */ - hw->max_noise = -20; /* noise level, negative indicates dBm */ - hw->max_signal = 100; /* link quality indication (%) */ - - /* Tell mac80211 our Tx characteristics */ - hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE; - - /* Default value; 4 EDCA QOS priorities */ - hw->queues = 4; -#ifdef CONFIG_IWL4965_HT - /* Enhanced value; more queues, to support 11n aggregation */ - hw->queues = 16; -#endif /* CONFIG_IWL4965_HT */ - - hw->rate_control_algorithm = "iwl-4965-rs"; - priv->antenna = (enum iwl4965_antenna)iwl4965_mod_params.antenna; - priv->retry_rate = 1; - priv->ibss_beacon = NULL; - - spin_lock_init(&priv->lock); - spin_lock_init(&priv->power_data.lock); - spin_lock_init(&priv->sta_lock); - spin_lock_init(&priv->hcmd_lock); - spin_lock_init(&priv->lq_mngr.lock); - - for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++) - INIT_LIST_HEAD(&priv->ibss_mac_hash[i]); - - INIT_LIST_HEAD(&priv->free_frames); - - mutex_init(&priv->mutex); - - /* Clear the driver's (not device's) station table */ - iwl4965_clear_stations_table(priv); - - priv->data_retry_limit = -1; - priv->ieee_channels = NULL; - priv->ieee_rates = NULL; - priv->band = IEEE80211_BAND_2GHZ; - - priv->iw_mode = IEEE80211_IF_TYPE_STA; - - priv->use_ant_b_for_management_frame = 1; /* start with ant B */ - priv->valid_antenna = 0x7; /* assume all 3 connected */ - priv->ps_mode = IWL_MIMO_PS_NONE; - - /* Choose which receivers/antennas to use */ - iwl4965_set_rxon_chain(priv); - - iwl4965_reset_qos(priv); - - priv->qos_data.qos_active = 0; - priv->qos_data.qos_cap.val = 0; - - iwl4965_set_rxon_channel(priv, IEEE80211_BAND_2GHZ, 6); - - priv->rates_mask = IWL_RATES_MASK; - /* If power management is turned on, default to AC mode */ - priv->power_mode = IWL_POWER_AC; - priv->user_txpower_limit = IWL_DEFAULT_TX_POWER; - - err = iwl4965_init_channel_map(priv); - if (err) { - IWL_ERROR("initializing regulatory failed: %d\n", err); + err = iwl_setup(priv); + if (err) goto out_unset_hw_settings; - } - - err = iwl4965_init_geos(priv); - if (err) { - IWL_ERROR("initializing geos failed: %d\n", err); - goto out_free_channel_map; - } - - iwl4965_rate_control_register(priv->hw); - err = ieee80211_register_hw(priv->hw); - if (err) { - IWL_ERROR("Failed to register network device (error %d)\n", err); - goto out_free_geos; - } - - priv->hw->conf.beacon_int = 100; - priv->mac80211_registered = 1; + /* At this point both hw and priv are initialized. */ /********************************** * 7. Initialize module parameters @@ -8743,7 +8216,7 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e err = sysfs_create_group(&pdev->dev.kobj, &iwl4965_attribute_group); if (err) { IWL_ERROR("failed to create sysfs device attributes\n"); - goto out_free_geos; + goto out_unset_hw_settings; } err = iwl_dbgfs_register(priv, DRV_NAME); @@ -8765,10 +8238,6 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e out_remove_sysfs: sysfs_remove_group(&pdev->dev.kobj, &iwl4965_attribute_group); - out_free_geos: - iwl4965_free_geos(priv); - out_free_channel_map: - iwl4965_free_channel_map(priv); out_unset_hw_settings: iwl4965_unset_hw_setting(priv); out_iounmap: @@ -8817,7 +8286,7 @@ static void iwl4965_pci_remove(struct pci_dev *pdev) iwl4965_hw_txq_ctx_free(priv); iwl4965_unset_hw_setting(priv); - iwl4965_clear_stations_table(priv); + iwlcore_clear_stations_table(priv); if (priv->mac80211_registered) { ieee80211_unregister_hw(priv->hw); @@ -8838,7 +8307,7 @@ static void iwl4965_pci_remove(struct pci_dev *pdev) pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); - iwl4965_free_channel_map(priv); + iwl_free_channel_map(priv); iwl4965_free_geos(priv); if (priv->ibss_beacon) -- cgit v1.2.1 From deb09c435e3f947f8b2c9d5df6a9c0a5b472b125 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Wed, 19 Mar 2008 16:41:41 -0700 Subject: iwlwifi-2.6: Cleans up set_key flow This patch cleans up the set_key flow. Rxon with hw encryption bit set is not sent upon each call to set_key. Separation is made between global key (WEP) and dynamic key (TKIP + CCMP and WEP in some cases). Signed-off-by: Emmanuel Grumbach Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965-commands.h | 1 + drivers/net/wireless/iwlwifi/iwl4965-base.c | 165 +++++++++++++++-------- 2 files changed, 110 insertions(+), 56 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h index 1025ffeb8fa8..085d8137bfb8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h @@ -741,6 +741,7 @@ struct iwl4965_qosparam_cmd { /* wep key in STA: 5-bytes (0) or 13-bytes (1) */ #define STA_KEY_FLG_KEY_SIZE_MSK __constant_cpu_to_le16(0x1000) #define STA_KEY_MULTICAST_MSK __constant_cpu_to_le16(0x4000) +#define STA_KEY_MAX_NUM 8 /* Flags indicate whether to modify vs. don't change various station params */ #define STA_MODIFY_KEY_MASK 0x01 diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 9cf1f204666d..fc3e23a2d8eb 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -796,6 +796,17 @@ out: return ret; } +static void iwl4965_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt) +{ + struct iwl4965_rxon_cmd *rxon = &priv->staging_rxon; + + if (hw_decrypt) + rxon->filter_flags &= ~RXON_FILTER_DIS_DECRYPT_MSK; + else + rxon->filter_flags |= RXON_FILTER_DIS_DECRYPT_MSK; + +} + int iwl4965_send_cmd(struct iwl_priv *priv, struct iwl4965_host_cmd *cmd) { if (cmd->meta.flags & CMD_ASYNC) @@ -1124,6 +1135,7 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv) le16_to_cpu(priv->staging_rxon.channel), print_mac(mac, priv->staging_rxon.bssid_addr)); + iwl4965_set_rxon_hwcrypto(priv, priv->cfg->mod_params->hw_crypto); /* Apply the new configuration */ rc = iwl4965_send_cmd_pdu(priv, REPLY_RXON, sizeof(struct iwl4965_rxon_cmd), &priv->staging_rxon); @@ -1336,33 +1348,36 @@ int iwl4965_send_add_station(struct iwl_priv *priv, return rc; } -static int iwl4965_update_sta_key_info(struct iwl_priv *priv, +static int iwl4965_set_ccmp_dynamic_key_info(struct iwl_priv *priv, struct ieee80211_key_conf *keyconf, u8 sta_id) { unsigned long flags; __le16 key_flags = 0; - switch (keyconf->alg) { - case ALG_CCMP: - key_flags |= STA_KEY_FLG_CCMP; - key_flags |= cpu_to_le16( - keyconf->keyidx << STA_KEY_FLG_KEYID_POS); - key_flags &= ~STA_KEY_FLG_INVALID; - break; - case ALG_TKIP: - case ALG_WEP: - default: - return -EINVAL; - } + key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK); + key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); + + if (sta_id == priv->hw_setting.bcast_sta_id) + key_flags |= STA_KEY_MULTICAST_MSK; + + keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; + keyconf->hw_key_idx = keyconf->keyidx; + + key_flags &= ~STA_KEY_FLG_INVALID; + spin_lock_irqsave(&priv->sta_lock, flags); priv->stations[sta_id].keyinfo.alg = keyconf->alg; priv->stations[sta_id].keyinfo.keylen = keyconf->keylen; + memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, keyconf->keylen); memcpy(priv->stations[sta_id].sta.key.key, keyconf->key, keyconf->keylen); + + priv->stations[sta_id].sta.key.key_offset + = (sta_id % STA_KEY_MAX_NUM);/*FIXME*/ priv->stations[sta_id].sta.key.key_flags = key_flags; priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; @@ -1370,8 +1385,15 @@ static int iwl4965_update_sta_key_info(struct iwl_priv *priv, spin_unlock_irqrestore(&priv->sta_lock, flags); IWL_DEBUG_INFO("hwcrypto: modify ucode station key info\n"); - iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, 0); - return 0; + return iwl4965_send_add_station(priv, + &priv->stations[sta_id].sta, CMD_ASYNC); +} + +static int iwl4965_set_tkip_dynamic_key_info(struct iwl_priv *priv, + struct ieee80211_key_conf *keyconf, + u8 sta_id) +{ + return -EOPNOTSUPP; } static int iwl4965_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id) @@ -1391,6 +1413,46 @@ static int iwl4965_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id) return 0; } +static int iwl4965_set_dynamic_key(struct iwl_priv *priv, + struct ieee80211_key_conf *key, u8 sta_id) +{ + int ret; + + switch (key->alg) { + case ALG_CCMP: + ret = iwl4965_set_ccmp_dynamic_key_info(priv, key, sta_id); + break; + case ALG_TKIP: + ret = iwl4965_set_tkip_dynamic_key_info(priv, key, sta_id); + break; + case ALG_WEP: + ret = -EOPNOTSUPP; + break; + default: + IWL_ERROR("Unknown alg: %s alg = %d\n", __func__, key->alg); + ret = -EINVAL; + } + + return ret; +} + +static int iwl4965_remove_static_key(struct iwl_priv *priv) +{ + int ret = -EOPNOTSUPP; + + return ret; +} + +static int iwl4965_set_static_key(struct iwl_priv *priv, + struct ieee80211_key_conf *key) +{ + if (key->alg == ALG_WEP) + return -EOPNOTSUPP; + + IWL_ERROR("Static key invalid: alg %d\n", key->alg); + return -EINVAL; +} + static void iwl4965_clear_free_frames(struct iwl_priv *priv) { struct list_head *element; @@ -2122,17 +2184,6 @@ static int iwl4965_scan_initiate(struct iwl_priv *priv) return 0; } -static int iwl4965_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt) -{ - struct iwl4965_rxon_cmd *rxon = &priv->staging_rxon; - - if (hw_decrypt) - rxon->filter_flags &= ~RXON_FILTER_DIS_DECRYPT_MSK; - else - rxon->filter_flags |= RXON_FILTER_DIS_DECRYPT_MSK; - - return 0; -} static void iwl4965_set_flags_for_phymode(struct iwl_priv *priv, enum ieee80211_band band) @@ -2276,9 +2327,9 @@ static void iwl4965_build_tx_cmd_hwcrypto(struct iwl_priv *priv, struct ieee80211_tx_control *ctl, struct iwl4965_cmd *cmd, struct sk_buff *skb_frag, - int last_frag) + int sta_id) { - struct iwl4965_hw_key *keyinfo = &priv->stations[ctl->key_idx].keyinfo; + struct iwl4965_hw_key *keyinfo = &priv->stations[sta_id].keyinfo; switch (keyinfo->alg) { case ALG_CCMP: @@ -2614,7 +2665,7 @@ static int iwl4965_tx_skb(struct iwl_priv *priv, iwl4965_hw_txq_attach_buf_to_tfd(priv, tfd, txcmd_phys, len); if (!(ctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT)) - iwl4965_build_tx_cmd_hwcrypto(priv, ctl, out_cmd, skb, 0); + iwl4965_build_tx_cmd_hwcrypto(priv, ctl, out_cmd, skb, sta_id); /* Set up TFD's 2nd entry to point directly to remainder of skb, * if any (802.11 null frames have no payload). */ @@ -7121,8 +7172,9 @@ static int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, { struct iwl_priv *priv = hw->priv; DECLARE_MAC_BUF(mac); - int rc = 0; - u8 sta_id; + int ret = 0; + u8 sta_id = IWL_INVALID_STATION; + u8 static_key; IWL_DEBUG_MAC80211("enter\n"); @@ -7135,44 +7187,45 @@ static int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, /* only support pairwise keys */ return -EOPNOTSUPP; - sta_id = iwl4965_hw_find_station(priv, addr); - if (sta_id == IWL_INVALID_STATION) { - IWL_DEBUG_MAC80211("leave - %s not in station map.\n", - print_mac(mac, addr)); - return -EINVAL; - } + /* FIXME: need to differenciate between static and dynamic key + * in the level of mac80211 */ + static_key = !iwl4965_is_associated(priv); - mutex_lock(&priv->mutex); + if (!static_key) { + sta_id = iwl4965_hw_find_station(priv, addr); + if (sta_id == IWL_INVALID_STATION) { + IWL_DEBUG_MAC80211("leave - %s not in station map.\n", + print_mac(mac, addr)); + return -EINVAL; + } + } iwl4965_scan_cancel_timeout(priv, 100); switch (cmd) { - case SET_KEY: - rc = iwl4965_update_sta_key_info(priv, key, sta_id); - if (!rc) { - iwl4965_set_rxon_hwcrypto(priv, 1); - iwl4965_commit_rxon(priv); - key->hw_key_idx = sta_id; - IWL_DEBUG_MAC80211("set_key success, using hwcrypto\n"); - key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; - } + case SET_KEY: + if (static_key) + ret = iwl4965_set_static_key(priv, key); + else + ret = iwl4965_set_dynamic_key(priv, key, sta_id); + + IWL_DEBUG_MAC80211("enable hwcrypto key\n"); break; case DISABLE_KEY: - rc = iwl4965_clear_sta_key_info(priv, sta_id); - if (!rc) { - iwl4965_set_rxon_hwcrypto(priv, 0); - iwl4965_commit_rxon(priv); - IWL_DEBUG_MAC80211("disable hwcrypto key\n"); - } + if (static_key) + ret = iwl4965_remove_static_key(priv); + else + ret = iwl4965_clear_sta_key_info(priv, sta_id); + + IWL_DEBUG_MAC80211("disable hwcrypto key\n"); break; default: - rc = -EINVAL; + ret = -EINVAL; } IWL_DEBUG_MAC80211("leave\n"); - mutex_unlock(&priv->mutex); - return rc; + return ret; } static int iwl4965_mac_conf_tx(struct ieee80211_hw *hw, int queue, -- cgit v1.2.1 From 17e476b8db13790c03e2c46d93abc71468fca47e Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Wed, 19 Mar 2008 16:41:42 -0700 Subject: iwlwifi-2.6: RX status translation to old scheme This patch adds translation for the RX status of an incoming packet. The incoming status has to be translated to the old scheme in order to know if the decryption has been done, MIC failure has occured, TTAK is valid etc... This translation is mandatory for all RX packets when using 5300 and for all HT packets using 4965. Signed-off-by: Emmanuel Grumbach Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965-commands.h | 9 ++++ drivers/net/wireless/iwlwifi/iwl-4965.c | 66 ++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl4965-base.c | 6 +++ 3 files changed, 81 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h index 085d8137bfb8..1d82f105cc26 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h @@ -890,6 +890,10 @@ struct iwl4965_rx_frame_hdr { #define RX_RES_STATUS_SEC_TYPE_WEP (0x1 << 8) #define RX_RES_STATUS_SEC_TYPE_CCMP (0x2 << 8) #define RX_RES_STATUS_SEC_TYPE_TKIP (0x3 << 8) +#define RX_RES_STATUS_SEC_TYPE_ERR (0x7 << 8) + +#define RX_RES_STATUS_STATION_FOUND (1<<6) +#define RX_RES_STATUS_NO_STATION_INFO_MISMATCH (1<<7) #define RX_RES_STATUS_DECRYPT_TYPE_MSK (0x3 << 11) #define RX_RES_STATUS_NOT_DECRYPT (0x0 << 11) @@ -897,6 +901,11 @@ struct iwl4965_rx_frame_hdr { #define RX_RES_STATUS_BAD_ICV_MIC (0x1 << 11) #define RX_RES_STATUS_BAD_KEY_TTAK (0x2 << 11) +#define RX_MPDU_RES_STATUS_ICV_OK (0x20) +#define RX_MPDU_RES_STATUS_MIC_OK (0x40) +#define RX_MPDU_RES_STATUS_TTAK_OK (1 << 7) +#define RX_MPDU_RES_STATUS_DEC_DONE_MSK (0x800) + struct iwl4965_rx_frame_end { __le32 status; __le64 timestamp; diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 8b2d04ed43d6..03c032e9b581 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -3393,6 +3393,65 @@ static void iwl_update_rx_stats(struct iwl_priv *priv, u16 fc, u16 len) priv->rx_stats[idx].bytes += len; } +static u32 iwl4965_translate_rx_status(u32 decrypt_in) +{ + u32 decrypt_out = 0; + + if ((decrypt_in & RX_RES_STATUS_STATION_FOUND) == + RX_RES_STATUS_STATION_FOUND) + decrypt_out |= (RX_RES_STATUS_STATION_FOUND | + RX_RES_STATUS_NO_STATION_INFO_MISMATCH); + + decrypt_out |= (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK); + + /* packet was not encrypted */ + if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) == + RX_RES_STATUS_SEC_TYPE_NONE) + return decrypt_out; + + /* packet was encrypted with unknown alg */ + if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) == + RX_RES_STATUS_SEC_TYPE_ERR) + return decrypt_out; + + /* decryption was not done in HW */ + if ((decrypt_in & RX_MPDU_RES_STATUS_DEC_DONE_MSK) != + RX_MPDU_RES_STATUS_DEC_DONE_MSK) + return decrypt_out; + + switch (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) { + + case RX_RES_STATUS_SEC_TYPE_CCMP: + /* alg is CCM: check MIC only */ + if (!(decrypt_in & RX_MPDU_RES_STATUS_MIC_OK)) + /* Bad MIC */ + decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC; + else + decrypt_out |= RX_RES_STATUS_DECRYPT_OK; + + break; + + case RX_RES_STATUS_SEC_TYPE_TKIP: + if (!(decrypt_in & RX_MPDU_RES_STATUS_TTAK_OK)) { + /* Bad TTAK */ + decrypt_out |= RX_RES_STATUS_BAD_KEY_TTAK; + break; + } + /* fall through if TTAK OK */ + default: + if (!(decrypt_in & RX_MPDU_RES_STATUS_ICV_OK)) + decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC; + else + decrypt_out |= RX_RES_STATUS_DECRYPT_OK; + break; + }; + + IWL_DEBUG_RX("decrypt_in:0x%x decrypt_out = 0x%x\n", + decrypt_in, decrypt_out); + + return decrypt_out; +} + static void iwl4965_handle_data_packet(struct iwl_priv *priv, int is_data, int include_phy, struct iwl4965_rx_mem_buffer *rxb, @@ -3406,6 +3465,7 @@ static void iwl4965_handle_data_packet(struct iwl_priv *priv, int is_data, __le32 *rx_end; unsigned int skblen; u32 ampdu_status; + u32 ampdu_status_legacy; if (!include_phy && priv->last_phy_res[0]) rx_start = (struct iwl4965_rx_phy_res *)&priv->last_phy_res[1]; @@ -3442,6 +3502,12 @@ static void iwl4965_handle_data_packet(struct iwl_priv *priv, int is_data, ampdu_status = le32_to_cpu(*rx_end); skblen = ((u8 *) rx_end - (u8 *) & pkt->u.raw[0]) + sizeof(u32); + if (!include_phy) { + /* New status scheme, need to translate */ + ampdu_status_legacy = ampdu_status; + ampdu_status = iwl4965_translate_rx_status(ampdu_status); + } + /* start from MAC */ skb_reserve(rxb->skb, (void *)hdr - (void *)pkt); skb_put(rxb->skb, len); /* end where data ends */ diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index fc3e23a2d8eb..8de301d1da8e 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -2856,6 +2856,12 @@ void iwl4965_set_decrypted_flag(struct iwl_priv *priv, struct sk_buff *skb, IWL_DEBUG_RX("decrypt_res:0x%x\n", decrypt_res); switch (decrypt_res & RX_RES_STATUS_SEC_TYPE_MSK) { case RX_RES_STATUS_SEC_TYPE_TKIP: + /* The uCode has got a bad phase 1 Key, pushes the packet. + * Decryption will be done in SW. */ + if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) == + RX_RES_STATUS_BAD_KEY_TTAK) + break; + if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) == RX_RES_STATUS_BAD_ICV_MIC) stats->flag |= RX_FLAG_MMIC_ERROR; -- cgit v1.2.1 From 2bc750899f2b1da010625d064ad46dc3a8e9a372 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Wed, 19 Mar 2008 16:41:45 -0700 Subject: iwlwifi-2.6: enables HW TKIP encryption This patch add support for TKIP encryption (TX) in HW. Signed-off-by: Emmanuel Grumbach Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965.h | 1 + drivers/net/wireless/iwlwifi/iwl4965-base.c | 33 +++++++++++++++++++++-------- 2 files changed, 25 insertions(+), 9 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index 7baed4db2f3f..1d7e8f9cf5ee 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -481,6 +481,7 @@ struct iwl4965_tid_data { struct iwl4965_hw_key { enum ieee80211_key_alg alg; int keylen; + struct ieee80211_key_conf *conf; u8 key[32]; }; diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 8de301d1da8e..ae8fc8cb4d18 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -1393,7 +1393,27 @@ static int iwl4965_set_tkip_dynamic_key_info(struct iwl_priv *priv, struct ieee80211_key_conf *keyconf, u8 sta_id) { - return -EOPNOTSUPP; + unsigned long flags; + int ret = 0; + + keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; + keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; + keyconf->hw_key_idx = keyconf->keyidx; + + spin_lock_irqsave(&priv->sta_lock, flags); + + priv->stations[sta_id].keyinfo.alg = keyconf->alg; + priv->stations[sta_id].keyinfo.conf = keyconf; + priv->stations[sta_id].keyinfo.keylen = 16; + + /* This copy is acutally not needed: we get the key with each TX */ + memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, 16); + + memcpy(priv->stations[sta_id].sta.key.key, keyconf->key, 16); + + spin_unlock_irqrestore(&priv->sta_lock, flags); + + return ret; } static int iwl4965_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id) @@ -2341,15 +2361,10 @@ static void iwl4965_build_tx_cmd_hwcrypto(struct iwl_priv *priv, break; case ALG_TKIP: -#if 0 cmd->cmd.tx.sec_ctl = TX_CMD_SEC_TKIP; - - if (last_frag) - memcpy(cmd->cmd.tx.tkip_mic.byte, skb_frag->tail - 8, - 8); - else - memset(cmd->cmd.tx.tkip_mic.byte, 0, 8); -#endif + ieee80211_get_tkip_key(keyinfo->conf, skb_frag, + IEEE80211_TKIP_P2_KEY, cmd->cmd.tx.key); + IWL_DEBUG_TX("tx_cmd with tkip hwcrypto\n"); break; case ALG_WEP: -- cgit v1.2.1 From ab885f8c45373dfaaa3ad251f38b4240c40b2eae Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 20 Mar 2008 15:06:43 +0200 Subject: iwlwifi-2.6: enables RX TKIP decryption in HW This patch enables RX TKIP decryption in HW. Signed-off-by: Emmanuel Grumbach Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl4965-base.c | 51 +++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index ae8fc8cb4d18..bd5375984045 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -7187,6 +7187,56 @@ out_unlock: return rc; } +static void iwl4965_mac_update_tkip_key(struct ieee80211_hw *hw, + struct ieee80211_key_conf *keyconf, const u8 *addr, + u32 iv32, u16 *phase1key) +{ + struct iwl_priv *priv = hw->priv; + u8 sta_id = IWL_INVALID_STATION; + unsigned long flags; + __le16 key_flags = 0; + int i; + DECLARE_MAC_BUF(mac); + + IWL_DEBUG_MAC80211("enter\n"); + + sta_id = iwl4965_hw_find_station(priv, addr); + if (sta_id == IWL_INVALID_STATION) { + IWL_DEBUG_MAC80211("leave - %s not in station map.\n", + print_mac(mac, addr)); + return; + } + + iwl4965_scan_cancel_timeout(priv, 100); + + key_flags |= (STA_KEY_FLG_TKIP | STA_KEY_FLG_MAP_KEY_MSK); + key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); + key_flags &= ~STA_KEY_FLG_INVALID; + + if (sta_id == priv->hw_setting.bcast_sta_id) + key_flags |= STA_KEY_MULTICAST_MSK; + + spin_lock_irqsave(&priv->sta_lock, flags); + + priv->stations[sta_id].sta.key.key_offset = + (sta_id % STA_KEY_MAX_NUM);/* FIXME */ + priv->stations[sta_id].sta.key.key_flags = key_flags; + priv->stations[sta_id].sta.key.tkip_rx_tsc_byte2 = (u8) iv32; + + for (i = 0; i < 5; i++) + priv->stations[sta_id].sta.key.tkip_rx_ttak[i] = + cpu_to_le16(phase1key[i]); + + priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; + priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; + + iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, CMD_ASYNC); + + spin_unlock_irqrestore(&priv->sta_lock, flags); + + IWL_DEBUG_MAC80211("leave\n"); +} + static int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, const u8 *local_addr, const u8 *addr, struct ieee80211_key_conf *key) @@ -8128,6 +8178,7 @@ static struct ieee80211_ops iwl4965_hw_ops = { .config_interface = iwl4965_mac_config_interface, .configure_filter = iwl4965_configure_filter, .set_key = iwl4965_mac_set_key, + .update_tkip_key = iwl4965_mac_update_tkip_key, .get_stats = iwl4965_mac_get_stats, .get_tx_stats = iwl4965_mac_get_tx_stats, .conf_tx = iwl4965_mac_conf_tx, -- cgit v1.2.1 From 410e088d53e40c8133f6f666992859cd0dd21ff5 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Fri, 21 Mar 2008 13:53:42 -0700 Subject: iwlwifi: iwl3945 remove 4965 commands This patch removes 4965 host commands from iwl-3945-commands.h Signed-off-by: Tomas Winkler Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-commands.h | 39 ------------------------ 1 file changed, 39 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-commands.h b/drivers/net/wireless/iwlwifi/iwl-3945-commands.h index 824a6e532de7..817ece773643 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-commands.h @@ -707,45 +707,6 @@ struct iwl3945_rx_frame { struct iwl3945_rx_frame_end end; } __attribute__ ((packed)); -/* Fixed (non-configurable) rx data from phy */ -#define RX_PHY_FLAGS_ANTENNAE_OFFSET (4) -#define RX_PHY_FLAGS_ANTENNAE_MASK (0x70) -#define IWL_AGC_DB_MASK (0x3f80) /* MASK(7,13) */ -#define IWL_AGC_DB_POS (7) -struct iwl4965_rx_non_cfg_phy { - __le16 ant_selection; /* ant A bit 4, ant B bit 5, ant C bit 6 */ - __le16 agc_info; /* agc code 0:6, agc dB 7:13, reserved 14:15 */ - u8 rssi_info[6]; /* we use even entries, 0/2/4 for A/B/C rssi */ - u8 pad[0]; -} __attribute__ ((packed)); - -/* - * REPLY_4965_RX = 0xc3 (response only, not a command) - * Used only for legacy (non 11n) frames. - */ -#define RX_RES_PHY_CNT 14 -struct iwl4965_rx_phy_res { - u8 non_cfg_phy_cnt; /* non configurable DSP phy data byte count */ - u8 cfg_phy_cnt; /* configurable DSP phy data byte count */ - u8 stat_id; /* configurable DSP phy data set ID */ - u8 reserved1; - __le64 timestamp; /* TSF at on air rise */ - __le32 beacon_time_stamp; /* beacon at on-air rise */ - __le16 phy_flags; /* general phy flags: band, modulation, ... */ - __le16 channel; /* channel number */ - __le16 non_cfg_phy[RX_RES_PHY_CNT]; /* upto 14 phy entries */ - __le32 reserved2; - __le32 rate_n_flags; - __le16 byte_count; /* frame's byte-count */ - __le16 reserved3; -} __attribute__ ((packed)); - -struct iwl4965_rx_mpdu_res_start { - __le16 byte_count; - __le16 reserved; -} __attribute__ ((packed)); - - /****************************************************************************** * (5) * Tx Commands & Responses: -- cgit v1.2.1 From 8622e7058a8764223ae2305d980a38d07f034717 Mon Sep 17 00:00:00 2001 From: Assaf Krauss Date: Fri, 21 Mar 2008 13:53:43 -0700 Subject: iwlwifi: rename iwl4965_get_channel_info to iwl_get_channel_info iwl4965_get_channel_info was moved to iwlcore module 4965 needs to be stripped off Signed-off-by: Assaf Krauss Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965.c | 6 +++--- drivers/net/wireless/iwlwifi/iwl-4965.h | 2 +- drivers/net/wireless/iwlwifi/iwl-core.c | 2 +- drivers/net/wireless/iwlwifi/iwl-eeprom.c | 6 +++--- drivers/net/wireless/iwlwifi/iwl-eeprom.h | 2 +- drivers/net/wireless/iwlwifi/iwl4965-base.c | 8 ++++---- 6 files changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 03c032e9b581..c0c35d38cf5e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2056,7 +2056,7 @@ iwl4965_get_channel_txpower_info(struct iwl_priv *priv, { const struct iwl_channel_info *ch_info; - ch_info = iwl4965_get_channel_info(priv, band, channel); + ch_info = iwl_get_channel_info(priv, band, channel); if (!is_channel_valid(ch_info)) return NULL; @@ -2764,7 +2764,7 @@ int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel) band = priv->band == IEEE80211_BAND_2GHZ; - ch_info = iwl4965_get_channel_info(priv, priv->band, channel); + ch_info = iwl_get_channel_info(priv, priv->band, channel); is_fat = is_fat_channel(priv->staging_rxon.flags); @@ -4574,7 +4574,7 @@ static u8 iwl4965_is_channel_extension(struct iwl_priv *priv, { const struct iwl_channel_info *ch_info; - ch_info = iwl4965_get_channel_info(priv, band, channel); + ch_info = iwl_get_channel_info(priv, band, channel); if (!is_channel_valid(ch_info)) return 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index 1d7e8f9cf5ee..b73c1544e909 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -1264,7 +1264,7 @@ static inline int is_channel_ibss(const struct iwl_channel_info *ch) return ((ch->flags & EEPROM_CHANNEL_IBSS)) ? 1 : 0; } -extern const struct iwl_channel_info *iwl4965_get_channel_info( +extern const struct iwl_channel_info *iwl_get_channel_info( const struct iwl_priv *priv, enum ieee80211_band band, u16 channel); /* Requires full declaration of iwl_priv before including */ diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 0e9c3b3d98ce..da51349cbd8b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -191,7 +191,7 @@ int iwlcore_set_rxon_channel(struct iwl_priv *priv, enum ieee80211_band band, u16 channel) { - if (!iwl4965_get_channel_info(priv, band, channel)) { + if (!iwl_get_channel_info(priv, band, channel)) { IWL_DEBUG_INFO("Could not set channel to %d [%d]\n", channel, band); return -EINVAL; diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index 32ebec35f2af..72cad56fbd93 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -329,7 +329,7 @@ static int iwl4965_set_fat_chan_info(struct iwl_priv *priv, struct iwl_channel_info *ch_info; ch_info = (struct iwl_channel_info *) - iwl4965_get_channel_info(priv, band, channel); + iwl_get_channel_info(priv, band, channel); if (!is_channel_valid(ch_info)) return -1; @@ -534,7 +534,7 @@ EXPORT_SYMBOL(iwl_free_channel_map); * * Based on band and channel number. */ -const struct iwl_channel_info *iwl4965_get_channel_info( +const struct iwl_channel_info *iwl_get_channel_info( const struct iwl_priv *priv, enum ieee80211_band band, u16 channel) { @@ -557,5 +557,5 @@ const struct iwl_channel_info *iwl4965_get_channel_info( return NULL; } -EXPORT_SYMBOL(iwl4965_get_channel_info); +EXPORT_SYMBOL(iwl_get_channel_info); diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h index 8a583947b2c7..bd0a042ca77f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h @@ -368,7 +368,7 @@ void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv); int iwl_init_channel_map(struct iwl_priv *priv); void iwl_free_channel_map(struct iwl_priv *priv); -const struct iwl_channel_info *iwl4965_get_channel_info( +const struct iwl_channel_info *iwl_get_channel_info( const struct iwl_priv *priv, enum ieee80211_band band, u16 channel); diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index bd5375984045..fac9bf1aa1d7 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -2271,7 +2271,7 @@ static void iwl4965_connection_init_rx_config(struct iwl_priv *priv) priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; #endif - ch_info = iwl4965_get_channel_info(priv, priv->band, + ch_info = iwl_get_channel_info(priv, priv->band, le16_to_cpu(priv->staging_rxon.channel)); if (!ch_info) @@ -2309,7 +2309,7 @@ static int iwl4965_set_mode(struct iwl_priv *priv, int mode) if (mode == IEEE80211_IF_TYPE_IBSS) { const struct iwl_channel_info *ch_info; - ch_info = iwl4965_get_channel_info(priv, + ch_info = iwl_get_channel_info(priv, priv->band, le16_to_cpu(priv->staging_rxon.channel)); @@ -5021,7 +5021,7 @@ static int iwl4965_get_channels_for_scan(struct iwl_priv *priv, scan_ch->channel = ieee80211_frequency_to_channel(channels[i].center_freq); - ch_info = iwl4965_get_channel_info(priv, band, + ch_info = iwl_get_channel_info(priv, band, scan_ch->channel); if (!is_channel_valid(ch_info)) { IWL_DEBUG_SCAN("Channel %d is INVALID for this SKU.\n", @@ -6823,7 +6823,7 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co spin_lock_irqsave(&priv->lock, flags); - ch_info = iwl4965_get_channel_info(priv, conf->channel->band, + ch_info = iwl_get_channel_info(priv, conf->channel->band, ieee80211_frequency_to_channel(conf->channel->center_freq)); if (!is_channel_valid(ch_info)) { IWL_DEBUG_MAC80211("leave - invalid channel\n"); -- cgit v1.2.1 From 857485c0c46ceee5c658c1761bba4d9a5ddf433f Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Fri, 21 Mar 2008 13:53:44 -0700 Subject: iwlwifi: move host command sending functions to core module 1. Host command sending functions moved from iwl4965-base.c to iwl-hcmd.c in iwlcore module 2. enqueue_hcmd function currently stays in iwl4965-base.c. It is invoked through the new 'utils' field in priv's ops. Signed-off-by: Tomas Winkler Signed-off-by: Assaf Krauss Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/Makefile | 2 +- drivers/net/wireless/iwlwifi/iwl-4965-commands.h | 14 +- drivers/net/wireless/iwlwifi/iwl-4965-hw.h | 3 - drivers/net/wireless/iwlwifi/iwl-4965-rs.c | 7 +- drivers/net/wireless/iwlwifi/iwl-4965.c | 86 +++---- drivers/net/wireless/iwlwifi/iwl-4965.h | 33 ++- drivers/net/wireless/iwlwifi/iwl-core.h | 26 ++ drivers/net/wireless/iwlwifi/iwl-hcmd.c | 251 +++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl4965-base.c | 299 ++++------------------- 9 files changed, 399 insertions(+), 322 deletions(-) create mode 100644 drivers/net/wireless/iwlwifi/iwl-hcmd.c (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 86ac1fc60bbb..6be8012a1743 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile @@ -1,5 +1,5 @@ obj-$(CONFIG_IWLCORE) += iwlcore.o -iwlcore-objs = iwl-core.o iwl-eeprom.o +iwlcore-objs = iwl-core.o iwl-eeprom.o iwl-hcmd.o ifeq ($(CONFIG_IWLWIFI_DEBUGFS),y) iwlcore-objs += iwl-debugfs.o diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h index 1d82f105cc26..7e36ecb27575 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h @@ -139,7 +139,7 @@ enum { REPLY_PHY_CALIBRATION_CMD = 0xb0, REPLY_RX_PHY_CMD = 0xc0, REPLY_RX_MPDU_CMD = 0xc1, - REPLY_4965_RX = 0xc3, + REPLY_RX = 0xc3, REPLY_COMPRESSED_BA = 0xc5, REPLY_MAX = 0xff }; @@ -151,16 +151,16 @@ enum { * *****************************************************************************/ -/* iwl4965_cmd_header flags value */ +/* iwl_cmd_header flags value */ #define IWL_CMD_FAILED_MSK 0x40 /** - * struct iwl4965_cmd_header + * struct iwl_cmd_header * * This header format appears in the beginning of each command sent from the * driver, and each response/notification received from uCode. */ -struct iwl4965_cmd_header { +struct iwl_cmd_header { u8 cmd; /* Command ID: REPLY_RXON, etc. */ u8 flags; /* IWL_CMD_* */ /* @@ -194,7 +194,7 @@ struct iwl4965_cmd_header { * 4965 rate_n_flags bit fields * * rate_n_flags format is used in following 4965 commands: - * REPLY_4965_RX (response only) + * REPLY_RX (response only) * REPLY_TX (both command and response) * REPLY_TX_LINK_QUALITY_CMD * @@ -939,7 +939,7 @@ struct iwl4965_rx_non_cfg_phy { } __attribute__ ((packed)); /* - * REPLY_4965_RX = 0xc3 (response only, not a command) + * REPLY_RX = 0xc3 (response only, not a command) * Used only for legacy (non 11n) frames. */ #define RX_RES_PHY_CNT 14 @@ -2664,7 +2664,7 @@ struct iwl4965_led_cmd { struct iwl4965_rx_packet { __le32 len; - struct iwl4965_cmd_header hdr; + struct iwl_cmd_header hdr; union { struct iwl4965_alive_resp alive_frame; struct iwl4965_rx_frame rx_frame; diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h index c66993eb5b6a..1898888e71f2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h @@ -113,9 +113,6 @@ #define TFD_TX_CMD_SLOTS 256 #define TFD_CMD_SLOTS 32 -#define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl4965_cmd) - \ - sizeof(struct iwl4965_cmd_meta)) - /* * RX related structures and functions */ diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c index 02990aeabab5..7d7ce7489ab5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c @@ -39,6 +39,7 @@ #include "../net/mac80211/ieee80211_rate.h" #include "iwl-4965.h" +#include "iwl-core.h" #include "iwl-helpers.h" #define RS_NAME "iwl-4965-rs" @@ -230,7 +231,7 @@ static s32 expected_tpt_mimo40MHzSGI[IWL_RATE_COUNT] = { }; static int iwl4965_lq_sync_callback(struct iwl_priv *priv, - struct iwl4965_cmd *cmd, struct sk_buff *skb) + struct iwl_cmd *cmd, struct sk_buff *skb) { /*We didn't cache the SKB; let the caller free it */ return 1; @@ -247,7 +248,7 @@ static int rs_send_lq_cmd(struct iwl_priv *priv, #ifdef CONFIG_IWLWIFI_DEBUG int i; #endif - struct iwl4965_host_cmd cmd = { + struct iwl_host_cmd cmd = { .id = REPLY_TX_LINK_QUALITY_CMD, .len = sizeof(struct iwl4965_link_quality_cmd), .meta.flags = flags, @@ -276,7 +277,7 @@ static int rs_send_lq_cmd(struct iwl_priv *priv, if (iwl4965_is_associated(priv) && priv->assoc_station_added && priv->lq_mngr.lq_ready) - return iwl4965_send_cmd(priv, &cmd); + return iwl_send_cmd(priv, &cmd); return 0; } diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index c0c35d38cf5e..46b3f47edefd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -861,7 +861,7 @@ void iwl4965_rf_kill_ct_config(struct iwl_priv *priv) u32 temp_th; u32 crit_temperature; unsigned long flags; - int rc = 0; + int ret = 0; spin_lock_irqsave(&priv->lock, flags); iwl4965_write32(priv, CSR_UCODE_DRV_GP1_CLR, @@ -882,9 +882,9 @@ void iwl4965_rf_kill_ct_config(struct iwl_priv *priv) crit_temperature = ((temp_th * (R3-R1))/CT_LIMIT_CONST) + R2; cmd.critical_temperature_R = cpu_to_le32(crit_temperature); - rc = iwl4965_send_cmd_pdu(priv, - REPLY_CT_KILL_CONFIG_CMD, sizeof(cmd), &cmd); - if (rc) + ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD, + sizeof(cmd), &cmd); + if (ret) IWL_ERROR("REPLY_CT_KILL_CONFIG_CMD failed\n"); else IWL_DEBUG_INFO("REPLY_CT_KILL_CONFIG_CMD succeeded\n"); @@ -1157,7 +1157,7 @@ static int iwl4965_sens_auto_corr_ofdm(struct iwl_priv *priv, } static int iwl4965_sensitivity_callback(struct iwl_priv *priv, - struct iwl4965_cmd *cmd, struct sk_buff *skb) + struct iwl_cmd *cmd, struct sk_buff *skb) { /* We didn't cache the SKB; let the caller free it */ return 1; @@ -1166,15 +1166,15 @@ static int iwl4965_sensitivity_callback(struct iwl_priv *priv, /* Prepare a SENSITIVITY_CMD, send to uCode if values have changed */ static int iwl4965_sensitivity_write(struct iwl_priv *priv, u8 flags) { - int rc = 0; struct iwl4965_sensitivity_cmd cmd ; struct iwl4965_sensitivity_data *data = NULL; - struct iwl4965_host_cmd cmd_out = { + struct iwl_host_cmd cmd_out = { .id = SENSITIVITY_CMD, .len = sizeof(struct iwl4965_sensitivity_cmd), .meta.flags = flags, .data = &cmd, }; + int ret; data = &(priv->sensitivity_data); @@ -1232,20 +1232,18 @@ static int iwl4965_sensitivity_write(struct iwl_priv *priv, u8 flags) memcpy(&(priv->sensitivity_tbl[0]), &(cmd.table[0]), sizeof(u16)*HD_TABLE_SIZE); - rc = iwl4965_send_cmd(priv, &cmd_out); - if (!rc) { - IWL_DEBUG_CALIB("SENSITIVITY_CMD succeeded\n"); - return rc; - } + ret = iwl_send_cmd(priv, &cmd_out); + if (ret) + IWL_ERROR("SENSITIVITY_CMD failed\n"); - return 0; + return ret; } void iwl4965_init_sensitivity(struct iwl_priv *priv, u8 flags, u8 force) { - int rc = 0; - int i; struct iwl4965_sensitivity_data *data = NULL; + int i; + int ret = 0; IWL_DEBUG_CALIB("Start iwl4965_init_sensitivity\n"); @@ -1289,8 +1287,8 @@ void iwl4965_init_sensitivity(struct iwl_priv *priv, u8 flags, u8 force) memset(&(priv->sensitivity_tbl[0]), 0, sizeof(u16)*HD_TABLE_SIZE); - rc |= iwl4965_sensitivity_write(priv, flags); - IWL_DEBUG_CALIB("<chain_noise_data); if ((data->state == IWL_CHAIN_NOISE_ALIVE) && iwl4965_is_associated(priv)) { @@ -1313,7 +1310,7 @@ void iwl4965_chain_noise_reset(struct iwl_priv *priv) cmd.diff_gain_a = 0; cmd.diff_gain_b = 0; cmd.diff_gain_c = 0; - rc = iwl4965_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD, + iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD, sizeof(cmd), &cmd); msleep(4); data->state = IWL_CHAIN_NOISE_ACCUMULATE; @@ -1332,7 +1329,7 @@ static void iwl4965_noise_calibration(struct iwl_priv *priv, struct iwl4965_notif_statistics *stat_resp) { struct iwl4965_chain_noise_data *data = NULL; - int rc = 0; + int ret = 0; u32 chain_noise_a; u32 chain_noise_b; @@ -1538,9 +1535,9 @@ static void iwl4965_noise_calibration(struct iwl_priv *priv, cmd.diff_gain_a = data->delta_gain_code[0]; cmd.diff_gain_b = data->delta_gain_code[1]; cmd.diff_gain_c = data->delta_gain_code[2]; - rc = iwl4965_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD, + ret = iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD, sizeof(cmd), &cmd); - if (rc) + if (ret) IWL_DEBUG_CALIB("fail sending cmd " "REPLY_PHY_CALIBRATION_CMD \n"); @@ -1564,7 +1561,6 @@ static void iwl4965_noise_calibration(struct iwl_priv *priv, static void iwl4965_sensitivity_calibration(struct iwl_priv *priv, struct iwl4965_notif_statistics *resp) { - int rc = 0; u32 rx_enable_time; u32 fa_cck; u32 fa_ofdm; @@ -1577,6 +1573,7 @@ static void iwl4965_sensitivity_calibration(struct iwl_priv *priv, struct statistics_rx *statistics = &(resp->rx); unsigned long flags; struct statistics_general_data statis; + int ret; data = &(priv->sensitivity_data); @@ -1661,7 +1658,7 @@ static void iwl4965_sensitivity_calibration(struct iwl_priv *priv, iwl4965_sens_auto_corr_ofdm(priv, norm_fa_ofdm, rx_enable_time); iwl4965_sens_energy_cck(priv, norm_fa_cck, rx_enable_time, &statis); - rc |= iwl4965_sensitivity_write(priv, CMD_ASYNC); + ret = iwl4965_sensitivity_write(priv, CMD_ASYNC); return; } @@ -1789,7 +1786,7 @@ int iwl4965_alive_notify(struct iwl_priv *priv) u32 a; int i = 0; unsigned long flags; - int rc; + int ret; spin_lock_irqsave(&priv->lock, flags); @@ -1802,10 +1799,10 @@ int iwl4965_alive_notify(struct iwl_priv *priv) priv->chain_noise_data.delta_gain_code[i] = CHAIN_NOISE_DELTA_GAIN_INIT_VAL; #endif /* CONFIG_IWL4965_SENSITIVITY*/ - rc = iwl4965_grab_nic_access(priv); - if (rc) { + ret = iwl4965_grab_nic_access(priv); + if (ret) { spin_unlock_irqrestore(&priv->lock, flags); - return rc; + return ret; } /* Clear 4965's internal Tx Scheduler data base */ @@ -1868,7 +1865,7 @@ int iwl4965_alive_notify(struct iwl_priv *priv) iwl4965_release_nic_access(priv); spin_unlock_irqrestore(&priv->lock, flags); - return 0; + return ret; } /** @@ -2719,7 +2716,7 @@ static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel, int iwl4965_hw_reg_send_txpower(struct iwl_priv *priv) { struct iwl4965_txpowertable_cmd cmd = { 0 }; - int rc = 0; + int ret; u8 band = 0; u8 is_fat = 0; u8 ctrl_chan_high = 0; @@ -2743,14 +2740,16 @@ int iwl4965_hw_reg_send_txpower(struct iwl_priv *priv) cmd.band = band; cmd.channel = priv->active_rxon.channel; - rc = iwl4965_fill_txpower_tbl(priv, band, + ret = iwl4965_fill_txpower_tbl(priv, band, le16_to_cpu(priv->active_rxon.channel), is_fat, ctrl_chan_high, &cmd.tx_power); - if (rc) - return rc; + if (ret) + goto out; - rc = iwl4965_send_cmd_pdu(priv, REPLY_TX_PWR_TABLE_CMD, sizeof(cmd), &cmd); - return rc; + ret = iwl_send_cmd_pdu(priv, REPLY_TX_PWR_TABLE_CMD, sizeof(cmd), &cmd); + +out: + return ret; } int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel) @@ -2790,7 +2789,7 @@ int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel) return rc; } - rc = iwl4965_send_cmd_pdu(priv, REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd); + rc = iwl_send_cmd_pdu(priv, REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd); return rc; } @@ -2798,7 +2797,7 @@ int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel) #define RTS_DFAULT_RETRY_LIMIT 60 void iwl4965_hw_build_tx_cmd_rate(struct iwl_priv *priv, - struct iwl4965_cmd *cmd, + struct iwl_cmd *cmd, struct ieee80211_tx_control *ctrl, struct ieee80211_hdr *hdr, int sta_id, int is_hcca) @@ -3863,7 +3862,7 @@ static inline void iwl4965_dbg_report_frame(struct iwl_priv *priv, #define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6) -/* Called for REPLY_4965_RX (legacy ABG frames), or +/* Called for REPLY_RX (legacy ABG frames), or * REPLY_RX_MPDU_CMD (HT high-throughput N frames). */ static void iwl4965_rx_reply_rx(struct iwl_priv *priv, struct iwl4965_rx_mem_buffer *rxb) @@ -3874,7 +3873,7 @@ static void iwl4965_rx_reply_rx(struct iwl_priv *priv, /* Use phy data (Rx signal strength, etc.) contained within * this rx packet for legacy frames, * or phy data cached from REPLY_RX_PHY_CMD for HT frames. */ - int include_phy = (pkt->hdr.cmd == REPLY_4965_RX); + int include_phy = (pkt->hdr.cmd == REPLY_RX); struct iwl4965_rx_phy_res *rx_start = (include_phy) ? (struct iwl4965_rx_phy_res *)&(pkt->u.raw[0]) : (struct iwl4965_rx_phy_res *)&priv->last_phy_res[1]; @@ -4562,7 +4561,7 @@ void iwl4965_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap) /* Update the rate scaling for control frame Tx to AP */ link_cmd.sta_id = is_ap ? IWL_AP_ID : priv->hw_setting.bcast_sta_id; - iwl4965_send_cmd_pdu(priv, REPLY_TX_LINK_QUALITY_CMD, sizeof(link_cmd), + iwl_send_cmd_pdu(priv, REPLY_TX_LINK_QUALITY_CMD, sizeof(link_cmd), &link_cmd); } @@ -4915,7 +4914,7 @@ int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw, void iwl4965_hw_rx_handler_setup(struct iwl_priv *priv) { /* Legacy Rx frames */ - priv->rx_handlers[REPLY_4965_RX] = iwl4965_rx_reply_rx; + priv->rx_handlers[REPLY_RX] = iwl4965_rx_reply_rx; /* High-throughput (HT) Rx frames */ priv->rx_handlers[REPLY_RX_PHY_CMD] = iwl4965_rx_reply_rx_phy; @@ -4948,6 +4947,10 @@ void iwl4965_hw_cancel_deferred_work(struct iwl_priv *priv) cancel_delayed_work(&priv->init_alive_start); } +static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = { + .enqueue_hcmd = iwl4965_enqueue_hcmd, +}; + static struct iwl_lib_ops iwl4965_lib = { .init_drv = iwl4965_init_drv, .eeprom_ops = { @@ -4959,6 +4962,7 @@ static struct iwl_lib_ops iwl4965_lib = { static struct iwl_ops iwl4965_ops = { .lib = &iwl4965_lib, + .utils = &iwl4965_hcmd_utils, }; static struct iwl_cfg iwl4965_agn_cfg = { diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index b73c1544e909..810b8e28dc83 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -140,7 +140,7 @@ struct iwl4965_tx_info { struct iwl4965_tx_queue { struct iwl4965_queue q; struct iwl4965_tfd_frame *bd; - struct iwl4965_cmd *cmd; + struct iwl_cmd *cmd; dma_addr_t dma_addr_cmd; struct iwl4965_tx_info *txb; int need_update; @@ -312,15 +312,15 @@ enum { CMD_WANT_SKB = (1 << 2), }; -struct iwl4965_cmd; +struct iwl_cmd; struct iwl_priv; -struct iwl4965_cmd_meta { - struct iwl4965_cmd_meta *source; +struct iwl_cmd_meta { + struct iwl_cmd_meta *source; union { struct sk_buff *skb; int (*callback)(struct iwl_priv *priv, - struct iwl4965_cmd *cmd, struct sk_buff *skb); + struct iwl_cmd *cmd, struct sk_buff *skb); } __attribute__ ((packed)) u; /* The CMD_SIZE_HUGE flag bit indicates that the command @@ -330,15 +330,15 @@ struct iwl4965_cmd_meta { } __attribute__ ((packed)); /** - * struct iwl4965_cmd + * struct iwl_cmd * * For allocation of the command and tx queues, this establishes the overall * size of the largest command we send to uCode, except for a scan command * (which is relatively huge; space is allocated separately). */ -struct iwl4965_cmd { - struct iwl4965_cmd_meta meta; /* driver data */ - struct iwl4965_cmd_header hdr; /* uCode API */ +struct iwl_cmd { + struct iwl_cmd_meta meta; /* driver data */ + struct iwl_cmd_header hdr; /* uCode API */ union { struct iwl4965_addsta_cmd addsta; struct iwl4965_led_cmd led; @@ -358,15 +358,15 @@ struct iwl4965_cmd { } __attribute__ ((packed)) cmd; } __attribute__ ((packed)); -struct iwl4965_host_cmd { +struct iwl_host_cmd { u8 id; u16 len; - struct iwl4965_cmd_meta meta; + struct iwl_cmd_meta meta; const void *data; }; -#define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl4965_cmd) - \ - sizeof(struct iwl4965_cmd_meta)) +#define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_cmd) - \ + sizeof(struct iwl_cmd_meta)) /* * RX related structures and functions @@ -656,10 +656,6 @@ extern int iwl4965_tx_queue_init(struct iwl_priv *priv, struct iwl4965_tx_queue *txq, int count, u32 id); extern void iwl4965_rx_replenish(void *data); extern void iwl4965_tx_queue_free(struct iwl_priv *priv, struct iwl4965_tx_queue *txq); -extern int iwl4965_send_cmd_pdu(struct iwl_priv *priv, u8 id, u16 len, - const void *data); -extern int __must_check iwl4965_send_cmd(struct iwl_priv *priv, - struct iwl4965_host_cmd *cmd); extern unsigned int iwl4965_fill_beacon_frame(struct iwl_priv *priv, struct ieee80211_hdr *hdr, const u8 *dest, int left); @@ -674,6 +670,7 @@ int iwl4965_init_geos(struct iwl_priv *priv); void iwl4965_free_geos(struct iwl_priv *priv); extern const u8 iwl4965_broadcast_addr[ETH_ALEN]; +int iwl4965_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd); /* * Currently used by iwl-3945-rs... look at restructuring so that it doesn't @@ -718,7 +715,7 @@ extern unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv, struct iwl4965_frame *frame, u8 rate); extern int iwl4965_hw_get_rx_read(struct iwl_priv *priv); extern void iwl4965_hw_build_tx_cmd_rate(struct iwl_priv *priv, - struct iwl4965_cmd *cmd, + struct iwl_cmd *cmd, struct ieee80211_tx_control *ctrl, struct ieee80211_hdr *hdr, int sta_id, int tx_id); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 4dde4d628a80..ce7f90ebf367 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -63,6 +63,13 @@ #ifndef __iwl_core_h__ #define __iwl_core_h__ +/************************ + * forward declarations * + ************************/ +struct iwl_host_cmd; +struct iwl_cmd; + + #define IWLWIFI_VERSION "1.2.26k" #define DRV_COPYRIGHT "Copyright(c) 2003-2008 Intel Corporation" @@ -75,6 +82,10 @@ #define IWL_SKU_A 0x2 #define IWL_SKU_N 0x8 +struct iwl_hcmd_utils_ops { + int (*enqueue_hcmd)(struct iwl_priv *priv, struct iwl_host_cmd *cmd); +}; + struct iwl_lib_ops { /* iwlwifi driver (priv) init */ int (*init_drv)(struct iwl_priv *priv); @@ -84,6 +95,7 @@ struct iwl_lib_ops { struct iwl_ops { const struct iwl_lib_ops *lib; + const struct iwl_hcmd_utils_ops *utils; }; struct iwl_mod_params { @@ -120,4 +132,18 @@ int iwlcore_set_rxon_channel(struct iwl_priv *priv, int iwl_setup(struct iwl_priv *priv); +/***************************************************** + * S e n d i n g H o s t C o m m a n d s * + *****************************************************/ + +const char *get_cmd_string(u8 cmd); +int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd); +int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd); +int iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u16 len, const void *data); +int iwl_send_cmd_pdu_async(struct iwl_priv *priv, u8 id, u16 len, + const void *data, + int (*callback)(struct iwl_priv *priv, + struct iwl_cmd *cmd, + struct sk_buff *skb)); + #endif /* __iwl_core_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c new file mode 100644 index 000000000000..559ff739961e --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c @@ -0,0 +1,251 @@ +/****************************************************************************** + * + * GPL LICENSE SUMMARY + * + * Copyright(c) 2008 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, + * USA + * + * The full GNU General Public License is included in this distribution + * in the file called LICENSE.GPL. + * + * Contact Information: + * Tomas Winkler + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + *****************************************************************************/ + +#include +#include +#include +#include + +#include "iwl-4965.h" /* FIXME: remove */ +#include "iwl-debug.h" +#include "iwl-eeprom.h" +#include "iwl-core.h" + + +#define IWL_CMD(x) case x : return #x + +const char *get_cmd_string(u8 cmd) +{ + switch (cmd) { + IWL_CMD(REPLY_ALIVE); + IWL_CMD(REPLY_ERROR); + IWL_CMD(REPLY_RXON); + IWL_CMD(REPLY_RXON_ASSOC); + IWL_CMD(REPLY_QOS_PARAM); + IWL_CMD(REPLY_RXON_TIMING); + IWL_CMD(REPLY_ADD_STA); + IWL_CMD(REPLY_REMOVE_STA); + IWL_CMD(REPLY_REMOVE_ALL_STA); + IWL_CMD(REPLY_TX); + IWL_CMD(REPLY_RATE_SCALE); + IWL_CMD(REPLY_LEDS_CMD); + IWL_CMD(REPLY_TX_LINK_QUALITY_CMD); + IWL_CMD(RADAR_NOTIFICATION); + IWL_CMD(REPLY_QUIET_CMD); + IWL_CMD(REPLY_CHANNEL_SWITCH); + IWL_CMD(CHANNEL_SWITCH_NOTIFICATION); + IWL_CMD(REPLY_SPECTRUM_MEASUREMENT_CMD); + IWL_CMD(SPECTRUM_MEASURE_NOTIFICATION); + IWL_CMD(POWER_TABLE_CMD); + IWL_CMD(PM_SLEEP_NOTIFICATION); + IWL_CMD(PM_DEBUG_STATISTIC_NOTIFIC); + IWL_CMD(REPLY_SCAN_CMD); + IWL_CMD(REPLY_SCAN_ABORT_CMD); + IWL_CMD(SCAN_START_NOTIFICATION); + IWL_CMD(SCAN_RESULTS_NOTIFICATION); + IWL_CMD(SCAN_COMPLETE_NOTIFICATION); + IWL_CMD(BEACON_NOTIFICATION); + IWL_CMD(REPLY_TX_BEACON); + IWL_CMD(WHO_IS_AWAKE_NOTIFICATION); + IWL_CMD(QUIET_NOTIFICATION); + IWL_CMD(REPLY_TX_PWR_TABLE_CMD); + IWL_CMD(MEASURE_ABORT_NOTIFICATION); + IWL_CMD(REPLY_BT_CONFIG); + IWL_CMD(REPLY_STATISTICS_CMD); + IWL_CMD(STATISTICS_NOTIFICATION); + IWL_CMD(REPLY_CARD_STATE_CMD); + IWL_CMD(CARD_STATE_NOTIFICATION); + IWL_CMD(MISSED_BEACONS_NOTIFICATION); + IWL_CMD(REPLY_CT_KILL_CONFIG_CMD); + IWL_CMD(SENSITIVITY_CMD); + IWL_CMD(REPLY_PHY_CALIBRATION_CMD); + IWL_CMD(REPLY_RX_PHY_CMD); + IWL_CMD(REPLY_RX_MPDU_CMD); + IWL_CMD(REPLY_RX); + IWL_CMD(REPLY_COMPRESSED_BA); + default: + return "UNKNOWN"; + + } +} +EXPORT_SYMBOL(get_cmd_string); + +#define HOST_COMPLETE_TIMEOUT (HZ / 2) + +static int iwl_send_cmd_async(struct iwl_priv *priv, struct iwl_host_cmd *cmd) +{ + int ret; + + BUG_ON(!(cmd->meta.flags & CMD_ASYNC)); + + /* An asynchronous command can not expect an SKB to be set. */ + BUG_ON(cmd->meta.flags & CMD_WANT_SKB); + + /* An asynchronous command MUST have a callback. */ + BUG_ON(!cmd->meta.u.callback); + + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + return -EBUSY; + + ret = priv->cfg->ops->utils->enqueue_hcmd(priv, cmd); + if (ret < 0) { + IWL_ERROR("Error sending %s: enqueue_hcmd failed: %d\n", + get_cmd_string(cmd->id), ret); + return ret; + } + return 0; +} + +int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) +{ + int cmd_idx; + int ret; + static atomic_t entry = ATOMIC_INIT(0); /* reentrance protection */ + + BUG_ON(cmd->meta.flags & CMD_ASYNC); + + /* A synchronous command can not have a callback set. */ + BUG_ON(cmd->meta.u.callback != NULL); + + if (atomic_xchg(&entry, 1)) { + IWL_ERROR("Error sending %s: Already sending a host command\n", + get_cmd_string(cmd->id)); + return -EBUSY; + } + + set_bit(STATUS_HCMD_ACTIVE, &priv->status); + + if (cmd->meta.flags & CMD_WANT_SKB) + cmd->meta.source = &cmd->meta; + + cmd_idx = priv->cfg->ops->utils->enqueue_hcmd(priv, cmd); + if (cmd_idx < 0) { + ret = cmd_idx; + IWL_ERROR("Error sending %s: enqueue_hcmd failed: %d\n", + get_cmd_string(cmd->id), ret); + goto out; + } + + ret = wait_event_interruptible_timeout(priv->wait_command_queue, + !test_bit(STATUS_HCMD_ACTIVE, &priv->status), + HOST_COMPLETE_TIMEOUT); + if (!ret) { + if (test_bit(STATUS_HCMD_ACTIVE, &priv->status)) { + IWL_ERROR("Error sending %s: time out after %dms.\n", + get_cmd_string(cmd->id), + jiffies_to_msecs(HOST_COMPLETE_TIMEOUT)); + + clear_bit(STATUS_HCMD_ACTIVE, &priv->status); + ret = -ETIMEDOUT; + goto cancel; + } + } + + if (test_bit(STATUS_RF_KILL_HW, &priv->status)) { + IWL_DEBUG_INFO("Command %s aborted: RF KILL Switch\n", + get_cmd_string(cmd->id)); + ret = -ECANCELED; + goto fail; + } + if (test_bit(STATUS_FW_ERROR, &priv->status)) { + IWL_DEBUG_INFO("Command %s failed: FW Error\n", + get_cmd_string(cmd->id)); + ret = -EIO; + goto fail; + } + if ((cmd->meta.flags & CMD_WANT_SKB) && !cmd->meta.u.skb) { + IWL_ERROR("Error: Response NULL in '%s'\n", + get_cmd_string(cmd->id)); + ret = -EIO; + goto out; + } + + ret = 0; + goto out; + +cancel: + if (cmd->meta.flags & CMD_WANT_SKB) { + struct iwl_cmd *qcmd; + + /* Cancel the CMD_WANT_SKB flag for the cmd in the + * TX cmd queue. Otherwise in case the cmd comes + * in later, it will possibly set an invalid + * address (cmd->meta.source). */ + qcmd = &priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_idx]; + qcmd->meta.flags &= ~CMD_WANT_SKB; + } +fail: + if (cmd->meta.u.skb) { + dev_kfree_skb_any(cmd->meta.u.skb); + cmd->meta.u.skb = NULL; + } +out: + atomic_set(&entry, 0); + return ret; +} +EXPORT_SYMBOL(iwl_send_cmd_sync); + +int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) +{ + if (cmd->meta.flags & CMD_ASYNC) + return iwl_send_cmd_async(priv, cmd); + + return iwl_send_cmd_sync(priv, cmd); +} +EXPORT_SYMBOL(iwl_send_cmd); + +int iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u16 len, const void *data) +{ + struct iwl_host_cmd cmd = { + .id = id, + .len = len, + .data = data, + }; + + return iwl_send_cmd_sync(priv, &cmd); +} +EXPORT_SYMBOL(iwl_send_cmd_pdu); + +int iwl_send_cmd_pdu_async(struct iwl_priv *priv, + u8 id, u16 len, const void *data, + int (*callback)(struct iwl_priv *priv, + struct iwl_cmd *cmd, + struct sk_buff *skb)) +{ + struct iwl_host_cmd cmd = { + .id = id, + .len = len, + .data = data, + }; + + cmd.meta.flags |= CMD_ASYNC; + cmd.meta.u.callback = callback; + + return iwl_send_cmd_async(priv, &cmd); +} +EXPORT_SYMBOL(iwl_send_cmd_pdu_async); diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index fac9bf1aa1d7..8fe09e893279 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -305,7 +305,7 @@ int iwl4965_tx_queue_init(struct iwl_priv *priv, * For normal Tx queues (all other queues), no super-size command * space is needed. */ - len = sizeof(struct iwl4965_cmd) * slots_num; + len = sizeof(struct iwl_cmd) * slots_num; if (txq_id == IWL_CMD_QUEUE_NUM) len += IWL_MAX_SCAN_SIZE; txq->cmd = pci_alloc_consistent(dev, len, &txq->dma_addr_cmd); @@ -356,7 +356,7 @@ void iwl4965_tx_queue_free(struct iwl_priv *priv, struct iwl4965_tx_queue *txq) q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) iwl4965_hw_txq_free_tfd(priv, txq); - len = sizeof(struct iwl4965_cmd) * q->n_window; + len = sizeof(struct iwl_cmd) * q->n_window; if (q->id == IWL_CMD_QUEUE_NUM) len += IWL_MAX_SCAN_SIZE; @@ -541,65 +541,6 @@ static inline int iwl4965_is_ready_rf(struct iwl_priv *priv) /*************** HOST COMMAND QUEUE FUNCTIONS *****/ -#define IWL_CMD(x) case x : return #x - -static const char *get_cmd_string(u8 cmd) -{ - switch (cmd) { - IWL_CMD(REPLY_ALIVE); - IWL_CMD(REPLY_ERROR); - IWL_CMD(REPLY_RXON); - IWL_CMD(REPLY_RXON_ASSOC); - IWL_CMD(REPLY_QOS_PARAM); - IWL_CMD(REPLY_RXON_TIMING); - IWL_CMD(REPLY_ADD_STA); - IWL_CMD(REPLY_REMOVE_STA); - IWL_CMD(REPLY_REMOVE_ALL_STA); - IWL_CMD(REPLY_TX); - IWL_CMD(REPLY_RATE_SCALE); - IWL_CMD(REPLY_LEDS_CMD); - IWL_CMD(REPLY_TX_LINK_QUALITY_CMD); - IWL_CMD(RADAR_NOTIFICATION); - IWL_CMD(REPLY_QUIET_CMD); - IWL_CMD(REPLY_CHANNEL_SWITCH); - IWL_CMD(CHANNEL_SWITCH_NOTIFICATION); - IWL_CMD(REPLY_SPECTRUM_MEASUREMENT_CMD); - IWL_CMD(SPECTRUM_MEASURE_NOTIFICATION); - IWL_CMD(POWER_TABLE_CMD); - IWL_CMD(PM_SLEEP_NOTIFICATION); - IWL_CMD(PM_DEBUG_STATISTIC_NOTIFIC); - IWL_CMD(REPLY_SCAN_CMD); - IWL_CMD(REPLY_SCAN_ABORT_CMD); - IWL_CMD(SCAN_START_NOTIFICATION); - IWL_CMD(SCAN_RESULTS_NOTIFICATION); - IWL_CMD(SCAN_COMPLETE_NOTIFICATION); - IWL_CMD(BEACON_NOTIFICATION); - IWL_CMD(REPLY_TX_BEACON); - IWL_CMD(WHO_IS_AWAKE_NOTIFICATION); - IWL_CMD(QUIET_NOTIFICATION); - IWL_CMD(REPLY_TX_PWR_TABLE_CMD); - IWL_CMD(MEASURE_ABORT_NOTIFICATION); - IWL_CMD(REPLY_BT_CONFIG); - IWL_CMD(REPLY_STATISTICS_CMD); - IWL_CMD(STATISTICS_NOTIFICATION); - IWL_CMD(REPLY_CARD_STATE_CMD); - IWL_CMD(CARD_STATE_NOTIFICATION); - IWL_CMD(MISSED_BEACONS_NOTIFICATION); - IWL_CMD(REPLY_CT_KILL_CONFIG_CMD); - IWL_CMD(SENSITIVITY_CMD); - IWL_CMD(REPLY_PHY_CALIBRATION_CMD); - IWL_CMD(REPLY_RX_PHY_CMD); - IWL_CMD(REPLY_RX_MPDU_CMD); - IWL_CMD(REPLY_4965_RX); - IWL_CMD(REPLY_COMPRESSED_BA); - default: - return "UNKNOWN"; - - } -} - -#define HOST_COMPLETE_TIMEOUT (HZ / 2) - /** * iwl4965_enqueue_hcmd - enqueue a uCode command * @priv: device private data point @@ -609,13 +550,13 @@ static const char *get_cmd_string(u8 cmd) * failed. On success, it turns the index (> 0) of command in the * command queue. */ -static int iwl4965_enqueue_hcmd(struct iwl_priv *priv, struct iwl4965_host_cmd *cmd) +int iwl4965_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) { struct iwl4965_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM]; struct iwl4965_queue *q = &txq->q; struct iwl4965_tfd_frame *tfd; u32 *control_flags; - struct iwl4965_cmd *out_cmd; + struct iwl_cmd *out_cmd; u32 idx; u16 fix_size = (u16)(cmd->len + sizeof(out_cmd->hdr)); dma_addr_t phys_addr; @@ -662,7 +603,7 @@ static int iwl4965_enqueue_hcmd(struct iwl_priv *priv, struct iwl4965_host_cmd * out_cmd->hdr.sequence |= cpu_to_le16(SEQ_HUGE_FRAME); phys_addr = txq->dma_addr_cmd + sizeof(txq->cmd[0]) * idx + - offsetof(struct iwl4965_cmd, hdr); + offsetof(struct iwl_cmd, hdr); iwl4965_hw_txq_attach_buf_to_tfd(priv, tfd, phys_addr, fix_size); IWL_DEBUG_HC("Sending command %s (#%x), seq: 0x%04X, " @@ -684,118 +625,6 @@ static int iwl4965_enqueue_hcmd(struct iwl_priv *priv, struct iwl4965_host_cmd * return ret ? ret : idx; } -static int iwl4965_send_cmd_async(struct iwl_priv *priv, struct iwl4965_host_cmd *cmd) -{ - int ret; - - BUG_ON(!(cmd->meta.flags & CMD_ASYNC)); - - /* An asynchronous command can not expect an SKB to be set. */ - BUG_ON(cmd->meta.flags & CMD_WANT_SKB); - - /* An asynchronous command MUST have a callback. */ - BUG_ON(!cmd->meta.u.callback); - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return -EBUSY; - - ret = iwl4965_enqueue_hcmd(priv, cmd); - if (ret < 0) { - IWL_ERROR("Error sending %s: iwl4965_enqueue_hcmd failed: %d\n", - get_cmd_string(cmd->id), ret); - return ret; - } - return 0; -} - -static int iwl4965_send_cmd_sync(struct iwl_priv *priv, struct iwl4965_host_cmd *cmd) -{ - int cmd_idx; - int ret; - static atomic_t entry = ATOMIC_INIT(0); /* reentrance protection */ - - BUG_ON(cmd->meta.flags & CMD_ASYNC); - - /* A synchronous command can not have a callback set. */ - BUG_ON(cmd->meta.u.callback != NULL); - - if (atomic_xchg(&entry, 1)) { - IWL_ERROR("Error sending %s: Already sending a host command\n", - get_cmd_string(cmd->id)); - return -EBUSY; - } - - set_bit(STATUS_HCMD_ACTIVE, &priv->status); - - if (cmd->meta.flags & CMD_WANT_SKB) - cmd->meta.source = &cmd->meta; - - cmd_idx = iwl4965_enqueue_hcmd(priv, cmd); - if (cmd_idx < 0) { - ret = cmd_idx; - IWL_ERROR("Error sending %s: iwl4965_enqueue_hcmd failed: %d\n", - get_cmd_string(cmd->id), ret); - goto out; - } - - ret = wait_event_interruptible_timeout(priv->wait_command_queue, - !test_bit(STATUS_HCMD_ACTIVE, &priv->status), - HOST_COMPLETE_TIMEOUT); - if (!ret) { - if (test_bit(STATUS_HCMD_ACTIVE, &priv->status)) { - IWL_ERROR("Error sending %s: time out after %dms.\n", - get_cmd_string(cmd->id), - jiffies_to_msecs(HOST_COMPLETE_TIMEOUT)); - - clear_bit(STATUS_HCMD_ACTIVE, &priv->status); - ret = -ETIMEDOUT; - goto cancel; - } - } - - if (test_bit(STATUS_RF_KILL_HW, &priv->status)) { - IWL_DEBUG_INFO("Command %s aborted: RF KILL Switch\n", - get_cmd_string(cmd->id)); - ret = -ECANCELED; - goto fail; - } - if (test_bit(STATUS_FW_ERROR, &priv->status)) { - IWL_DEBUG_INFO("Command %s failed: FW Error\n", - get_cmd_string(cmd->id)); - ret = -EIO; - goto fail; - } - if ((cmd->meta.flags & CMD_WANT_SKB) && !cmd->meta.u.skb) { - IWL_ERROR("Error: Response NULL in '%s'\n", - get_cmd_string(cmd->id)); - ret = -EIO; - goto out; - } - - ret = 0; - goto out; - -cancel: - if (cmd->meta.flags & CMD_WANT_SKB) { - struct iwl4965_cmd *qcmd; - - /* Cancel the CMD_WANT_SKB flag for the cmd in the - * TX cmd queue. Otherwise in case the cmd comes - * in later, it will possibly set an invalid - * address (cmd->meta.source). */ - qcmd = &priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_idx]; - qcmd->meta.flags &= ~CMD_WANT_SKB; - } -fail: - if (cmd->meta.u.skb) { - dev_kfree_skb_any(cmd->meta.u.skb); - cmd->meta.u.skb = NULL; - } -out: - atomic_set(&entry, 0); - return ret; -} - static void iwl4965_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt) { struct iwl4965_rxon_cmd *rxon = &priv->staging_rxon; @@ -807,39 +636,11 @@ static void iwl4965_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt) } -int iwl4965_send_cmd(struct iwl_priv *priv, struct iwl4965_host_cmd *cmd) -{ - if (cmd->meta.flags & CMD_ASYNC) - return iwl4965_send_cmd_async(priv, cmd); - - return iwl4965_send_cmd_sync(priv, cmd); -} - -int iwl4965_send_cmd_pdu(struct iwl_priv *priv, u8 id, u16 len, const void *data) -{ - struct iwl4965_host_cmd cmd = { - .id = id, - .len = len, - .data = data, - }; - - return iwl4965_send_cmd_sync(priv, &cmd); -} - -static int __must_check iwl4965_send_cmd_u32(struct iwl_priv *priv, u8 id, u32 val) -{ - struct iwl4965_host_cmd cmd = { - .id = id, - .len = sizeof(val), - .data = &val, - }; - - return iwl4965_send_cmd_sync(priv, &cmd); -} - int iwl4965_send_statistics_request(struct iwl_priv *priv) { - return iwl4965_send_cmd_u32(priv, REPLY_STATISTICS_CMD, 0); + u32 flags = 0; + return iwl_send_cmd_pdu(priv, REPLY_STATISTICS_CMD, + sizeof(flags), &flags); } /** @@ -1000,7 +801,7 @@ static int iwl4965_send_rxon_assoc(struct iwl_priv *priv) int rc = 0; struct iwl4965_rx_packet *res = NULL; struct iwl4965_rxon_assoc_cmd rxon_assoc; - struct iwl4965_host_cmd cmd = { + struct iwl_host_cmd cmd = { .id = REPLY_RXON_ASSOC, .len = sizeof(rxon_assoc), .meta.flags = CMD_WANT_SKB, @@ -1033,7 +834,7 @@ static int iwl4965_send_rxon_assoc(struct iwl_priv *priv) priv->staging_rxon.ofdm_ht_dual_stream_basic_rates; rxon_assoc.rx_chain_select_flags = priv->staging_rxon.rx_chain; - rc = iwl4965_send_cmd_sync(priv, &cmd); + rc = iwl_send_cmd_sync(priv, &cmd); if (rc) return rc; @@ -1112,7 +913,7 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv) IWL_DEBUG_INFO("Toggling associated bit on current RXON\n"); active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; - rc = iwl4965_send_cmd_pdu(priv, REPLY_RXON, + rc = iwl_send_cmd_pdu(priv, REPLY_RXON, sizeof(struct iwl4965_rxon_cmd), &priv->active_rxon); @@ -1137,7 +938,7 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv) iwl4965_set_rxon_hwcrypto(priv, priv->cfg->mod_params->hw_crypto); /* Apply the new configuration */ - rc = iwl4965_send_cmd_pdu(priv, REPLY_RXON, + rc = iwl_send_cmd_pdu(priv, REPLY_RXON, sizeof(struct iwl4965_rxon_cmd), &priv->staging_rxon); if (rc) { IWL_ERROR("Error setting new configuration (%d).\n", rc); @@ -1196,7 +997,7 @@ static int iwl4965_send_bt_config(struct iwl_priv *priv) .kill_cts_mask = 0, }; - return iwl4965_send_cmd_pdu(priv, REPLY_BT_CONFIG, + return iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG, sizeof(struct iwl4965_bt_cmd), &bt_cmd); } @@ -1204,7 +1005,7 @@ static int iwl4965_send_scan_abort(struct iwl_priv *priv) { int rc = 0; struct iwl4965_rx_packet *res; - struct iwl4965_host_cmd cmd = { + struct iwl_host_cmd cmd = { .id = REPLY_SCAN_ABORT_CMD, .meta.flags = CMD_WANT_SKB, }; @@ -1217,7 +1018,7 @@ static int iwl4965_send_scan_abort(struct iwl_priv *priv) return 0; } - rc = iwl4965_send_cmd_sync(priv, &cmd); + rc = iwl_send_cmd_sync(priv, &cmd); if (rc) { clear_bit(STATUS_SCAN_ABORTING, &priv->status); return rc; @@ -1242,7 +1043,7 @@ static int iwl4965_send_scan_abort(struct iwl_priv *priv) } static int iwl4965_card_state_sync_callback(struct iwl_priv *priv, - struct iwl4965_cmd *cmd, + struct iwl_cmd *cmd, struct sk_buff *skb) { return 1; @@ -1260,7 +1061,7 @@ static int iwl4965_card_state_sync_callback(struct iwl_priv *priv, */ static int iwl4965_send_card_state(struct iwl_priv *priv, u32 flags, u8 meta_flag) { - struct iwl4965_host_cmd cmd = { + struct iwl_host_cmd cmd = { .id = REPLY_CARD_STATE_CMD, .len = sizeof(u32), .data = &flags, @@ -1270,11 +1071,11 @@ static int iwl4965_send_card_state(struct iwl_priv *priv, u32 flags, u8 meta_fla if (meta_flag & CMD_ASYNC) cmd.meta.u.callback = iwl4965_card_state_sync_callback; - return iwl4965_send_cmd(priv, &cmd); + return iwl_send_cmd(priv, &cmd); } static int iwl4965_add_sta_sync_callback(struct iwl_priv *priv, - struct iwl4965_cmd *cmd, struct sk_buff *skb) + struct iwl_cmd *cmd, struct sk_buff *skb) { struct iwl4965_rx_packet *res = NULL; @@ -1306,7 +1107,7 @@ int iwl4965_send_add_station(struct iwl_priv *priv, { struct iwl4965_rx_packet *res = NULL; int rc = 0; - struct iwl4965_host_cmd cmd = { + struct iwl_host_cmd cmd = { .id = REPLY_ADD_STA, .len = sizeof(struct iwl4965_addsta_cmd), .meta.flags = flags, @@ -1318,7 +1119,7 @@ int iwl4965_send_add_station(struct iwl_priv *priv, else cmd.meta.flags |= CMD_WANT_SKB; - rc = iwl4965_send_cmd(priv, &cmd); + rc = iwl_send_cmd(priv, &cmd); if (rc || (flags & CMD_ASYNC)) return rc; @@ -1579,7 +1380,7 @@ static int iwl4965_send_beacon_cmd(struct iwl_priv *priv) frame_size = iwl4965_hw_get_beacon_cmd(priv, frame, rate); - rc = iwl4965_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size, + rc = iwl_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size, &frame->u.cmd[0]); iwl4965_free_frame(priv, frame); @@ -1756,7 +1557,7 @@ static int iwl4965_send_qos_params_command(struct iwl_priv *priv, struct iwl4965_qosparam_cmd *qos) { - return iwl4965_send_cmd_pdu(priv, REPLY_QOS_PARAM, + return iwl_send_cmd_pdu(priv, REPLY_QOS_PARAM, sizeof(struct iwl4965_qosparam_cmd), qos); } @@ -1966,7 +1767,7 @@ static int iwl4965_send_power_mode(struct iwl_priv *priv, u32 mode) iwl4965_update_power_cmd(priv, &cmd, final_mode); - rc = iwl4965_send_cmd_pdu(priv, POWER_TABLE_CMD, sizeof(cmd), &cmd); + rc = iwl_send_cmd_pdu(priv, POWER_TABLE_CMD, sizeof(cmd), &cmd); if (final_mode == IWL_POWER_MODE_CAM) clear_bit(STATUS_POWER_PMI, &priv->status); @@ -2345,7 +2146,7 @@ static int iwl4965_set_mode(struct iwl_priv *priv, int mode) static void iwl4965_build_tx_cmd_hwcrypto(struct iwl_priv *priv, struct ieee80211_tx_control *ctl, - struct iwl4965_cmd *cmd, + struct iwl_cmd *cmd, struct sk_buff *skb_frag, int sta_id) { @@ -2390,7 +2191,7 @@ static void iwl4965_build_tx_cmd_hwcrypto(struct iwl_priv *priv, * handle build REPLY_TX command notification. */ static void iwl4965_build_tx_cmd_basic(struct iwl_priv *priv, - struct iwl4965_cmd *cmd, + struct iwl_cmd *cmd, struct ieee80211_tx_control *ctrl, struct ieee80211_hdr *hdr, int is_unicast, u8 std_id) @@ -2531,7 +2332,7 @@ static int iwl4965_tx_skb(struct iwl_priv *priv, dma_addr_t phys_addr; dma_addr_t txcmd_phys; dma_addr_t scratch_phys; - struct iwl4965_cmd *out_cmd = NULL; + struct iwl_cmd *out_cmd = NULL; u16 len, idx, len_org; u8 id, hdr_len, unicast; u8 sta_id; @@ -2660,7 +2461,7 @@ static int iwl4965_tx_skb(struct iwl_priv *priv, * We'll tell device about this padding later. */ len = priv->hw_setting.tx_cmd_len + - sizeof(struct iwl4965_cmd_header) + hdr_len; + sizeof(struct iwl_cmd_header) + hdr_len; len_org = len; len = (len + 3) & ~3; @@ -2672,8 +2473,8 @@ static int iwl4965_tx_skb(struct iwl_priv *priv, /* Physical address of this Tx command's header (not MAC header!), * within command buffer array. */ - txcmd_phys = txq->dma_addr_cmd + sizeof(struct iwl4965_cmd) * idx + - offsetof(struct iwl4965_cmd, hdr); + txcmd_phys = txq->dma_addr_cmd + sizeof(struct iwl_cmd) * idx + + offsetof(struct iwl_cmd, hdr); /* Add buffer containing Tx command and MAC(!) header to TFD's * first entry */ @@ -2707,7 +2508,7 @@ static int iwl4965_tx_skb(struct iwl_priv *priv, iwl_update_tx_stats(priv, fc, len); - scratch_phys = txcmd_phys + sizeof(struct iwl4965_cmd_header) + + scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) + offsetof(struct iwl4965_tx_cmd, scratch); out_cmd->cmd.tx.dram_lsb_ptr = cpu_to_le32(scratch_phys); out_cmd->cmd.tx.dram_msb_ptr = iwl_get_dma_hi_address(scratch_phys); @@ -3020,7 +2821,7 @@ static int iwl4965_get_measurement(struct iwl_priv *priv, { struct iwl4965_spectrum_cmd spectrum; struct iwl4965_rx_packet *res; - struct iwl4965_host_cmd cmd = { + struct iwl_host_cmd cmd = { .id = REPLY_SPECTRUM_MEASUREMENT_CMD, .data = (void *)&spectrum, .meta.flags = CMD_WANT_SKB, @@ -3060,7 +2861,7 @@ static int iwl4965_get_measurement(struct iwl_priv *priv, spectrum.flags |= RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_TGG_PROTECT_MSK; - rc = iwl4965_send_cmd_sync(priv, &cmd); + rc = iwl_send_cmd_sync(priv, &cmd); if (rc) return rc; @@ -3835,7 +3636,7 @@ static void iwl4965_tx_cmd_complete(struct iwl_priv *priv, int index = SEQ_TO_INDEX(sequence); int huge = sequence & SEQ_HUGE_FRAME; int cmd_index; - struct iwl4965_cmd *cmd; + struct iwl_cmd *cmd; /* If a Tx command is being handled and it isn't in the actual * command queue then there a command routing bug has been introduced @@ -4337,7 +4138,7 @@ static void iwl4965_rx_handle(struct iwl_priv *priv) * but apparently a few don't get set; catch them here. */ reclaim = !(pkt->hdr.sequence & SEQ_RX_FRAME) && (pkt->hdr.cmd != REPLY_RX_PHY_CMD) && - (pkt->hdr.cmd != REPLY_4965_RX) && + (pkt->hdr.cmd != REPLY_RX) && (pkt->hdr.cmd != REPLY_COMPRESSED_BA) && (pkt->hdr.cmd != STATISTICS_NOTIFICATION) && (pkt->hdr.cmd != REPLY_TX); @@ -4360,7 +4161,7 @@ static void iwl4965_rx_handle(struct iwl_priv *priv) if (reclaim) { /* Invoke any callbacks, transfer the skb to caller, and - * fire off the (possibly) blocking iwl4965_send_cmd() + * fire off the (possibly) blocking iwl_send_cmd() * as we reclaim the driver command queue */ if (rxb && rxb->skb) iwl4965_tx_cmd_complete(priv, rxb); @@ -6213,17 +6014,17 @@ static void iwl4965_bg_request_scan(struct work_struct *data) { struct iwl_priv *priv = container_of(data, struct iwl_priv, request_scan); - struct iwl4965_host_cmd cmd = { + struct iwl_host_cmd cmd = { .id = REPLY_SCAN_CMD, .len = sizeof(struct iwl4965_scan_cmd), .meta.flags = CMD_SIZE_HUGE, }; - int rc = 0; struct iwl4965_scan_cmd *scan; struct ieee80211_conf *conf = NULL; u16 cmd_len; enum ieee80211_band band; u8 direct_mask; + int ret = 0; conf = ieee80211_get_hw_conf(priv->hw); @@ -6244,7 +6045,7 @@ static void iwl4965_bg_request_scan(struct work_struct *data) if (test_bit(STATUS_SCAN_HW, &priv->status)) { IWL_DEBUG_INFO("Multiple concurrent scan requests in parallel. " "Ignoring second request.\n"); - rc = -EIO; + ret = -EIO; goto done; } @@ -6277,7 +6078,7 @@ static void iwl4965_bg_request_scan(struct work_struct *data) priv->scan = kmalloc(sizeof(struct iwl4965_scan_cmd) + IWL_MAX_SCAN_SIZE, GFP_KERNEL); if (!priv->scan) { - rc = -ENOMEM; + ret = -ENOMEM; goto done; } } @@ -6329,8 +6130,9 @@ static void iwl4965_bg_request_scan(struct work_struct *data) scan->direct_scan[0].len = priv->essid_len; memcpy(scan->direct_scan[0].ssid, priv->essid, priv->essid_len); direct_mask = 1; - } else + } else { direct_mask = 0; + } scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; scan->tx_cmd.sta_id = priv->hw_setting.bcast_sta_id; @@ -6405,8 +6207,8 @@ static void iwl4965_bg_request_scan(struct work_struct *data) scan->len = cpu_to_le16(cmd.len); set_bit(STATUS_SCAN_HW, &priv->status); - rc = iwl4965_send_cmd_sync(priv, &cmd); - if (rc) + ret = iwl_send_cmd_sync(priv, &cmd); + if (ret) goto done; queue_delayed_work(priv->workqueue, &priv->scan_check, @@ -6463,9 +6265,8 @@ static void iwl4965_bg_post_associate(struct work_struct *data) { struct iwl_priv *priv = container_of(data, struct iwl_priv, post_associate.work); - - int rc = 0; struct ieee80211_conf *conf = NULL; + int ret = 0; DECLARE_MAC_BUF(mac); if (priv->iw_mode == IEEE80211_IF_TYPE_AP) { @@ -6496,9 +6297,9 @@ static void iwl4965_bg_post_associate(struct work_struct *data) memset(&priv->rxon_timing, 0, sizeof(struct iwl4965_rxon_time_cmd)); iwl4965_setup_rxon_timing(priv); - rc = iwl4965_send_cmd_pdu(priv, REPLY_RXON_TIMING, + ret = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING, sizeof(priv->rxon_timing), &priv->rxon_timing); - if (rc) + if (ret) IWL_WARNING("REPLY_RXON_TIMING failed - " "Attempting to continue.\n"); @@ -6894,7 +6695,7 @@ out: static void iwl4965_config_ap(struct iwl_priv *priv) { - int rc = 0; + int ret = 0; if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; @@ -6909,9 +6710,9 @@ static void iwl4965_config_ap(struct iwl_priv *priv) /* RXON Timing */ memset(&priv->rxon_timing, 0, sizeof(struct iwl4965_rxon_time_cmd)); iwl4965_setup_rxon_timing(priv); - rc = iwl4965_send_cmd_pdu(priv, REPLY_RXON_TIMING, + ret = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING, sizeof(priv->rxon_timing), &priv->rxon_timing); - if (rc) + if (ret) IWL_WARNING("REPLY_RXON_TIMING failed - " "Attempting to continue.\n"); -- cgit v1.2.1 From 19d30e02998ef1eb9f82a7d3ce9b4a97dba5aa13 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sat, 15 Mar 2008 21:38:07 +0100 Subject: rt2x00: Add dev_flags to rx descriptor The rxdone_entry_desc structure contains 3 fields which are always 1 or 0. We can safe 8 bytes by replacing them with a single dev_flags fields which contain the flags for those settings. Additionally we can remove the OFDM flag since it is no longer used since the introduction of the SIGNAL_PLCP flag. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 7 ++++--- drivers/net/wireless/rt2x00/rt2500pci.c | 9 ++++++--- drivers/net/wireless/rt2x00/rt2500usb.c | 9 ++++++--- drivers/net/wireless/rt2x00/rt2x00dev.c | 8 +++++--- drivers/net/wireless/rt2x00/rt2x00queue.h | 22 +++++++++++++++------- drivers/net/wireless/rt2x00/rt61pci.c | 9 ++++++--- drivers/net/wireless/rt2x00/rt73usb.c | 9 ++++++--- 7 files changed, 48 insertions(+), 25 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 1f49561d3ddc..c58b1c0abc3c 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1076,12 +1076,13 @@ static void rt2400pci_fill_rxdone(struct queue_entry *entry, * of the preamble bit (0x08). */ rxdesc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL) & ~0x08; - rxdesc->signal_plcp = 1; rxdesc->rssi = rt2x00_get_field32(word2, RXD_W3_RSSI) - entry->queue->rt2x00dev->rssi_offset; - rxdesc->ofdm = 0; rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); - rxdesc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS); + + rxdesc->dev_flags = RXDONE_SIGNAL_PLCP; + if (rt2x00_get_field32(word0, RXD_W0_MY_BSS)) + rxdesc->dev_flags |= RXDONE_MY_BSS; } /* diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 0f5139a2f238..9468dde3c95e 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1225,13 +1225,16 @@ static void rt2500pci_fill_rxdone(struct queue_entry *entry, * the signal is the PLCP value. If it was received with * a CCK bitrate the signal is the rate in 100kbit/s. */ - rxdesc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM); rxdesc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL); - rxdesc->signal_plcp = rxdesc->ofdm; rxdesc->rssi = rt2x00_get_field32(word2, RXD_W2_RSSI) - entry->queue->rt2x00dev->rssi_offset; rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); - rxdesc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS); + + rxdesc->dev_flags = 0; + if (rt2x00_get_field32(word0, RXD_W0_OFDM)) + rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP; + if (rt2x00_get_field32(word0, RXD_W0_MY_BSS)) + rxdesc->dev_flags |= RXDONE_MY_BSS; } /* diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index c8216d755835..8959a684f40b 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -1139,13 +1139,16 @@ static void rt2500usb_fill_rxdone(struct queue_entry *entry, * the signal is the PLCP value. If it was received with * a CCK bitrate the signal is the rate in 100kbit/s. */ - rxdesc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM); rxdesc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL); - rxdesc->signal_plcp = rxdesc->ofdm; rxdesc->rssi = rt2x00_get_field32(word1, RXD_W1_RSSI) - entry->queue->rt2x00dev->rssi_offset; rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); - rxdesc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS); + + rxdesc->dev_flags = 0; + if (rt2x00_get_field32(word0, RXD_W0_OFDM)) + rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP; + if (rt2x00_get_field32(word0, RXD_W0_MY_BSS)) + rxdesc->dev_flags |= RXDONE_MY_BSS; /* * Adjust the skb memory window to the frame boundaries. diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index acf4d67ba43d..4fd0c25aebf3 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -580,8 +580,10 @@ void rt2x00lib_rxdone(struct queue_entry *entry, for (i = 0; i < sband->n_bitrates; i++) { rate = rt2x00_get_rate(sband->bitrates[i].hw_value); - if ((rxdesc->signal_plcp && rate->plcp == rxdesc->signal) || - (!rxdesc->signal_plcp && rate->bitrate == rxdesc->signal)) { + if (((rxdesc->dev_flags & RXDONE_SIGNAL_PLCP) && + (rate->plcp == rxdesc->signal)) || + (!(rxdesc->dev_flags & RXDONE_SIGNAL_PLCP) && + (rate->bitrate == rxdesc->signal))) { idx = i; break; } @@ -592,7 +594,7 @@ void rt2x00lib_rxdone(struct queue_entry *entry, */ hdr = (struct ieee80211_hdr *)entry->skb->data; fc = le16_to_cpu(hdr->frame_control); - if (is_beacon(fc) && rxdesc->my_bss) + if (is_beacon(fc) && (rxdesc->dev_flags & RXDONE_MY_BSS)) rt2x00lib_update_link_stats(&rt2x00dev->link, rxdesc->rssi); rt2x00dev->link.qual.rx_success++; diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index c5f46f234083..7027c9f47d3f 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -128,28 +128,36 @@ static inline struct skb_frame_desc* get_skb_frame_desc(struct sk_buff *skb) return (struct skb_frame_desc *)&skb->cb[0]; } +/** + * enum rxdone_entry_desc_flags: Flags for &struct rxdone_entry_desc + * + * @RXDONE_SIGNAL_PLCP: Does the signal field contain the plcp value, + * or does it contain the bitrate itself. + * @RXDONE_MY_BSS: Does this frame originate from device's BSS. + */ +enum rxdone_entry_desc_flags { + RXDONE_SIGNAL_PLCP = 1 << 0, + RXDONE_MY_BSS = 1 << 1, +}; + /** * struct rxdone_entry_desc: RX Entry descriptor * * Summary of information that has been read from the RX frame descriptor. * * @signal: Signal of the received frame. - * @signal_plcp: Does the signal field contain the plcp value, - * or does it contain the bitrate itself. * @rssi: RSSI of the received frame. - * @ofdm: Was frame send with an OFDM rate. * @size: Data size of the received frame. * @flags: MAC80211 receive flags (See &enum mac80211_rx_flags). - * @my_bss: Does this frame originate from device's BSS. + * @dev_flags: Ralink receive flags (See &enum rxdone_entry_desc_flags). + */ struct rxdone_entry_desc { int signal; - int signal_plcp; int rssi; - int ofdm; int size; int flags; - int my_bss; + int dev_flags; }; /** diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index babb240cef3d..6e643c8db42e 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -1649,12 +1649,15 @@ static void rt61pci_fill_rxdone(struct queue_entry *entry, * the signal is the PLCP value. If it was received with * a CCK bitrate the signal is the rate in 100kbit/s. */ - rxdesc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM); rxdesc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL); - rxdesc->signal_plcp = rxdesc->ofdm; rxdesc->rssi = rt61pci_agc_to_rssi(entry->queue->rt2x00dev, word1); rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); - rxdesc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS); + + rxdesc->dev_flags = 0; + if (rt2x00_get_field32(word0, RXD_W0_OFDM)) + rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP; + if (rt2x00_get_field32(word0, RXD_W0_MY_BSS)) + rxdesc->dev_flags |= RXDONE_MY_BSS; } /* diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 46b040bf62de..b50f476e4bd1 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -1409,12 +1409,15 @@ static void rt73usb_fill_rxdone(struct queue_entry *entry, * the signal is the PLCP value. If it was received with * a CCK bitrate the signal is the rate in 100kbit/s. */ - rxdesc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM); rxdesc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL); - rxdesc->signal_plcp = rxdesc->ofdm; rxdesc->rssi = rt73usb_agc_to_rssi(entry->queue->rt2x00dev, word1); rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); - rxdesc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS); + + rxdesc->dev_flags = 0; + if (rt2x00_get_field32(word0, RXD_W0_OFDM)) + rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP; + if (rt2x00_get_field32(word0, RXD_W0_MY_BSS)) + rxdesc->dev_flags |= RXDONE_MY_BSS; /* * Adjust the skb memory window to the frame boundaries. -- cgit v1.2.1 From 83f7d57c37e83ab11009d58565e1010597b88db6 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 16 Mar 2008 22:26:44 +0000 Subject: ipw2200 annotations and fixes a) a bunch of printks in error-handling assums that ->status is big-endian. b) bitfields trouble c) missing annotations NB: a bunch of structs is declared packed for no good reason, AFAICS. Signed-off-by: Al Viro Acked-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/ipw2200.c | 12 ++--- drivers/net/wireless/ipw2200.h | 112 +++++++++++++++++++++-------------------- 2 files changed, 64 insertions(+), 60 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 3d4b590046a8..e79de53bd4f3 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -4495,9 +4495,9 @@ static void ipw_rx_notification(struct ipw_priv *priv, priv-> essid_len), print_mac(mac, priv->bssid), - ntohs(auth->status), + le16_to_cpu(auth->status), ipw_get_status_code - (ntohs + (le16_to_cpu (auth->status))); priv->status &= @@ -4532,9 +4532,9 @@ static void ipw_rx_notification(struct ipw_priv *priv, IPW_DL_STATE | IPW_DL_ASSOC, "association failed (0x%04X): %s\n", - ntohs(resp->status), + le16_to_cpu(resp->status), ipw_get_status_code - (ntohs + (le16_to_cpu (resp->status))); } @@ -4591,8 +4591,8 @@ static void ipw_rx_notification(struct ipw_priv *priv, IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | IPW_DL_ASSOC, "authentication failed (0x%04X): %s\n", - ntohs(auth->status), - ipw_get_status_code(ntohs + le16_to_cpu(auth->status), + ipw_get_status_code(le16_to_cpu (auth-> status))); } diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h index fdc187e0769d..cd3295b66dd6 100644 --- a/drivers/net/wireless/ipw2200.h +++ b/drivers/net/wireless/ipw2200.h @@ -385,73 +385,73 @@ struct clx2_queue { dma_addr_t dma_addr; /**< physical addr for BD's */ int low_mark; /**< low watermark, resume queue if free space more than this */ int high_mark; /**< high watermark, stop queue if free space less than this */ -} __attribute__ ((packed)); +} __attribute__ ((packed)); /* XXX */ struct machdr32 { __le16 frame_ctl; - u16 duration; // watch out for endians! + __le16 duration; // watch out for endians! u8 addr1[MACADRR_BYTE_LEN]; u8 addr2[MACADRR_BYTE_LEN]; u8 addr3[MACADRR_BYTE_LEN]; - u16 seq_ctrl; // more endians! + __le16 seq_ctrl; // more endians! u8 addr4[MACADRR_BYTE_LEN]; __le16 qos_ctrl; } __attribute__ ((packed)); struct machdr30 { __le16 frame_ctl; - u16 duration; // watch out for endians! + __le16 duration; // watch out for endians! u8 addr1[MACADRR_BYTE_LEN]; u8 addr2[MACADRR_BYTE_LEN]; u8 addr3[MACADRR_BYTE_LEN]; - u16 seq_ctrl; // more endians! + __le16 seq_ctrl; // more endians! u8 addr4[MACADRR_BYTE_LEN]; } __attribute__ ((packed)); struct machdr26 { __le16 frame_ctl; - u16 duration; // watch out for endians! + __le16 duration; // watch out for endians! u8 addr1[MACADRR_BYTE_LEN]; u8 addr2[MACADRR_BYTE_LEN]; u8 addr3[MACADRR_BYTE_LEN]; - u16 seq_ctrl; // more endians! + __le16 seq_ctrl; // more endians! __le16 qos_ctrl; } __attribute__ ((packed)); struct machdr24 { __le16 frame_ctl; - u16 duration; // watch out for endians! + __le16 duration; // watch out for endians! u8 addr1[MACADRR_BYTE_LEN]; u8 addr2[MACADRR_BYTE_LEN]; u8 addr3[MACADRR_BYTE_LEN]; - u16 seq_ctrl; // more endians! + __le16 seq_ctrl; // more endians! } __attribute__ ((packed)); // TX TFD with 32 byte MAC Header struct tx_tfd_32 { struct machdr32 mchdr; // 32 - u32 uivplaceholder[2]; // 8 + __le32 uivplaceholder[2]; // 8 } __attribute__ ((packed)); // TX TFD with 30 byte MAC Header struct tx_tfd_30 { struct machdr30 mchdr; // 30 u8 reserved[2]; // 2 - u32 uivplaceholder[2]; // 8 + __le32 uivplaceholder[2]; // 8 } __attribute__ ((packed)); // tx tfd with 26 byte mac header struct tx_tfd_26 { struct machdr26 mchdr; // 26 u8 reserved1[2]; // 2 - u32 uivplaceholder[2]; // 8 + __le32 uivplaceholder[2]; // 8 u8 reserved2[4]; // 4 } __attribute__ ((packed)); // tx tfd with 24 byte mac header struct tx_tfd_24 { struct machdr24 mchdr; // 24 - u32 uivplaceholder[2]; // 8 + __le32 uivplaceholder[2]; // 8 u8 reserved[8]; // 8 } __attribute__ ((packed)); @@ -460,7 +460,7 @@ struct tx_tfd_24 { struct tfd_command { u8 index; u8 length; - u16 reserved; + __le16 reserved; u8 payload[0]; } __attribute__ ((packed)); @@ -562,27 +562,27 @@ struct rate_histogram { struct ipw_cmd_stats { u8 cmd_id; u8 seq_num; - u16 good_sfd; - u16 bad_plcp; - u16 wrong_bssid; - u16 valid_mpdu; - u16 bad_mac_header; - u16 reserved_frame_types; - u16 rx_ina; - u16 bad_crc32; - u16 invalid_cts; - u16 invalid_acks; - u16 long_distance_ina_fina; - u16 dsp_silence_unreachable; - u16 accumulated_rssi; - u16 rx_ovfl_frame_tossed; - u16 rssi_silence_threshold; - u16 rx_ovfl_frame_supplied; - u16 last_rx_frame_signal; - u16 last_rx_frame_noise; - u16 rx_autodetec_no_ofdm; - u16 rx_autodetec_no_barker; - u16 reserved; + __le16 good_sfd; + __le16 bad_plcp; + __le16 wrong_bssid; + __le16 valid_mpdu; + __le16 bad_mac_header; + __le16 reserved_frame_types; + __le16 rx_ina; + __le16 bad_crc32; + __le16 invalid_cts; + __le16 invalid_acks; + __le16 long_distance_ina_fina; + __le16 dsp_silence_unreachable; + __le16 accumulated_rssi; + __le16 rx_ovfl_frame_tossed; + __le16 rssi_silence_threshold; + __le16 rx_ovfl_frame_supplied; + __le16 last_rx_frame_signal; + __le16 last_rx_frame_noise; + __le16 rx_autodetec_no_ofdm; + __le16 rx_autodetec_no_barker; + __le16 reserved; } __attribute__ ((packed)); struct notif_channel_result { @@ -637,7 +637,7 @@ struct notif_association { struct notif_authenticate { u8 state; struct machdr24 addr; - u16 status; + __le16 status; } __attribute__ ((packed)); struct notif_calibration { @@ -732,14 +732,14 @@ struct ipw_rx_queue { struct alive_command_responce { u8 alive_command; u8 sequence_number; - u16 software_revision; + __le16 software_revision; u8 device_identifier; u8 reserved1[5]; - u16 reserved2; - u16 reserved3; - u16 clock_settle_time; - u16 powerup_settle_time; - u16 reserved4; + __le16 reserved2; + __le16 reserved3; + __le16 clock_settle_time; + __le16 powerup_settle_time; + __le16 reserved4; u8 time_stamp[5]; /* month, day, year, hours, minutes */ u8 ucode_valid; } __attribute__ ((packed)); @@ -878,7 +878,11 @@ static inline void ipw_set_scan_type(struct ipw_scan_request_ext *scan, struct ipw_associate { u8 channel; +#ifdef __LITTLE_ENDIAN_BITFIELD u8 auth_type:4, auth_key:4; +#else + u8 auth_key:4, auth_type:4; +#endif u8 assoc_type; u8 reserved; __le16 policy_support; @@ -918,12 +922,12 @@ struct ipw_frag_threshold { struct ipw_retry_limit { u8 short_retry_limit; u8 long_retry_limit; - u16 reserved; + __le16 reserved; } __attribute__ ((packed)); struct ipw_dino_config { - u32 dino_config_addr; - u16 dino_config_size; + __le32 dino_config_addr; + __le16 dino_config_size; u8 dino_response; u8 reserved; } __attribute__ ((packed)); @@ -998,7 +1002,7 @@ struct ipw_sensitivity_calib { * - \a status contains status; * - \a param filled with status parameters. */ -struct ipw_cmd { +struct ipw_cmd { /* XXX */ u32 cmd; /**< Host command */ u32 status;/**< Status */ u32 status_len; @@ -1092,7 +1096,7 @@ struct ipw_ibss_seq { struct list_head list; }; -struct ipw_error_elem { +struct ipw_error_elem { /* XXX */ u32 desc; u32 time; u32 blink1; @@ -1102,13 +1106,13 @@ struct ipw_error_elem { u32 data; }; -struct ipw_event { +struct ipw_event { /* XXX */ u32 event; u32 time; u32 data; } __attribute__ ((packed)); -struct ipw_fw_error { +struct ipw_fw_error { /* XXX */ unsigned long jiffies; u32 status; u32 config; @@ -1153,7 +1157,7 @@ struct ipw_prom_priv { */ struct ipw_rt_hdr { struct ieee80211_radiotap_header rt_hdr; - u64 rt_tsf; /* TSF */ + u64 rt_tsf; /* TSF */ /* XXX */ u8 rt_flags; /* radiotap packet flags */ u8 rt_rate; /* rate in 500kb/s */ __le16 rt_channel; /* channel in mhz */ @@ -1940,8 +1944,8 @@ enum { #define IPW_MEM_FIXED_OVERRIDE (IPW_SHARED_LOWER_BOUND + 0x41C) struct ipw_fixed_rate { - u16 tx_rates; - u16 reserved; + __le16 tx_rates; + __le16 reserved; } __attribute__ ((packed)); #define IPW_INDIRECT_ADDR_MASK (~0x3ul) @@ -1951,12 +1955,12 @@ struct host_cmd { u8 len; u16 reserved; u32 *param; -} __attribute__ ((packed)); +} __attribute__ ((packed)); /* XXX */ struct cmdlog_host_cmd { u8 cmd; u8 len; - u16 reserved; + __le16 reserved; char param[124]; } __attribute__ ((packed)); -- cgit v1.2.1 From 1ea8739648cfff4027c3db0f4cee5de87bfd3886 Mon Sep 17 00:00:00 2001 From: Assaf Krauss Date: Tue, 18 Mar 2008 14:57:50 -0700 Subject: iwlwifi: Completing the parameter packaging This patch completes the changes regarding the packaging of user parameters. Signed-off-by: Assaf Krauss Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965.c | 54 +++++++++++++++++++++++------ drivers/net/wireless/iwlwifi/iwl-4965.h | 9 +++-- drivers/net/wireless/iwlwifi/iwl4965-base.c | 46 +++++------------------- 3 files changed, 55 insertions(+), 54 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 46b3f47edefd..1db873b02f1e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -43,6 +43,14 @@ #include "iwl-4965.h" #include "iwl-helpers.h" +/* module parameters */ +static struct iwl_mod_params iwl4965_mod_params = { + .num_of_queues = IWL_MAX_NUM_QUEUES, + .enable_qos = 1, + .amsdu_size_8K = 1, + /* the rest are 0 by default */ +}; + static void iwl4965_hw_card_show_info(struct iwl_priv *priv); #define IWL_DECLARE_RATE_INFO(r, s, ip, in, rp, rn, pp, np) \ @@ -110,7 +118,7 @@ static int iwl4965_init_drv(struct iwl_priv *priv) int ret; int i; - priv->antenna = (enum iwl4965_antenna)iwl4965_mod_params.antenna; + priv->antenna = (enum iwl4965_antenna)priv->cfg->mod_params->antenna; priv->retry_rate = 1; priv->ibss_beacon = NULL; @@ -404,7 +412,7 @@ static int iwl4965_rx_init(struct iwl_priv *priv, struct iwl4965_rx_queue *rxq) return rc; } - if (iwl4965_mod_params.amsdu_size_8K) + if (priv->cfg->mod_params->amsdu_size_8K) rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K; else rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K; @@ -1877,8 +1885,8 @@ int iwl4965_hw_set_hw_setting(struct iwl_priv *priv) { int ret = 0; - if ((iwl4965_mod_params.num_of_queues > IWL_MAX_NUM_QUEUES) || - (iwl4965_mod_params.num_of_queues < IWL_MIN_NUM_QUEUES)) { + if ((priv->cfg->mod_params->num_of_queues > IWL_MAX_NUM_QUEUES) || + (priv->cfg->mod_params->num_of_queues < IWL_MIN_NUM_QUEUES)) { IWL_ERROR("invalid queues_num, should be between %d and %d\n", IWL_MIN_NUM_QUEUES, IWL_MAX_NUM_QUEUES); ret = -EINVAL; @@ -1898,11 +1906,11 @@ int iwl4965_hw_set_hw_setting(struct iwl_priv *priv) memset(priv->hw_setting.shared_virt, 0, sizeof(struct iwl4965_shared)); - priv->hw_setting.max_txq_num = iwl4965_mod_params.num_of_queues; + priv->hw_setting.max_txq_num = priv->cfg->mod_params->num_of_queues; priv->hw_setting.tx_cmd_len = sizeof(struct iwl4965_tx_cmd); priv->hw_setting.max_rxq_size = RX_QUEUE_SIZE; priv->hw_setting.max_rxq_log = RX_QUEUE_SIZE_LOG; - if (iwl4965_mod_params.amsdu_size_8K) + if (priv->cfg->mod_params->amsdu_size_8K) priv->hw_setting.rx_buf_size = IWL_RX_BUF_SIZE_8K; else priv->hw_setting.rx_buf_size = IWL_RX_BUF_SIZE_4K; @@ -3521,7 +3529,7 @@ static void iwl4965_handle_data_packet(struct iwl_priv *priv, int is_data, stats->flag = 0; hdr = (struct ieee80211_hdr *)rxb->skb->data; - if (iwl4965_mod_params.hw_crypto) + if (priv->cfg->mod_params->hw_crypto) iwl4965_set_decrypted_flag(priv, rxb->skb, ampdu_status, stats); if (priv->add_radiotap) @@ -3644,7 +3652,8 @@ static int parse_elems(u8 *start, size_t len, struct ieee802_11_elems *elems) return 0; } -void iwl4965_init_ht_hw_capab(struct ieee80211_ht_info *ht_info, +void iwl4965_init_ht_hw_capab(struct iwl_priv *priv, + struct ieee80211_ht_info *ht_info, enum ieee80211_band band) { ht_info->cap = 0; @@ -3661,10 +3670,9 @@ void iwl4965_init_ht_hw_capab(struct ieee80211_ht_info *ht_info, ht_info->cap |= (u16)IEEE80211_HT_CAP_SGI_20; ht_info->cap |= (u16)(IEEE80211_HT_CAP_MIMO_PS & (IWL_MIMO_PS_NONE << 2)); - if (iwl4965_mod_params.amsdu_size_8K) { - printk(KERN_DEBUG "iwl4965 in A-MSDU 8K support mode\n"); + + if (priv->cfg->mod_params->amsdu_size_8K) ht_info->cap |= (u16)IEEE80211_HT_CAP_MAX_AMSDU; - } ht_info->ampdu_factor = CFG_HT_RX_AMPDU_FACTOR_DEF; ht_info->ampdu_density = CFG_HT_MPDU_DENSITY_DEF; @@ -4970,6 +4978,7 @@ static struct iwl_cfg iwl4965_agn_cfg = { .fw_name = "iwlwifi-4965" IWL4965_UCODE_API ".ucode", .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, .ops = &iwl4965_ops, + .mod_params = &iwl4965_mod_params, }; struct pci_device_id iwl4965_hw_card_ids[] = { @@ -4979,3 +4988,26 @@ struct pci_device_id iwl4965_hw_card_ids[] = { }; MODULE_DEVICE_TABLE(pci, iwl4965_hw_card_ids); + +module_param_named(antenna, iwl4965_mod_params.antenna, int, 0444); +MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); +module_param_named(disable, iwl4965_mod_params.disable, int, 0444); +MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])"); +module_param_named(hwcrypto, iwl4965_mod_params.hw_crypto, int, 0444); +MODULE_PARM_DESC(hwcrypto, + "using hardware crypto engine (default 0 [software])\n"); +module_param_named(debug, iwl4965_mod_params.debug, int, 0444); +MODULE_PARM_DESC(debug, "debug output mask"); +module_param_named( + disable_hw_scan, iwl4965_mod_params.disable_hw_scan, int, 0444); +MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)"); + +module_param_named(queues_num, iwl4965_mod_params.num_of_queues, int, 0444); +MODULE_PARM_DESC(queues_num, "number of hw queues."); + +/* QoS */ +module_param_named(qos_enable, iwl4965_mod_params.enable_qos, int, 0444); +MODULE_PARM_DESC(qos_enable, "enable all QoS functionality"); +module_param_named(amsdu_size_8K, iwl4965_mod_params.amsdu_size_8K, int, 0444); +MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size"); + diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index 810b8e28dc83..960b53b20df8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -66,9 +66,6 @@ extern struct pci_device_id iwl4965_hw_card_ids[]; * averages within an s8's (used in some apps) range of negative values. */ #define IWL_NOISE_MEAS_NOT_AVAILABLE (-127) -/* Module parameters accessible from iwl-*.c */ -extern struct iwl_mod_params iwl4965_mod_params; - enum iwl4965_antenna { IWL_ANTENNA_DIVERSITY, IWL_ANTENNA_MAIN, @@ -761,7 +758,8 @@ extern void iwl4965_hwrate_to_tx_control(struct iwl_priv *priv, struct ieee80211_tx_control *control); #ifdef CONFIG_IWL4965_HT -void iwl4965_init_ht_hw_capab(struct ieee80211_ht_info *ht_info, +void iwl4965_init_ht_hw_capab(struct iwl_priv *priv, + struct ieee80211_ht_info *ht_info, enum ieee80211_band band); void iwl4965_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info); @@ -773,7 +771,8 @@ int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw, int iwl4965_check_empty_hw_queue(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id); #else -static inline void iwl4965_init_ht_hw_capab(struct ieee80211_ht_info *ht_info, +static inline void iwl4965_init_ht_hw_capab(struct iwl_priv *priv, + struct ieee80211_ht_info *ht_info, enum ieee80211_band band) {} #endif /*CONFIG_IWL4965_HT */ diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 8fe09e893279..44cfd0274976 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -59,14 +59,6 @@ static int iwl4965_tx_queue_update_write_ptr(struct iwl_priv *priv, * ******************************************************************************/ -/* module parameters */ -struct iwl_mod_params iwl4965_mod_params = { - .num_of_queues = IWL_MAX_NUM_QUEUES, - .enable_qos = 1, - .amsdu_size_8K = 1, - /* the rest are 0 by default */ -}; - /* * module name, copyright, version, etc. * NOTE: DRV_NAME is defined in iwlwifi.h for use by iwl-debug.h and printk @@ -4933,7 +4925,7 @@ int iwl4965_init_geos(struct iwl_priv *priv) sband->bitrates = &rates[IWL_FIRST_OFDM_RATE]; sband->n_bitrates = IWL_RATE_COUNT - IWL_FIRST_OFDM_RATE; - iwl4965_init_ht_hw_capab(&sband->ht_info, IEEE80211_BAND_5GHZ); + iwl4965_init_ht_hw_capab(priv, &sband->ht_info, IEEE80211_BAND_5GHZ); sband = &priv->bands[IEEE80211_BAND_2GHZ]; sband->channels = channels; @@ -4941,7 +4933,7 @@ int iwl4965_init_geos(struct iwl_priv *priv) sband->bitrates = rates; sband->n_bitrates = IWL_RATE_COUNT; - iwl4965_init_ht_hw_capab(&sband->ht_info, IEEE80211_BAND_2GHZ); + iwl4965_init_ht_hw_capab(priv, &sband->ht_info, IEEE80211_BAND_2GHZ); priv->ieee_channels = channels; priv->ieee_rates = rates; @@ -6614,7 +6606,7 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co goto out; } - if (unlikely(!iwl4965_mod_params.disable_hw_scan && + if (unlikely(!priv->cfg->mod_params->disable_hw_scan && test_bit(STATUS_SCANNING, &priv->status))) { IWL_DEBUG_MAC80211("leave - scanning\n"); set_bit(STATUS_CONF_PENDING, &priv->status); @@ -7050,7 +7042,7 @@ static int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, IWL_DEBUG_MAC80211("enter\n"); - if (!iwl4965_mod_params.hw_crypto) { + if (!priv->cfg->mod_params->hw_crypto) { IWL_DEBUG_MAC80211("leave - hwcrypto disabled\n"); return -EOPNOTSUPP; } @@ -8008,7 +8000,7 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e /* Disabling hardware scan means that mac80211 will perform scans * "the hard way", rather than using device's scan. */ - if (iwl4965_mod_params.disable_hw_scan) { + if (cfg->mod_params->disable_hw_scan) { IWL_DEBUG_INFO("Disabling hw_scan\n"); iwl4965_hw_ops.hw_scan = NULL; } @@ -8028,7 +8020,7 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e priv->pci_dev = pdev; #ifdef CONFIG_IWLWIFI_DEBUG - iwl_debug_level = iwl4965_mod_params.debug; + iwl_debug_level = priv->cfg->mod_params->debug; atomic_set(&priv->restrict_refcnt, 0); #endif @@ -8126,12 +8118,12 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e **********************************/ /* Disable radio (SW RF KILL) via parameter when loading driver */ - if (iwl4965_mod_params.disable) { + if (priv->cfg->mod_params->disable) { set_bit(STATUS_RF_KILL_SW, &priv->status); IWL_DEBUG_INFO("Radio disabled.\n"); } - if (iwl4965_mod_params.enable_qos) + if (priv->cfg->mod_params->enable_qos) priv->qos_data.qos_enable = 1; /******************** @@ -8322,27 +8314,5 @@ static void __exit iwl4965_exit(void) pci_unregister_driver(&iwl4965_driver); } -module_param_named(antenna, iwl4965_mod_params.antenna, int, 0444); -MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); -module_param_named(disable, iwl4965_mod_params.disable, int, 0444); -MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])"); -module_param_named(hwcrypto, iwl4965_mod_params.hw_crypto, int, 0444); -MODULE_PARM_DESC(hwcrypto, - "using hardware crypto engine (default 0 [software])\n"); -module_param_named(debug, iwl4965_mod_params.debug, int, 0444); -MODULE_PARM_DESC(debug, "debug output mask"); -module_param_named( - disable_hw_scan, iwl4965_mod_params.disable_hw_scan, int, 0444); -MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)"); - -module_param_named(queues_num, iwl4965_mod_params.num_of_queues, int, 0444); -MODULE_PARM_DESC(queues_num, "number of hw queues."); - -/* QoS */ -module_param_named(qos_enable, iwl4965_mod_params.enable_qos, int, 0444); -MODULE_PARM_DESC(qos_enable, "enable all QoS functionality"); -module_param_named(amsdu_size_8K, iwl4965_mod_params.amsdu_size_8K, int, 0444); -MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size"); - module_exit(iwl4965_exit); module_init(iwl4965_init); -- cgit v1.2.1 From c01f9c6f1d5ceffda59a983c95338be45223d155 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sun, 23 Mar 2008 01:33:58 +0100 Subject: b43: Don't compile N-PHY code when N-PHY is disabled There's no need to compile the N-PHY support code, when the N-PHY support is disabled in Kconfig. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/Makefile | 4 ++-- drivers/net/wireless/b43/nphy.h | 40 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/b43/Makefile b/drivers/net/wireless/b43/Makefile index ac1329dba045..ae11fe4c0be6 100644 --- a/drivers/net/wireless/b43/Makefile +++ b/drivers/net/wireless/b43/Makefile @@ -1,8 +1,8 @@ b43-y += main.o b43-y += tables.o -b43-y += tables_nphy.o +b43-$(CONFIG_B43_NPHY) += tables_nphy.o b43-y += phy.o -b43-y += nphy.o +b43-$(CONFIG_B43_NPHY) += nphy.o b43-y += sysfs.o b43-y += xmit.o b43-y += lo.o diff --git a/drivers/net/wireless/b43/nphy.h b/drivers/net/wireless/b43/nphy.h index 5d95118b8193..faf46b9cbf1b 100644 --- a/drivers/net/wireless/b43/nphy.h +++ b/drivers/net/wireless/b43/nphy.h @@ -919,6 +919,10 @@ struct b43_wldev; + +#ifdef CONFIG_B43_NPHY +/* N-PHY support enabled */ + int b43_phy_initn(struct b43_wldev *dev); void b43_nphy_radio_turn_on(struct b43_wldev *dev); @@ -929,4 +933,40 @@ int b43_nphy_selectchannel(struct b43_wldev *dev, u8 channel); void b43_nphy_xmitpower(struct b43_wldev *dev); void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna); + +#else /* CONFIG_B43_NPHY */ +/* N-PHY support disabled */ + + +static inline +int b43_phy_initn(struct b43_wldev *dev) +{ + return -EOPNOTSUPP; +} + +static inline +void b43_nphy_radio_turn_on(struct b43_wldev *dev) +{ +} +static inline +void b43_nphy_radio_turn_off(struct b43_wldev *dev) +{ +} + +static inline +int b43_nphy_selectchannel(struct b43_wldev *dev, u8 channel) +{ + return -ENOSYS; +} + +static inline +void b43_nphy_xmitpower(struct b43_wldev *dev) +{ +} +static inline +void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna) +{ +} + +#endif /* CONFIG_B43_NPHY */ #endif /* B43_NPHY_H_ */ -- cgit v1.2.1 From 866a05038481d77cac6fc0186250b4c44e691b42 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Tue, 25 Mar 2008 14:12:45 +0100 Subject: rt2x00: Fix rate detection for invalid signals It has been observed on rt2500pci hardware that some frames received with signal 0x0C do not have the OFDM flag set. Signals can have 2 meanings: 1) The PLCP value 2) The bitrate * 10 For rt2500pci (1) is for frames received with a OFDM rate, and (2) is for frames received with a CCK rate. But 0x0C is a invalid bitrate value but is a valid PLCP value for 54Mbs (obvious OFDM rate). This means that it is possible that the hardware does not set the OFDM bit correctly under all circumstances. This results in rt2x00 failing to detect the rate and mac80211 triggering a WARN_ON() and dropping the frame. To bypass this, print a warning when such a frame is received, and reset the rate to the lowest supported rate for the current band. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00dev.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 4fd0c25aebf3..f52e92512f90 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -589,6 +589,13 @@ void rt2x00lib_rxdone(struct queue_entry *entry, } } + if (idx < 0) { + WARNING(rt2x00dev, "Frame received with unrecognized signal," + "signal=0x%.2x, plcp=%d.\n", rxdesc->signal, + !!(rxdesc->dev_flags & RXDONE_SIGNAL_PLCP)); + idx = 0; + } + /* * Only update link status if this is a beacon frame carrying our bssid. */ -- cgit v1.2.1 From 3a643d244f09fa1fdd25d48a56a073c1a69583ee Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Tue, 25 Mar 2008 14:13:18 +0100 Subject: rt2x00: Fix in_atomic() usage rt73usb and rt2500usb used in_atomic to determine if a configuration step should be rescheduled or not. Since in_atomic() is not a valid method to determine if sleeping is allowed we should fix the way this is handled by adding a new flag to rt2x00. In addition mark LED class support for the drivers broken since that also uses the broken in_atomic() method but so far no solution exists to have LED triggers work only in scheduled context. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/Kconfig | 4 +- drivers/net/wireless/rt2x00/rt2400pci.c | 92 +++++++--------------- drivers/net/wireless/rt2x00/rt2500pci.c | 101 ++++++++---------------- drivers/net/wireless/rt2x00/rt2500usb.c | 118 ++++++++-------------------- drivers/net/wireless/rt2x00/rt2x00.h | 11 ++- drivers/net/wireless/rt2x00/rt2x00config.c | 10 +-- drivers/net/wireless/rt2x00/rt2x00mac.c | 57 +++++++++++++- drivers/net/wireless/rt2x00/rt61pci.c | 105 +++++++++---------------- drivers/net/wireless/rt2x00/rt73usb.c | 122 +++++++++-------------------- 9 files changed, 234 insertions(+), 386 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index 4709c11da419..ad1549592c00 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig @@ -134,7 +134,7 @@ config RT2500USB config RT2500USB_LEDS bool "RT2500 leds support" - depends on RT2500USB + depends on RT2500USB && BROKEN select RT2X00_LIB_LEDS ---help--- This adds support for led triggers provided my mac80211. @@ -152,7 +152,7 @@ config RT73USB config RT73USB_LEDS bool "RT73 leds support" - depends on RT73USB + depends on RT73USB && BROKEN select RT2X00_LIB_LEDS ---help--- This adds support for led triggers provided my mac80211. diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index c58b1c0abc3c..a6e9c89c802a 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -270,6 +270,31 @@ static void rt2400pci_led_brightness(struct led_classdev *led_cdev, /* * Configuration handlers. */ +static void rt2400pci_config_filter(struct rt2x00_dev *rt2x00dev, + const unsigned int filter_flags) +{ + u32 reg; + + /* + * Start configuration steps. + * Note that the version error will always be dropped + * since there is no filter for it at this time. + */ + rt2x00pci_register_read(rt2x00dev, RXCSR0, ®); + rt2x00_set_field32(®, RXCSR0_DROP_CRC, + !(filter_flags & FIF_FCSFAIL)); + rt2x00_set_field32(®, RXCSR0_DROP_PHYSICAL, + !(filter_flags & FIF_PLCPFAIL)); + rt2x00_set_field32(®, RXCSR0_DROP_CONTROL, + !(filter_flags & FIF_CONTROL)); + rt2x00_set_field32(®, RXCSR0_DROP_NOT_TO_ME, + !(filter_flags & FIF_PROMISC_IN_BSS)); + rt2x00_set_field32(®, RXCSR0_DROP_TODS, + !(filter_flags & FIF_PROMISC_IN_BSS)); + rt2x00_set_field32(®, RXCSR0_DROP_VERSION_ERROR, 1); + rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); +} + static void rt2400pci_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf, struct rt2x00intf_conf *conf, @@ -306,8 +331,8 @@ static void rt2400pci_config_intf(struct rt2x00_dev *rt2x00dev, conf->bssid, sizeof(conf->bssid)); } -static int rt2400pci_config_erp(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_erp *erp) +static void rt2400pci_config_erp(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_erp *erp) { int preamble_mask; u32 reg; @@ -347,8 +372,6 @@ static int rt2400pci_config_erp(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(®, ARCSR5_SERVICE, 0x84); rt2x00_set_field32(®, ARCSR2_LENGTH, get_duration(ACK_SIZE, 110)); rt2x00pci_register_write(rt2x00dev, ARCSR5, reg); - - return 0; } static void rt2400pci_config_phymode(struct rt2x00_dev *rt2x00dev, @@ -1397,64 +1420,6 @@ static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev) /* * IEEE80211 stack callback functions. */ -static void rt2400pci_configure_filter(struct ieee80211_hw *hw, - unsigned int changed_flags, - unsigned int *total_flags, - int mc_count, - struct dev_addr_list *mc_list) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - u32 reg; - - /* - * Mask off any flags we are going to ignore from - * the total_flags field. - */ - *total_flags &= - FIF_ALLMULTI | - FIF_FCSFAIL | - FIF_PLCPFAIL | - FIF_CONTROL | - FIF_OTHER_BSS | - FIF_PROMISC_IN_BSS; - - /* - * Apply some rules to the filters: - * - Some filters imply different filters to be set. - * - Some things we can't filter out at all. - */ - *total_flags |= FIF_ALLMULTI; - if (*total_flags & FIF_OTHER_BSS || - *total_flags & FIF_PROMISC_IN_BSS) - *total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS; - - /* - * Check if there is any work left for us. - */ - if (rt2x00dev->packet_filter == *total_flags) - return; - rt2x00dev->packet_filter = *total_flags; - - /* - * Start configuration steps. - * Note that the version error will always be dropped - * since there is no filter for it at this time. - */ - rt2x00pci_register_read(rt2x00dev, RXCSR0, ®); - rt2x00_set_field32(®, RXCSR0_DROP_CRC, - !(*total_flags & FIF_FCSFAIL)); - rt2x00_set_field32(®, RXCSR0_DROP_PHYSICAL, - !(*total_flags & FIF_PLCPFAIL)); - rt2x00_set_field32(®, RXCSR0_DROP_CONTROL, - !(*total_flags & FIF_CONTROL)); - rt2x00_set_field32(®, RXCSR0_DROP_NOT_TO_ME, - !(*total_flags & FIF_PROMISC_IN_BSS)); - rt2x00_set_field32(®, RXCSR0_DROP_TODS, - !(*total_flags & FIF_PROMISC_IN_BSS)); - rt2x00_set_field32(®, RXCSR0_DROP_VERSION_ERROR, 1); - rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); -} - static int rt2400pci_set_retry_limit(struct ieee80211_hw *hw, u32 short_retry, u32 long_retry) { @@ -1580,7 +1545,7 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = { .remove_interface = rt2x00mac_remove_interface, .config = rt2x00mac_config, .config_interface = rt2x00mac_config_interface, - .configure_filter = rt2400pci_configure_filter, + .configure_filter = rt2x00mac_configure_filter, .get_stats = rt2x00mac_get_stats, .set_retry_limit = rt2400pci_set_retry_limit, .bss_info_changed = rt2x00mac_bss_info_changed, @@ -1608,6 +1573,7 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { .write_tx_data = rt2x00pci_write_tx_data, .kick_tx_queue = rt2400pci_kick_tx_queue, .fill_rxdone = rt2400pci_fill_rxdone, + .config_filter = rt2400pci_config_filter, .config_intf = rt2400pci_config_intf, .config_erp = rt2400pci_config_erp, .config = rt2400pci_config, diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 9468dde3c95e..1bdb873b65f2 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -270,6 +270,35 @@ static void rt2500pci_led_brightness(struct led_classdev *led_cdev, /* * Configuration handlers. */ +static void rt2500pci_config_filter(struct rt2x00_dev *rt2x00dev, + const unsigned int filter_flags) +{ + u32 reg; + + /* + * Start configuration steps. + * Note that the version error will always be dropped + * and broadcast frames will always be accepted since + * there is no filter for it at this time. + */ + rt2x00pci_register_read(rt2x00dev, RXCSR0, ®); + rt2x00_set_field32(®, RXCSR0_DROP_CRC, + !(filter_flags & FIF_FCSFAIL)); + rt2x00_set_field32(®, RXCSR0_DROP_PHYSICAL, + !(filter_flags & FIF_PLCPFAIL)); + rt2x00_set_field32(®, RXCSR0_DROP_CONTROL, + !(filter_flags & FIF_CONTROL)); + rt2x00_set_field32(®, RXCSR0_DROP_NOT_TO_ME, + !(filter_flags & FIF_PROMISC_IN_BSS)); + rt2x00_set_field32(®, RXCSR0_DROP_TODS, + !(filter_flags & FIF_PROMISC_IN_BSS)); + rt2x00_set_field32(®, RXCSR0_DROP_VERSION_ERROR, 1); + rt2x00_set_field32(®, RXCSR0_DROP_MCAST, + !(filter_flags & FIF_ALLMULTI)); + rt2x00_set_field32(®, RXCSR0_DROP_BCAST, 0); + rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); +} + static void rt2500pci_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf, struct rt2x00intf_conf *conf, @@ -309,8 +338,8 @@ static void rt2500pci_config_intf(struct rt2x00_dev *rt2x00dev, conf->bssid, sizeof(conf->bssid)); } -static int rt2500pci_config_erp(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_erp *erp) +static void rt2500pci_config_erp(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_erp *erp) { int preamble_mask; u32 reg; @@ -350,8 +379,6 @@ static int rt2500pci_config_erp(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(®, ARCSR5_SERVICE, 0x84); rt2x00_set_field32(®, ARCSR2_LENGTH, get_duration(ACK_SIZE, 110)); rt2x00pci_register_write(rt2x00dev, ARCSR5, reg); - - return 0; } static void rt2500pci_config_phymode(struct rt2x00_dev *rt2x00dev, @@ -1731,69 +1758,6 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev) /* * IEEE80211 stack callback functions. */ -static void rt2500pci_configure_filter(struct ieee80211_hw *hw, - unsigned int changed_flags, - unsigned int *total_flags, - int mc_count, - struct dev_addr_list *mc_list) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - u32 reg; - - /* - * Mask off any flags we are going to ignore from - * the total_flags field. - */ - *total_flags &= - FIF_ALLMULTI | - FIF_FCSFAIL | - FIF_PLCPFAIL | - FIF_CONTROL | - FIF_OTHER_BSS | - FIF_PROMISC_IN_BSS; - - /* - * Apply some rules to the filters: - * - Some filters imply different filters to be set. - * - Some things we can't filter out at all. - */ - if (mc_count) - *total_flags |= FIF_ALLMULTI; - if (*total_flags & FIF_OTHER_BSS || - *total_flags & FIF_PROMISC_IN_BSS) - *total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS; - - /* - * Check if there is any work left for us. - */ - if (rt2x00dev->packet_filter == *total_flags) - return; - rt2x00dev->packet_filter = *total_flags; - - /* - * Start configuration steps. - * Note that the version error will always be dropped - * and broadcast frames will always be accepted since - * there is no filter for it at this time. - */ - rt2x00pci_register_read(rt2x00dev, RXCSR0, ®); - rt2x00_set_field32(®, RXCSR0_DROP_CRC, - !(*total_flags & FIF_FCSFAIL)); - rt2x00_set_field32(®, RXCSR0_DROP_PHYSICAL, - !(*total_flags & FIF_PLCPFAIL)); - rt2x00_set_field32(®, RXCSR0_DROP_CONTROL, - !(*total_flags & FIF_CONTROL)); - rt2x00_set_field32(®, RXCSR0_DROP_NOT_TO_ME, - !(*total_flags & FIF_PROMISC_IN_BSS)); - rt2x00_set_field32(®, RXCSR0_DROP_TODS, - !(*total_flags & FIF_PROMISC_IN_BSS)); - rt2x00_set_field32(®, RXCSR0_DROP_VERSION_ERROR, 1); - rt2x00_set_field32(®, RXCSR0_DROP_MCAST, - !(*total_flags & FIF_ALLMULTI)); - rt2x00_set_field32(®, RXCSR0_DROP_BCAST, 0); - rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); -} - static int rt2500pci_set_retry_limit(struct ieee80211_hw *hw, u32 short_retry, u32 long_retry) { @@ -1894,7 +1858,7 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = { .remove_interface = rt2x00mac_remove_interface, .config = rt2x00mac_config, .config_interface = rt2x00mac_config_interface, - .configure_filter = rt2500pci_configure_filter, + .configure_filter = rt2x00mac_configure_filter, .get_stats = rt2x00mac_get_stats, .set_retry_limit = rt2500pci_set_retry_limit, .bss_info_changed = rt2x00mac_bss_info_changed, @@ -1922,6 +1886,7 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = { .write_tx_data = rt2x00pci_write_tx_data, .kick_tx_queue = rt2500pci_kick_tx_queue, .fill_rxdone = rt2500pci_fill_rxdone, + .config_filter = rt2500pci_config_filter, .config_intf = rt2500pci_config_intf, .config_erp = rt2500pci_config_erp, .config = rt2500pci_config, diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 8959a684f40b..f5c18f011e93 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -316,6 +316,35 @@ static void rt2500usb_led_brightness(struct led_classdev *led_cdev, /* * Configuration handlers. */ +static void rt2500usb_config_filter(struct rt2x00_dev *rt2x00dev, + const unsigned int filter_flags) +{ + u16 reg; + + /* + * Start configuration steps. + * Note that the version error will always be dropped + * and broadcast frames will always be accepted since + * there is no filter for it at this time. + */ + rt2500usb_register_read(rt2x00dev, TXRX_CSR2, ®); + rt2x00_set_field16(®, TXRX_CSR2_DROP_CRC, + !(filter_flags & FIF_FCSFAIL)); + rt2x00_set_field16(®, TXRX_CSR2_DROP_PHYSICAL, + !(filter_flags & FIF_PLCPFAIL)); + rt2x00_set_field16(®, TXRX_CSR2_DROP_CONTROL, + !(filter_flags & FIF_CONTROL)); + rt2x00_set_field16(®, TXRX_CSR2_DROP_NOT_TO_ME, + !(filter_flags & FIF_PROMISC_IN_BSS)); + rt2x00_set_field16(®, TXRX_CSR2_DROP_TODS, + !(filter_flags & FIF_PROMISC_IN_BSS)); + rt2x00_set_field16(®, TXRX_CSR2_DROP_VERSION_ERROR, 1); + rt2x00_set_field16(®, TXRX_CSR2_DROP_MULTICAST, + !(filter_flags & FIF_ALLMULTI)); + rt2x00_set_field16(®, TXRX_CSR2_DROP_BROADCAST, 0); + rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg); +} + static void rt2500usb_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf, struct rt2x00intf_conf *conf, @@ -358,18 +387,11 @@ static void rt2500usb_config_intf(struct rt2x00_dev *rt2x00dev, (3 * sizeof(__le16))); } -static int rt2500usb_config_erp(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_erp *erp) +static void rt2500usb_config_erp(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_erp *erp) { u16 reg; - /* - * When in atomic context, we should let rt2x00lib - * try this configuration again later. - */ - if (in_atomic()) - return -EAGAIN; - rt2500usb_register_read(rt2x00dev, TXRX_CSR1, ®); rt2x00_set_field16(®, TXRX_CSR1_ACK_TIMEOUT, erp->ack_timeout); rt2500usb_register_write(rt2x00dev, TXRX_CSR1, reg); @@ -378,8 +400,6 @@ static int rt2500usb_config_erp(struct rt2x00_dev *rt2x00dev, rt2x00_set_field16(®, TXRX_CSR10_AUTORESPOND_PREAMBLE, !!erp->short_preamble); rt2500usb_register_write(rt2x00dev, TXRX_CSR10, reg); - - return 0; } static void rt2500usb_config_phymode(struct rt2x00_dev *rt2x00dev, @@ -1644,6 +1664,7 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev) */ __set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags); __set_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags); + __set_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags); /* * Set the rssi offset. @@ -1656,78 +1677,6 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev) /* * IEEE80211 stack callback functions. */ -static void rt2500usb_configure_filter(struct ieee80211_hw *hw, - unsigned int changed_flags, - unsigned int *total_flags, - int mc_count, - struct dev_addr_list *mc_list) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - u16 reg; - - /* - * Mask off any flags we are going to ignore from - * the total_flags field. - */ - *total_flags &= - FIF_ALLMULTI | - FIF_FCSFAIL | - FIF_PLCPFAIL | - FIF_CONTROL | - FIF_OTHER_BSS | - FIF_PROMISC_IN_BSS; - - /* - * Apply some rules to the filters: - * - Some filters imply different filters to be set. - * - Some things we can't filter out at all. - */ - if (mc_count) - *total_flags |= FIF_ALLMULTI; - if (*total_flags & FIF_OTHER_BSS || - *total_flags & FIF_PROMISC_IN_BSS) - *total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS; - - /* - * Check if there is any work left for us. - */ - if (rt2x00dev->packet_filter == *total_flags) - return; - rt2x00dev->packet_filter = *total_flags; - - /* - * When in atomic context, reschedule and let rt2x00lib - * call this function again. - */ - if (in_atomic()) { - queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->filter_work); - return; - } - - /* - * Start configuration steps. - * Note that the version error will always be dropped - * and broadcast frames will always be accepted since - * there is no filter for it at this time. - */ - rt2500usb_register_read(rt2x00dev, TXRX_CSR2, ®); - rt2x00_set_field16(®, TXRX_CSR2_DROP_CRC, - !(*total_flags & FIF_FCSFAIL)); - rt2x00_set_field16(®, TXRX_CSR2_DROP_PHYSICAL, - !(*total_flags & FIF_PLCPFAIL)); - rt2x00_set_field16(®, TXRX_CSR2_DROP_CONTROL, - !(*total_flags & FIF_CONTROL)); - rt2x00_set_field16(®, TXRX_CSR2_DROP_NOT_TO_ME, - !(*total_flags & FIF_PROMISC_IN_BSS)); - rt2x00_set_field16(®, TXRX_CSR2_DROP_TODS, - !(*total_flags & FIF_PROMISC_IN_BSS)); - rt2x00_set_field16(®, TXRX_CSR2_DROP_VERSION_ERROR, 1); - rt2x00_set_field16(®, TXRX_CSR2_DROP_MULTICAST, - !(*total_flags & FIF_ALLMULTI)); - rt2x00_set_field16(®, TXRX_CSR2_DROP_BROADCAST, 0); - rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg); -} - static int rt2500usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, struct ieee80211_tx_control *control) @@ -1824,7 +1773,7 @@ static const struct ieee80211_ops rt2500usb_mac80211_ops = { .remove_interface = rt2x00mac_remove_interface, .config = rt2x00mac_config, .config_interface = rt2x00mac_config_interface, - .configure_filter = rt2500usb_configure_filter, + .configure_filter = rt2x00mac_configure_filter, .get_stats = rt2x00mac_get_stats, .bss_info_changed = rt2x00mac_bss_info_changed, .conf_tx = rt2x00mac_conf_tx, @@ -1848,6 +1797,7 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { .get_tx_data_len = rt2500usb_get_tx_data_len, .kick_tx_queue = rt2500usb_kick_tx_queue, .fill_rxdone = rt2500usb_fill_rxdone, + .config_filter = rt2500usb_config_filter, .config_intf = rt2500usb_config_intf, .config_erp = rt2500usb_config_erp, .config = rt2500usb_config, diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index c016bfe1defd..333484ddb993 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -560,6 +560,8 @@ struct rt2x00lib_ops { /* * Configuration handlers. */ + void (*config_filter) (struct rt2x00_dev *rt2x00dev, + const unsigned int filter_flags); void (*config_intf) (struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf, struct rt2x00intf_conf *conf, @@ -568,8 +570,8 @@ struct rt2x00lib_ops { #define CONFIG_UPDATE_MAC ( 1 << 2 ) #define CONFIG_UPDATE_BSSID ( 1 << 3 ) - int (*config_erp) (struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_erp *erp); + void (*config_erp) (struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_erp *erp); void (*config) (struct rt2x00_dev *rt2x00dev, struct rt2x00lib_conf *libconf, const unsigned int flags); @@ -624,6 +626,7 @@ enum rt2x00_flags { DRIVER_REQUIRE_FIRMWARE, DRIVER_REQUIRE_BEACON_GUARD, DRIVER_REQUIRE_ATIM_QUEUE, + DRIVER_REQUIRE_SCHEDULED, /* * Driver configuration @@ -987,6 +990,10 @@ int rt2x00mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf); int rt2x00mac_config_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_if_conf *conf); +void rt2x00mac_configure_filter(struct ieee80211_hw *hw, + unsigned int changed_flags, + unsigned int *total_flags, + int mc_count, struct dev_addr_list *mc_list); int rt2x00mac_get_stats(struct ieee80211_hw *hw, struct ieee80211_low_level_stats *stats); int rt2x00mac_get_tx_stats(struct ieee80211_hw *hw, diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index 5e2d81a9e438..a9930a03f450 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c @@ -80,7 +80,6 @@ void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev, struct ieee80211_bss_conf *bss_conf) { struct rt2x00lib_erp erp; - int retval; memset(&erp, 0, sizeof(erp)); @@ -101,14 +100,7 @@ void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev, erp.ack_consume_time += PREAMBLE; } - retval = rt2x00dev->ops->lib->config_erp(rt2x00dev, &erp); - - if (retval) { - spin_lock(&intf->lock); - intf->delayed_flags |= DELAYED_CONFIG_ERP; - queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->intf_work); - spin_unlock(&intf->lock); - } + rt2x00dev->ops->lib->config_erp(rt2x00dev, &erp); } void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 0a11c27d603b..17b6bb034ebf 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -380,6 +380,50 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw, } EXPORT_SYMBOL_GPL(rt2x00mac_config_interface); +void rt2x00mac_configure_filter(struct ieee80211_hw *hw, + unsigned int changed_flags, + unsigned int *total_flags, + int mc_count, struct dev_addr_list *mc_list) +{ + struct rt2x00_dev *rt2x00dev = hw->priv; + + /* + * Mask off any flags we are going to ignore + * from the total_flags field. + */ + *total_flags &= + FIF_ALLMULTI | + FIF_FCSFAIL | + FIF_PLCPFAIL | + FIF_CONTROL | + FIF_OTHER_BSS | + FIF_PROMISC_IN_BSS; + + /* + * Apply some rules to the filters: + * - Some filters imply different filters to be set. + * - Some things we can't filter out at all. + * - Multicast filter seems to kill broadcast traffic so never use it. + */ + *total_flags |= FIF_ALLMULTI; + if (*total_flags & FIF_OTHER_BSS || + *total_flags & FIF_PROMISC_IN_BSS) + *total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS; + + /* + * Check if there is any work left for us. + */ + if (rt2x00dev->packet_filter == *total_flags) + return; + rt2x00dev->packet_filter = *total_flags; + + if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags)) + queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->filter_work); + else + rt2x00dev->ops->lib->config_filter(rt2x00dev, *total_flags); +} +EXPORT_SYMBOL_GPL(rt2x00mac_configure_filter); + int rt2x00mac_get_stats(struct ieee80211_hw *hw, struct ieee80211_low_level_stats *stats) { @@ -419,6 +463,7 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, { struct rt2x00_dev *rt2x00dev = hw->priv; struct rt2x00_intf *intf = vif_to_intf(vif); + unsigned int delayed = 0; /* * When the association status has changed we must reset the link @@ -439,11 +484,19 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, * When the erp information has changed, we should perform * additional configuration steps. For all other changes we are done. */ - if (changes & BSS_CHANGED_ERP_PREAMBLE) - rt2x00lib_config_erp(rt2x00dev, intf, bss_conf); + if (changes & BSS_CHANGED_ERP_PREAMBLE) { + if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags)) + rt2x00lib_config_erp(rt2x00dev, intf, bss_conf); + else + delayed |= DELAYED_CONFIG_ERP; + } spin_lock(&intf->lock); memcpy(&intf->conf, bss_conf, sizeof(*bss_conf)); + if (delayed) { + intf->delayed_flags |= delayed; + queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->intf_work); + } spin_unlock(&intf->lock); } EXPORT_SYMBOL_GPL(rt2x00mac_bss_info_changed); diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 6e643c8db42e..0d2e6f7dd692 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -321,6 +321,37 @@ static void rt61pci_led_brightness(struct led_classdev *led_cdev, /* * Configuration handlers. */ +static void rt61pci_config_filter(struct rt2x00_dev *rt2x00dev, + const unsigned int filter_flags) +{ + u32 reg; + + /* + * Start configuration steps. + * Note that the version error will always be dropped + * and broadcast frames will always be accepted since + * there is no filter for it at this time. + */ + rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, ®); + rt2x00_set_field32(®, TXRX_CSR0_DROP_CRC, + !(filter_flags & FIF_FCSFAIL)); + rt2x00_set_field32(®, TXRX_CSR0_DROP_PHYSICAL, + !(filter_flags & FIF_PLCPFAIL)); + rt2x00_set_field32(®, TXRX_CSR0_DROP_CONTROL, + !(filter_flags & FIF_CONTROL)); + rt2x00_set_field32(®, TXRX_CSR0_DROP_NOT_TO_ME, + !(filter_flags & FIF_PROMISC_IN_BSS)); + rt2x00_set_field32(®, TXRX_CSR0_DROP_TO_DS, + !(filter_flags & FIF_PROMISC_IN_BSS)); + rt2x00_set_field32(®, TXRX_CSR0_DROP_VERSION_ERROR, 1); + rt2x00_set_field32(®, TXRX_CSR0_DROP_MULTICAST, + !(filter_flags & FIF_ALLMULTI)); + rt2x00_set_field32(®, TXRX_CSR0_DROP_BROADCAST, 0); + rt2x00_set_field32(®, TXRX_CSR0_DROP_ACK_CTS, + !(filter_flags & FIF_CONTROL)); + rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg); +} + static void rt61pci_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf, struct rt2x00intf_conf *conf, @@ -368,8 +399,8 @@ static void rt61pci_config_intf(struct rt2x00_dev *rt2x00dev, } } -static int rt61pci_config_erp(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_erp *erp) +static void rt61pci_config_erp(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_erp *erp) { u32 reg; @@ -381,8 +412,6 @@ static int rt61pci_config_erp(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_PREAMBLE, !!erp->short_preamble); rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg); - - return 0; } static void rt61pci_config_phymode(struct rt2x00_dev *rt2x00dev, @@ -2284,71 +2313,6 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev) /* * IEEE80211 stack callback functions. */ -static void rt61pci_configure_filter(struct ieee80211_hw *hw, - unsigned int changed_flags, - unsigned int *total_flags, - int mc_count, - struct dev_addr_list *mc_list) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - u32 reg; - - /* - * Mask off any flags we are going to ignore from - * the total_flags field. - */ - *total_flags &= - FIF_ALLMULTI | - FIF_FCSFAIL | - FIF_PLCPFAIL | - FIF_CONTROL | - FIF_OTHER_BSS | - FIF_PROMISC_IN_BSS; - - /* - * Apply some rules to the filters: - * - Some filters imply different filters to be set. - * - Some things we can't filter out at all. - * - Multicast filter seems to kill broadcast traffic so never use it. - */ - *total_flags |= FIF_ALLMULTI; - if (*total_flags & FIF_OTHER_BSS || - *total_flags & FIF_PROMISC_IN_BSS) - *total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS; - - /* - * Check if there is any work left for us. - */ - if (rt2x00dev->packet_filter == *total_flags) - return; - rt2x00dev->packet_filter = *total_flags; - - /* - * Start configuration steps. - * Note that the version error will always be dropped - * and broadcast frames will always be accepted since - * there is no filter for it at this time. - */ - rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, ®); - rt2x00_set_field32(®, TXRX_CSR0_DROP_CRC, - !(*total_flags & FIF_FCSFAIL)); - rt2x00_set_field32(®, TXRX_CSR0_DROP_PHYSICAL, - !(*total_flags & FIF_PLCPFAIL)); - rt2x00_set_field32(®, TXRX_CSR0_DROP_CONTROL, - !(*total_flags & FIF_CONTROL)); - rt2x00_set_field32(®, TXRX_CSR0_DROP_NOT_TO_ME, - !(*total_flags & FIF_PROMISC_IN_BSS)); - rt2x00_set_field32(®, TXRX_CSR0_DROP_TO_DS, - !(*total_flags & FIF_PROMISC_IN_BSS)); - rt2x00_set_field32(®, TXRX_CSR0_DROP_VERSION_ERROR, 1); - rt2x00_set_field32(®, TXRX_CSR0_DROP_MULTICAST, - !(*total_flags & FIF_ALLMULTI)); - rt2x00_set_field32(®, TXRX_CSR0_DROP_BROADCAST, 0); - rt2x00_set_field32(®, TXRX_CSR0_DROP_ACK_CTS, - !(*total_flags & FIF_CONTROL)); - rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg); -} - static int rt61pci_set_retry_limit(struct ieee80211_hw *hw, u32 short_retry, u32 long_retry) { @@ -2457,7 +2421,7 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = { .remove_interface = rt2x00mac_remove_interface, .config = rt2x00mac_config, .config_interface = rt2x00mac_config_interface, - .configure_filter = rt61pci_configure_filter, + .configure_filter = rt2x00mac_configure_filter, .get_stats = rt2x00mac_get_stats, .set_retry_limit = rt61pci_set_retry_limit, .bss_info_changed = rt2x00mac_bss_info_changed, @@ -2487,6 +2451,7 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { .write_tx_data = rt2x00pci_write_tx_data, .kick_tx_queue = rt61pci_kick_tx_queue, .fill_rxdone = rt61pci_fill_rxdone, + .config_filter = rt61pci_config_filter, .config_intf = rt61pci_config_intf, .config_erp = rt61pci_config_erp, .config = rt61pci_config, diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index b50f476e4bd1..187e832bab2e 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -333,6 +333,37 @@ static void rt73usb_led_brightness(struct led_classdev *led_cdev, /* * Configuration handlers. */ +static void rt73usb_config_filter(struct rt2x00_dev *rt2x00dev, + const unsigned int filter_flags) +{ + u32 reg; + + /* + * Start configuration steps. + * Note that the version error will always be dropped + * and broadcast frames will always be accepted since + * there is no filter for it at this time. + */ + rt73usb_register_read(rt2x00dev, TXRX_CSR0, ®); + rt2x00_set_field32(®, TXRX_CSR0_DROP_CRC, + !(filter_flags & FIF_FCSFAIL)); + rt2x00_set_field32(®, TXRX_CSR0_DROP_PHYSICAL, + !(filter_flags & FIF_PLCPFAIL)); + rt2x00_set_field32(®, TXRX_CSR0_DROP_CONTROL, + !(filter_flags & FIF_CONTROL)); + rt2x00_set_field32(®, TXRX_CSR0_DROP_NOT_TO_ME, + !(filter_flags & FIF_PROMISC_IN_BSS)); + rt2x00_set_field32(®, TXRX_CSR0_DROP_TO_DS, + !(filter_flags & FIF_PROMISC_IN_BSS)); + rt2x00_set_field32(®, TXRX_CSR0_DROP_VERSION_ERROR, 1); + rt2x00_set_field32(®, TXRX_CSR0_DROP_MULTICAST, + !(filter_flags & FIF_ALLMULTI)); + rt2x00_set_field32(®, TXRX_CSR0_DROP_BROADCAST, 0); + rt2x00_set_field32(®, TXRX_CSR0_DROP_ACK_CTS, + !(filter_flags & FIF_CONTROL)); + rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg); +} + static void rt73usb_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf, struct rt2x00intf_conf *conf, @@ -380,18 +411,11 @@ static void rt73usb_config_intf(struct rt2x00_dev *rt2x00dev, } } -static int rt73usb_config_erp(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_erp *erp) +static void rt73usb_config_erp(struct rt2x00_dev *rt2x00dev, + struct rt2x00lib_erp *erp) { u32 reg; - /* - * When in atomic context, we should let rt2x00lib - * try this configuration again later. - */ - if (in_atomic()) - return -EAGAIN; - rt73usb_register_read(rt2x00dev, TXRX_CSR0, ®); rt2x00_set_field32(®, TXRX_CSR0_RX_ACK_TIMEOUT, erp->ack_timeout); rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg); @@ -400,8 +424,6 @@ static int rt73usb_config_erp(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_PREAMBLE, !!erp->short_preamble); rt73usb_register_write(rt2x00dev, TXRX_CSR4, reg); - - return 0; } static void rt73usb_config_phymode(struct rt2x00_dev *rt2x00dev, @@ -1872,6 +1894,7 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev) * This device requires firmware. */ __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); + __set_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags); /* * Set the rssi offset. @@ -1884,80 +1907,6 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev) /* * IEEE80211 stack callback functions. */ -static void rt73usb_configure_filter(struct ieee80211_hw *hw, - unsigned int changed_flags, - unsigned int *total_flags, - int mc_count, - struct dev_addr_list *mc_list) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - u32 reg; - - /* - * Mask off any flags we are going to ignore from - * the total_flags field. - */ - *total_flags &= - FIF_ALLMULTI | - FIF_FCSFAIL | - FIF_PLCPFAIL | - FIF_CONTROL | - FIF_OTHER_BSS | - FIF_PROMISC_IN_BSS; - - /* - * Apply some rules to the filters: - * - Some filters imply different filters to be set. - * - Some things we can't filter out at all. - * - Multicast filter seems to kill broadcast traffic so never use it. - */ - *total_flags |= FIF_ALLMULTI; - if (*total_flags & FIF_OTHER_BSS || - *total_flags & FIF_PROMISC_IN_BSS) - *total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS; - - /* - * Check if there is any work left for us. - */ - if (rt2x00dev->packet_filter == *total_flags) - return; - rt2x00dev->packet_filter = *total_flags; - - /* - * When in atomic context, reschedule and let rt2x00lib - * call this function again. - */ - if (in_atomic()) { - queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->filter_work); - return; - } - - /* - * Start configuration steps. - * Note that the version error will always be dropped - * and broadcast frames will always be accepted since - * there is no filter for it at this time. - */ - rt73usb_register_read(rt2x00dev, TXRX_CSR0, ®); - rt2x00_set_field32(®, TXRX_CSR0_DROP_CRC, - !(*total_flags & FIF_FCSFAIL)); - rt2x00_set_field32(®, TXRX_CSR0_DROP_PHYSICAL, - !(*total_flags & FIF_PLCPFAIL)); - rt2x00_set_field32(®, TXRX_CSR0_DROP_CONTROL, - !(*total_flags & FIF_CONTROL)); - rt2x00_set_field32(®, TXRX_CSR0_DROP_NOT_TO_ME, - !(*total_flags & FIF_PROMISC_IN_BSS)); - rt2x00_set_field32(®, TXRX_CSR0_DROP_TO_DS, - !(*total_flags & FIF_PROMISC_IN_BSS)); - rt2x00_set_field32(®, TXRX_CSR0_DROP_VERSION_ERROR, 1); - rt2x00_set_field32(®, TXRX_CSR0_DROP_MULTICAST, - !(*total_flags & FIF_ALLMULTI)); - rt2x00_set_field32(®, TXRX_CSR0_DROP_BROADCAST, 0); - rt2x00_set_field32(®, TXRX_CSR0_DROP_ACK_CTS, - !(*total_flags & FIF_CONTROL)); - rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg); -} - static int rt73usb_set_retry_limit(struct ieee80211_hw *hw, u32 short_retry, u32 long_retry) { @@ -2067,7 +2016,7 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = { .remove_interface = rt2x00mac_remove_interface, .config = rt2x00mac_config, .config_interface = rt2x00mac_config_interface, - .configure_filter = rt73usb_configure_filter, + .configure_filter = rt2x00mac_configure_filter, .get_stats = rt2x00mac_get_stats, .set_retry_limit = rt73usb_set_retry_limit, .bss_info_changed = rt2x00mac_bss_info_changed, @@ -2096,6 +2045,7 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { .get_tx_data_len = rt73usb_get_tx_data_len, .kick_tx_queue = rt73usb_kick_tx_queue, .fill_rxdone = rt73usb_fill_rxdone, + .config_filter = rt73usb_config_filter, .config_intf = rt73usb_config_intf, .config_erp = rt73usb_config_erp, .config = rt73usb_config, -- cgit v1.2.1 From e0e0a67e44ce13e34f553b6ab6377560fa9813f1 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Tue, 25 Mar 2008 15:58:40 -0400 Subject: iwlwifi: do not register bands with no supported channels Otherwise, b/g-only devices fail in wiphy_register. Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl3945-base.c | 8 ++++++-- drivers/net/wireless/iwlwifi/iwl4965-base.c | 8 ++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 093b863ef904..4ba959153cb1 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -5136,8 +5136,12 @@ static int iwl3945_init_geos(struct iwl3945_priv *priv) priv->bands[IEEE80211_BAND_2GHZ].n_channels, priv->bands[IEEE80211_BAND_5GHZ].n_channels); - priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->bands[IEEE80211_BAND_2GHZ]; - priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &priv->bands[IEEE80211_BAND_5GHZ]; + if (priv->bands[IEEE80211_BAND_2GHZ].n_channels) + priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = + &priv->bands[IEEE80211_BAND_2GHZ]; + if (priv->bands[IEEE80211_BAND_5GHZ].n_channels) + priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = + &priv->bands[IEEE80211_BAND_5GHZ]; set_bit(STATUS_GEO_CONFIGURED, &priv->status); diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 44cfd0274976..9ae3d2981df5 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -5001,8 +5001,12 @@ int iwl4965_init_geos(struct iwl_priv *priv) priv->bands[IEEE80211_BAND_2GHZ].n_channels, priv->bands[IEEE80211_BAND_5GHZ].n_channels); - priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->bands[IEEE80211_BAND_2GHZ]; - priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &priv->bands[IEEE80211_BAND_5GHZ]; + if (priv->bands[IEEE80211_BAND_2GHZ].n_channels) + priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = + &priv->bands[IEEE80211_BAND_2GHZ]; + if (priv->bands[IEEE80211_BAND_5GHZ].n_channels) + priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = + &priv->bands[IEEE80211_BAND_5GHZ]; set_bit(STATUS_GEO_CONFIGURED, &priv->status); -- cgit v1.2.1 From ab53d8af6772b22d4d68b1bcd74f7a5dba693983 Mon Sep 17 00:00:00 2001 From: Mohamed Abbas Date: Tue, 25 Mar 2008 16:33:36 -0700 Subject: iwlwifi: Add led support This patch add LEDS support to 3965 and 4965 drivers. It is based on led trigger and class. For our drivers we needed to avoid two things. 1- We receive led trigger on/off on each Rx\Tx frame. In our driver we can not call led command like that. In this driver once driver receive a start of traffic it call the led command to start blinking then we count all bytes of Tx and Rx frame, after two second we count the blink rate of last two second then id blink rate changed we call the led commands 2- Since we can call led command very often, we make sure we call the led command after we receive the statistics notification so we don't need to wake up the ucode id it is in sleep state. This patch was tested with 4965 and 3945. Signed-off-by: Mohamed Abbas Signed-off-by: Ian Schram Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/Kconfig | 20 ++ drivers/net/wireless/iwlwifi/Makefile | 10 + drivers/net/wireless/iwlwifi/iwl-3945-led.c | 433 +++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-3945-led.h | 73 +++++ drivers/net/wireless/iwlwifi/iwl-3945.c | 6 + drivers/net/wireless/iwlwifi/iwl-3945.h | 13 +- drivers/net/wireless/iwlwifi/iwl-4965.c | 6 +- drivers/net/wireless/iwlwifi/iwl-4965.h | 12 +- drivers/net/wireless/iwlwifi/iwl-csr.h | 6 + drivers/net/wireless/iwlwifi/iwl-led.c | 446 ++++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-led.h | 82 +++++ drivers/net/wireless/iwlwifi/iwl3945-base.c | 9 +- drivers/net/wireless/iwlwifi/iwl4965-base.c | 7 +- 13 files changed, 1107 insertions(+), 16 deletions(-) create mode 100644 drivers/net/wireless/iwlwifi/iwl-3945-led.c create mode 100644 drivers/net/wireless/iwlwifi/iwl-3945-led.h create mode 100644 drivers/net/wireless/iwlwifi/iwl-led.c create mode 100644 drivers/net/wireless/iwlwifi/iwl-led.h (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index 1ab14ed33f58..4bdb75ecb170 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig @@ -2,6 +2,13 @@ config IWLCORE tristate "Intel Wireless Wifi Core" depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL +config IWLWIFI_LEDS + bool "Enable LEDS features in iwlwifi driver" + depends on IWLCORE && MAC80211_LEDS && LEDS_CLASS + ---help--- + This option enables LEDS for the iwlwifi drivers + + config IWL4965 tristate "Intel Wireless WiFi 4965AGN" depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL @@ -37,6 +44,13 @@ config IWL4965_HT This option enables IEEE 802.11n High Throughput features for the iwl4965 driver. +config IWL4965_LEDS + bool "Enable LEDS features in iwl4965 driver" + depends on IWL4965 && IWLWIFI_LEDS + ---help--- + This option enables LEDS for the iwlwifi drivers + + config IWL4965_SPECTRUM_MEASUREMENT bool "Enable Spectrum Measurement in iwl4965 driver" depends on IWL4965 @@ -114,6 +128,12 @@ config IWL3945_SPECTRUM_MEASUREMENT ---help--- This option will enable spectrum measurement for the iwl3945 driver. +config IWL3945_LEDS + bool "Enable LEDS features in iwl3945 driver" + depends on IWL3945 && MAC80211_LEDS && LEDS_CLASS + ---help--- + This option enables LEDS for the iwl3945 driver. + config IWL3945_DEBUG bool "Enable full debugging output in iwl3945 driver" depends on IWL3945 diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 6be8012a1743..64fca4d9ac76 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile @@ -5,8 +5,18 @@ ifeq ($(CONFIG_IWLWIFI_DEBUGFS),y) iwlcore-objs += iwl-debugfs.o endif +ifeq ($(CONFIG_IWLWIFI_LEDS),y) + iwlcore-objs += iwl-led.o +endif + obj-$(CONFIG_IWL3945) += iwl3945.o iwl3945-objs = iwl3945-base.o iwl-3945.o iwl-3945-rs.o +ifeq ($(CONFIG_IWL3945_LEDS),y) + iwl3945-objs += iwl-3945-led.o +endif + + obj-$(CONFIG_IWL4965) += iwl4965.o iwl4965-objs = iwl4965-base.o iwl-4965.o iwl-4965-rs.o + diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.c b/drivers/net/wireless/iwlwifi/iwl-3945-led.c new file mode 100644 index 000000000000..d200d08fb086 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.c @@ -0,0 +1,433 @@ +/****************************************************************************** + * + * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * James P. Ketrenos + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + *****************************************************************************/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "iwl-3945.h" +#include "iwl-helpers.h" + +#define IWL_1MB_RATE (128 * 1024) +#define IWL_LED_THRESHOLD (16) +#define IWL_MAX_BLINK_TBL (10) + +static const struct { + u16 brightness; + u8 on_time; + u8 of_time; +} blink_tbl[] = +{ + {300, 25, 25}, + {200, 40, 40}, + {100, 55, 55}, + {70, 65, 65}, + {50, 75, 75}, + {20, 85, 85}, + {15, 95, 95 }, + {10, 110, 110}, + {5, 130, 130}, + {0, 167, 167} +}; + +static int iwl3945_led_cmd_callback(struct iwl3945_priv *priv, + struct iwl3945_cmd *cmd, + struct sk_buff *skb) +{ + return 1; +} + + +/* Send led command */ +static int iwl_send_led_cmd(struct iwl3945_priv *priv, + struct iwl3945_led_cmd *led_cmd) +{ + struct iwl3945_host_cmd cmd = { + .id = REPLY_LEDS_CMD, + .len = sizeof(struct iwl3945_led_cmd), + .data = led_cmd, + .meta.flags = CMD_ASYNC, + .meta.u.callback = iwl3945_led_cmd_callback + }; + + return iwl3945_send_cmd(priv, &cmd); +} + + +/* Set led on command */ +static int iwl3945_led_on(struct iwl3945_priv *priv, int led_id) +{ + struct iwl3945_led_cmd led_cmd = { + .id = led_id, + .on = IWL_LED_SOLID, + .off = 0, + .interval = IWL_DEF_LED_INTRVL + }; + return iwl_send_led_cmd(priv, &led_cmd); +} + +/* Set led on command */ +static int iwl3945_led_pattern(struct iwl3945_priv *priv, int led_id, + enum led_brightness brightness) +{ + struct iwl3945_led_cmd led_cmd = { + .id = led_id, + .on = brightness, + .off = brightness, + .interval = IWL_DEF_LED_INTRVL + }; + if (brightness == LED_FULL) { + led_cmd.on = IWL_LED_SOLID; + led_cmd.off = 0; + } + return iwl_send_led_cmd(priv, &led_cmd); +} + +/* Set led register off */ +static int iwl3945_led_on_reg(struct iwl3945_priv *priv, int led_id) +{ + IWL_DEBUG_LED("led on %d\n", led_id); + return iwl3945_led_on(priv, led_id); +} + +/* Set led off command */ +static int iwl3945_led_off(struct iwl3945_priv *priv, int led_id) +{ + struct iwl3945_led_cmd led_cmd = { + .id = led_id, + .on = 0, + .off = 0, + .interval = IWL_DEF_LED_INTRVL + }; + IWL_DEBUG_LED("led off %d\n", led_id); + return iwl_send_led_cmd(priv, &led_cmd); +} + +/* Set led register off */ +static int iwl3945_led_off_reg(struct iwl3945_priv *priv, int led_id) +{ + iwl3945_led_off(priv, led_id); + return 0; +} + +/* Set led blink command */ +static int iwl3945_led_not_solid(struct iwl3945_priv *priv, int led_id, + u8 brightness) +{ + struct iwl3945_led_cmd led_cmd = { + .id = led_id, + .on = brightness, + .off = brightness, + .interval = IWL_DEF_LED_INTRVL + }; + + return iwl_send_led_cmd(priv, &led_cmd); +} + + +/* + * brightness call back function for Tx/Rx LED + */ +static int iwl3945_led_associated(struct iwl3945_priv *priv, int led_id) +{ + if (test_bit(STATUS_EXIT_PENDING, &priv->status) || + !test_bit(STATUS_READY, &priv->status)) + return 0; + + + /* start counting Tx/Rx bytes */ + if (!priv->last_blink_time && priv->allow_blinking) + priv->last_blink_time = jiffies; + return 0; +} + +/* + * brightness call back for association and radio + */ +static void iwl3945_led_brightness_set(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + struct iwl3945_led *led = container_of(led_cdev, + struct iwl3945_led, led_dev); + struct iwl3945_priv *priv = led->priv; + + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + return; + + switch (brightness) { + case LED_FULL: + if (led->type == IWL_LED_TRG_ASSOC) { + priv->allow_blinking = 1; + IWL_DEBUG_LED("MAC is associated\n"); + } + if (led->led_on) + led->led_on(priv, IWL_LED_LINK); + break; + case LED_OFF: + if (led->type == IWL_LED_TRG_ASSOC) { + priv->allow_blinking = 0; + IWL_DEBUG_LED("MAC is disassociated\n"); + } + if (led->led_off) + led->led_off(priv, IWL_LED_LINK); + break; + default: + if (led->led_pattern) + led->led_pattern(priv, IWL_LED_LINK, brightness); + break; + } +} + + + +/* + * Register led class with the system + */ +static int iwl3945_led_register_led(struct iwl3945_priv *priv, + struct iwl3945_led *led, + enum led_type type, u8 set_led, + const char *name, char *trigger) +{ + struct device *device = wiphy_dev(priv->hw->wiphy); + int ret; + + led->led_dev.name = name; + led->led_dev.brightness_set = iwl3945_led_brightness_set; + led->led_dev.default_trigger = trigger; + + ret = led_classdev_register(device, &led->led_dev); + if (ret) { + IWL_ERROR("Error: failed to register led handler.\n"); + return ret; + } + + led->priv = priv; + led->type = type; + led->registered = 1; + + if (set_led && led->led_on) + led->led_on(priv, IWL_LED_LINK); + return 0; +} + + +/* + * calculate blink rate according to last 2 sec Tx/Rx activities + */ +static inline u8 get_blink_rate(struct iwl3945_priv *priv) +{ + int index; + u8 blink_rate; + + if (priv->rxtxpackets < IWL_LED_THRESHOLD) + index = 10; + else { + for (index = 0; index < IWL_MAX_BLINK_TBL; index++) { + if (priv->rxtxpackets > (blink_tbl[index].brightness * + IWL_1MB_RATE)) + break; + } + } + /* if 0 frame is transfered */ + if ((index == IWL_MAX_BLINK_TBL) || !priv->allow_blinking) + blink_rate = IWL_LED_SOLID; + else + blink_rate = blink_tbl[index].on_time; + + return blink_rate; +} + +static inline int is_rf_kill(struct iwl3945_priv *priv) +{ + return test_bit(STATUS_RF_KILL_HW, &priv->status) || + test_bit(STATUS_RF_KILL_SW, &priv->status); +} + +/* + * this function called from handler. Since setting Led command can + * happen very frequent we postpone led command to be called from + * REPLY handler so we know ucode is up + */ +void iwl3945_led_background(struct iwl3945_priv *priv) +{ + u8 blink_rate; + + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { + priv->last_blink_time = 0; + return; + } + if (is_rf_kill(priv)) { + priv->last_blink_time = 0; + return; + } + + if (!priv->allow_blinking) { + priv->last_blink_time = 0; + if (priv->last_blink_rate != IWL_LED_SOLID) { + priv->last_blink_rate = IWL_LED_SOLID; + iwl3945_led_on(priv, IWL_LED_LINK); + } + return; + } + if (!priv->last_blink_time || + !time_after(jiffies, priv->last_blink_time + + msecs_to_jiffies(1000))) + return; + + blink_rate = get_blink_rate(priv); + + /* call only if blink rate change */ + if (blink_rate != priv->last_blink_rate) { + if (blink_rate != IWL_LED_SOLID) { + priv->last_blink_time = jiffies + + msecs_to_jiffies(1000); + iwl3945_led_not_solid(priv, IWL_LED_LINK, blink_rate); + } else { + priv->last_blink_time = 0; + iwl3945_led_on(priv, IWL_LED_LINK); + } + } + + priv->last_blink_rate = blink_rate; + priv->rxtxpackets = 0; +} + + +/* Register all led handler */ +int iwl3945_led_register(struct iwl3945_priv *priv) +{ + char *trigger; + char name[32]; + int ret; + + priv->last_blink_rate = 0; + priv->rxtxpackets = 0; + priv->last_blink_time = 0; + priv->allow_blinking = 0; + + trigger = ieee80211_get_radio_led_name(priv->hw); + snprintf(name, sizeof(name), "iwl-%s:radio", + wiphy_name(priv->hw->wiphy)); + + priv->led[IWL_LED_TRG_RADIO].led_on = iwl3945_led_on_reg; + priv->led[IWL_LED_TRG_RADIO].led_off = iwl3945_led_off_reg; + priv->led[IWL_LED_TRG_RADIO].led_pattern = NULL; + + ret = iwl3945_led_register_led(priv, + &priv->led[IWL_LED_TRG_RADIO], + IWL_LED_TRG_RADIO, 1, + name, trigger); + if (ret) + goto exit_fail; + + trigger = ieee80211_get_assoc_led_name(priv->hw); + snprintf(name, sizeof(name), "iwl-%s:assoc", + wiphy_name(priv->hw->wiphy)); + + ret = iwl3945_led_register_led(priv, + &priv->led[IWL_LED_TRG_ASSOC], + IWL_LED_TRG_ASSOC, 0, + name, trigger); + /* for assoc always turn led on */ + priv->led[IWL_LED_TRG_ASSOC].led_on = iwl3945_led_on_reg; + priv->led[IWL_LED_TRG_ASSOC].led_off = iwl3945_led_on_reg; + priv->led[IWL_LED_TRG_ASSOC].led_pattern = NULL; + + if (ret) + goto exit_fail; + + trigger = ieee80211_get_rx_led_name(priv->hw); + snprintf(name, sizeof(name), "iwl-%s:RX", + wiphy_name(priv->hw->wiphy)); + + + ret = iwl3945_led_register_led(priv, + &priv->led[IWL_LED_TRG_RX], + IWL_LED_TRG_RX, 0, + name, trigger); + + priv->led[IWL_LED_TRG_RX].led_on = iwl3945_led_associated; + priv->led[IWL_LED_TRG_RX].led_off = iwl3945_led_associated; + priv->led[IWL_LED_TRG_RX].led_pattern = iwl3945_led_pattern; + + if (ret) + goto exit_fail; + + trigger = ieee80211_get_tx_led_name(priv->hw); + snprintf(name, sizeof(name), "iwl-%s:TX", + wiphy_name(priv->hw->wiphy)); + ret = iwl3945_led_register_led(priv, + &priv->led[IWL_LED_TRG_TX], + IWL_LED_TRG_TX, 0, + name, trigger); + priv->led[IWL_LED_TRG_TX].led_on = iwl3945_led_associated; + priv->led[IWL_LED_TRG_TX].led_off = iwl3945_led_associated; + priv->led[IWL_LED_TRG_TX].led_pattern = iwl3945_led_pattern; + + if (ret) + goto exit_fail; + + return 0; + +exit_fail: + iwl3945_led_unregister(priv); + return ret; +} + + +/* unregister led class */ +static void iwl3945_led_unregister_led(struct iwl3945_led *led, u8 set_led) +{ + if (!led->registered) + return; + + led_classdev_unregister(&led->led_dev); + + if (set_led) + led->led_dev.brightness_set(&led->led_dev, LED_OFF); + led->registered = 0; +} + +/* Unregister all led handlers */ +void iwl3945_led_unregister(struct iwl3945_priv *priv) +{ + iwl3945_led_unregister_led(&priv->led[IWL_LED_TRG_ASSOC], 0); + iwl3945_led_unregister_led(&priv->led[IWL_LED_TRG_RX], 0); + iwl3945_led_unregister_led(&priv->led[IWL_LED_TRG_TX], 0); + iwl3945_led_unregister_led(&priv->led[IWL_LED_TRG_RADIO], 1); +} + diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.h b/drivers/net/wireless/iwlwifi/iwl-3945-led.h new file mode 100644 index 000000000000..b1d2f6b8b259 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.h @@ -0,0 +1,73 @@ +/****************************************************************************** + * + * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * James P. Ketrenos + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + *****************************************************************************/ + +#ifndef IWL3945_LEDS_H +#define IWL3945_LEDS_H + +struct iwl3945_priv; + +#ifdef CONFIG_IWL3945_LEDS +#define IWL_LED_SOLID 11 +#define IWL_LED_NAME_LEN 31 +#define IWL_DEF_LED_INTRVL __constant_cpu_to_le32(1000) + +#define IWL_LED_ACTIVITY (0<<1) +#define IWL_LED_LINK (1<<1) + +enum led_type { + IWL_LED_TRG_TX, + IWL_LED_TRG_RX, + IWL_LED_TRG_ASSOC, + IWL_LED_TRG_RADIO, + IWL_LED_TRG_MAX, +}; + +#include + +struct iwl3945_led { + struct iwl3945_priv *priv; + struct led_classdev led_dev; + + int (*led_on) (struct iwl3945_priv *priv, int led_id); + int (*led_off) (struct iwl3945_priv *priv, int led_id); + int (*led_pattern) (struct iwl3945_priv *priv, int led_id, + enum led_brightness brightness); + + enum led_type type; + unsigned int registered; +}; + +extern int iwl3945_led_register(struct iwl3945_priv *priv); +extern void iwl3945_led_unregister(struct iwl3945_priv *priv); +extern void iwl3945_led_background(struct iwl3945_priv *priv); + +#else +static inline int iwl3945_led_register(struct iwl3945_priv *priv) { return 0; } +static inline void iwl3945_led_unregister(struct iwl3945_priv *priv) {} +static inline void iwl3945_led_background(struct iwl3945_priv *priv) {} +#endif /* CONFIG_IWL3945_LEDS */ + +#endif /* IWL3945_LEDS_H */ diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index e116ed77c5ad..eb30819cddc4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -358,6 +358,8 @@ void iwl3945_hw_rx_statistics(struct iwl3945_priv *priv, struct iwl3945_rx_mem_b memcpy(&priv->statistics, pkt->u.raw, sizeof(priv->statistics)); + iwl3945_led_background(priv); + priv->last_statistics_time = jiffies; } @@ -640,6 +642,10 @@ static void iwl3945_handle_data_packet(struct iwl3945_priv *priv, int is_data, if (priv->add_radiotap) iwl3945_add_radiotap(priv, rxb->skb, rx_hdr, stats); +#ifdef CONFIG_IWL3945_LEDS + if (is_data) + priv->rxtxpackets += len; +#endif ieee80211_rx_irqsafe(priv->hw, rxb->skb, stats); rxb->skb = NULL; } diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 931c465f9e5e..e0655b988f44 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -44,6 +44,7 @@ extern struct pci_device_id iwl3945_hw_card_ids[]; #include "iwl-prph.h" #include "iwl-3945-hw.h" #include "iwl-3945-debug.h" +#include "iwl-3945-led.h" /* Change firmware file name, using "-" and incrementing number, * *only* when uCode interface or architecture changes so that it @@ -777,13 +778,15 @@ struct iwl3945_priv { struct iwl3945_init_alive_resp card_alive_init; struct iwl3945_alive_resp card_alive; -#ifdef LED - /* LED related variables */ - struct iwl3945_activity_blink activity; - unsigned long led_packets; - int led_state; +#ifdef CONFIG_IWL4965_LEDS + struct iwl3945_led led[IWL_LED_TRG_MAX]; + unsigned long last_blink_time; + u8 last_blink_rate; + u8 allow_blinking; + unsigned int rxtxpackets; #endif + u16 active_rate; u16 active_rate_basic; diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 1db873b02f1e..8b5cacb14618 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -3258,6 +3258,8 @@ void iwl4965_hw_rx_statistics(struct iwl_priv *priv, struct iwl4965_rx_mem_buffe #endif } + iwl_leds_background(priv); + /* If the hardware hasn't reported a change in * temperature then don't bother computing a * calibrated temperature value */ @@ -3539,10 +3541,6 @@ static void iwl4965_handle_data_packet(struct iwl_priv *priv, int is_data, ieee80211_rx_irqsafe(priv->hw, rxb->skb, stats); priv->alloc_rxb_skb--; rxb->skb = NULL; -#ifdef LED - priv->led_packets += len; - iwl4965_setup_activity_timer(priv); -#endif } /* Calc max signal level (dBm) among 3 possible receivers */ diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index 960b53b20df8..32c21d266f98 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -45,6 +45,7 @@ extern struct pci_device_id iwl4965_hw_card_ids[]; #include "iwl-csr.h" #include "iwl-prph.h" #include "iwl-debug.h" +#include "iwl-led.h" /* Change firmware file name, using "-" and incrementing number, * *only* when uCode interface or architecture changes so that it @@ -1050,11 +1051,12 @@ struct iwl_priv { struct iwl4965_init_alive_resp card_alive_init; struct iwl4965_alive_resp card_alive; -#ifdef LED - /* LED related variables */ - struct iwl4965_activity_blink activity; - unsigned long led_packets; - int led_state; +#ifdef CONFIG_IWL4965_LEDS + struct iwl4965_led led[IWL_LED_TRG_MAX]; + unsigned long last_blink_time; + u8 last_blink_rate; + u8 allow_blinking; + u64 led_tpt; #endif u16 active_rate; diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index f0a2c8d180f0..12725796ea5f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h @@ -93,6 +93,7 @@ #define CSR_UCODE_DRV_GP1_CLR (CSR_BASE+0x05c) #define CSR_UCODE_DRV_GP2 (CSR_BASE+0x060) #define CSR_GIO_CHICKEN_BITS (CSR_BASE+0x100) +#define CSR_LED_REG (CSR_BASE+0x094) /* Analog phase-lock-loop configuration (3945 only) * Set bit 24. */ @@ -214,6 +215,11 @@ #define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX (0x00800000) #define CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER (0x20000000) +/* LED */ +#define CSR_LED_BSM_CTRL_MSK (0xFFFFFFDF) +#define CSR_LED_REG_TRUN_ON (0x78) +#define CSR_LED_REG_TRUN_OFF (0x38) + /*=== HBUS (Host-side Bus) ===*/ #define HBUS_BASE (0x400) /* diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c new file mode 100644 index 000000000000..6f5424bd365b --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-led.c @@ -0,0 +1,446 @@ +/****************************************************************************** + * + * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * James P. Ketrenos + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + *****************************************************************************/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "iwl-4965.h" +#include "iwl-core.h" +#include "iwl-helpers.h" + +#define IWL_1MB_RATE (128 * 1024) +#define IWL_LED_THRESHOLD (16) +#define IWL_MAX_BLINK_TBL (10) + +static const struct { + u16 tpt; + u8 on_time; + u8 of_time; +} blink_tbl[] = +{ + {300, 25, 25}, + {200, 40, 40}, + {100, 55, 55}, + {70, 65, 65}, + {50, 75, 75}, + {20, 85, 85}, + {15, 95, 95 }, + {10, 110, 110}, + {5, 130, 130}, + {0, 167, 167} +}; + +static int iwl_led_cmd_callback(struct iwl_priv *priv, + struct iwl_cmd *cmd, struct sk_buff *skb) +{ + return 1; +} + + +/* Send led command */ +static int iwl_send_led_cmd(struct iwl_priv *priv, + struct iwl4965_led_cmd *led_cmd) +{ + struct iwl_host_cmd cmd = { + .id = REPLY_LEDS_CMD, + .len = sizeof(struct iwl4965_led_cmd), + .data = led_cmd, + .meta.flags = CMD_ASYNC, + .meta.u.callback = iwl_led_cmd_callback + }; + u32 reg; + + reg = iwl4965_read32(priv, CSR_LED_REG); + if (reg != (reg & CSR_LED_BSM_CTRL_MSK)) + iwl4965_write32(priv, CSR_LED_REG, reg & CSR_LED_BSM_CTRL_MSK); + + return iwl_send_cmd(priv, &cmd); +} + + +/* Set led on command */ +static int iwl4965_led_on(struct iwl_priv *priv, int led_id) +{ + struct iwl4965_led_cmd led_cmd = { + .id = led_id, + .on = IWL_LED_SOLID, + .off = 0, + .interval = IWL_DEF_LED_INTRVL + }; + return iwl_send_led_cmd(priv, &led_cmd); +} + +/* Set led on command */ +static int iwl4965_led_pattern(struct iwl_priv *priv, int led_id, + enum led_brightness brightness) +{ + struct iwl4965_led_cmd led_cmd = { + .id = led_id, + .on = brightness, + .off = brightness, + .interval = IWL_DEF_LED_INTRVL + }; + if (brightness == LED_FULL) { + led_cmd.on = IWL_LED_SOLID; + led_cmd.off = 0; + } + return iwl_send_led_cmd(priv, &led_cmd); +} + +/* Set led register off */ +static int iwl4965_led_on_reg(struct iwl_priv *priv, int led_id) +{ + IWL_DEBUG_LED("led on %d\n", led_id); + iwl4965_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_ON); + return 0; +} + +#if 0 +/* Set led off command */ +int iwl4965_led_off(struct iwl_priv *priv, int led_id) +{ + struct iwl4965_led_cmd led_cmd = { + .id = led_id, + .on = 0, + .off = 0, + .interval = IWL_DEF_LED_INTRVL + }; + IWL_DEBUG_LED("led off %d\n", led_id); + return iwl_send_led_cmd(priv, &led_cmd); +} +#endif + + +/* Set led register off */ +static int iwl4965_led_off_reg(struct iwl_priv *priv, int led_id) +{ + IWL_DEBUG_LED("radio off\n"); + iwl4965_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_OFF); + return 0; +} + +/* Set led blink command */ +static int iwl4965_led_not_solid(struct iwl_priv *priv, int led_id, + u8 brightness) +{ + struct iwl4965_led_cmd led_cmd = { + .id = led_id, + .on = brightness, + .off = brightness, + .interval = IWL_DEF_LED_INTRVL + }; + + return iwl_send_led_cmd(priv, &led_cmd); +} + + +/* + * brightness call back function for Tx/Rx LED + */ +static int iwl4965_led_associated(struct iwl_priv *priv, int led_id) +{ + if (test_bit(STATUS_EXIT_PENDING, &priv->status) || + !test_bit(STATUS_READY, &priv->status)) + return 0; + + + /* start counting Tx/Rx bytes */ + if (!priv->last_blink_time && priv->allow_blinking) + priv->last_blink_time = jiffies; + return 0; +} + +/* + * brightness call back for association and radio + */ +static void iwl4965_led_brightness_set(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + struct iwl4965_led *led = container_of(led_cdev, + struct iwl4965_led, led_dev); + struct iwl_priv *priv = led->priv; + + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + return; + + switch (brightness) { + case LED_FULL: + if (led->type == IWL_LED_TRG_ASSOC) + priv->allow_blinking = 1; + + if (led->led_on) + led->led_on(priv, IWL_LED_LINK); + break; + case LED_OFF: + if (led->type == IWL_LED_TRG_ASSOC) + priv->allow_blinking = 0; + + if (led->led_off) + led->led_off(priv, IWL_LED_LINK); + break; + default: + if (led->led_pattern) + led->led_pattern(priv, IWL_LED_LINK, brightness); + break; + } +} + + + +/* + * Register led class with the system + */ +static int iwl_leds_register_led(struct iwl_priv *priv, + struct iwl4965_led *led, + enum led_type type, u8 set_led, + const char *name, char *trigger) +{ + struct device *device = wiphy_dev(priv->hw->wiphy); + int ret; + + led->led_dev.name = name; + led->led_dev.brightness_set = iwl4965_led_brightness_set; + led->led_dev.default_trigger = trigger; + + ret = led_classdev_register(device, &led->led_dev); + if (ret) { + IWL_ERROR("Error: failed to register led handler.\n"); + return ret; + } + + led->priv = priv; + led->type = type; + led->registered = 1; + + if (set_led && led->led_on) + led->led_on(priv, IWL_LED_LINK); + return 0; +} + + +/* + * calculate blink rate according to last 2 sec Tx/Rx activities + */ +static inline u8 get_blink_rate(struct iwl_priv *priv) +{ + int i; + u8 blink_rate; + u64 current_tpt = priv->tx_stats[2].bytes + priv->rx_stats[2].bytes; + s64 tpt = current_tpt - priv->led_tpt; + + if (tpt < 0) /* wrapparound */ + tpt = -tpt; + + priv->led_tpt = current_tpt; + + if (tpt < IWL_LED_THRESHOLD) { + i = IWL_MAX_BLINK_TBL; + } else { + for (i = 0; i < IWL_MAX_BLINK_TBL; i++) + if (tpt > (blink_tbl[i].tpt * IWL_1MB_RATE)) + break; + } + /* if 0 frame is transfered */ + if ((i == IWL_MAX_BLINK_TBL) || !priv->allow_blinking) + blink_rate = IWL_LED_SOLID; + else + blink_rate = blink_tbl[i].on_time; + + return blink_rate; +} + +static inline int is_rf_kill(struct iwl_priv *priv) +{ + return test_bit(STATUS_RF_KILL_HW, &priv->status) || + test_bit(STATUS_RF_KILL_SW, &priv->status); +} + +/* + * this function called from handler. Since setting Led command can + * happen very frequent we postpone led command to be called from + * REPLY handler so we know ucode is up + */ +void iwl_leds_background(struct iwl_priv *priv) +{ + u8 blink_rate; + + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { + priv->last_blink_time = 0; + return; + } + if (is_rf_kill(priv)) { + priv->last_blink_time = 0; + return; + } + + if (!priv->allow_blinking) { + priv->last_blink_time = 0; + if (priv->last_blink_rate != IWL_LED_SOLID) { + priv->last_blink_rate = IWL_LED_SOLID; + iwl4965_led_on(priv, IWL_LED_LINK); + } + return; + } + if (!priv->last_blink_time || + !time_after(jiffies, priv->last_blink_time + + msecs_to_jiffies(1000))) + return; + + blink_rate = get_blink_rate(priv); + + /* call only if blink rate change */ + if (blink_rate != priv->last_blink_rate) { + if (blink_rate != IWL_LED_SOLID) { + priv->last_blink_time = jiffies + + msecs_to_jiffies(1000); + iwl4965_led_not_solid(priv, IWL_LED_LINK, blink_rate); + } else { + priv->last_blink_time = 0; + iwl4965_led_on(priv, IWL_LED_LINK); + } + } + + priv->last_blink_rate = blink_rate; +} +EXPORT_SYMBOL(iwl_leds_background); + +/* Register all led handler */ +int iwl_leds_register(struct iwl_priv *priv) +{ + char *trigger; + char name[32]; + int ret; + + priv->last_blink_rate = 0; + priv->led_tpt = 0; + priv->last_blink_time = 0; + priv->allow_blinking = 0; + + trigger = ieee80211_get_radio_led_name(priv->hw); + snprintf(name, sizeof(name), "iwl-%s:radio", + wiphy_name(priv->hw->wiphy)); + + priv->led[IWL_LED_TRG_RADIO].led_on = iwl4965_led_on_reg; + priv->led[IWL_LED_TRG_RADIO].led_off = iwl4965_led_off_reg; + priv->led[IWL_LED_TRG_RADIO].led_pattern = NULL; + + ret = iwl_leds_register_led(priv, + &priv->led[IWL_LED_TRG_RADIO], + IWL_LED_TRG_RADIO, 1, + name, trigger); + if (ret) + goto exit_fail; + + trigger = ieee80211_get_assoc_led_name(priv->hw); + snprintf(name, sizeof(name), "iwl-%s:assoc", + wiphy_name(priv->hw->wiphy)); + + ret = iwl_leds_register_led(priv, + &priv->led[IWL_LED_TRG_ASSOC], + IWL_LED_TRG_ASSOC, 0, + name, trigger); + /* for assoc always turn led on */ + priv->led[IWL_LED_TRG_ASSOC].led_on = iwl4965_led_on_reg; + priv->led[IWL_LED_TRG_ASSOC].led_off = iwl4965_led_on_reg; + priv->led[IWL_LED_TRG_ASSOC].led_pattern = NULL; + + if (ret) + goto exit_fail; + + trigger = ieee80211_get_rx_led_name(priv->hw); + snprintf(name, sizeof(name), "iwl-%s:RX", + wiphy_name(priv->hw->wiphy)); + + + ret = iwl_leds_register_led(priv, + &priv->led[IWL_LED_TRG_RX], + IWL_LED_TRG_RX, 0, + name, trigger); + + priv->led[IWL_LED_TRG_RX].led_on = iwl4965_led_associated; + priv->led[IWL_LED_TRG_RX].led_off = iwl4965_led_associated; + priv->led[IWL_LED_TRG_RX].led_pattern = iwl4965_led_pattern; + + if (ret) + goto exit_fail; + + trigger = ieee80211_get_tx_led_name(priv->hw); + snprintf(name, sizeof(name), "iwl-%s:TX", + wiphy_name(priv->hw->wiphy)); + ret = iwl_leds_register_led(priv, + &priv->led[IWL_LED_TRG_TX], + IWL_LED_TRG_TX, 0, + name, trigger); + priv->led[IWL_LED_TRG_TX].led_on = iwl4965_led_associated; + priv->led[IWL_LED_TRG_TX].led_off = iwl4965_led_associated; + priv->led[IWL_LED_TRG_TX].led_pattern = iwl4965_led_pattern; + + if (ret) + goto exit_fail; + + return 0; + +exit_fail: + iwl_leds_unregister(priv); + return ret; +} +EXPORT_SYMBOL(iwl_leds_register); + +/* unregister led class */ +static void iwl_leds_unregister_led(struct iwl4965_led *led, u8 set_led) +{ + if (!led->registered) + return; + + led_classdev_unregister(&led->led_dev); + + if (set_led) + led->led_dev.brightness_set(&led->led_dev, LED_OFF); + led->registered = 0; +} + +/* Unregister all led handlers */ +void iwl_leds_unregister(struct iwl_priv *priv) +{ + iwl_leds_unregister_led(&priv->led[IWL_LED_TRG_ASSOC], 0); + iwl_leds_unregister_led(&priv->led[IWL_LED_TRG_RX], 0); + iwl_leds_unregister_led(&priv->led[IWL_LED_TRG_TX], 0); + iwl_leds_unregister_led(&priv->led[IWL_LED_TRG_RADIO], 1); +} +EXPORT_SYMBOL(iwl_leds_unregister); + diff --git a/drivers/net/wireless/iwlwifi/iwl-led.h b/drivers/net/wireless/iwlwifi/iwl-led.h new file mode 100644 index 000000000000..5bb04128cd65 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-led.h @@ -0,0 +1,82 @@ +/****************************************************************************** + * + * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * James P. Ketrenos + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + *****************************************************************************/ + +#ifndef __iwl_leds_h__ +#define __iwl_leds_h__ + + +struct iwl_priv; + +#ifdef CONFIG_IWLWIFI_LEDS +#include + +#define IWL_LED_SOLID 11 +#define IWL_LED_NAME_LEN 31 +#define IWL_DEF_LED_INTRVL __constant_cpu_to_le32(1000) + +#define IWL_LED_ACTIVITY (0<<1) +#define IWL_LED_LINK (1<<1) + +enum led_type { + IWL_LED_TRG_TX, + IWL_LED_TRG_RX, + IWL_LED_TRG_ASSOC, + IWL_LED_TRG_RADIO, + IWL_LED_TRG_MAX, +}; + + +struct iwl4965_led { + struct iwl_priv *priv; + struct led_classdev led_dev; + + int (*led_on) (struct iwl_priv *priv, int led_id); + int (*led_off) (struct iwl_priv *priv, int led_id); + int (*led_pattern) (struct iwl_priv *priv, int led_id, + enum led_brightness brightness); + + enum led_type type; + unsigned int registered; +}; + +int iwl_leds_register(struct iwl_priv *priv); +void iwl_leds_unregister(struct iwl_priv *priv); +void iwl_leds_background(struct iwl_priv *priv); + +#else +static inline int iwl_leds_register(struct iwl_priv *priv) +{ + return 0; +} +static inline void iwl_leds_unregister(struct iwl_priv *priv) +{ +} +static inline void iwl_leds_background(struct iwl_priv *priv) +{ +} + +#endif /* CONFIG_IWLWIFI_LEDS */ +#endif /* __iwl_leds_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 4ba959153cb1..470a9abf12c3 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2481,8 +2481,12 @@ static void iwl3945_build_tx_cmd_basic(struct iwl3945_priv *priv, cmd->cmd.tx.timeout.pm_frame_timeout = cpu_to_le16(3); else cmd->cmd.tx.timeout.pm_frame_timeout = cpu_to_le16(2); - } else + } else { cmd->cmd.tx.timeout.pm_frame_timeout = 0; +#ifdef CONFIG_IWL3945_LEDS + priv->rxtxpackets += le16_to_cpu(cmd->cmd.tx.len); +#endif + } cmd->cmd.tx.driver_txop = 0; cmd->cmd.tx.tx_flags = tx_flags; @@ -5855,6 +5859,8 @@ static void iwl3945_alive_start(struct iwl3945_priv *priv) IWL_DEBUG_INFO("ALIVE processing complete.\n"); wake_up_interruptible(&priv->wait_command_queue); + iwl3945_led_register(priv); + if (priv->error_recovering) iwl3945_error_recovery(priv); @@ -5879,6 +5885,7 @@ static void __iwl3945_down(struct iwl3945_priv *priv) if (!exit_pending) set_bit(STATUS_EXIT_PENDING, &priv->status); + iwl3945_led_unregister(priv); iwl3945_clear_stations_table(priv); /* Unblock any waiting calls */ diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 9ae3d2981df5..a04127a8acf7 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -2238,8 +2238,9 @@ static void iwl4965_build_tx_cmd_basic(struct iwl_priv *priv, cmd->cmd.tx.timeout.pm_frame_timeout = cpu_to_le16(3); else cmd->cmd.tx.timeout.pm_frame_timeout = cpu_to_le16(2); - } else + } else { cmd->cmd.tx.timeout.pm_frame_timeout = 0; + } cmd->cmd.tx.driver_txop = 0; cmd->cmd.tx.tx_flags = tx_flags; @@ -5712,6 +5713,8 @@ static void iwl4965_alive_start(struct iwl_priv *priv) IWL_DEBUG_INFO("ALIVE processing complete.\n"); wake_up_interruptible(&priv->wait_command_queue); + iwl_leds_register(priv); + if (priv->error_recovering) iwl4965_error_recovery(priv); @@ -5736,6 +5739,8 @@ static void __iwl4965_down(struct iwl_priv *priv) if (!exit_pending) set_bit(STATUS_EXIT_PENDING, &priv->status); + iwl_leds_unregister(priv); + iwlcore_clear_stations_table(priv); /* Unblock any waiting calls */ -- cgit v1.2.1 From 3395f6e9cf48469d7ee05703cad1502002741c16 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Tue, 25 Mar 2008 16:33:37 -0700 Subject: iwlwifi: rename iwl-4965-io.h to iwl-io.h This patch renames iwl-4965-io.h back to iw-io.h it also remove 4965 from all functions it supplies Signed-off-by: Tomas Winkler Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965-io.h | 426 ---------------------------- drivers/net/wireless/iwlwifi/iwl-4965.c | 215 +++++++------- drivers/net/wireless/iwlwifi/iwl-4965.h | 1 - drivers/net/wireless/iwlwifi/iwl-debugfs.c | 8 +- drivers/net/wireless/iwlwifi/iwl-eeprom.c | 26 +- drivers/net/wireless/iwlwifi/iwl-io.h | 426 ++++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-led.c | 9 +- drivers/net/wireless/iwlwifi/iwl4965-base.c | 233 +++++++-------- 8 files changed, 671 insertions(+), 673 deletions(-) delete mode 100644 drivers/net/wireless/iwlwifi/iwl-4965-io.h create mode 100644 drivers/net/wireless/iwlwifi/iwl-io.h (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-io.h b/drivers/net/wireless/iwlwifi/iwl-4965-io.h deleted file mode 100644 index fba7d03d4291..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-4965-io.h +++ /dev/null @@ -1,426 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. - * - * Portions of this file are derived from the ipw3945 project. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * James P. Ketrenos - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - *****************************************************************************/ - -#ifndef __iwl4965_io_h__ -#define __iwl4965_io_h__ - -#include - -#include "iwl-debug.h" - -/* - * IO, register, and NIC memory access functions - * - * NOTE on naming convention and macro usage for these - * - * A single _ prefix before a an access function means that no state - * check or debug information is printed when that function is called. - * - * A double __ prefix before an access function means that state is checked - * and the current line number is printed in addition to any other debug output. - * - * The non-prefixed name is the #define that maps the caller into a - * #define that provides the caller's __LINE__ to the double prefix version. - * - * If you wish to call the function without any debug or state checking, - * you should use the single _ prefix version (as is used by dependent IO - * routines, for example _iwl4965_read_direct32 calls the non-check version of - * _iwl4965_read32.) - * - * These declarations are *extremely* useful in quickly isolating code deltas - * which result in misconfiguring of the hardware I/O. In combination with - * git-bisect and the IO debug level you can quickly determine the specific - * commit which breaks the IO sequence to the hardware. - * - */ - -#define _iwl4965_write32(priv, ofs, val) writel((val), (priv)->hw_base + (ofs)) -#ifdef CONFIG_IWLWIFI_DEBUG -static inline void __iwl4965_write32(const char *f, u32 l, struct iwl_priv *priv, - u32 ofs, u32 val) -{ - IWL_DEBUG_IO("write32(0x%08X, 0x%08X) - %s %d\n", ofs, val, f, l); - _iwl4965_write32(priv, ofs, val); -} -#define iwl4965_write32(priv, ofs, val) \ - __iwl4965_write32(__FILE__, __LINE__, priv, ofs, val) -#else -#define iwl4965_write32(priv, ofs, val) _iwl4965_write32(priv, ofs, val) -#endif - -#define _iwl4965_read32(priv, ofs) readl((priv)->hw_base + (ofs)) -#ifdef CONFIG_IWLWIFI_DEBUG -static inline u32 __iwl4965_read32(char *f, u32 l, struct iwl_priv *priv, u32 ofs) -{ - IWL_DEBUG_IO("read_direct32(0x%08X) - %s %d\n", ofs, f, l); - return _iwl4965_read32(priv, ofs); -} -#define iwl4965_read32(priv, ofs) __iwl4965_read32(__FILE__, __LINE__, priv, ofs) -#else -#define iwl4965_read32(p, o) _iwl4965_read32(p, o) -#endif - -static inline int _iwl4965_poll_bit(struct iwl_priv *priv, u32 addr, - u32 bits, u32 mask, int timeout) -{ - int i = 0; - - do { - if ((_iwl4965_read32(priv, addr) & mask) == (bits & mask)) - return i; - mdelay(10); - i += 10; - } while (i < timeout); - - return -ETIMEDOUT; -} -#ifdef CONFIG_IWLWIFI_DEBUG -static inline int __iwl4965_poll_bit(const char *f, u32 l, - struct iwl_priv *priv, u32 addr, - u32 bits, u32 mask, int timeout) -{ - int ret = _iwl4965_poll_bit(priv, addr, bits, mask, timeout); - IWL_DEBUG_IO("poll_bit(0x%08X, 0x%08X, 0x%08X) - %s- %s %d\n", - addr, bits, mask, - unlikely(ret == -ETIMEDOUT)?"timeout":"", f, l); - return ret; -} -#define iwl4965_poll_bit(priv, addr, bits, mask, timeout) \ - __iwl4965_poll_bit(__FILE__, __LINE__, priv, addr, bits, mask, timeout) -#else -#define iwl4965_poll_bit(p, a, b, m, t) _iwl4965_poll_bit(p, a, b, m, t) -#endif - -static inline void _iwl4965_set_bit(struct iwl_priv *priv, u32 reg, u32 mask) -{ - _iwl4965_write32(priv, reg, _iwl4965_read32(priv, reg) | mask); -} -#ifdef CONFIG_IWLWIFI_DEBUG -static inline void __iwl4965_set_bit(const char *f, u32 l, - struct iwl_priv *priv, u32 reg, u32 mask) -{ - u32 val = _iwl4965_read32(priv, reg) | mask; - IWL_DEBUG_IO("set_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val); - _iwl4965_write32(priv, reg, val); -} -#define iwl4965_set_bit(p, r, m) __iwl4965_set_bit(__FILE__, __LINE__, p, r, m) -#else -#define iwl4965_set_bit(p, r, m) _iwl4965_set_bit(p, r, m) -#endif - -static inline void _iwl4965_clear_bit(struct iwl_priv *priv, u32 reg, u32 mask) -{ - _iwl4965_write32(priv, reg, _iwl4965_read32(priv, reg) & ~mask); -} -#ifdef CONFIG_IWLWIFI_DEBUG -static inline void __iwl4965_clear_bit(const char *f, u32 l, - struct iwl_priv *priv, u32 reg, u32 mask) -{ - u32 val = _iwl4965_read32(priv, reg) & ~mask; - IWL_DEBUG_IO("clear_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val); - _iwl4965_write32(priv, reg, val); -} -#define iwl4965_clear_bit(p, r, m) __iwl4965_clear_bit(__FILE__, __LINE__, p, r, m) -#else -#define iwl4965_clear_bit(p, r, m) _iwl4965_clear_bit(p, r, m) -#endif - -static inline int _iwl4965_grab_nic_access(struct iwl_priv *priv) -{ - int ret; - u32 gp_ctl; - -#ifdef CONFIG_IWLWIFI_DEBUG - if (atomic_read(&priv->restrict_refcnt)) - return 0; -#endif - if (test_bit(STATUS_RF_KILL_HW, &priv->status) || - test_bit(STATUS_RF_KILL_SW, &priv->status)) { - IWL_WARNING("WARNING: Requesting MAC access during RFKILL " - "wakes up NIC\n"); - - /* 10 msec allows time for NIC to complete its data save */ - gp_ctl = _iwl4965_read32(priv, CSR_GP_CNTRL); - if (gp_ctl & CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY) { - IWL_DEBUG_RF_KILL("Wait for complete power-down, " - "gpctl = 0x%08x\n", gp_ctl); - mdelay(10); - } else - IWL_DEBUG_RF_KILL("power-down complete, " - "gpctl = 0x%08x\n", gp_ctl); - } - - /* this bit wakes up the NIC */ - _iwl4965_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); - ret = _iwl4965_poll_bit(priv, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN, - (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY | - CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 50); - if (ret < 0) { - IWL_ERROR("MAC is in deep sleep!\n"); - return -EIO; - } - -#ifdef CONFIG_IWLWIFI_DEBUG - atomic_inc(&priv->restrict_refcnt); -#endif - return 0; -} - -#ifdef CONFIG_IWLWIFI_DEBUG -static inline int __iwl4965_grab_nic_access(const char *f, u32 l, - struct iwl_priv *priv) -{ - if (atomic_read(&priv->restrict_refcnt)) - IWL_DEBUG_INFO("Grabbing access while already held at " - "line %d.\n", l); - - IWL_DEBUG_IO("grabbing nic access - %s %d\n", f, l); - return _iwl4965_grab_nic_access(priv); -} -#define iwl4965_grab_nic_access(priv) \ - __iwl4965_grab_nic_access(__FILE__, __LINE__, priv) -#else -#define iwl4965_grab_nic_access(priv) \ - _iwl4965_grab_nic_access(priv) -#endif - -static inline void _iwl4965_release_nic_access(struct iwl_priv *priv) -{ -#ifdef CONFIG_IWLWIFI_DEBUG - if (atomic_dec_and_test(&priv->restrict_refcnt)) -#endif - _iwl4965_clear_bit(priv, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); -} -#ifdef CONFIG_IWLWIFI_DEBUG -static inline void __iwl4965_release_nic_access(const char *f, u32 l, - struct iwl_priv *priv) -{ - if (atomic_read(&priv->restrict_refcnt) <= 0) - IWL_ERROR("Release unheld nic access at line %d.\n", l); - - IWL_DEBUG_IO("releasing nic access - %s %d\n", f, l); - _iwl4965_release_nic_access(priv); -} -#define iwl4965_release_nic_access(priv) \ - __iwl4965_release_nic_access(__FILE__, __LINE__, priv) -#else -#define iwl4965_release_nic_access(priv) \ - _iwl4965_release_nic_access(priv) -#endif - -static inline u32 _iwl4965_read_direct32(struct iwl_priv *priv, u32 reg) -{ - return _iwl4965_read32(priv, reg); -} -#ifdef CONFIG_IWLWIFI_DEBUG -static inline u32 __iwl4965_read_direct32(const char *f, u32 l, - struct iwl_priv *priv, u32 reg) -{ - u32 value = _iwl4965_read_direct32(priv, reg); - if (!atomic_read(&priv->restrict_refcnt)) - IWL_ERROR("Nic access not held from %s %d\n", f, l); - IWL_DEBUG_IO("read_direct32(0x%4X) = 0x%08x - %s %d \n", reg, value, - f, l); - return value; -} -#define iwl4965_read_direct32(priv, reg) \ - __iwl4965_read_direct32(__FILE__, __LINE__, priv, reg) -#else -#define iwl4965_read_direct32 _iwl4965_read_direct32 -#endif - -static inline void _iwl4965_write_direct32(struct iwl_priv *priv, - u32 reg, u32 value) -{ - _iwl4965_write32(priv, reg, value); -} -#ifdef CONFIG_IWLWIFI_DEBUG -static void __iwl4965_write_direct32(u32 line, - struct iwl_priv *priv, u32 reg, u32 value) -{ - if (!atomic_read(&priv->restrict_refcnt)) - IWL_ERROR("Nic access not held from line %d\n", line); - _iwl4965_write_direct32(priv, reg, value); -} -#define iwl4965_write_direct32(priv, reg, value) \ - __iwl4965_write_direct32(__LINE__, priv, reg, value) -#else -#define iwl4965_write_direct32 _iwl4965_write_direct32 -#endif - -static inline void iwl4965_write_reg_buf(struct iwl_priv *priv, - u32 reg, u32 len, u32 *values) -{ - u32 count = sizeof(u32); - - if ((priv != NULL) && (values != NULL)) { - for (; 0 < len; len -= count, reg += count, values++) - _iwl4965_write_direct32(priv, reg, *values); - } -} - -static inline int _iwl4965_poll_direct_bit(struct iwl_priv *priv, - u32 addr, u32 mask, int timeout) -{ - int i = 0; - - do { - if ((_iwl4965_read_direct32(priv, addr) & mask) == mask) - return i; - mdelay(10); - i += 10; - } while (i < timeout); - - return -ETIMEDOUT; -} - -#ifdef CONFIG_IWLWIFI_DEBUG -static inline int __iwl4965_poll_direct_bit(const char *f, u32 l, - struct iwl_priv *priv, - u32 addr, u32 mask, int timeout) -{ - int ret = _iwl4965_poll_direct_bit(priv, addr, mask, timeout); - - if (unlikely(ret == -ETIMEDOUT)) - IWL_DEBUG_IO("poll_direct_bit(0x%08X, 0x%08X) - " - "timedout - %s %d\n", addr, mask, f, l); - else - IWL_DEBUG_IO("poll_direct_bit(0x%08X, 0x%08X) = 0x%08X " - "- %s %d\n", addr, mask, ret, f, l); - return ret; -} -#define iwl4965_poll_direct_bit(priv, addr, mask, timeout) \ - __iwl4965_poll_direct_bit(__FILE__, __LINE__, priv, addr, mask, timeout) -#else -#define iwl4965_poll_direct_bit _iwl4965_poll_direct_bit -#endif - -static inline u32 _iwl4965_read_prph(struct iwl_priv *priv, u32 reg) -{ - _iwl4965_write_direct32(priv, HBUS_TARG_PRPH_RADDR, reg | (3 << 24)); - return _iwl4965_read_direct32(priv, HBUS_TARG_PRPH_RDAT); -} -#ifdef CONFIG_IWLWIFI_DEBUG -static inline u32 __iwl4965_read_prph(u32 line, struct iwl_priv *priv, u32 reg) -{ - if (!atomic_read(&priv->restrict_refcnt)) - IWL_ERROR("Nic access not held from line %d\n", line); - return _iwl4965_read_prph(priv, reg); -} - -#define iwl4965_read_prph(priv, reg) \ - __iwl4965_read_prph(__LINE__, priv, reg) -#else -#define iwl4965_read_prph _iwl4965_read_prph -#endif - -static inline void _iwl4965_write_prph(struct iwl_priv *priv, - u32 addr, u32 val) -{ - _iwl4965_write_direct32(priv, HBUS_TARG_PRPH_WADDR, - ((addr & 0x0000FFFF) | (3 << 24))); - _iwl4965_write_direct32(priv, HBUS_TARG_PRPH_WDAT, val); -} -#ifdef CONFIG_IWLWIFI_DEBUG -static inline void __iwl4965_write_prph(u32 line, struct iwl_priv *priv, - u32 addr, u32 val) -{ - if (!atomic_read(&priv->restrict_refcnt)) - IWL_ERROR("Nic access from line %d\n", line); - _iwl4965_write_prph(priv, addr, val); -} - -#define iwl4965_write_prph(priv, addr, val) \ - __iwl4965_write_prph(__LINE__, priv, addr, val); -#else -#define iwl4965_write_prph _iwl4965_write_prph -#endif - -#define _iwl4965_set_bits_prph(priv, reg, mask) \ - _iwl4965_write_prph(priv, reg, (_iwl4965_read_prph(priv, reg) | mask)) -#ifdef CONFIG_IWLWIFI_DEBUG -static inline void __iwl4965_set_bits_prph(u32 line, struct iwl_priv *priv, - u32 reg, u32 mask) -{ - if (!atomic_read(&priv->restrict_refcnt)) - IWL_ERROR("Nic access not held from line %d\n", line); - - _iwl4965_set_bits_prph(priv, reg, mask); -} -#define iwl4965_set_bits_prph(priv, reg, mask) \ - __iwl4965_set_bits_prph(__LINE__, priv, reg, mask) -#else -#define iwl4965_set_bits_prph _iwl4965_set_bits_prph -#endif - -#define _iwl4965_set_bits_mask_prph(priv, reg, bits, mask) \ - _iwl4965_write_prph(priv, reg, ((_iwl4965_read_prph(priv, reg) & mask) | bits)) - -#ifdef CONFIG_IWLWIFI_DEBUG -static inline void __iwl4965_set_bits_mask_prph(u32 line, - struct iwl_priv *priv, u32 reg, u32 bits, u32 mask) -{ - if (!atomic_read(&priv->restrict_refcnt)) - IWL_ERROR("Nic access not held from line %d\n", line); - _iwl4965_set_bits_mask_prph(priv, reg, bits, mask); -} -#define iwl4965_set_bits_mask_prph(priv, reg, bits, mask) \ - __iwl4965_set_bits_mask_prph(__LINE__, priv, reg, bits, mask) -#else -#define iwl4965_set_bits_mask_prph _iwl4965_set_bits_mask_prph -#endif - -static inline void iwl4965_clear_bits_prph(struct iwl_priv - *priv, u32 reg, u32 mask) -{ - u32 val = _iwl4965_read_prph(priv, reg); - _iwl4965_write_prph(priv, reg, (val & ~mask)); -} - -static inline u32 iwl4965_read_targ_mem(struct iwl_priv *priv, u32 addr) -{ - iwl4965_write_direct32(priv, HBUS_TARG_MEM_RADDR, addr); - return iwl4965_read_direct32(priv, HBUS_TARG_MEM_RDAT); -} - -static inline void iwl4965_write_targ_mem(struct iwl_priv *priv, u32 addr, u32 val) -{ - iwl4965_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr); - iwl4965_write_direct32(priv, HBUS_TARG_MEM_WDAT, val); -} - -static inline void iwl4965_write_targ_mem_buf(struct iwl_priv *priv, u32 addr, - u32 len, u32 *values) -{ - iwl4965_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr); - for (; 0 < len; len -= sizeof(u32), values++) - iwl4965_write_direct32(priv, HBUS_TARG_MEM_WDAT, *values); -} -#endif diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 8b5cacb14618..e5f64d7fbfde 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -41,6 +41,7 @@ #include "iwl-eeprom.h" #include "iwl-core.h" #include "iwl-4965.h" +#include "iwl-io.h" #include "iwl-helpers.h" /* module parameters */ @@ -315,20 +316,20 @@ int iwl4965_hw_rxq_stop(struct iwl_priv *priv) unsigned long flags; spin_lock_irqsave(&priv->lock, flags); - rc = iwl4965_grab_nic_access(priv); + rc = iwl_grab_nic_access(priv); if (rc) { spin_unlock_irqrestore(&priv->lock, flags); return rc; } /* stop Rx DMA */ - iwl4965_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); - rc = iwl4965_poll_direct_bit(priv, FH_MEM_RSSR_RX_STATUS_REG, + iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); + rc = iwl_poll_direct_bit(priv, FH_MEM_RSSR_RX_STATUS_REG, (1 << 24), 1000); if (rc < 0) IWL_ERROR("Can't stop Rx DMA.\n"); - iwl4965_release_nic_access(priv); + iwl_release_nic_access(priv); spin_unlock_irqrestore(&priv->lock, flags); return 0; @@ -372,7 +373,7 @@ static int iwl4965_nic_set_pwr_src(struct iwl_priv *priv, int pwr_max) unsigned long flags; spin_lock_irqsave(&priv->lock, flags); - ret = iwl4965_grab_nic_access(priv); + ret = iwl_grab_nic_access(priv); if (ret) { spin_unlock_irqrestore(&priv->lock, flags); return ret; @@ -385,15 +386,15 @@ static int iwl4965_nic_set_pwr_src(struct iwl_priv *priv, int pwr_max) &val); if (val & PCI_CFG_PMC_PME_FROM_D3COLD_SUPPORT) - iwl4965_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, + iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_PWR_SRC_VAUX, ~APMG_PS_CTRL_MSK_PWR_SRC); } else - iwl4965_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, + iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_PWR_SRC_VMAIN, ~APMG_PS_CTRL_MSK_PWR_SRC); - iwl4965_release_nic_access(priv); + iwl_release_nic_access(priv); spin_unlock_irqrestore(&priv->lock, flags); return ret; @@ -406,7 +407,7 @@ static int iwl4965_rx_init(struct iwl_priv *priv, struct iwl4965_rx_queue *rxq) unsigned int rb_size; spin_lock_irqsave(&priv->lock, flags); - rc = iwl4965_grab_nic_access(priv); + rc = iwl_grab_nic_access(priv); if (rc) { spin_unlock_irqrestore(&priv->lock, flags); return rc; @@ -418,34 +419,34 @@ static int iwl4965_rx_init(struct iwl_priv *priv, struct iwl4965_rx_queue *rxq) rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K; /* Stop Rx DMA */ - iwl4965_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); + iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); /* Reset driver's Rx queue write index */ - iwl4965_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0); + iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0); /* Tell device where to find RBD circular buffer in DRAM */ - iwl4965_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_BASE_REG, - rxq->dma_addr >> 8); + iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_BASE_REG, + rxq->dma_addr >> 8); /* Tell device where in DRAM to update its Rx status */ - iwl4965_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG, - (priv->hw_setting.shared_phys + - offsetof(struct iwl4965_shared, val0)) >> 4); + iwl_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG, + (priv->hw_setting.shared_phys + + offsetof(struct iwl4965_shared, val0)) >> 4); /* Enable Rx DMA, enable host interrupt, Rx buffer size 4k, 256 RBDs */ - iwl4965_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, - FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL | - FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL | - rb_size | + iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, + FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL | + FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL | + rb_size | /*0x10 << 4 | */ - (RX_QUEUE_SIZE_LOG << + (RX_QUEUE_SIZE_LOG << FH_RCSR_RX_CONFIG_RBDCB_SIZE_BITSHIFT)); /* - * iwl4965_write32(priv,CSR_INT_COAL_REG,0); + * iwl_write32(priv,CSR_INT_COAL_REG,0); */ - iwl4965_release_nic_access(priv); + iwl_release_nic_access(priv); spin_unlock_irqrestore(&priv->lock, flags); return 0; @@ -458,13 +459,13 @@ static int iwl4965_kw_init(struct iwl_priv *priv) int rc; spin_lock_irqsave(&priv->lock, flags); - rc = iwl4965_grab_nic_access(priv); + rc = iwl_grab_nic_access(priv); if (rc) goto out; - iwl4965_write_direct32(priv, IWL_FH_KW_MEM_ADDR_REG, + iwl_write_direct32(priv, IWL_FH_KW_MEM_ADDR_REG, priv->kw.dma_addr >> 4); - iwl4965_release_nic_access(priv); + iwl_release_nic_access(priv); out: spin_unlock_irqrestore(&priv->lock, flags); return rc; @@ -524,7 +525,7 @@ static int iwl4965_txq_ctx_reset(struct iwl_priv *priv) spin_lock_irqsave(&priv->lock, flags); - rc = iwl4965_grab_nic_access(priv); + rc = iwl_grab_nic_access(priv); if (unlikely(rc)) { IWL_ERROR("TX reset failed"); spin_unlock_irqrestore(&priv->lock, flags); @@ -532,8 +533,8 @@ static int iwl4965_txq_ctx_reset(struct iwl_priv *priv) } /* Turn off all Tx DMA channels */ - iwl4965_write_prph(priv, KDR_SCD_TXFACT, 0); - iwl4965_release_nic_access(priv); + iwl_write_prph(priv, KDR_SCD_TXFACT, 0); + iwl_release_nic_access(priv); spin_unlock_irqrestore(&priv->lock, flags); /* Tell 4965 where to find the keep-warm buffer */ @@ -580,11 +581,11 @@ int iwl4965_hw_nic_init(struct iwl_priv *priv) /* nic_init */ spin_lock_irqsave(&priv->lock, flags); - iwl4965_set_bit(priv, CSR_GIO_CHICKEN_BITS, + iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS, CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); - iwl4965_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); - rc = iwl4965_poll_bit(priv, CSR_GP_CNTRL, + iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); + rc = iwl_poll_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); if (rc < 0) { @@ -593,26 +594,25 @@ int iwl4965_hw_nic_init(struct iwl_priv *priv) return rc; } - rc = iwl4965_grab_nic_access(priv); + rc = iwl_grab_nic_access(priv); if (rc) { spin_unlock_irqrestore(&priv->lock, flags); return rc; } - iwl4965_read_prph(priv, APMG_CLK_CTRL_REG); + iwl_read_prph(priv, APMG_CLK_CTRL_REG); - iwl4965_write_prph(priv, APMG_CLK_CTRL_REG, - APMG_CLK_VAL_DMA_CLK_RQT | - APMG_CLK_VAL_BSM_CLK_RQT); - iwl4965_read_prph(priv, APMG_CLK_CTRL_REG); + iwl_write_prph(priv, APMG_CLK_CTRL_REG, + APMG_CLK_VAL_DMA_CLK_RQT | APMG_CLK_VAL_BSM_CLK_RQT); + iwl_read_prph(priv, APMG_CLK_CTRL_REG); udelay(20); - iwl4965_set_bits_prph(priv, APMG_PCIDEV_STT_REG, - APMG_PCIDEV_STT_VAL_L1_ACT_DIS); + iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG, + APMG_PCIDEV_STT_VAL_L1_ACT_DIS); - iwl4965_release_nic_access(priv); - iwl4965_write32(priv, CSR_INT_COALESCING, 512 / 32); + iwl_release_nic_access(priv); + iwl_write32(priv, CSR_INT_COALESCING, 512 / 32); spin_unlock_irqrestore(&priv->lock, flags); /* Determine HW type */ @@ -648,26 +648,24 @@ int iwl4965_hw_nic_init(struct iwl_priv *priv) /* set CSR_HW_CONFIG_REG for uCode use */ - iwl4965_set_bit(priv, CSR_HW_IF_CONFIG_REG, - CSR49_HW_IF_CONFIG_REG_BIT_4965_R | - CSR49_HW_IF_CONFIG_REG_BIT_RADIO_SI | - CSR49_HW_IF_CONFIG_REG_BIT_MAC_SI); + iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, + CSR49_HW_IF_CONFIG_REG_BIT_4965_R | + CSR49_HW_IF_CONFIG_REG_BIT_RADIO_SI | + CSR49_HW_IF_CONFIG_REG_BIT_MAC_SI); - rc = iwl4965_grab_nic_access(priv); + rc = iwl_grab_nic_access(priv); if (rc < 0) { spin_unlock_irqrestore(&priv->lock, flags); IWL_DEBUG_INFO("Failed to init the card\n"); return rc; } - iwl4965_read_prph(priv, APMG_PS_CTRL_REG); - iwl4965_set_bits_prph(priv, APMG_PS_CTRL_REG, - APMG_PS_CTRL_VAL_RESET_REQ); + iwl_read_prph(priv, APMG_PS_CTRL_REG); + iwl_set_bits_prph(priv, APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_RESET_REQ); udelay(5); - iwl4965_clear_bits_prph(priv, APMG_PS_CTRL_REG, - APMG_PS_CTRL_VAL_RESET_REQ); + iwl_clear_bits_prph(priv, APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_RESET_REQ); - iwl4965_release_nic_access(priv); + iwl_release_nic_access(priv); spin_unlock_irqrestore(&priv->lock, flags); iwl4965_hw_card_show_info(priv); @@ -720,16 +718,16 @@ int iwl4965_hw_nic_stop_master(struct iwl_priv *priv) spin_lock_irqsave(&priv->lock, flags); /* set stop master bit */ - iwl4965_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER); + iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER); - reg_val = iwl4965_read32(priv, CSR_GP_CNTRL); + reg_val = iwl_read32(priv, CSR_GP_CNTRL); if (CSR_GP_CNTRL_REG_FLAG_MAC_POWER_SAVE == (reg_val & CSR_GP_CNTRL_REG_MSK_POWER_SAVE_TYPE)) IWL_DEBUG_INFO("Card in power save, master is already " "stopped\n"); else { - rc = iwl4965_poll_bit(priv, CSR_RESET, + rc = iwl_poll_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_MASTER_DISABLED, CSR_RESET_REG_FLAG_MASTER_DISABLED, 100); if (rc < 0) { @@ -756,18 +754,17 @@ void iwl4965_hw_txq_ctx_stop(struct iwl_priv *priv) /* Stop each Tx DMA channel, and wait for it to be idle */ for (txq_id = 0; txq_id < priv->hw_setting.max_txq_num; txq_id++) { spin_lock_irqsave(&priv->lock, flags); - if (iwl4965_grab_nic_access(priv)) { + if (iwl_grab_nic_access(priv)) { spin_unlock_irqrestore(&priv->lock, flags); continue; } - iwl4965_write_direct32(priv, - IWL_FH_TCSR_CHNL_TX_CONFIG_REG(txq_id), - 0x0); - iwl4965_poll_direct_bit(priv, IWL_FH_TSSR_TX_STATUS_REG, - IWL_FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE - (txq_id), 200); - iwl4965_release_nic_access(priv); + iwl_write_direct32(priv, + IWL_FH_TCSR_CHNL_TX_CONFIG_REG(txq_id), 0x0); + iwl_poll_direct_bit(priv, IWL_FH_TSSR_TX_STATUS_REG, + IWL_FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE + (txq_id), 200); + iwl_release_nic_access(priv); spin_unlock_irqrestore(&priv->lock, flags); } @@ -784,29 +781,29 @@ int iwl4965_hw_nic_reset(struct iwl_priv *priv) spin_lock_irqsave(&priv->lock, flags); - iwl4965_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); + iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); udelay(10); - iwl4965_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); - rc = iwl4965_poll_bit(priv, CSR_RESET, + iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); + rc = iwl_poll_bit(priv, CSR_RESET, CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25); udelay(10); - rc = iwl4965_grab_nic_access(priv); + rc = iwl_grab_nic_access(priv); if (!rc) { - iwl4965_write_prph(priv, APMG_CLK_EN_REG, - APMG_CLK_VAL_DMA_CLK_RQT | - APMG_CLK_VAL_BSM_CLK_RQT); + iwl_write_prph(priv, APMG_CLK_EN_REG, + APMG_CLK_VAL_DMA_CLK_RQT | + APMG_CLK_VAL_BSM_CLK_RQT); udelay(10); - iwl4965_set_bits_prph(priv, APMG_PCIDEV_STT_REG, - APMG_PCIDEV_STT_VAL_L1_ACT_DIS); + iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG, + APMG_PCIDEV_STT_VAL_L1_ACT_DIS); - iwl4965_release_nic_access(priv); + iwl_release_nic_access(priv); } clear_bit(STATUS_HCMD_ACTIVE, &priv->status); @@ -872,7 +869,7 @@ void iwl4965_rf_kill_ct_config(struct iwl_priv *priv) int ret = 0; spin_lock_irqsave(&priv->lock, flags); - iwl4965_write32(priv, CSR_UCODE_DRV_GP1_CLR, + iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); spin_unlock_irqrestore(&priv->lock, flags); @@ -1733,9 +1730,9 @@ static void iwl4965_bg_txpower_work(struct work_struct *work) */ static void iwl4965_set_wr_ptrs(struct iwl_priv *priv, int txq_id, u32 index) { - iwl4965_write_direct32(priv, HBUS_TARG_WRPTR, + iwl_write_direct32(priv, HBUS_TARG_WRPTR, (index & 0xff) | (txq_id << 8)); - iwl4965_write_prph(priv, KDR_SCD_QUEUE_RDPTR(txq_id), index); + iwl_write_prph(priv, KDR_SCD_QUEUE_RDPTR(txq_id), index); } /** @@ -1755,7 +1752,7 @@ static void iwl4965_tx_queue_set_status(struct iwl_priv *priv, int active = test_bit(txq_id, &priv->txq_ctx_active_msk)?1:0; /* Set up and activate */ - iwl4965_write_prph(priv, KDR_SCD_QUEUE_STATUS_BITS(txq_id), + iwl_write_prph(priv, KDR_SCD_QUEUE_STATUS_BITS(txq_id), (active << SCD_QUEUE_STTS_REG_POS_ACTIVE) | (tx_fifo_id << SCD_QUEUE_STTS_REG_POS_TXF) | (scd_retry << SCD_QUEUE_STTS_REG_POS_WSL) | @@ -1807,46 +1804,46 @@ int iwl4965_alive_notify(struct iwl_priv *priv) priv->chain_noise_data.delta_gain_code[i] = CHAIN_NOISE_DELTA_GAIN_INIT_VAL; #endif /* CONFIG_IWL4965_SENSITIVITY*/ - ret = iwl4965_grab_nic_access(priv); + ret = iwl_grab_nic_access(priv); if (ret) { spin_unlock_irqrestore(&priv->lock, flags); return ret; } /* Clear 4965's internal Tx Scheduler data base */ - priv->scd_base_addr = iwl4965_read_prph(priv, KDR_SCD_SRAM_BASE_ADDR); + priv->scd_base_addr = iwl_read_prph(priv, KDR_SCD_SRAM_BASE_ADDR); a = priv->scd_base_addr + SCD_CONTEXT_DATA_OFFSET; for (; a < priv->scd_base_addr + SCD_TX_STTS_BITMAP_OFFSET; a += 4) - iwl4965_write_targ_mem(priv, a, 0); + iwl_write_targ_mem(priv, a, 0); for (; a < priv->scd_base_addr + SCD_TRANSLATE_TBL_OFFSET; a += 4) - iwl4965_write_targ_mem(priv, a, 0); + iwl_write_targ_mem(priv, a, 0); for (; a < sizeof(u16) * priv->hw_setting.max_txq_num; a += 4) - iwl4965_write_targ_mem(priv, a, 0); + iwl_write_targ_mem(priv, a, 0); /* Tel 4965 where to find Tx byte count tables */ - iwl4965_write_prph(priv, KDR_SCD_DRAM_BASE_ADDR, + iwl_write_prph(priv, KDR_SCD_DRAM_BASE_ADDR, (priv->hw_setting.shared_phys + offsetof(struct iwl4965_shared, queues_byte_cnt_tbls)) >> 10); /* Disable chain mode for all queues */ - iwl4965_write_prph(priv, KDR_SCD_QUEUECHAIN_SEL, 0); + iwl_write_prph(priv, KDR_SCD_QUEUECHAIN_SEL, 0); /* Initialize each Tx queue (including the command queue) */ for (i = 0; i < priv->hw_setting.max_txq_num; i++) { /* TFD circular buffer read/write indexes */ - iwl4965_write_prph(priv, KDR_SCD_QUEUE_RDPTR(i), 0); - iwl4965_write_direct32(priv, HBUS_TARG_WRPTR, 0 | (i << 8)); + iwl_write_prph(priv, KDR_SCD_QUEUE_RDPTR(i), 0); + iwl_write_direct32(priv, HBUS_TARG_WRPTR, 0 | (i << 8)); /* Max Tx Window size for Scheduler-ACK mode */ - iwl4965_write_targ_mem(priv, priv->scd_base_addr + + iwl_write_targ_mem(priv, priv->scd_base_addr + SCD_CONTEXT_QUEUE_OFFSET(i), (SCD_WIN_SIZE << SCD_QUEUE_CTX_REG1_WIN_SIZE_POS) & SCD_QUEUE_CTX_REG1_WIN_SIZE_MSK); /* Frame limit */ - iwl4965_write_targ_mem(priv, priv->scd_base_addr + + iwl_write_targ_mem(priv, priv->scd_base_addr + SCD_CONTEXT_QUEUE_OFFSET(i) + sizeof(u32), (SCD_FRAME_LIMIT << @@ -1854,11 +1851,11 @@ int iwl4965_alive_notify(struct iwl_priv *priv) SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK); } - iwl4965_write_prph(priv, KDR_SCD_INTERRUPT_MASK, + iwl_write_prph(priv, KDR_SCD_INTERRUPT_MASK, (1 << priv->hw_setting.max_txq_num) - 1); /* Activate all Tx DMA/FIFO channels */ - iwl4965_write_prph(priv, KDR_SCD_TXFACT, + iwl_write_prph(priv, KDR_SCD_TXFACT, SCD_TXFACT_REG_TXFIFO_MASK(0, 7)); iwl4965_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0); @@ -1870,7 +1867,7 @@ int iwl4965_alive_notify(struct iwl_priv *priv) iwl4965_tx_queue_set_status(priv, &priv->txq[i], ac, 0); } - iwl4965_release_nic_access(priv); + iwl_release_nic_access(priv); spin_unlock_irqrestore(&priv->lock, flags); return ret; @@ -2929,22 +2926,22 @@ int iwl4965_hw_tx_queue_init(struct iwl_priv *priv, struct iwl4965_tx_queue *txq int txq_id = txq->q.id; spin_lock_irqsave(&priv->lock, flags); - rc = iwl4965_grab_nic_access(priv); + rc = iwl_grab_nic_access(priv); if (rc) { spin_unlock_irqrestore(&priv->lock, flags); return rc; } /* Circular buffer (TFD queue in DRAM) physical base address */ - iwl4965_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id), + iwl_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id), txq->q.dma_addr >> 8); /* Enable DMA channel, using same id as for TFD queue */ - iwl4965_write_direct32( + iwl_write_direct32( priv, IWL_FH_TCSR_CHNL_TX_CONFIG_REG(txq_id), IWL_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | IWL_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL); - iwl4965_release_nic_access(priv); + iwl_release_nic_access(priv); spin_unlock_irqrestore(&priv->lock, flags); return 0; @@ -4259,7 +4256,7 @@ static void iwl4965_tx_queue_stop_scheduler(struct iwl_priv *priv, { /* Simply stop the queue, but don't change any configuration; * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */ - iwl4965_write_prph(priv, + iwl_write_prph(priv, KDR_SCD_QUEUE_STATUS_BITS(txq_id), (0 << SCD_QUEUE_STTS_REG_POS_ACTIVE)| (1 << SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN)); @@ -4280,24 +4277,24 @@ static int iwl4965_tx_queue_agg_disable(struct iwl_priv *priv, u16 txq_id, return -EINVAL; } - ret = iwl4965_grab_nic_access(priv); + ret = iwl_grab_nic_access(priv); if (ret) return ret; iwl4965_tx_queue_stop_scheduler(priv, txq_id); - iwl4965_clear_bits_prph(priv, KDR_SCD_QUEUECHAIN_SEL, (1 << txq_id)); + iwl_clear_bits_prph(priv, KDR_SCD_QUEUECHAIN_SEL, (1 << txq_id)); priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff); priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); /* supposes that ssn_idx is valid (!= 0xFFF) */ iwl4965_set_wr_ptrs(priv, txq_id, ssn_idx); - iwl4965_clear_bits_prph(priv, KDR_SCD_INTERRUPT_MASK, (1 << txq_id)); + iwl_clear_bits_prph(priv, KDR_SCD_INTERRUPT_MASK, (1 << txq_id)); iwl4965_txq_ctx_deactivate(priv, txq_id); iwl4965_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0); - iwl4965_release_nic_access(priv); + iwl_release_nic_access(priv); return 0; } @@ -4432,14 +4429,14 @@ static int iwl4965_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid, tbl_dw_addr = priv->scd_base_addr + SCD_TRANSLATE_TBL_OFFSET_QUEUE(txq_id); - tbl_dw = iwl4965_read_targ_mem(priv, tbl_dw_addr); + tbl_dw = iwl_read_targ_mem(priv, tbl_dw_addr); if (txq_id & 0x1) tbl_dw = (scd_q2ratid << 16) | (tbl_dw & 0x0000FFFF); else tbl_dw = scd_q2ratid | (tbl_dw & 0xFFFF0000); - iwl4965_write_targ_mem(priv, tbl_dw_addr, tbl_dw); + iwl_write_targ_mem(priv, tbl_dw_addr, tbl_dw); return 0; } @@ -4469,7 +4466,7 @@ static int iwl4965_tx_queue_agg_enable(struct iwl_priv *priv, int txq_id, iwl4965_sta_modify_enable_tid_tx(priv, sta_id, tid); spin_lock_irqsave(&priv->lock, flags); - rc = iwl4965_grab_nic_access(priv); + rc = iwl_grab_nic_access(priv); if (rc) { spin_unlock_irqrestore(&priv->lock, flags); return rc; @@ -4482,7 +4479,7 @@ static int iwl4965_tx_queue_agg_enable(struct iwl_priv *priv, int txq_id, iwl4965_tx_queue_set_q2ratid(priv, ra_tid, txq_id); /* Set this queue as a chain-building queue */ - iwl4965_set_bits_prph(priv, KDR_SCD_QUEUECHAIN_SEL, (1 << txq_id)); + iwl_set_bits_prph(priv, KDR_SCD_QUEUECHAIN_SEL, (1 << txq_id)); /* Place first TFD at index corresponding to start sequence number. * Assumes that ssn_idx is valid (!= 0xFFF) */ @@ -4491,22 +4488,22 @@ static int iwl4965_tx_queue_agg_enable(struct iwl_priv *priv, int txq_id, iwl4965_set_wr_ptrs(priv, txq_id, ssn_idx); /* Set up Tx window size and frame limit for this queue */ - iwl4965_write_targ_mem(priv, + iwl_write_targ_mem(priv, priv->scd_base_addr + SCD_CONTEXT_QUEUE_OFFSET(txq_id), (SCD_WIN_SIZE << SCD_QUEUE_CTX_REG1_WIN_SIZE_POS) & SCD_QUEUE_CTX_REG1_WIN_SIZE_MSK); - iwl4965_write_targ_mem(priv, priv->scd_base_addr + + iwl_write_targ_mem(priv, priv->scd_base_addr + SCD_CONTEXT_QUEUE_OFFSET(txq_id) + sizeof(u32), (SCD_FRAME_LIMIT << SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK); - iwl4965_set_bits_prph(priv, KDR_SCD_INTERRUPT_MASK, (1 << txq_id)); + iwl_set_bits_prph(priv, KDR_SCD_INTERRUPT_MASK, (1 << txq_id)); /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */ iwl4965_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1); - iwl4965_release_nic_access(priv); + iwl_release_nic_access(priv); spin_unlock_irqrestore(&priv->lock, flags); return 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index 32c21d266f98..98644d9c7803 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -1266,6 +1266,5 @@ extern const struct iwl_channel_info *iwl_get_channel_info( const struct iwl_priv *priv, enum ieee80211_band band, u16 channel); /* Requires full declaration of iwl_priv before including */ -#include "iwl-4965-io.h" #endif /* __iwl4965_4965_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index c659bd3bc346..b2cc552de738 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -36,7 +36,7 @@ #include "iwl-4965.h" #include "iwl-debug.h" -#include "iwl-4965-io.h" +#include "iwl-io.h" /* create and remove of files */ @@ -141,9 +141,9 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, printk(KERN_DEBUG "offset is: 0x%x\tlen is: 0x%x\n", priv->dbgfs->sram_offset, priv->dbgfs->sram_len); - iwl4965_grab_nic_access(priv); + iwl_grab_nic_access(priv); for (i = priv->dbgfs->sram_len; i > 0; i -= 4) { - val = iwl4965_read_targ_mem(priv, priv->dbgfs->sram_offset + \ + val = iwl_read_targ_mem(priv, priv->dbgfs->sram_offset + \ priv->dbgfs->sram_len - i); if (i < 4) { switch (i) { @@ -161,7 +161,7 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, pos += sprintf(buf+pos, "0x%08x ", val); } pos += sprintf(buf+pos, "\n"); - iwl4965_release_nic_access(priv); + iwl_release_nic_access(priv); ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); return ret; diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index 72cad56fbd93..a07d5dcb7abc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -73,7 +73,7 @@ #include "iwl-core.h" #include "iwl-debug.h" #include "iwl-eeprom.h" -#include "iwl-4965-io.h" +#include "iwl-io.h" /************************** EEPROM BANDS **************************** * @@ -144,7 +144,7 @@ static const u8 iwl_eeprom_band_7[] = { /* 5.2 FAT channel */ int iwlcore_eeprom_verify_signature(struct iwl_priv *priv) { - u32 gp = iwl4965_read32(priv, CSR_EEPROM_GP); + u32 gp = iwl_read32(priv, CSR_EEPROM_GP); if ((gp & CSR_EEPROM_GP_VALID_MSK) == CSR_EEPROM_GP_BAD_SIGNATURE) { IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x", gp); return -ENOENT; @@ -166,14 +166,14 @@ int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv) for (count = 0; count < EEPROM_SEM_RETRY_LIMIT; count++) { /* Request semaphore */ - iwl4965_set_bit(priv, CSR_HW_IF_CONFIG_REG, - CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); + iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, + CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); /* See if we got it */ - ret = iwl4965_poll_bit(priv, CSR_HW_IF_CONFIG_REG, - CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, - CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, - EEPROM_SEM_TIMEOUT); + ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG, + CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, + CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, + EEPROM_SEM_TIMEOUT); if (ret >= 0) { IWL_DEBUG_IO("Acquired semaphore after %d tries.\n", count+1); @@ -187,7 +187,7 @@ EXPORT_SYMBOL(iwlcore_eeprom_acquire_semaphore); void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv) { - iwl4965_clear_bit(priv, CSR_HW_IF_CONFIG_REG, + iwl_clear_bit(priv, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); } @@ -204,7 +204,7 @@ EXPORT_SYMBOL(iwlcore_eeprom_release_semaphore); int iwl_eeprom_init(struct iwl_priv *priv) { u16 *e = (u16 *)&priv->eeprom; - u32 gp = iwl4965_read32(priv, CSR_EEPROM_GP); + u32 gp = iwl_read32(priv, CSR_EEPROM_GP); u32 r; int sz = sizeof(priv->eeprom); int ret; @@ -231,12 +231,12 @@ int iwl_eeprom_init(struct iwl_priv *priv) /* eeprom is an array of 16bit values */ for (addr = 0; addr < sz; addr += sizeof(u16)) { - _iwl4965_write32(priv, CSR_EEPROM_REG, addr << 1); - _iwl4965_clear_bit(priv, CSR_EEPROM_REG, CSR_EEPROM_REG_BIT_CMD); + _iwl_write32(priv, CSR_EEPROM_REG, addr << 1); + _iwl_clear_bit(priv, CSR_EEPROM_REG, CSR_EEPROM_REG_BIT_CMD); for (i = 0; i < IWL_EEPROM_ACCESS_TIMEOUT; i += IWL_EEPROM_ACCESS_DELAY) { - r = _iwl4965_read_direct32(priv, CSR_EEPROM_REG); + r = _iwl_read_direct32(priv, CSR_EEPROM_REG); if (r & CSR_EEPROM_REG_READ_VALID_MSK) break; udelay(IWL_EEPROM_ACCESS_DELAY); diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h new file mode 100644 index 000000000000..09cc094340b0 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-io.h @@ -0,0 +1,426 @@ +/****************************************************************************** + * + * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. + * + * Portions of this file are derived from the ipw3945 project. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * James P. Ketrenos + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + *****************************************************************************/ + +#ifndef __iwl_io_h__ +#define __iwl_io_h__ + +#include + +#include "iwl-debug.h" + +/* + * IO, register, and NIC memory access functions + * + * NOTE on naming convention and macro usage for these + * + * A single _ prefix before a an access function means that no state + * check or debug information is printed when that function is called. + * + * A double __ prefix before an access function means that state is checked + * and the current line number is printed in addition to any other debug output. + * + * The non-prefixed name is the #define that maps the caller into a + * #define that provides the caller's __LINE__ to the double prefix version. + * + * If you wish to call the function without any debug or state checking, + * you should use the single _ prefix version (as is used by dependent IO + * routines, for example _iwl_read_direct32 calls the non-check version of + * _iwl_read32.) + * + * These declarations are *extremely* useful in quickly isolating code deltas + * which result in misconfiguring of the hardware I/O. In combination with + * git-bisect and the IO debug level you can quickly determine the specific + * commit which breaks the IO sequence to the hardware. + * + */ + +#define _iwl_write32(priv, ofs, val) writel((val), (priv)->hw_base + (ofs)) +#ifdef CONFIG_IWLWIFI_DEBUG +static inline void __iwl_write32(const char *f, u32 l, struct iwl_priv *priv, + u32 ofs, u32 val) +{ + IWL_DEBUG_IO("write32(0x%08X, 0x%08X) - %s %d\n", ofs, val, f, l); + _iwl_write32(priv, ofs, val); +} +#define iwl_write32(priv, ofs, val) \ + __iwl_write32(__FILE__, __LINE__, priv, ofs, val) +#else +#define iwl_write32(priv, ofs, val) _iwl_write32(priv, ofs, val) +#endif + +#define _iwl_read32(priv, ofs) readl((priv)->hw_base + (ofs)) +#ifdef CONFIG_IWLWIFI_DEBUG +static inline u32 __iwl_read32(char *f, u32 l, struct iwl_priv *priv, u32 ofs) +{ + IWL_DEBUG_IO("read_direct32(0x%08X) - %s %d\n", ofs, f, l); + return _iwl_read32(priv, ofs); +} +#define iwl_read32(priv, ofs) __iwl_read32(__FILE__, __LINE__, priv, ofs) +#else +#define iwl_read32(p, o) _iwl_read32(p, o) +#endif + +static inline int _iwl_poll_bit(struct iwl_priv *priv, u32 addr, + u32 bits, u32 mask, int timeout) +{ + int i = 0; + + do { + if ((_iwl_read32(priv, addr) & mask) == (bits & mask)) + return i; + mdelay(10); + i += 10; + } while (i < timeout); + + return -ETIMEDOUT; +} +#ifdef CONFIG_IWLWIFI_DEBUG +static inline int __iwl_poll_bit(const char *f, u32 l, + struct iwl_priv *priv, u32 addr, + u32 bits, u32 mask, int timeout) +{ + int ret = _iwl_poll_bit(priv, addr, bits, mask, timeout); + IWL_DEBUG_IO("poll_bit(0x%08X, 0x%08X, 0x%08X) - %s- %s %d\n", + addr, bits, mask, + unlikely(ret == -ETIMEDOUT)?"timeout":"", f, l); + return ret; +} +#define iwl_poll_bit(priv, addr, bits, mask, timeout) \ + __iwl_poll_bit(__FILE__, __LINE__, priv, addr, bits, mask, timeout) +#else +#define iwl_poll_bit(p, a, b, m, t) _iwl_poll_bit(p, a, b, m, t) +#endif + +static inline void _iwl_set_bit(struct iwl_priv *priv, u32 reg, u32 mask) +{ + _iwl_write32(priv, reg, _iwl_read32(priv, reg) | mask); +} +#ifdef CONFIG_IWLWIFI_DEBUG +static inline void __iwl_set_bit(const char *f, u32 l, + struct iwl_priv *priv, u32 reg, u32 mask) +{ + u32 val = _iwl_read32(priv, reg) | mask; + IWL_DEBUG_IO("set_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val); + _iwl_write32(priv, reg, val); +} +#define iwl_set_bit(p, r, m) __iwl_set_bit(__FILE__, __LINE__, p, r, m) +#else +#define iwl_set_bit(p, r, m) _iwl_set_bit(p, r, m) +#endif + +static inline void _iwl_clear_bit(struct iwl_priv *priv, u32 reg, u32 mask) +{ + _iwl_write32(priv, reg, _iwl_read32(priv, reg) & ~mask); +} +#ifdef CONFIG_IWLWIFI_DEBUG +static inline void __iwl_clear_bit(const char *f, u32 l, + struct iwl_priv *priv, u32 reg, u32 mask) +{ + u32 val = _iwl_read32(priv, reg) & ~mask; + IWL_DEBUG_IO("clear_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val); + _iwl_write32(priv, reg, val); +} +#define iwl_clear_bit(p, r, m) __iwl_clear_bit(__FILE__, __LINE__, p, r, m) +#else +#define iwl_clear_bit(p, r, m) _iwl_clear_bit(p, r, m) +#endif + +static inline int _iwl_grab_nic_access(struct iwl_priv *priv) +{ + int ret; + u32 gp_ctl; + +#ifdef CONFIG_IWLWIFI_DEBUG + if (atomic_read(&priv->restrict_refcnt)) + return 0; +#endif + if (test_bit(STATUS_RF_KILL_HW, &priv->status) || + test_bit(STATUS_RF_KILL_SW, &priv->status)) { + IWL_WARNING("WARNING: Requesting MAC access during RFKILL " + "wakes up NIC\n"); + + /* 10 msec allows time for NIC to complete its data save */ + gp_ctl = _iwl_read32(priv, CSR_GP_CNTRL); + if (gp_ctl & CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY) { + IWL_DEBUG_RF_KILL("Wait for complete power-down, " + "gpctl = 0x%08x\n", gp_ctl); + mdelay(10); + } else + IWL_DEBUG_RF_KILL("power-down complete, " + "gpctl = 0x%08x\n", gp_ctl); + } + + /* this bit wakes up the NIC */ + _iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); + ret = _iwl_poll_bit(priv, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN, + (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY | + CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 50); + if (ret < 0) { + IWL_ERROR("MAC is in deep sleep!\n"); + return -EIO; + } + +#ifdef CONFIG_IWLWIFI_DEBUG + atomic_inc(&priv->restrict_refcnt); +#endif + return 0; +} + +#ifdef CONFIG_IWLWIFI_DEBUG +static inline int __iwl_grab_nic_access(const char *f, u32 l, + struct iwl_priv *priv) +{ + if (atomic_read(&priv->restrict_refcnt)) + IWL_DEBUG_INFO("Grabbing access while already held at " + "line %d.\n", l); + + IWL_DEBUG_IO("grabbing nic access - %s %d\n", f, l); + return _iwl_grab_nic_access(priv); +} +#define iwl_grab_nic_access(priv) \ + __iwl_grab_nic_access(__FILE__, __LINE__, priv) +#else +#define iwl_grab_nic_access(priv) \ + _iwl_grab_nic_access(priv) +#endif + +static inline void _iwl_release_nic_access(struct iwl_priv *priv) +{ +#ifdef CONFIG_IWLWIFI_DEBUG + if (atomic_dec_and_test(&priv->restrict_refcnt)) +#endif + _iwl_clear_bit(priv, CSR_GP_CNTRL, + CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); +} +#ifdef CONFIG_IWLWIFI_DEBUG +static inline void __iwl_release_nic_access(const char *f, u32 l, + struct iwl_priv *priv) +{ + if (atomic_read(&priv->restrict_refcnt) <= 0) + IWL_ERROR("Release unheld nic access at line %d.\n", l); + + IWL_DEBUG_IO("releasing nic access - %s %d\n", f, l); + _iwl_release_nic_access(priv); +} +#define iwl_release_nic_access(priv) \ + __iwl_release_nic_access(__FILE__, __LINE__, priv) +#else +#define iwl_release_nic_access(priv) \ + _iwl_release_nic_access(priv) +#endif + +static inline u32 _iwl_read_direct32(struct iwl_priv *priv, u32 reg) +{ + return _iwl_read32(priv, reg); +} +#ifdef CONFIG_IWLWIFI_DEBUG +static inline u32 __iwl_read_direct32(const char *f, u32 l, + struct iwl_priv *priv, u32 reg) +{ + u32 value = _iwl_read_direct32(priv, reg); + if (!atomic_read(&priv->restrict_refcnt)) + IWL_ERROR("Nic access not held from %s %d\n", f, l); + IWL_DEBUG_IO("read_direct32(0x%4X) = 0x%08x - %s %d \n", reg, value, + f, l); + return value; +} +#define iwl_read_direct32(priv, reg) \ + __iwl_read_direct32(__FILE__, __LINE__, priv, reg) +#else +#define iwl_read_direct32 _iwl_read_direct32 +#endif + +static inline void _iwl_write_direct32(struct iwl_priv *priv, + u32 reg, u32 value) +{ + _iwl_write32(priv, reg, value); +} +#ifdef CONFIG_IWLWIFI_DEBUG +static void __iwl_write_direct32(u32 line, + struct iwl_priv *priv, u32 reg, u32 value) +{ + if (!atomic_read(&priv->restrict_refcnt)) + IWL_ERROR("Nic access not held from line %d\n", line); + _iwl_write_direct32(priv, reg, value); +} +#define iwl_write_direct32(priv, reg, value) \ + __iwl_write_direct32(__LINE__, priv, reg, value) +#else +#define iwl_write_direct32 _iwl_write_direct32 +#endif + +static inline void iwl_write_reg_buf(struct iwl_priv *priv, + u32 reg, u32 len, u32 *values) +{ + u32 count = sizeof(u32); + + if ((priv != NULL) && (values != NULL)) { + for (; 0 < len; len -= count, reg += count, values++) + _iwl_write_direct32(priv, reg, *values); + } +} + +static inline int _iwl_poll_direct_bit(struct iwl_priv *priv, + u32 addr, u32 mask, int timeout) +{ + int i = 0; + + do { + if ((_iwl_read_direct32(priv, addr) & mask) == mask) + return i; + mdelay(10); + i += 10; + } while (i < timeout); + + return -ETIMEDOUT; +} + +#ifdef CONFIG_IWLWIFI_DEBUG +static inline int __iwl_poll_direct_bit(const char *f, u32 l, + struct iwl_priv *priv, + u32 addr, u32 mask, int timeout) +{ + int ret = _iwl_poll_direct_bit(priv, addr, mask, timeout); + + if (unlikely(ret == -ETIMEDOUT)) + IWL_DEBUG_IO("poll_direct_bit(0x%08X, 0x%08X) - " + "timedout - %s %d\n", addr, mask, f, l); + else + IWL_DEBUG_IO("poll_direct_bit(0x%08X, 0x%08X) = 0x%08X " + "- %s %d\n", addr, mask, ret, f, l); + return ret; +} +#define iwl_poll_direct_bit(priv, addr, mask, timeout) \ + __iwl_poll_direct_bit(__FILE__, __LINE__, priv, addr, mask, timeout) +#else +#define iwl_poll_direct_bit _iwl_poll_direct_bit +#endif + +static inline u32 _iwl_read_prph(struct iwl_priv *priv, u32 reg) +{ + _iwl_write_direct32(priv, HBUS_TARG_PRPH_RADDR, reg | (3 << 24)); + return _iwl_read_direct32(priv, HBUS_TARG_PRPH_RDAT); +} +#ifdef CONFIG_IWLWIFI_DEBUG +static inline u32 __iwl_read_prph(u32 line, struct iwl_priv *priv, u32 reg) +{ + if (!atomic_read(&priv->restrict_refcnt)) + IWL_ERROR("Nic access not held from line %d\n", line); + return _iwl_read_prph(priv, reg); +} + +#define iwl_read_prph(priv, reg) \ + __iwl_read_prph(__LINE__, priv, reg) +#else +#define iwl_read_prph _iwl_read_prph +#endif + +static inline void _iwl_write_prph(struct iwl_priv *priv, + u32 addr, u32 val) +{ + _iwl_write_direct32(priv, HBUS_TARG_PRPH_WADDR, + ((addr & 0x0000FFFF) | (3 << 24))); + _iwl_write_direct32(priv, HBUS_TARG_PRPH_WDAT, val); +} +#ifdef CONFIG_IWLWIFI_DEBUG +static inline void __iwl_write_prph(u32 line, struct iwl_priv *priv, + u32 addr, u32 val) +{ + if (!atomic_read(&priv->restrict_refcnt)) + IWL_ERROR("Nic access from line %d\n", line); + _iwl_write_prph(priv, addr, val); +} + +#define iwl_write_prph(priv, addr, val) \ + __iwl_write_prph(__LINE__, priv, addr, val); +#else +#define iwl_write_prph _iwl_write_prph +#endif + +#define _iwl_set_bits_prph(priv, reg, mask) \ + _iwl_write_prph(priv, reg, (_iwl_read_prph(priv, reg) | mask)) +#ifdef CONFIG_IWLWIFI_DEBUG +static inline void __iwl_set_bits_prph(u32 line, struct iwl_priv *priv, + u32 reg, u32 mask) +{ + if (!atomic_read(&priv->restrict_refcnt)) + IWL_ERROR("Nic access not held from line %d\n", line); + + _iwl_set_bits_prph(priv, reg, mask); +} +#define iwl_set_bits_prph(priv, reg, mask) \ + __iwl_set_bits_prph(__LINE__, priv, reg, mask) +#else +#define iwl_set_bits_prph _iwl_set_bits_prph +#endif + +#define _iwl_set_bits_mask_prph(priv, reg, bits, mask) \ + _iwl_write_prph(priv, reg, ((_iwl_read_prph(priv, reg) & mask) | bits)) + +#ifdef CONFIG_IWLWIFI_DEBUG +static inline void __iwl_set_bits_mask_prph(u32 line, + struct iwl_priv *priv, u32 reg, u32 bits, u32 mask) +{ + if (!atomic_read(&priv->restrict_refcnt)) + IWL_ERROR("Nic access not held from line %d\n", line); + _iwl_set_bits_mask_prph(priv, reg, bits, mask); +} +#define iwl_set_bits_mask_prph(priv, reg, bits, mask) \ + __iwl_set_bits_mask_prph(__LINE__, priv, reg, bits, mask) +#else +#define iwl_set_bits_mask_prph _iwl_set_bits_mask_prph +#endif + +static inline void iwl_clear_bits_prph(struct iwl_priv + *priv, u32 reg, u32 mask) +{ + u32 val = _iwl_read_prph(priv, reg); + _iwl_write_prph(priv, reg, (val & ~mask)); +} + +static inline u32 iwl_read_targ_mem(struct iwl_priv *priv, u32 addr) +{ + iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, addr); + return iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); +} + +static inline void iwl_write_targ_mem(struct iwl_priv *priv, u32 addr, u32 val) +{ + iwl_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr); + iwl_write_direct32(priv, HBUS_TARG_MEM_WDAT, val); +} + +static inline void iwl_write_targ_mem_buf(struct iwl_priv *priv, u32 addr, + u32 len, u32 *values) +{ + iwl_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr); + for (; 0 < len; len -= sizeof(u32), values++) + iwl_write_direct32(priv, HBUS_TARG_MEM_WDAT, *values); +} +#endif diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index 6f5424bd365b..d59ad1844e25 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c @@ -40,6 +40,7 @@ #include #include "iwl-4965.h" +#include "iwl-io.h" #include "iwl-core.h" #include "iwl-helpers.h" @@ -85,9 +86,9 @@ static int iwl_send_led_cmd(struct iwl_priv *priv, }; u32 reg; - reg = iwl4965_read32(priv, CSR_LED_REG); + reg = iwl_read32(priv, CSR_LED_REG); if (reg != (reg & CSR_LED_BSM_CTRL_MSK)) - iwl4965_write32(priv, CSR_LED_REG, reg & CSR_LED_BSM_CTRL_MSK); + iwl_write32(priv, CSR_LED_REG, reg & CSR_LED_BSM_CTRL_MSK); return iwl_send_cmd(priv, &cmd); } @@ -126,7 +127,7 @@ static int iwl4965_led_pattern(struct iwl_priv *priv, int led_id, static int iwl4965_led_on_reg(struct iwl_priv *priv, int led_id) { IWL_DEBUG_LED("led on %d\n", led_id); - iwl4965_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_ON); + iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_ON); return 0; } @@ -150,7 +151,7 @@ int iwl4965_led_off(struct iwl_priv *priv, int led_id) static int iwl4965_led_off_reg(struct iwl_priv *priv, int led_id) { IWL_DEBUG_LED("radio off\n"); - iwl4965_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_OFF); + iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_OFF); return 0; } diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index a04127a8acf7..9e49e8ce3348 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -48,6 +48,7 @@ #include "iwl-eeprom.h" #include "iwl-core.h" #include "iwl-4965.h" +#include "iwl-io.h" #include "iwl-helpers.h" static int iwl4965_tx_queue_update_write_ptr(struct iwl_priv *priv, @@ -2616,7 +2617,7 @@ static void iwl4965_radio_kill_sw(struct iwl_priv *priv, int disable_radio) /* FIXME: This is a workaround for AP */ if (priv->iw_mode != IEEE80211_IF_TYPE_AP) { spin_lock_irqsave(&priv->lock, flags); - iwl4965_write32(priv, CSR_UCODE_DRV_GP1_SET, + iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, CSR_UCODE_SW_BIT_RFKILL); spin_unlock_irqrestore(&priv->lock, flags); iwl4965_send_card_state(priv, CARD_STATE_CMD_DISABLE, 0); @@ -2626,7 +2627,7 @@ static void iwl4965_radio_kill_sw(struct iwl_priv *priv, int disable_radio) } spin_lock_irqsave(&priv->lock, flags); - iwl4965_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); + iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); clear_bit(STATUS_RF_KILL_SW, &priv->status); spin_unlock_irqrestore(&priv->lock, flags); @@ -2635,9 +2636,9 @@ static void iwl4965_radio_kill_sw(struct iwl_priv *priv, int disable_radio) msleep(10); spin_lock_irqsave(&priv->lock, flags); - iwl4965_read32(priv, CSR_UCODE_DRV_GP1); - if (!iwl4965_grab_nic_access(priv)) - iwl4965_release_nic_access(priv); + iwl_read32(priv, CSR_UCODE_DRV_GP1); + if (!iwl_grab_nic_access(priv)) + iwl_release_nic_access(priv); spin_unlock_irqrestore(&priv->lock, flags); if (test_bit(STATUS_RF_KILL_HW, &priv->status)) { @@ -3514,35 +3515,35 @@ static void iwl4965_rx_card_state_notif(struct iwl_priv *priv, if (flags & (SW_CARD_DISABLED | HW_CARD_DISABLED | RF_CARD_DISABLED)) { - iwl4965_write32(priv, CSR_UCODE_DRV_GP1_SET, + iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); - if (!iwl4965_grab_nic_access(priv)) { - iwl4965_write_direct32( + if (!iwl_grab_nic_access(priv)) { + iwl_write_direct32( priv, HBUS_TARG_MBX_C, HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED); - iwl4965_release_nic_access(priv); + iwl_release_nic_access(priv); } if (!(flags & RXON_CARD_DISABLED)) { - iwl4965_write32(priv, CSR_UCODE_DRV_GP1_CLR, + iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); - if (!iwl4965_grab_nic_access(priv)) { - iwl4965_write_direct32( + if (!iwl_grab_nic_access(priv)) { + iwl_write_direct32( priv, HBUS_TARG_MBX_C, HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED); - iwl4965_release_nic_access(priv); + iwl_release_nic_access(priv); } } if (flags & RF_CARD_DISABLED) { - iwl4965_write32(priv, CSR_UCODE_DRV_GP1_SET, + iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); - iwl4965_read32(priv, CSR_UCODE_DRV_GP1); - if (!iwl4965_grab_nic_access(priv)) - iwl4965_release_nic_access(priv); + iwl_read32(priv, CSR_UCODE_DRV_GP1); + if (!iwl_grab_nic_access(priv)) + iwl_release_nic_access(priv); } } @@ -3756,27 +3757,27 @@ int iwl4965_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl4965_rx_q /* If power-saving is in use, make sure device is awake */ if (test_bit(STATUS_POWER_PMI, &priv->status)) { - reg = iwl4965_read32(priv, CSR_UCODE_DRV_GP1); + reg = iwl_read32(priv, CSR_UCODE_DRV_GP1); if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { - iwl4965_set_bit(priv, CSR_GP_CNTRL, + iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); goto exit_unlock; } - rc = iwl4965_grab_nic_access(priv); + rc = iwl_grab_nic_access(priv); if (rc) goto exit_unlock; /* Device expects a multiple of 8 */ - iwl4965_write_direct32(priv, FH_RSCSR_CHNL0_WPTR, + iwl_write_direct32(priv, FH_RSCSR_CHNL0_WPTR, q->write & ~0x7); - iwl4965_release_nic_access(priv); + iwl_release_nic_access(priv); /* Else device is assumed to be awake */ } else /* Device expects a multiple of 8 */ - iwl4965_write32(priv, FH_RSCSR_CHNL0_WPTR, q->write & ~0x7); + iwl_write32(priv, FH_RSCSR_CHNL0_WPTR, q->write & ~0x7); q->need_update = 0; @@ -4213,27 +4214,27 @@ static int iwl4965_tx_queue_update_write_ptr(struct iwl_priv *priv, /* wake up nic if it's powered down ... * uCode will wake up, and interrupt us again, so next * time we'll skip this part. */ - reg = iwl4965_read32(priv, CSR_UCODE_DRV_GP1); + reg = iwl_read32(priv, CSR_UCODE_DRV_GP1); if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { IWL_DEBUG_INFO("Requesting wakeup, GP1 = 0x%x\n", reg); - iwl4965_set_bit(priv, CSR_GP_CNTRL, + iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); return rc; } /* restore this queue's parameters in nic hardware. */ - rc = iwl4965_grab_nic_access(priv); + rc = iwl_grab_nic_access(priv); if (rc) return rc; - iwl4965_write_direct32(priv, HBUS_TARG_WRPTR, + iwl_write_direct32(priv, HBUS_TARG_WRPTR, txq->q.write_ptr | (txq_id << 8)); - iwl4965_release_nic_access(priv); + iwl_release_nic_access(priv); /* else not in power-save mode, uCode will never sleep when we're * trying to tx (during RFKILL, we're not trying to tx). */ } else - iwl4965_write32(priv, HBUS_TARG_WRPTR, + iwl_write32(priv, HBUS_TARG_WRPTR, txq->q.write_ptr | (txq_id << 8)); txq->need_update = 0; @@ -4268,7 +4269,7 @@ static void iwl4965_enable_interrupts(struct iwl_priv *priv) { IWL_DEBUG_ISR("Enabling interrupts\n"); set_bit(STATUS_INT_ENABLED, &priv->status); - iwl4965_write32(priv, CSR_INT_MASK, CSR_INI_SET_MASK); + iwl_write32(priv, CSR_INT_MASK, CSR_INI_SET_MASK); } static inline void iwl4965_disable_interrupts(struct iwl_priv *priv) @@ -4276,12 +4277,12 @@ static inline void iwl4965_disable_interrupts(struct iwl_priv *priv) clear_bit(STATUS_INT_ENABLED, &priv->status); /* disable interrupts from uCode/NIC to host */ - iwl4965_write32(priv, CSR_INT_MASK, 0x00000000); + iwl_write32(priv, CSR_INT_MASK, 0x00000000); /* acknowledge/clear/reset any interrupts still pending * from uCode or flow handler (Rx/Tx DMA) */ - iwl4965_write32(priv, CSR_INT, 0xffffffff); - iwl4965_write32(priv, CSR_FH_INT_STATUS, 0xffffffff); + iwl_write32(priv, CSR_INT, 0xffffffff); + iwl_write32(priv, CSR_FH_INT_STATUS, 0xffffffff); IWL_DEBUG_ISR("Disabled interrupts\n"); } @@ -4322,28 +4323,28 @@ static void iwl4965_dump_nic_error_log(struct iwl_priv *priv) return; } - rc = iwl4965_grab_nic_access(priv); + rc = iwl_grab_nic_access(priv); if (rc) { IWL_WARNING("Can not read from adapter at this time.\n"); return; } - count = iwl4965_read_targ_mem(priv, base); + count = iwl_read_targ_mem(priv, base); if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) { IWL_ERROR("Start IWL Error Log Dump:\n"); IWL_ERROR("Status: 0x%08lX, count: %d\n", priv->status, count); } - desc = iwl4965_read_targ_mem(priv, base + 1 * sizeof(u32)); - blink1 = iwl4965_read_targ_mem(priv, base + 3 * sizeof(u32)); - blink2 = iwl4965_read_targ_mem(priv, base + 4 * sizeof(u32)); - ilink1 = iwl4965_read_targ_mem(priv, base + 5 * sizeof(u32)); - ilink2 = iwl4965_read_targ_mem(priv, base + 6 * sizeof(u32)); - data1 = iwl4965_read_targ_mem(priv, base + 7 * sizeof(u32)); - data2 = iwl4965_read_targ_mem(priv, base + 8 * sizeof(u32)); - line = iwl4965_read_targ_mem(priv, base + 9 * sizeof(u32)); - time = iwl4965_read_targ_mem(priv, base + 11 * sizeof(u32)); + desc = iwl_read_targ_mem(priv, base + 1 * sizeof(u32)); + blink1 = iwl_read_targ_mem(priv, base + 3 * sizeof(u32)); + blink2 = iwl_read_targ_mem(priv, base + 4 * sizeof(u32)); + ilink1 = iwl_read_targ_mem(priv, base + 5 * sizeof(u32)); + ilink2 = iwl_read_targ_mem(priv, base + 6 * sizeof(u32)); + data1 = iwl_read_targ_mem(priv, base + 7 * sizeof(u32)); + data2 = iwl_read_targ_mem(priv, base + 8 * sizeof(u32)); + line = iwl_read_targ_mem(priv, base + 9 * sizeof(u32)); + time = iwl_read_targ_mem(priv, base + 11 * sizeof(u32)); IWL_ERROR("Desc Time " "data1 data2 line\n"); @@ -4353,7 +4354,7 @@ static void iwl4965_dump_nic_error_log(struct iwl_priv *priv) IWL_ERROR("0x%05X 0x%05X 0x%05X 0x%05X\n", blink1, blink2, ilink1, ilink2); - iwl4965_release_nic_access(priv); + iwl_release_nic_access(priv); } #define EVENT_START_OFFSET (4 * sizeof(u32)) @@ -4361,7 +4362,7 @@ static void iwl4965_dump_nic_error_log(struct iwl_priv *priv) /** * iwl4965_print_event_log - Dump error event log to syslog * - * NOTE: Must be called with iwl4965_grab_nic_access() already obtained! + * NOTE: Must be called with iwl_grab_nic_access() already obtained! */ static void iwl4965_print_event_log(struct iwl_priv *priv, u32 start_idx, u32 num_events, u32 mode) @@ -4387,14 +4388,14 @@ static void iwl4965_print_event_log(struct iwl_priv *priv, u32 start_idx, /* "time" is actually "data" for mode 0 (no timestamp). * place event id # at far right for easier visual parsing. */ for (i = 0; i < num_events; i++) { - ev = iwl4965_read_targ_mem(priv, ptr); + ev = iwl_read_targ_mem(priv, ptr); ptr += sizeof(u32); - time = iwl4965_read_targ_mem(priv, ptr); + time = iwl_read_targ_mem(priv, ptr); ptr += sizeof(u32); if (mode == 0) IWL_ERROR("0x%08x\t%04u\n", time, ev); /* data, ev */ else { - data = iwl4965_read_targ_mem(priv, ptr); + data = iwl_read_targ_mem(priv, ptr); ptr += sizeof(u32); IWL_ERROR("%010u\t0x%08x\t%04u\n", time, data, ev); } @@ -4417,24 +4418,24 @@ static void iwl4965_dump_nic_event_log(struct iwl_priv *priv) return; } - rc = iwl4965_grab_nic_access(priv); + rc = iwl_grab_nic_access(priv); if (rc) { IWL_WARNING("Can not read from adapter at this time.\n"); return; } /* event log header */ - capacity = iwl4965_read_targ_mem(priv, base); - mode = iwl4965_read_targ_mem(priv, base + (1 * sizeof(u32))); - num_wraps = iwl4965_read_targ_mem(priv, base + (2 * sizeof(u32))); - next_entry = iwl4965_read_targ_mem(priv, base + (3 * sizeof(u32))); + capacity = iwl_read_targ_mem(priv, base); + mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32))); + num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); + next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); size = num_wraps ? capacity : next_entry; /* bail out if nothing in log */ if (size == 0) { IWL_ERROR("Start IWL Event Log Dump: nothing in log\n"); - iwl4965_release_nic_access(priv); + iwl_release_nic_access(priv); return; } @@ -4450,7 +4451,7 @@ static void iwl4965_dump_nic_event_log(struct iwl_priv *priv) /* (then/else) start at top of log */ iwl4965_print_event_log(priv, 0, next_entry, mode); - iwl4965_release_nic_access(priv); + iwl_release_nic_access(priv); } /** @@ -4522,19 +4523,19 @@ static void iwl4965_irq_tasklet(struct iwl_priv *priv) /* Ack/clear/reset pending uCode interrupts. * Note: Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS, * and will clear only when CSR_FH_INT_STATUS gets cleared. */ - inta = iwl4965_read32(priv, CSR_INT); - iwl4965_write32(priv, CSR_INT, inta); + inta = iwl_read32(priv, CSR_INT); + iwl_write32(priv, CSR_INT, inta); /* Ack/clear/reset pending flow-handler (DMA) interrupts. * Any new interrupts that happen after this, either while we're * in this tasklet, or later, will show up in next ISR/tasklet. */ - inta_fh = iwl4965_read32(priv, CSR_FH_INT_STATUS); - iwl4965_write32(priv, CSR_FH_INT_STATUS, inta_fh); + inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); + iwl_write32(priv, CSR_FH_INT_STATUS, inta_fh); #ifdef CONFIG_IWLWIFI_DEBUG if (iwl_debug_level & IWL_DL_ISR) { /* just for debug */ - inta_mask = iwl4965_read32(priv, CSR_INT_MASK); + inta_mask = iwl_read32(priv, CSR_INT_MASK); IWL_DEBUG_ISR("inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", inta, inta_mask, inta_fh); } @@ -4583,7 +4584,7 @@ static void iwl4965_irq_tasklet(struct iwl_priv *priv) /* HW RF KILL switch toggled */ if (inta & CSR_INT_BIT_RF_KILL) { int hw_rf_kill = 0; - if (!(iwl4965_read32(priv, CSR_GP_CNTRL) & + if (!(iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)) hw_rf_kill = 1; @@ -4658,9 +4659,9 @@ static void iwl4965_irq_tasklet(struct iwl_priv *priv) #ifdef CONFIG_IWLWIFI_DEBUG if (iwl_debug_level & (IWL_DL_ISR)) { - inta = iwl4965_read32(priv, CSR_INT); - inta_mask = iwl4965_read32(priv, CSR_INT_MASK); - inta_fh = iwl4965_read32(priv, CSR_FH_INT_STATUS); + inta = iwl_read32(priv, CSR_INT); + inta_mask = iwl_read32(priv, CSR_INT_MASK); + inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); IWL_DEBUG_ISR("End inta 0x%08x, enabled 0x%08x, fh 0x%08x, " "flags 0x%08lx\n", inta, inta_mask, inta_fh, flags); } @@ -4682,12 +4683,12 @@ static irqreturn_t iwl4965_isr(int irq, void *data) * back-to-back ISRs and sporadic interrupts from our NIC. * If we have something to service, the tasklet will re-enable ints. * If we *don't* have something, we'll re-enable before leaving here. */ - inta_mask = iwl4965_read32(priv, CSR_INT_MASK); /* just for debug */ - iwl4965_write32(priv, CSR_INT_MASK, 0x00000000); + inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */ + iwl_write32(priv, CSR_INT_MASK, 0x00000000); /* Discover which interrupts are active/pending */ - inta = iwl4965_read32(priv, CSR_INT); - inta_fh = iwl4965_read32(priv, CSR_FH_INT_STATUS); + inta = iwl_read32(priv, CSR_INT); + inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); /* Ignore interrupt if there's nothing in NIC to service. * This may be due to IRQ shared with another device, @@ -5054,18 +5055,18 @@ static int iwl4965_verify_inst_full(struct iwl_priv *priv, __le32 *image, IWL_DEBUG_INFO("ucode inst image size is %u\n", len); - rc = iwl4965_grab_nic_access(priv); + rc = iwl_grab_nic_access(priv); if (rc) return rc; - iwl4965_write_direct32(priv, HBUS_TARG_MEM_RADDR, RTC_INST_LOWER_BOUND); + iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, RTC_INST_LOWER_BOUND); errcnt = 0; for (; len > 0; len -= sizeof(u32), image++) { /* read data comes through single port, auto-incr addr */ /* NOTE: Use the debugless read so we don't flood kernel log * if IWL_DL_IO is set */ - val = _iwl4965_read_direct32(priv, HBUS_TARG_MEM_RDAT); + val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); if (val != le32_to_cpu(*image)) { IWL_ERROR("uCode INST section is invalid at " "offset 0x%x, is 0x%x, s/b 0x%x\n", @@ -5077,7 +5078,7 @@ static int iwl4965_verify_inst_full(struct iwl_priv *priv, __le32 *image, } } - iwl4965_release_nic_access(priv); + iwl_release_nic_access(priv); if (!errcnt) IWL_DEBUG_INFO @@ -5101,7 +5102,7 @@ static int iwl4965_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 IWL_DEBUG_INFO("ucode inst image size is %u\n", len); - rc = iwl4965_grab_nic_access(priv); + rc = iwl_grab_nic_access(priv); if (rc) return rc; @@ -5109,9 +5110,9 @@ static int iwl4965_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 /* read data comes through single port, auto-incr addr */ /* NOTE: Use the debugless read so we don't flood kernel log * if IWL_DL_IO is set */ - iwl4965_write_direct32(priv, HBUS_TARG_MEM_RADDR, + iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, i + RTC_INST_LOWER_BOUND); - val = _iwl4965_read_direct32(priv, HBUS_TARG_MEM_RDAT); + val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); if (val != le32_to_cpu(*image)) { #if 0 /* Enable this if you want to see details */ IWL_ERROR("uCode INST section is invalid at " @@ -5125,7 +5126,7 @@ static int iwl4965_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 } } - iwl4965_release_nic_access(priv); + iwl_release_nic_access(priv); return rc; } @@ -5192,11 +5193,11 @@ static int iwl4965_verify_bsm(struct iwl_priv *priv) IWL_DEBUG_INFO("Begin verify bsm\n"); /* verify BSM SRAM contents */ - val = iwl4965_read_prph(priv, BSM_WR_DWCOUNT_REG); + val = iwl_read_prph(priv, BSM_WR_DWCOUNT_REG); for (reg = BSM_SRAM_LOWER_BOUND; reg < BSM_SRAM_LOWER_BOUND + len; reg += sizeof(u32), image ++) { - val = iwl4965_read_prph(priv, reg); + val = iwl_read_prph(priv, reg); if (val != le32_to_cpu(*image)) { IWL_ERROR("BSM uCode verification failed at " "addr 0x%08X+%u (of %u), is 0x%x, s/b 0x%x\n", @@ -5273,42 +5274,42 @@ static int iwl4965_load_bsm(struct iwl_priv *priv) inst_len = priv->ucode_init.len; data_len = priv->ucode_init_data.len; - rc = iwl4965_grab_nic_access(priv); + rc = iwl_grab_nic_access(priv); if (rc) return rc; - iwl4965_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst); - iwl4965_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata); - iwl4965_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, inst_len); - iwl4965_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG, data_len); + iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst); + iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata); + iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, inst_len); + iwl_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG, data_len); /* Fill BSM memory with bootstrap instructions */ for (reg_offset = BSM_SRAM_LOWER_BOUND; reg_offset < BSM_SRAM_LOWER_BOUND + len; reg_offset += sizeof(u32), image++) - _iwl4965_write_prph(priv, reg_offset, + _iwl_write_prph(priv, reg_offset, le32_to_cpu(*image)); rc = iwl4965_verify_bsm(priv); if (rc) { - iwl4965_release_nic_access(priv); + iwl_release_nic_access(priv); return rc; } /* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */ - iwl4965_write_prph(priv, BSM_WR_MEM_SRC_REG, 0x0); - iwl4965_write_prph(priv, BSM_WR_MEM_DST_REG, + iwl_write_prph(priv, BSM_WR_MEM_SRC_REG, 0x0); + iwl_write_prph(priv, BSM_WR_MEM_DST_REG, RTC_INST_LOWER_BOUND); - iwl4965_write_prph(priv, BSM_WR_DWCOUNT_REG, len / sizeof(u32)); + iwl_write_prph(priv, BSM_WR_DWCOUNT_REG, len / sizeof(u32)); /* Load bootstrap code into instruction SRAM now, * to prepare to load "initialize" uCode */ - iwl4965_write_prph(priv, BSM_WR_CTRL_REG, + iwl_write_prph(priv, BSM_WR_CTRL_REG, BSM_WR_CTRL_REG_BIT_START); /* Wait for load of bootstrap uCode to finish */ for (i = 0; i < 100; i++) { - done = iwl4965_read_prph(priv, BSM_WR_CTRL_REG); + done = iwl_read_prph(priv, BSM_WR_CTRL_REG); if (!(done & BSM_WR_CTRL_REG_BIT_START)) break; udelay(10); @@ -5322,10 +5323,10 @@ static int iwl4965_load_bsm(struct iwl_priv *priv) /* Enable future boot loads whenever power management unit triggers it * (e.g. when powering back up after power-save shutdown) */ - iwl4965_write_prph(priv, BSM_WR_CTRL_REG, + iwl_write_prph(priv, BSM_WR_CTRL_REG, BSM_WR_CTRL_REG_BIT_START_EN); - iwl4965_release_nic_access(priv); + iwl_release_nic_access(priv); return 0; } @@ -5333,7 +5334,7 @@ static int iwl4965_load_bsm(struct iwl_priv *priv) static void iwl4965_nic_start(struct iwl_priv *priv) { /* Remove all resets to allow NIC to operate */ - iwl4965_write32(priv, CSR_RESET, 0); + iwl_write32(priv, CSR_RESET, 0); } @@ -5555,24 +5556,24 @@ static int iwl4965_set_ucode_ptrs(struct iwl_priv *priv) pdata = priv->ucode_data_backup.p_addr >> 4; spin_lock_irqsave(&priv->lock, flags); - rc = iwl4965_grab_nic_access(priv); + rc = iwl_grab_nic_access(priv); if (rc) { spin_unlock_irqrestore(&priv->lock, flags); return rc; } /* Tell bootstrap uCode where to find image to load */ - iwl4965_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst); - iwl4965_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata); - iwl4965_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG, + iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst); + iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata); + iwl_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG, priv->ucode_data.len); /* Inst bytecount must be last to set up, bit 31 signals uCode * that all new ptr/size info is in place */ - iwl4965_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, + iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, priv->ucode_code.len | BSM_DRAM_INST_LOAD); - iwl4965_release_nic_access(priv); + iwl_release_nic_access(priv); spin_unlock_irqrestore(&priv->lock, flags); @@ -5752,7 +5753,7 @@ static void __iwl4965_down(struct iwl_priv *priv) clear_bit(STATUS_EXIT_PENDING, &priv->status); /* stop and reset the on-board processor */ - iwl4965_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); + iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); /* tell the device to stop sending interrupts */ iwl4965_disable_interrupts(priv); @@ -5788,7 +5789,7 @@ static void __iwl4965_down(struct iwl_priv *priv) STATUS_FW_ERROR; spin_lock_irqsave(&priv->lock, flags); - iwl4965_clear_bit(priv, CSR_GP_CNTRL, + iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); spin_unlock_irqrestore(&priv->lock, flags); @@ -5796,17 +5797,17 @@ static void __iwl4965_down(struct iwl_priv *priv) iwl4965_hw_rxq_stop(priv); spin_lock_irqsave(&priv->lock, flags); - if (!iwl4965_grab_nic_access(priv)) { - iwl4965_write_prph(priv, APMG_CLK_DIS_REG, + if (!iwl_grab_nic_access(priv)) { + iwl_write_prph(priv, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT); - iwl4965_release_nic_access(priv); + iwl_release_nic_access(priv); } spin_unlock_irqrestore(&priv->lock, flags); udelay(5); iwl4965_hw_nic_stop_master(priv); - iwl4965_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); + iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); iwl4965_hw_nic_reset(priv); exit: @@ -5852,7 +5853,7 @@ static int __iwl4965_up(struct iwl_priv *priv) } /* If platform's RF_KILL switch is NOT set to KILL */ - if (iwl4965_read32(priv, CSR_GP_CNTRL) & + if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) clear_bit(STATUS_RF_KILL_HW, &priv->status); else { @@ -5863,7 +5864,7 @@ static int __iwl4965_up(struct iwl_priv *priv) } } - iwl4965_write32(priv, CSR_INT, 0xFFFFFFFF); + iwl_write32(priv, CSR_INT, 0xFFFFFFFF); rc = iwl4965_hw_nic_init(priv); if (rc) { @@ -5872,17 +5873,17 @@ static int __iwl4965_up(struct iwl_priv *priv) } /* make sure rfkill handshake bits are cleared */ - iwl4965_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); - iwl4965_write32(priv, CSR_UCODE_DRV_GP1_CLR, + iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); + iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); /* clear (again), then enable host interrupts */ - iwl4965_write32(priv, CSR_INT, 0xFFFFFFFF); + iwl_write32(priv, CSR_INT, 0xFFFFFFFF); iwl4965_enable_interrupts(priv); /* really make sure rfkill handshake bits are cleared */ - iwl4965_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); - iwl4965_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); + iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); + iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); /* Copy original ucode data image from disk into backup cache. * This will be used to initialize the on-board processor's @@ -8082,11 +8083,11 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e * 4. Read EEPROM *****************/ /* nic init */ - iwl4965_set_bit(priv, CSR_GIO_CHICKEN_BITS, + iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS, CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); - iwl4965_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); - err = iwl4965_poll_bit(priv, CSR_GP_CNTRL, + iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); + err = iwl_poll_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); if (err < 0) { -- cgit v1.2.1 From 775ea378fa04f39164f170f308ec467ee4ab6d34 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Tue, 25 Mar 2008 16:33:38 -0700 Subject: iwlwifi: improve NIC i/o debug prints information This patch gives the function's caller name in case NIC access reference count was not used by it. Signed-off-by: Tomas Winkler Signed-off-by: Ron Rindjunsky Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-io.h | 47 +++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 22 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h index 09cc094340b0..5bc3df432d2d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-io.h @@ -42,10 +42,12 @@ * check or debug information is printed when that function is called. * * A double __ prefix before an access function means that state is checked - * and the current line number is printed in addition to any other debug output. + * and the current line number and caller function name are printed in addition + * to any other debug output. * * The non-prefixed name is the #define that maps the caller into a - * #define that provides the caller's __LINE__ to the double prefix version. + * #define that provides the caller's name and __LINE__ to the double + * prefix version. * * If you wish to call the function without any debug or state checking, * you should use the single _ prefix version (as is used by dependent IO @@ -197,8 +199,7 @@ static inline int __iwl_grab_nic_access(const char *f, u32 l, struct iwl_priv *priv) { if (atomic_read(&priv->restrict_refcnt)) - IWL_DEBUG_INFO("Grabbing access while already held at " - "line %d.\n", l); + IWL_ERROR("Grabbing access while already held %s %d.\n", f, l); IWL_DEBUG_IO("grabbing nic access - %s %d\n", f, l); return _iwl_grab_nic_access(priv); @@ -223,7 +224,7 @@ static inline void __iwl_release_nic_access(const char *f, u32 l, struct iwl_priv *priv) { if (atomic_read(&priv->restrict_refcnt) <= 0) - IWL_ERROR("Release unheld nic access at line %d.\n", l); + IWL_ERROR("Release unheld nic access at line %s %d.\n", f, l); IWL_DEBUG_IO("releasing nic access - %s %d\n", f, l); _iwl_release_nic_access(priv); @@ -262,15 +263,15 @@ static inline void _iwl_write_direct32(struct iwl_priv *priv, _iwl_write32(priv, reg, value); } #ifdef CONFIG_IWLWIFI_DEBUG -static void __iwl_write_direct32(u32 line, +static void __iwl_write_direct32(const char *f , u32 line, struct iwl_priv *priv, u32 reg, u32 value) { if (!atomic_read(&priv->restrict_refcnt)) - IWL_ERROR("Nic access not held from line %d\n", line); + IWL_ERROR("Nic access not held from %s line %d\n", f, line); _iwl_write_direct32(priv, reg, value); } #define iwl_write_direct32(priv, reg, value) \ - __iwl_write_direct32(__LINE__, priv, reg, value) + __iwl_write_direct32(__func__, __LINE__, priv, reg, value) #else #define iwl_write_direct32 _iwl_write_direct32 #endif @@ -328,15 +329,16 @@ static inline u32 _iwl_read_prph(struct iwl_priv *priv, u32 reg) return _iwl_read_direct32(priv, HBUS_TARG_PRPH_RDAT); } #ifdef CONFIG_IWLWIFI_DEBUG -static inline u32 __iwl_read_prph(u32 line, struct iwl_priv *priv, u32 reg) +static inline u32 __iwl_read_prph(const char *f, u32 line, + struct iwl_priv *priv, u32 reg) { if (!atomic_read(&priv->restrict_refcnt)) - IWL_ERROR("Nic access not held from line %d\n", line); + IWL_ERROR("Nic access not held from %s line %d\n", f, line); return _iwl_read_prph(priv, reg); } #define iwl_read_prph(priv, reg) \ - __iwl_read_prph(__LINE__, priv, reg) + __iwl_read_prph(__func__, __LINE__, priv, reg) #else #define iwl_read_prph _iwl_read_prph #endif @@ -349,16 +351,16 @@ static inline void _iwl_write_prph(struct iwl_priv *priv, _iwl_write_direct32(priv, HBUS_TARG_PRPH_WDAT, val); } #ifdef CONFIG_IWLWIFI_DEBUG -static inline void __iwl_write_prph(u32 line, struct iwl_priv *priv, - u32 addr, u32 val) +static inline void __iwl_write_prph(const char *f, u32 line, + struct iwl_priv *priv, u32 addr, u32 val) { if (!atomic_read(&priv->restrict_refcnt)) - IWL_ERROR("Nic access from line %d\n", line); + IWL_ERROR("Nic access not held from %s line %d\n", f, line); _iwl_write_prph(priv, addr, val); } #define iwl_write_prph(priv, addr, val) \ - __iwl_write_prph(__LINE__, priv, addr, val); + __iwl_write_prph(__func__, __LINE__, priv, addr, val); #else #define iwl_write_prph _iwl_write_prph #endif @@ -366,16 +368,17 @@ static inline void __iwl_write_prph(u32 line, struct iwl_priv *priv, #define _iwl_set_bits_prph(priv, reg, mask) \ _iwl_write_prph(priv, reg, (_iwl_read_prph(priv, reg) | mask)) #ifdef CONFIG_IWLWIFI_DEBUG -static inline void __iwl_set_bits_prph(u32 line, struct iwl_priv *priv, - u32 reg, u32 mask) +static inline void __iwl_set_bits_prph(const char *f, u32 line, + struct iwl_priv *priv, + u32 reg, u32 mask) { if (!atomic_read(&priv->restrict_refcnt)) - IWL_ERROR("Nic access not held from line %d\n", line); + IWL_ERROR("Nic access not held from %s line %d\n", f, line); _iwl_set_bits_prph(priv, reg, mask); } #define iwl_set_bits_prph(priv, reg, mask) \ - __iwl_set_bits_prph(__LINE__, priv, reg, mask) + __iwl_set_bits_prph(__func__, __LINE__, priv, reg, mask) #else #define iwl_set_bits_prph _iwl_set_bits_prph #endif @@ -384,15 +387,15 @@ static inline void __iwl_set_bits_prph(u32 line, struct iwl_priv *priv, _iwl_write_prph(priv, reg, ((_iwl_read_prph(priv, reg) & mask) | bits)) #ifdef CONFIG_IWLWIFI_DEBUG -static inline void __iwl_set_bits_mask_prph(u32 line, +static inline void __iwl_set_bits_mask_prph(const char *f, u32 line, struct iwl_priv *priv, u32 reg, u32 bits, u32 mask) { if (!atomic_read(&priv->restrict_refcnt)) - IWL_ERROR("Nic access not held from line %d\n", line); + IWL_ERROR("Nic access not held from %s line %d\n", f, line); _iwl_set_bits_mask_prph(priv, reg, bits, mask); } #define iwl_set_bits_mask_prph(priv, reg, bits, mask) \ - __iwl_set_bits_mask_prph(__LINE__, priv, reg, bits, mask) + __iwl_set_bits_mask_prph(__func__, __LINE__, priv, reg, bits, mask) #else #define iwl_set_bits_mask_prph _iwl_set_bits_mask_prph #endif -- cgit v1.2.1 From 0472f887e0689fff2dce82c01d40698432965b5a Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Tue, 25 Mar 2008 16:33:40 -0700 Subject: iwlwifi: allow a default callback for ASYNC host commands This patch provides a default callback for ASYNC host commands instead of calling to BUG_ON. Most of the callbacks are now just empty functions Signed-off-by: Emmanuel Grumbach Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-hcmd.c | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c index 559ff739961e..51c9949633e3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c @@ -97,6 +97,31 @@ EXPORT_SYMBOL(get_cmd_string); #define HOST_COMPLETE_TIMEOUT (HZ / 2) +static int iwl_generic_cmd_callback(struct iwl_priv *priv, + struct iwl_cmd *cmd, struct sk_buff *skb) +{ + struct iwl4965_rx_packet *pkt = NULL; + + if (!skb) { + IWL_ERROR("Error: Response NULL in %s.\n", + get_cmd_string(cmd->hdr.cmd)); + return 1; + } + + pkt = (struct iwl4965_rx_packet *)skb->data; + if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { + IWL_ERROR("Bad return from %s (0x%08X)\n", + get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags); + return 1; + } + + IWL_DEBUG_HC("back from %s (0x%08X)\n", + get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags); + + /* Let iwl_tx_complete free the response skb */ + return 1; +} + static int iwl_send_cmd_async(struct iwl_priv *priv, struct iwl_host_cmd *cmd) { int ret; @@ -106,8 +131,9 @@ static int iwl_send_cmd_async(struct iwl_priv *priv, struct iwl_host_cmd *cmd) /* An asynchronous command can not expect an SKB to be set. */ BUG_ON(cmd->meta.flags & CMD_WANT_SKB); - /* An asynchronous command MUST have a callback. */ - BUG_ON(!cmd->meta.u.callback); + /* Assign a generic callback if one is not provided */ + if (!cmd->meta.u.callback) + cmd->meta.u.callback = iwl_generic_cmd_callback; if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return -EBUSY; -- cgit v1.2.1 From 69dc5d9da5c499c23db7b80217023403da103816 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Tue, 25 Mar 2008 16:33:41 -0700 Subject: iwlwifi: iwl_priv - clean up in types of members This patch fix types of is_open and iw_mode members of iwl_priv sturct Signed-off-by: Tomas Winkler Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-4965.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl3945-base.c | 5 +++++ drivers/net/wireless/iwlwifi/iwl4965-base.c | 5 +++++ 4 files changed, 14 insertions(+), 4 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index e0655b988f44..d7ccf13b875d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -830,7 +830,7 @@ struct iwl3945_priv { struct iwl3945_station_entry stations[IWL_STATION_COUNT]; /* Indication if ieee80211_ops->open has been called */ - int is_open; + u8 is_open; u8 mac80211_registered; @@ -851,7 +851,7 @@ struct iwl3945_priv { /* eeprom */ struct iwl3945_eeprom eeprom; - int iw_mode; + enum ieee80211_if_types iw_mode; struct sk_buff *ibss_beacon; diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index 98644d9c7803..069e591981b2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -1129,7 +1129,7 @@ struct iwl_priv { struct iwl4965_station_entry stations[IWL_STATION_COUNT]; /* Indication if ieee80211_ops->open has been called */ - int is_open; + u8 is_open; u8 mac80211_registered; @@ -1150,7 +1150,7 @@ struct iwl_priv { /* eeprom */ struct iwl4965_eeprom eeprom; - int iw_mode; + enum ieee80211_if_types iw_mode; struct sk_buff *ibss_beacon; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 470a9abf12c3..ce8a31103eee 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2058,6 +2058,8 @@ int iwl3945_is_network_packet(struct iwl3945_priv *priv, struct ieee80211_hdr *h return !compare_ether_addr(header->addr2, priv->bssid); /* packets to our adapter go through */ return !compare_ether_addr(header->addr1, priv->mac_addr); + default: + return 1; } return 1; @@ -2302,6 +2304,9 @@ static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv) priv->staging_rxon.filter_flags = RXON_FILTER_PROMISC_MSK | RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_ACCEPT_GRP_MSK; break; + default: + IWL_ERROR("Unsupported interface type %d\n", priv->iw_mode); + break; } #if 0 diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 9e49e8ce3348..e487432ef56e 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -1793,6 +1793,8 @@ int iwl4965_is_network_packet(struct iwl_priv *priv, struct ieee80211_hdr *heade return !compare_ether_addr(header->addr2, priv->bssid); /* packets to our adapter go through */ return !compare_ether_addr(header->addr1, priv->mac_addr); + default: + break; } return 1; @@ -2054,6 +2056,9 @@ static void iwl4965_connection_init_rx_config(struct iwl_priv *priv) priv->staging_rxon.filter_flags = RXON_FILTER_PROMISC_MSK | RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_ACCEPT_GRP_MSK; break; + default: + IWL_ERROR("Unsupported interface type %d\n", priv->iw_mode); + break; } #if 0 -- cgit v1.2.1 From c2b310a73b62f074b0019b940417cafbdbafde41 Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Wed, 26 Mar 2008 09:57:14 +0100 Subject: libertas: kill useless #define LBS_MONITOR_OFF 0 Signed-off-by: Holger Schurig Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/main.c | 12 ++++++------ drivers/net/wireless/libertas/rx.c | 2 +- drivers/net/wireless/libertas/tx.c | 5 ++--- drivers/net/wireless/libertas/wext.h | 2 -- 4 files changed, 9 insertions(+), 12 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 1eb0cb0a82b7..dac72f7af701 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -277,10 +277,10 @@ static ssize_t lbs_rtap_set(struct device *dev, struct lbs_private *priv = to_net_dev(dev)->priv; sscanf(buf, "%x", &monitor_mode); - if (monitor_mode != LBS_MONITOR_OFF) { - if(priv->monitormode == monitor_mode) + if (monitor_mode) { + if (priv->monitormode == monitor_mode) return strlen(buf); - if (priv->monitormode == LBS_MONITOR_OFF) { + if (!priv->monitormode) { if (priv->infra_open || priv->mesh_open) return -EBUSY; if (priv->mode == IW_MODE_INFRA) @@ -293,9 +293,9 @@ static ssize_t lbs_rtap_set(struct device *dev, } else { - if (priv->monitormode == LBS_MONITOR_OFF) + if (!priv->monitormode) return strlen(buf); - priv->monitormode = LBS_MONITOR_OFF; + priv->monitormode = 0; lbs_remove_rtap(priv); if (priv->currenttxskb) { @@ -392,7 +392,7 @@ static int lbs_dev_open(struct net_device *dev) spin_lock_irq(&priv->driver_lock); - if (priv->monitormode != LBS_MONITOR_OFF) { + if (priv->monitormode) { ret = -EBUSY; goto out; } diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c index 149557a478ac..09f023089ea4 100644 --- a/drivers/net/wireless/libertas/rx.c +++ b/drivers/net/wireless/libertas/rx.c @@ -155,7 +155,7 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb) skb->ip_summed = CHECKSUM_NONE; - if (priv->monitormode != LBS_MONITOR_OFF) + if (priv->monitormode) return process_rxed_802_11_packet(priv, skb); p_rx_pkt = (struct rxpackethdr *) skb->data; diff --git a/drivers/net/wireless/libertas/tx.c b/drivers/net/wireless/libertas/tx.c index 00d95f75bd89..77f1f9525b81 100644 --- a/drivers/net/wireless/libertas/tx.c +++ b/drivers/net/wireless/libertas/tx.c @@ -151,7 +151,7 @@ int lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) dev->trans_start = jiffies; - if (priv->monitormode != LBS_MONITOR_OFF) { + if (priv->monitormode) { /* Keep the skb to echo it back once Tx feedback is received from FW */ skb_orphan(skb); @@ -186,8 +186,7 @@ void lbs_send_tx_feedback(struct lbs_private *priv) int txfail; int try_count; - if (priv->monitormode == LBS_MONITOR_OFF || - priv->currenttxskb == NULL) + if (!priv->monitormode || priv->currenttxskb == NULL) return; radiotap_hdr = (struct tx_radiotap_hdr *)priv->currenttxskb->data; diff --git a/drivers/net/wireless/libertas/wext.h b/drivers/net/wireless/libertas/wext.h index a563d9a231b6..f0f439a6ab49 100644 --- a/drivers/net/wireless/libertas/wext.h +++ b/drivers/net/wireless/libertas/wext.h @@ -15,8 +15,6 @@ struct lbs_ioctl_regrdwr { u32 value; }; -#define LBS_MONITOR_OFF 0 - extern struct iw_handler_def lbs_handler_def; extern struct iw_handler_def mesh_handler_def; -- cgit v1.2.1 From 62436138c83f221943c1f5d9cff41305d3d26ac4 Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Wed, 26 Mar 2008 09:57:45 +0100 Subject: libertas: remove CMD_802_11_PWR_CFG This has nowhere been used. Note: in the firmware manual this was documented as CMD_802_11_PA_CFG. If we ever need it, we can/should re-implement it as a direct command. Signed-off-by: Holger Schurig Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/cmd.c | 10 ---------- drivers/net/wireless/libertas/cmdresp.c | 8 -------- drivers/net/wireless/libertas/host.h | 1 - drivers/net/wireless/libertas/hostcmd.h | 9 --------- 4 files changed, 28 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index 59801f103e66..f3e0818d94a3 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -1496,16 +1496,6 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, break; } - case CMD_802_11_PWR_CFG: - cmdptr->command = cpu_to_le16(CMD_802_11_PWR_CFG); - cmdptr->size = - cpu_to_le16(sizeof(struct cmd_ds_802_11_pwr_cfg) + - S_DS_GEN); - memmove(&cmdptr->params.pwrcfg, pdata_buf, - sizeof(struct cmd_ds_802_11_pwr_cfg)); - - ret = 0; - break; case CMD_BT_ACCESS: ret = lbs_cmd_bt_access(cmdptr, cmd_action, pdata_buf); break; diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c index 888f92d8afc9..711f5ebd13c0 100644 --- a/drivers/net/wireless/libertas/cmdresp.c +++ b/drivers/net/wireless/libertas/cmdresp.c @@ -397,14 +397,6 @@ static inline int handle_cmd_response(struct lbs_private *priv, spin_unlock_irqrestore(&priv->driver_lock, flags); break; - case CMD_RET(CMD_802_11_PWR_CFG): - spin_lock_irqsave(&priv->driver_lock, flags); - memmove((void *)priv->cur_cmd->callback_arg, &resp->params.pwrcfg, - sizeof(struct cmd_ds_802_11_pwr_cfg)); - spin_unlock_irqrestore(&priv->driver_lock, flags); - - break; - case CMD_RET(CMD_GET_TSF): spin_lock_irqsave(&priv->driver_lock, flags); memcpy((void *)priv->cur_cmd->callback_arg, diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h index aae878b042c0..3915c3144fad 100644 --- a/drivers/net/wireless/libertas/host.h +++ b/drivers/net/wireless/libertas/host.h @@ -84,7 +84,6 @@ #define CMD_802_11_INACTIVITY_TIMEOUT 0x0067 #define CMD_802_11_SLEEP_PERIOD 0x0068 #define CMD_802_11_TPC_CFG 0x0072 -#define CMD_802_11_PWR_CFG 0x0073 #define CMD_802_11_FW_WAKE_METHOD 0x0074 #define CMD_802_11_SUBSCRIBE_EVENT 0x0075 #define CMD_802_11_RATE_ADAPT_RATESET 0x0076 diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h index acbcd56831cb..b8e372007bb9 100644 --- a/drivers/net/wireless/libertas/hostcmd.h +++ b/drivers/net/wireless/libertas/hostcmd.h @@ -609,14 +609,6 @@ struct cmd_ds_802_11_led_ctrl { u8 data[256]; } __attribute__ ((packed)); -struct cmd_ds_802_11_pwr_cfg { - __le16 action; - u8 enable; - s8 PA_P0; - s8 PA_P1; - s8 PA_P2; -} __attribute__ ((packed)); - struct cmd_ds_802_11_afc { __le16 afc_auto; union { @@ -726,7 +718,6 @@ struct cmd_ds_command { struct cmd_ds_802_11d_domain_info domaininforesp; struct cmd_ds_802_11_tpc_cfg tpccfg; - struct cmd_ds_802_11_pwr_cfg pwrcfg; struct cmd_ds_802_11_afc afc; struct cmd_ds_802_11_led_ctrl ledgpio; -- cgit v1.2.1 From 7d5796118353cd45e9e301fdf3ff99fdec5390e9 Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Wed, 26 Mar 2008 13:26:55 +0100 Subject: libertas: the compact flash driver is no longer experimental Signed-off-by: Holger Schurig Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index f4ca6fd4a29f..9cba8ea58ca8 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -284,7 +284,7 @@ config LIBERTAS_USB config LIBERTAS_CS tristate "Marvell Libertas 8385 CompactFlash 802.11b/g cards" - depends on LIBERTAS && PCMCIA && EXPERIMENTAL + depends on LIBERTAS && PCMCIA select FW_LOADER ---help--- A driver for Marvell Libertas 8385 CompactFlash devices. -- cgit v1.2.1 From cee24a3e580f1062c8bb8b1692b95014d882bc7d Mon Sep 17 00:00:00 2001 From: Ron Rindjunsky Date: Wed, 26 Mar 2008 20:36:03 +0200 Subject: mac80211: A-MPDU MLME use dynamic allocation This patch alters the A-MPDU MLME in sta_info to use dynamic allocation, thus drastically improving memory usage - from a constant ~2 Kbyte in the previous (static) allocation to a lower limit of ~200 Byte and an upper limit of ~2 Kbyte. Signed-off-by: Ron Rindjunsky Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965-rs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c index 7d7ce7489ab5..735eadd57d18 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c @@ -397,7 +397,7 @@ static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, DECLARE_MAC_BUF(mac); spin_lock_bh(&sta->ampdu_mlme.ampdu_tx); - state = sta->ampdu_mlme.tid_tx[tid].state; + state = sta->ampdu_mlme.tid_state_tx[tid]; spin_unlock_bh(&sta->ampdu_mlme.ampdu_tx); if (state == HT_AGG_STATE_IDLE && -- cgit v1.2.1 From 8dd62822ddbf6a9314e9b92a3816c04490c91293 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Wed, 26 Mar 2008 15:21:33 -0400 Subject: prism54: correct thinko in "prism54: Convert stats_sem in a mutex" mutex_trylock has different return code semantics than down_trylock... Signed-off-by: John W. Linville --- drivers/net/wireless/prism54/isl_ioctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c index 2d91a56d6a39..2e25e190f334 100644 --- a/drivers/net/wireless/prism54/isl_ioctl.c +++ b/drivers/net/wireless/prism54/isl_ioctl.c @@ -218,7 +218,7 @@ prism54_get_wireless_stats(struct net_device *ndev) islpci_private *priv = netdev_priv(ndev); /* If the stats are being updated return old data */ - if (mutex_trylock(&priv->stats_lock) == 0) { + if (mutex_trylock(&priv->stats_lock)) { memcpy(&priv->iwstatistics, &priv->local_iwstatistics, sizeof (struct iw_statistics)); /* They won't be marked updated for the next time */ -- cgit v1.2.1 From e5225b397308f9eea86327293b73dc88068e0179 Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Wed, 26 Mar 2008 10:04:44 +0100 Subject: libertas: reduce debug output This patch tries to make dmesg logs between different runs easier to compare by * removing the jiffies (use CONFIG_PRINTK_TIME if you need timing) * remove the line numbers, they change with each applied patch It also changes the deprecated __FUNCTION__ to __func__ to make checkpatch.pl happy. Signed-off-by: Holger Schurig Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/cmd.c | 4 ++-- drivers/net/wireless/libertas/cmdresp.c | 4 ++-- drivers/net/wireless/libertas/defs.h | 10 +++++----- 3 files changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index f3e0818d94a3..44b918a6c219 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -1186,8 +1186,8 @@ static void lbs_submit_command(struct lbs_private *priv, command == CMD_802_11_AUTHENTICATE) timeo = 10 * HZ; - lbs_deb_cmd("DNLD_CMD: command 0x%04x, seq %d, size %d, jiffies %lu\n", - command, le16_to_cpu(cmd->seqnum), cmdsize, jiffies); + lbs_deb_cmd("DNLD_CMD: command 0x%04x, seq %d, size %d\n", + command, le16_to_cpu(cmd->seqnum), cmdsize); lbs_deb_hex(LBS_DEB_CMD, "DNLD_CMD", (void *) cmdnode->cmdbuf, cmdsize); ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) cmd, cmdsize); diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c index 711f5ebd13c0..9de9666d495b 100644 --- a/drivers/net/wireless/libertas/cmdresp.c +++ b/drivers/net/wireless/libertas/cmdresp.c @@ -455,8 +455,8 @@ int lbs_process_rx_command(struct lbs_private *priv) respcmd = le16_to_cpu(resp->command); result = le16_to_cpu(resp->result); - lbs_deb_cmd("CMD_RESP: response 0x%04x, seq %d, size %d, jiffies %lu\n", - respcmd, le16_to_cpu(resp->seqnum), priv->upld_len, jiffies); + lbs_deb_cmd("CMD_RESP: response 0x%04x, seq %d, size %d\n", + respcmd, le16_to_cpu(resp->seqnum), priv->upld_len); lbs_deb_hex(LBS_DEB_CMD, "CMD_RESP", (void *) resp, priv->upld_len); if (resp->seqnum != priv->cur_cmd->cmdbuf->seqnum) { diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h index 3053cc2160bc..84e8de5e21da 100644 --- a/drivers/net/wireless/libertas/defs.h +++ b/drivers/net/wireless/libertas/defs.h @@ -53,14 +53,14 @@ do { if ((lbs_debug & (grp)) == (grp)) \ #endif #define lbs_deb_enter(grp) \ - LBS_DEB_LL(grp | LBS_DEB_ENTER, " enter", "%s():%d\n", __FUNCTION__, __LINE__); + LBS_DEB_LL(grp | LBS_DEB_ENTER, " enter", "%s()\n", __func__); #define lbs_deb_enter_args(grp, fmt, args...) \ - LBS_DEB_LL(grp | LBS_DEB_ENTER, " enter", "%s(" fmt "):%d\n", __FUNCTION__, ## args, __LINE__); + LBS_DEB_LL(grp | LBS_DEB_ENTER, " enter", "%s(" fmt ")\n", __func__, ## args); #define lbs_deb_leave(grp) \ - LBS_DEB_LL(grp | LBS_DEB_LEAVE, " leave", "%s():%d\n", __FUNCTION__, __LINE__); + LBS_DEB_LL(grp | LBS_DEB_LEAVE, " leave", "%s()\n", __func__); #define lbs_deb_leave_args(grp, fmt, args...) \ - LBS_DEB_LL(grp | LBS_DEB_LEAVE, " leave", "%s():%d, " fmt "\n", \ - __FUNCTION__, __LINE__, ##args); + LBS_DEB_LL(grp | LBS_DEB_LEAVE, " leave", "%s(), " fmt "\n", \ + __func__, ##args); #define lbs_deb_main(fmt, args...) LBS_DEB_LL(LBS_DEB_MAIN, " main", fmt, ##args) #define lbs_deb_net(fmt, args...) LBS_DEB_LL(LBS_DEB_NET, " net", fmt, ##args) #define lbs_deb_mesh(fmt, args...) LBS_DEB_LL(LBS_DEB_MESH, " mesh", fmt, ##args) -- cgit v1.2.1 From 717ddc0ebdd00c233fcb1ae9a243e69f301cde24 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 16 Mar 2008 22:43:06 +0000 Subject: endianness annotations: drivers/net/wireless/rtl8180_dev.c Signed-off-by: Al Viro Signed-off-by: John W. Linville --- drivers/net/wireless/rtl8180_dev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rtl8180_dev.c b/drivers/net/wireless/rtl8180_dev.c index b1b3a478335b..c181f23e930d 100644 --- a/drivers/net/wireless/rtl8180_dev.c +++ b/drivers/net/wireless/rtl8180_dev.c @@ -688,9 +688,9 @@ static int rtl8180_add_interface(struct ieee80211_hw *dev, rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); rtl818x_iowrite32(priv, (__le32 __iomem *)&priv->map->MAC[0], - cpu_to_le32(*(u32 *)conf->mac_addr)); + le32_to_cpu(*(__le32 *)conf->mac_addr)); rtl818x_iowrite16(priv, (__le16 __iomem *)&priv->map->MAC[4], - cpu_to_le16(*(u16 *)(conf->mac_addr + 4))); + le16_to_cpu(*(__le16 *)(conf->mac_addr + 4))); rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); return 0; -- cgit v1.2.1 From 2af9f039a17c0acd9e5b21d10058688687bad86d Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Wed, 26 Mar 2008 09:58:32 +0100 Subject: libertas: convert CMD_802_11_MAC_ADDRESS to a direct command * directly call lbs_cmd_with_response() * only overwrite priv->current_addr once the firmware call succeeded Signed-off-by: Holger Schurig Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/cmd.c | 27 --------------------------- drivers/net/wireless/libertas/cmdresp.c | 17 ----------------- drivers/net/wireless/libertas/hostcmd.h | 3 ++- drivers/net/wireless/libertas/main.c | 25 +++++++++---------------- 4 files changed, 11 insertions(+), 61 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index 44b918a6c219..d396a5f06666 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -953,29 +953,6 @@ static int lbs_cmd_reg_access(struct cmd_ds_command *cmdptr, return 0; } -static int lbs_cmd_802_11_mac_address(struct lbs_private *priv, - struct cmd_ds_command *cmd, - u16 cmd_action) -{ - - lbs_deb_enter(LBS_DEB_CMD); - cmd->command = cpu_to_le16(CMD_802_11_MAC_ADDRESS); - cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_mac_address) + - S_DS_GEN); - cmd->result = 0; - - cmd->params.macadd.action = cpu_to_le16(cmd_action); - - if (cmd_action == CMD_ACT_SET) { - memcpy(cmd->params.macadd.macadd, - priv->current_addr, ETH_ALEN); - lbs_deb_hex(LBS_DEB_CMD, "SET_CMD: MAC addr", priv->current_addr, 6); - } - - lbs_deb_leave(LBS_DEB_CMD); - return 0; -} - static int lbs_cmd_802_11_eeprom_access(struct cmd_ds_command *cmd, void *pdata_buf) { @@ -1435,10 +1412,6 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, ret = lbs_cmd_80211_ad_hoc_stop(cmdptr); break; - case CMD_802_11_MAC_ADDRESS: - ret = lbs_cmd_802_11_mac_address(priv, cmdptr, cmd_action); - break; - case CMD_802_11_EEPROM_ACCESS: ret = lbs_cmd_802_11_eeprom_access(cmdptr, pdata_buf); break; diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c index 9de9666d495b..c3b80c139d4f 100644 --- a/drivers/net/wireless/libertas/cmdresp.c +++ b/drivers/net/wireless/libertas/cmdresp.c @@ -188,19 +188,6 @@ static int lbs_ret_802_11_snmp_mib(struct lbs_private *priv, return 0; } -static int lbs_ret_802_11_mac_address(struct lbs_private *priv, - struct cmd_ds_command *resp) -{ - struct cmd_ds_802_11_mac_address *macadd = &resp->params.macadd; - - lbs_deb_enter(LBS_DEB_CMD); - - memcpy(priv->current_addr, macadd->macadd, ETH_ALEN); - - lbs_deb_enter(LBS_DEB_CMD); - return 0; -} - static int lbs_ret_802_11_rf_tx_power(struct lbs_private *priv, struct cmd_ds_command *resp) { @@ -368,10 +355,6 @@ static inline int handle_cmd_response(struct lbs_private *priv, ret = lbs_ret_802_11_rssi(priv, resp); break; - case CMD_RET(CMD_802_11_MAC_ADDRESS): - ret = lbs_ret_802_11_mac_address(priv, resp); - break; - case CMD_RET(CMD_802_11_AD_HOC_STOP): ret = lbs_ret_80211_ad_hoc_stop(priv); break; diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h index b8e372007bb9..e56d0049f5fd 100644 --- a/drivers/net/wireless/libertas/hostcmd.h +++ b/drivers/net/wireless/libertas/hostcmd.h @@ -427,6 +427,8 @@ struct cmd_ds_802_11_rssi_rsp { }; struct cmd_ds_802_11_mac_address { + struct cmd_header hdr; + __le16 action; u8 macadd[ETH_ALEN]; }; @@ -708,7 +710,6 @@ struct cmd_ds_command { struct cmd_ds_802_11_rssi rssi; struct cmd_ds_802_11_rssi_rsp rssirsp; struct cmd_ds_802_11_disassociate dassociate; - struct cmd_ds_802_11_mac_address macadd; struct cmd_ds_mac_reg_access macreg; struct cmd_ds_bbp_reg_access bbpreg; struct cmd_ds_rf_reg_access rfreg; diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index dac72f7af701..d0e4c3b6deaa 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -531,34 +531,27 @@ static int lbs_set_mac_address(struct net_device *dev, void *addr) int ret = 0; struct lbs_private *priv = (struct lbs_private *) dev->priv; struct sockaddr *phwaddr = addr; + struct cmd_ds_802_11_mac_address cmd; lbs_deb_enter(LBS_DEB_NET); /* In case it was called from the mesh device */ - dev = priv->dev ; - - memset(priv->current_addr, 0, ETH_ALEN); - - /* dev->dev_addr is 8 bytes */ - lbs_deb_hex(LBS_DEB_NET, "dev->dev_addr", dev->dev_addr, ETH_ALEN); - - lbs_deb_hex(LBS_DEB_NET, "addr", phwaddr->sa_data, ETH_ALEN); - memcpy(priv->current_addr, phwaddr->sa_data, ETH_ALEN); + dev = priv->dev; - ret = lbs_prepare_and_send_command(priv, CMD_802_11_MAC_ADDRESS, - CMD_ACT_SET, - CMD_OPTION_WAITFORRSP, 0, NULL); + cmd.hdr.size = cpu_to_le16(sizeof(cmd)); + cmd.action = cpu_to_le16(CMD_ACT_SET); + memcpy(cmd.macadd, phwaddr->sa_data, ETH_ALEN); + ret = lbs_cmd_with_response(priv, CMD_802_11_MAC_ADDRESS, &cmd); if (ret) { lbs_deb_net("set MAC address failed\n"); - ret = -1; goto done; } - lbs_deb_hex(LBS_DEB_NET, "priv->macaddr", priv->current_addr, ETH_ALEN); - memcpy(dev->dev_addr, priv->current_addr, ETH_ALEN); + memcpy(priv->current_addr, phwaddr->sa_data, ETH_ALEN); + memcpy(dev->dev_addr, phwaddr->sa_data, ETH_ALEN); if (priv->mesh_dev) - memcpy(priv->mesh_dev->dev_addr, priv->current_addr, ETH_ALEN); + memcpy(priv->mesh_dev->dev_addr, phwaddr->sa_data, ETH_ALEN); done: lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret); -- cgit v1.2.1 From 7460f5a69055357bf97f1890db547aba0c4bf2fa Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Wed, 26 Mar 2008 10:03:48 +0100 Subject: libertas: convert CMD_802_11_EEPROM_ACCESS to a direct command Signed-off-by: Holger Schurig Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/cmd.c | 25 ------------ drivers/net/wireless/libertas/cmdresp.c | 29 -------------- drivers/net/wireless/libertas/dev.h | 1 - drivers/net/wireless/libertas/ethtool.c | 67 +++++++++------------------------ drivers/net/wireless/libertas/hostcmd.h | 10 ++--- drivers/net/wireless/libertas/wext.h | 11 ------ 6 files changed, 22 insertions(+), 121 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index d396a5f06666..6e7bfb36b491 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -953,27 +953,6 @@ static int lbs_cmd_reg_access(struct cmd_ds_command *cmdptr, return 0; } -static int lbs_cmd_802_11_eeprom_access(struct cmd_ds_command *cmd, - void *pdata_buf) -{ - struct lbs_ioctl_regrdwr *ea = pdata_buf; - - lbs_deb_enter(LBS_DEB_CMD); - - cmd->command = cpu_to_le16(CMD_802_11_EEPROM_ACCESS); - cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_eeprom_access) + - S_DS_GEN); - cmd->result = 0; - - cmd->params.rdeeprom.action = cpu_to_le16(ea->action); - cmd->params.rdeeprom.offset = cpu_to_le16(ea->offset); - cmd->params.rdeeprom.bytecount = cpu_to_le16(ea->NOB); - cmd->params.rdeeprom.value = 0; - - lbs_deb_leave(LBS_DEB_CMD); - return 0; -} - static int lbs_cmd_bt_access(struct cmd_ds_command *cmd, u16 cmd_action, void *pdata_buf) { @@ -1412,10 +1391,6 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, ret = lbs_cmd_80211_ad_hoc_stop(cmdptr); break; - case CMD_802_11_EEPROM_ACCESS: - ret = lbs_cmd_802_11_eeprom_access(cmdptr, pdata_buf); - break; - case CMD_802_11_SET_AFC: case CMD_802_11_GET_AFC: diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c index c3b80c139d4f..8b5d1a55a0e9 100644 --- a/drivers/net/wireless/libertas/cmdresp.c +++ b/drivers/net/wireless/libertas/cmdresp.c @@ -249,31 +249,6 @@ static int lbs_ret_802_11_rssi(struct lbs_private *priv, return 0; } -static int lbs_ret_802_11_eeprom_access(struct lbs_private *priv, - struct cmd_ds_command *resp) -{ - struct lbs_ioctl_regrdwr *pbuf; - pbuf = (struct lbs_ioctl_regrdwr *) priv->prdeeprom; - - lbs_deb_enter_args(LBS_DEB_CMD, "len %d", - le16_to_cpu(resp->params.rdeeprom.bytecount)); - if (pbuf->NOB < le16_to_cpu(resp->params.rdeeprom.bytecount)) { - pbuf->NOB = 0; - lbs_deb_cmd("EEPROM read length too big\n"); - return -1; - } - pbuf->NOB = le16_to_cpu(resp->params.rdeeprom.bytecount); - if (pbuf->NOB > 0) { - - memcpy(&pbuf->value, (u8 *) & resp->params.rdeeprom.value, - le16_to_cpu(resp->params.rdeeprom.bytecount)); - lbs_deb_hex(LBS_DEB_CMD, "EEPROM", (char *)&pbuf->value, - le16_to_cpu(resp->params.rdeeprom.bytecount)); - } - lbs_deb_leave(LBS_DEB_CMD); - return 0; -} - static int lbs_ret_802_11_bcn_ctrl(struct lbs_private * priv, struct cmd_ds_command *resp) { @@ -359,10 +334,6 @@ static inline int handle_cmd_response(struct lbs_private *priv, ret = lbs_ret_80211_ad_hoc_stop(priv); break; - case CMD_RET(CMD_802_11_EEPROM_ACCESS): - ret = lbs_ret_802_11_eeprom_access(priv, resp); - break; - case CMD_RET(CMD_802_11D_DOMAIN_INFO): ret = lbs_ret_802_11d_domain_info(resp); break; diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index 17e02bed6bfa..8e770dd6ef6b 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h @@ -320,7 +320,6 @@ struct lbs_private { u32 enable11d; /** MISCELLANEOUS */ - u8 *prdeeprom; struct lbs_offset_value offsetvalue; u32 monitormode; diff --git a/drivers/net/wireless/libertas/ethtool.c b/drivers/net/wireless/libertas/ethtool.c index 21e6f988ea81..7c8ce7d0f23a 100644 --- a/drivers/net/wireless/libertas/ethtool.c +++ b/drivers/net/wireless/libertas/ethtool.c @@ -48,61 +48,28 @@ static int lbs_ethtool_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 * bytes) { struct lbs_private *priv = (struct lbs_private *) dev->priv; - struct lbs_ioctl_regrdwr regctrl; - char *ptr; + struct cmd_ds_802_11_eeprom_access cmd; int ret; - regctrl.action = 0; - regctrl.offset = eeprom->offset; - regctrl.NOB = eeprom->len; - - if (eeprom->offset + eeprom->len > LBS_EEPROM_LEN) - return -EINVAL; - -// mutex_lock(&priv->mutex); - - priv->prdeeprom = kmalloc(eeprom->len+sizeof(regctrl), GFP_KERNEL); - if (!priv->prdeeprom) - return -ENOMEM; - memcpy(priv->prdeeprom, ®ctrl, sizeof(regctrl)); - - /* +14 is for action, offset, and NOB in - * response */ - lbs_deb_ethtool("action:%d offset: %x NOB: %02x\n", - regctrl.action, regctrl.offset, regctrl.NOB); + lbs_deb_enter(LBS_DEB_ETHTOOL); - ret = lbs_prepare_and_send_command(priv, - CMD_802_11_EEPROM_ACCESS, - regctrl.action, - CMD_OPTION_WAITFORRSP, 0, - ®ctrl); - - if (ret) { - if (priv->prdeeprom) - kfree(priv->prdeeprom); - goto done; + if (eeprom->offset + eeprom->len > LBS_EEPROM_LEN || + eeprom->len > LBS_EEPROM_READ_LEN) { + ret = -EINVAL; + goto out; } - mdelay(10); - - ptr = (char *)priv->prdeeprom; - - /* skip the command header, but include the "value" u32 variable */ - ptr = ptr + sizeof(struct lbs_ioctl_regrdwr) - 4; - - /* - * Return the result back to the user - */ - memcpy(bytes, ptr, eeprom->len); - - if (priv->prdeeprom) - kfree(priv->prdeeprom); -// mutex_unlock(&priv->mutex); - - ret = 0; - -done: - lbs_deb_enter_args(LBS_DEB_ETHTOOL, "ret %d", ret); + cmd.hdr.size = cpu_to_le16(sizeof(struct cmd_ds_802_11_eeprom_access) - + LBS_EEPROM_READ_LEN + eeprom->len); + cmd.action = cpu_to_le16(CMD_ACT_GET); + cmd.offset = cpu_to_le16(eeprom->offset); + cmd.len = cpu_to_le16(eeprom->len); + ret = lbs_cmd_with_response(priv, CMD_802_11_EEPROM_ACCESS, &cmd); + if (!ret) + memcpy(bytes, cmd.value, eeprom->len); + +out: + lbs_deb_leave_args(LBS_DEB_ETHTOOL, "ret %d", ret); return ret; } diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h index e56d0049f5fd..9256daba48fc 100644 --- a/drivers/net/wireless/libertas/hostcmd.h +++ b/drivers/net/wireless/libertas/hostcmd.h @@ -588,12 +588,13 @@ struct cmd_ds_802_11_key_material { } __attribute__ ((packed)); struct cmd_ds_802_11_eeprom_access { + struct cmd_header hdr; __le16 action; - - /* multiple 4 */ __le16 offset; - __le16 bytecount; - u8 value; + __le16 len; + /* firmware says it returns a maximum of 20 bytes */ +#define LBS_EEPROM_READ_LEN 20 + u8 value[LBS_EEPROM_READ_LEN]; } __attribute__ ((packed)); struct cmd_ds_802_11_tpc_cfg { @@ -713,7 +714,6 @@ struct cmd_ds_command { struct cmd_ds_mac_reg_access macreg; struct cmd_ds_bbp_reg_access bbpreg; struct cmd_ds_rf_reg_access rfreg; - struct cmd_ds_802_11_eeprom_access rdeeprom; struct cmd_ds_802_11d_domain_info domaininfo; struct cmd_ds_802_11d_domain_info domaininforesp; diff --git a/drivers/net/wireless/libertas/wext.h b/drivers/net/wireless/libertas/wext.h index f0f439a6ab49..4c08db497606 100644 --- a/drivers/net/wireless/libertas/wext.h +++ b/drivers/net/wireless/libertas/wext.h @@ -4,17 +4,6 @@ #ifndef _LBS_WEXT_H_ #define _LBS_WEXT_H_ -/** lbs_ioctl_regrdwr */ -struct lbs_ioctl_regrdwr { - /** Which register to access */ - u16 whichreg; - /** Read or Write */ - u16 action; - u32 offset; - u16 NOB; - u32 value; -}; - extern struct iw_handler_def lbs_handler_def; extern struct iw_handler_def mesh_handler_def; -- cgit v1.2.1 From f539f2efe9fdf9e7db2022a757190858576d34fd Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Wed, 26 Mar 2008 13:22:11 +0100 Subject: libertas: convert sleep/wake config direct commands Confirm sleep event: they come very regularly, eventually several times per second. Therefore we want to send the config command as fast as possible. The old code pre-set the command in priv->lbs_ps_confirm_sleep. However, the byte sequence to be sent to the hardware is the same for all interfaces. So this patch make this an extern structure, initialized at module load time. Config wake event: normal conversion to a direct command. However, I don't know how to trigger a "HOST AWAKE" event from the firmware, so this part is untested. Signed-off-by: Holger Schurig Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/cmd.c | 32 ++++++++++---------------------- drivers/net/wireless/libertas/cmdresp.c | 17 ++++++++--------- drivers/net/wireless/libertas/dev.h | 5 ++--- drivers/net/wireless/libertas/hostcmd.h | 9 +++------ drivers/net/wireless/libertas/main.c | 17 +++++++++-------- 5 files changed, 32 insertions(+), 48 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index 6e7bfb36b491..dbaf8b9e47d5 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -1802,38 +1802,27 @@ void lbs_send_iwevcustom_event(struct lbs_private *priv, s8 *str) lbs_deb_leave(LBS_DEB_WEXT); } -static int sendconfirmsleep(struct lbs_private *priv, u8 *cmdptr, u16 size) +static void lbs_send_confirmsleep(struct lbs_private *priv) { unsigned long flags; - int ret = 0; + int ret; lbs_deb_enter(LBS_DEB_HOST); - lbs_deb_hex(LBS_DEB_HOST, "sleep confirm command", cmdptr, size); - - ret = priv->hw_host_to_card(priv, MVMS_CMD, cmdptr, size); + lbs_deb_hex(LBS_DEB_HOST, "sleep confirm", (u8 *) &confirm_sleep, + sizeof(confirm_sleep)); - spin_lock_irqsave(&priv->driver_lock, flags); - if (priv->intcounter || priv->currenttxskb) - lbs_deb_host("SEND_SLEEPC_CMD: intcounter %d, currenttxskb %p\n", - priv->intcounter, priv->currenttxskb); - spin_unlock_irqrestore(&priv->driver_lock, flags); + ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) &confirm_sleep, + sizeof(confirm_sleep)); if (ret) { - lbs_pr_alert( - "SEND_SLEEPC_CMD: Host to Card failed for Confirm Sleep\n"); + lbs_pr_alert("confirm_sleep failed\n"); } else { spin_lock_irqsave(&priv->driver_lock, flags); - if (!priv->intcounter) { + if (!priv->intcounter) priv->psstate = PS_STATE_SLEEP; - } else { - lbs_deb_host("SEND_SLEEPC_CMD: after sent, intcounter %d\n", - priv->intcounter); - } spin_unlock_irqrestore(&priv->driver_lock, flags); } - - lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret); - return ret; + lbs_deb_leave(LBS_DEB_HOST); } void lbs_ps_sleep(struct lbs_private *priv, int wait_option) @@ -1906,8 +1895,7 @@ void lbs_ps_confirm_sleep(struct lbs_private *priv) if (allowed) { lbs_deb_host("sending lbs_ps_confirm_sleep\n"); - sendconfirmsleep(priv, (u8 *) & priv->lbs_ps_confirm_sleep, - sizeof(struct PS_CMD_ConfirmSleep)); + lbs_send_confirmsleep(priv); } else { lbs_deb_host("sleep confirm has been delayed\n"); } diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c index 8b5d1a55a0e9..e60d03bf8d11 100644 --- a/drivers/net/wireless/libertas/cmdresp.c +++ b/drivers/net/wireless/libertas/cmdresp.c @@ -548,21 +548,20 @@ done: static int lbs_send_confirmwake(struct lbs_private *priv) { - struct cmd_header *cmd = &priv->lbs_ps_confirm_wake; + struct cmd_header cmd; int ret = 0; lbs_deb_enter(LBS_DEB_HOST); - cmd->command = cpu_to_le16(CMD_802_11_WAKEUP_CONFIRM); - cmd->size = cpu_to_le16(sizeof(*cmd)); - cmd->seqnum = cpu_to_le16(++priv->seqnum); - cmd->result = 0; + cmd.command = cpu_to_le16(CMD_802_11_WAKEUP_CONFIRM); + cmd.size = cpu_to_le16(sizeof(cmd)); + cmd.seqnum = cpu_to_le16(++priv->seqnum); + cmd.result = 0; - lbs_deb_host("SEND_WAKEC_CMD: before download\n"); + lbs_deb_hex(LBS_DEB_HOST, "wake confirm", (u8 *) &cmd, + sizeof(cmd)); - lbs_deb_hex(LBS_DEB_HOST, "wake confirm command", (void *)cmd, sizeof(*cmd)); - - ret = priv->hw_host_to_card(priv, MVMS_CMD, (void *)cmd, sizeof(*cmd)); + ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) &cmd, sizeof(cmd)); if (ret) lbs_pr_alert("SEND_WAKEC_CMD: Host to Card failed for Confirm Wake\n"); diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index 8e770dd6ef6b..3f3e7f6e68b3 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h @@ -267,9 +267,6 @@ struct lbs_private { char ps_supported; u8 needtowakeup; - struct PS_CMD_ConfirmSleep lbs_ps_confirm_sleep; - struct cmd_header lbs_ps_confirm_wake; - struct assoc_request * pending_assoc_req; struct assoc_request * in_progress_assoc_req; @@ -326,6 +323,8 @@ struct lbs_private { u8 fw_ready; }; +extern struct cmd_confirm_sleep confirm_sleep; + /** Association request * * Encapsulates all the options that describe a specific assocation request diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h index 9256daba48fc..f29bc5bbda3e 100644 --- a/drivers/net/wireless/libertas/hostcmd.h +++ b/drivers/net/wireless/libertas/hostcmd.h @@ -480,14 +480,11 @@ struct cmd_ds_802_11_ps_mode { __le16 locallisteninterval; }; -struct PS_CMD_ConfirmSleep { - __le16 command; - __le16 size; - __le16 seqnum; - __le16 result; +struct cmd_confirm_sleep { + struct cmd_header hdr; __le16 action; - __le16 reserved1; + __le16 nullpktinterval; __le16 multipledtim; __le16 reserved; __le16 locallisteninterval; diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index d0e4c3b6deaa..efff63fb6b66 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -37,6 +37,11 @@ EXPORT_SYMBOL_GPL(lbs_debug); module_param_named(libertas_debug, lbs_debug, int, 0644); +/* This global structure is used to send the confirm_sleep command as + * fast as possible down to the firmware. */ +struct cmd_confirm_sleep confirm_sleep; + + #define LBS_TX_PWR_DEFAULT 20 /*100mW */ #define LBS_TX_PWR_US_DEFAULT 20 /*100mW */ #define LBS_TX_PWR_JP_DEFAULT 16 /*50mW */ @@ -1013,14 +1018,6 @@ static int lbs_init_adapter(struct lbs_private *priv) &priv->network_free_list); } - priv->lbs_ps_confirm_sleep.seqnum = cpu_to_le16(++priv->seqnum); - priv->lbs_ps_confirm_sleep.command = - cpu_to_le16(CMD_802_11_PS_MODE); - priv->lbs_ps_confirm_sleep.size = - cpu_to_le16(sizeof(struct PS_CMD_ConfirmSleep)); - priv->lbs_ps_confirm_sleep.action = - cpu_to_le16(CMD_SUBCMD_SLEEP_CONFIRMED); - memset(priv->current_addr, 0xff, ETH_ALEN); priv->connect_status = LBS_DISCONNECTED; @@ -1462,6 +1459,10 @@ EXPORT_SYMBOL_GPL(lbs_interrupt); static int __init lbs_init_module(void) { lbs_deb_enter(LBS_DEB_MAIN); + memset(&confirm_sleep, 0, sizeof(confirm_sleep)); + confirm_sleep.hdr.command = cpu_to_le16(CMD_802_11_PS_MODE); + confirm_sleep.hdr.size = cpu_to_le16(sizeof(confirm_sleep)); + confirm_sleep.action = cpu_to_le16(CMD_SUBCMD_SLEEP_CONFIRMED); lbs_debugfs_init(); lbs_deb_leave(LBS_DEB_MAIN); return 0; -- cgit v1.2.1 From 04850a47aa7d03cbf651a91262fdaa9f18373dfc Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Wed, 26 Mar 2008 17:56:26 +0100 Subject: libertas: don't depend on IEEE80211 Runtime-wise we only need escape_ssid from the deprecated IEEE80211 subsystem. However, it's easy to provide our own copy. Signed-off-by: Holger Schurig Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/Kconfig | 1 - drivers/net/wireless/libertas/decl.h | 5 +++++ drivers/net/wireless/libertas/main.c | 26 ++++++++++++++++++++++++++ 3 files changed, 31 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 9cba8ea58ca8..3c8cf682e9bd 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -271,7 +271,6 @@ config LIBERTAS tristate "Marvell 8xxx Libertas WLAN driver support" depends on WLAN_80211 select WIRELESS_EXT - select IEEE80211 select FW_LOADER ---help--- A library for Marvell Libertas 8xxx devices. diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h index cadc59d7f77f..1ca747b28ef5 100644 --- a/drivers/net/wireless/libertas/decl.h +++ b/drivers/net/wireless/libertas/decl.h @@ -71,4 +71,9 @@ int lbs_stop_card(struct lbs_private *priv); void lbs_host_to_card_done(struct lbs_private *priv); int lbs_update_channel(struct lbs_private *priv); + +#ifndef CONFIG_IEEE80211 +const char *escape_essid(const char *essid, u8 essid_len); +#endif + #endif diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index efff63fb6b66..6c2af176da20 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -1559,6 +1559,32 @@ out: return ret; } +#ifndef CONFIG_IEEE80211 +const char *escape_essid(const char *essid, u8 essid_len) +{ + static char escaped[IW_ESSID_MAX_SIZE * 2 + 1]; + const char *s = essid; + char *d = escaped; + + if (ieee80211_is_empty_essid(essid, essid_len)) { + memcpy(escaped, "", sizeof("")); + return escaped; + } + + essid_len = min(essid_len, (u8) IW_ESSID_MAX_SIZE); + while (essid_len--) { + if (*s == '\0') { + *d++ = '\\'; + *d++ = '0'; + s++; + } else { + *d++ = *s++; + } + } + *d = '\0'; + return escaped; +} +#endif module_init(lbs_init_module); module_exit(lbs_exit_module); -- cgit v1.2.1 From 3480a58a90cd505578b9979d878a5ad9c347d424 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Thu, 27 Mar 2008 19:54:13 -0400 Subject: rt2x00: fixup some non-functional merge errors These small changes restore the rt2x00 sources to the way Ivo intended. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00.h | 2 +- drivers/net/wireless/rt2x00/rt2x00dev.c | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 333484ddb993..30f9f3afdaef 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -674,7 +674,7 @@ struct rt2x00_dev { * This will only be compiled in when required. */ #ifdef CONFIG_RT2X00_LIB_RFKILL -unsigned long rfkill_state; + unsigned long rfkill_state; #define RFKILL_STATE_ALLOCATED 1 #define RFKILL_STATE_REGISTERED 2 struct rfkill *rfkill; diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index f52e92512f90..d2c096708e8c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -1194,10 +1194,6 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev) */ rt2x00debug_deregister(rt2x00dev); rt2x00rfkill_free(rt2x00dev); - - /* - * Free LED. - */ rt2x00leds_unregister(rt2x00dev); /* -- cgit v1.2.1 From c8381fdcab98b74f670d879097bab35d97d88400 Mon Sep 17 00:00:00 2001 From: Mohamed Abbas Date: Fri, 28 Mar 2008 16:21:05 -0700 Subject: iwlwifi: add notification infrastructure to iwlcore This patch add notification function to be called by low level iwl driver to notify iwlcore with current state. This function will call iwlcore subsystem with the new state. This will help make the code more consistent and easy to extend. For example the rf-kill need to know when the driver in init, start, stop or remove state. Instead doing the same call in 3945 and 4965, we just do it from this function. Signed-off-by: Mohamed Abbas Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-core.c | 21 +++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-core.h | 9 +++++++++ drivers/net/wireless/iwlwifi/iwl4965-base.c | 6 ++++++ 3 files changed, 36 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index da51349cbd8b..342a269b8abb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -249,3 +249,24 @@ int iwl_setup(struct iwl_priv *priv) } EXPORT_SYMBOL(iwl_setup); +/* Low level driver call this function to update iwlcore with + * driver status. + */ +int iwlcore_low_level_notify(struct iwl_priv *priv, + enum iwlcore_card_notify notify) +{ + switch (notify) { + case IWLCORE_INIT_EVT: + break; + case IWLCORE_START_EVT: + break; + case IWLCORE_STOP_EVT: + break; + case IWLCORE_REMOVE_EVT: + break; + } + + return 0; +} +EXPORT_SYMBOL(iwlcore_low_level_notify); + diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index ce7f90ebf367..4dfa05948d73 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -146,4 +146,13 @@ int iwl_send_cmd_pdu_async(struct iwl_priv *priv, u8 id, u16 len, struct iwl_cmd *cmd, struct sk_buff *skb)); +enum iwlcore_card_notify { + IWLCORE_INIT_EVT = 0, + IWLCORE_START_EVT = 1, + IWLCORE_STOP_EVT = 2, + IWLCORE_REMOVE_EVT = 3, +}; + +int iwlcore_low_level_notify(struct iwl_priv *priv, + enum iwlcore_card_notify notify); #endif /* __iwl_core_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index cf56b95dd221..5261b6179a86 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -5724,6 +5724,7 @@ static void iwl4965_alive_start(struct iwl_priv *priv) if (priv->error_recovering) iwl4965_error_recovery(priv); + iwlcore_low_level_notify(priv, IWLCORE_START_EVT); return; restart: @@ -5747,6 +5748,8 @@ static void __iwl4965_down(struct iwl_priv *priv) iwl_leds_unregister(priv); + iwlcore_low_level_notify(priv, IWLCORE_STOP_EVT); + iwlcore_clear_stations_table(priv); /* Unblock any waiting calls */ @@ -8167,6 +8170,8 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e pci_save_state(pdev); pci_disable_device(pdev); + /* notify iwlcore to init */ + iwlcore_low_level_notify(priv, IWLCORE_INIT_EVT); return 0; out_remove_sysfs: @@ -8209,6 +8214,7 @@ static void __devexit iwl4965_pci_remove(struct pci_dev *pdev) } } + iwlcore_low_level_notify(priv, IWLCORE_REMOVE_EVT); iwl_dbgfs_unregister(priv); sysfs_remove_group(&pdev->dev.kobj, &iwl4965_attribute_group); -- cgit v1.2.1 From ad97edd2f524940d524c26ae273a4eb23067a7c0 Mon Sep 17 00:00:00 2001 From: Mohamed Abbas Date: Fri, 28 Mar 2008 16:21:06 -0700 Subject: iwlwifi: hook iwlwifi with Linux rfkill This patch hook IWL with Linux rfkill. Signed-off-by: Mohamed Abbas Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/Kconfig | 6 + drivers/net/wireless/iwlwifi/Makefile | 4 + drivers/net/wireless/iwlwifi/iwl-4965.c | 1 + drivers/net/wireless/iwlwifi/iwl-4965.h | 5 + drivers/net/wireless/iwlwifi/iwl-core.c | 4 + drivers/net/wireless/iwlwifi/iwl-core.h | 1 + drivers/net/wireless/iwlwifi/iwl-rfkill.c | 174 ++++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-rfkill.h | 56 +++++++++ drivers/net/wireless/iwlwifi/iwl4965-base.c | 54 ++++----- 9 files changed, 271 insertions(+), 34 deletions(-) create mode 100644 drivers/net/wireless/iwlwifi/iwl-rfkill.c create mode 100644 drivers/net/wireless/iwlwifi/iwl-rfkill.h (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index c26ca749fc1e..4a5c8c0d007d 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig @@ -9,6 +9,12 @@ config IWLWIFI_LEDS This option enables LEDS for the iwlwifi drivers +config IWLCORE_RFKILL + boolean "IWLWIFI RF kill support" + depends on IWLCORE + select RFKILL + select RFKILL_INPUT + config IWL4965 tristate "Intel Wireless WiFi 4965AGN" depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 64fca4d9ac76..2751e8aa97d7 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile @@ -9,6 +9,10 @@ ifeq ($(CONFIG_IWLWIFI_LEDS),y) iwlcore-objs += iwl-led.o endif +ifeq ($(CONFIG_IWLCORE_RFKILL),y) + iwlcore-objs += iwl-rfkill.o +endif + obj-$(CONFIG_IWL3945) += iwl3945.o iwl3945-objs = iwl3945-base.o iwl-3945.o iwl-3945-rs.o diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index e5f64d7fbfde..3ab5d8292502 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -4961,6 +4961,7 @@ static struct iwl_lib_ops iwl4965_lib = { .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, .release_semaphore = iwlcore_eeprom_release_semaphore, }, + .radio_kill_sw = iwl4965_radio_kill_sw, }; static struct iwl_ops iwl4965_ops = { diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index 069e591981b2..ca864fa65ca4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -40,6 +40,7 @@ extern struct pci_device_id iwl4965_hw_card_ids[]; #define DRV_NAME "iwl4965" +#include "iwl-rfkill.h" #include "iwl-eeprom.h" #include "iwl-4965-hw.h" #include "iwl-csr.h" @@ -739,6 +740,7 @@ extern int iwl4965_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index extern int iwl4965_queue_space(const struct iwl4965_queue *q); struct iwl_priv; +extern void iwl4965_radio_kill_sw(struct iwl_priv *priv, int disable_radio); /* * Forward declare iwl-4965.c functions for iwl-base.c */ @@ -1050,6 +1052,9 @@ struct iwl_priv { * 4965's initialize alive response contains some calibration data. */ struct iwl4965_init_alive_resp card_alive_init; struct iwl4965_alive_resp card_alive; +#ifdef CONFIG_IWLCORE_RFKILL + struct iwl_rfkill_mngr rfkill_mngr; +#endif #ifdef CONFIG_IWL4965_LEDS struct iwl4965_led led[IWL_LED_TRG_MAX]; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 342a269b8abb..49fb52f07354 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -35,6 +35,7 @@ struct iwl_priv; /* FIXME: remove */ #include "iwl-debug.h" #include "iwl-eeprom.h" #include "iwl-core.h" +#include "iwl-rfkill.h" #include "iwl-4965.h" /* FIXME: remove */ @@ -257,12 +258,15 @@ int iwlcore_low_level_notify(struct iwl_priv *priv, { switch (notify) { case IWLCORE_INIT_EVT: + iwl_rfkill_init(priv); break; case IWLCORE_START_EVT: break; case IWLCORE_STOP_EVT: break; case IWLCORE_REMOVE_EVT: + iwl_rfkill_unregister(priv); + iwl_rfkill_free(priv); break; } diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 4dfa05948d73..5efafe1a1d86 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -91,6 +91,7 @@ struct iwl_lib_ops { int (*init_drv)(struct iwl_priv *priv); /* eeprom operations (as defined in iwl-eeprom.h) */ struct iwl_eeprom_ops eeprom_ops; + void (*radio_kill_sw)(struct iwl_priv *priv, int disable_radio); }; struct iwl_ops { diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.c b/drivers/net/wireless/iwlwifi/iwl-rfkill.c new file mode 100644 index 000000000000..66abf52e8987 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.c @@ -0,0 +1,174 @@ +/****************************************************************************** + * + * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. + * + * Portions of this file are derived from the ipw3945 project, as well + * as portions of the ieee80211 subsystem header files. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * James P. Ketrenos + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + *****************************************************************************/ +#include +#include +#include +#include + +#include + +#include "iwl-eeprom.h" +#include "iwl-core.h" +#include "iwl-4965.h" +#include "iwl-helpers.h" + + +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); +} + + +/* software rf-kill from user */ +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) + return 0; + + IWL_DEBUG_RF_KILL("we recieved soft RFKILL set to state %d\n", state); + mutex_lock(&priv->mutex); + + switch (state) { + case RFKILL_STATE_ON: + priv->cfg->ops->lib->radio_kill_sw(priv, 0); + /* if HW rf-kill is set dont allow ON state */ + if (iwl_is_rfkill(priv)) + err = -EBUSY; + break; + case RFKILL_STATE_OFF: + priv->cfg->ops->lib->radio_kill_sw(priv, 1); + if (!iwl_is_rfkill(priv)) + err = -EBUSY; + break; + } + mutex_unlock(&priv->mutex); + + return err; +} + +int iwl_rfkill_init(struct iwl_priv *priv) +{ + struct device *device = wiphy_dev(priv->hw->wiphy); + int ret = 0; + + BUG_ON(device == NULL); + + priv->rfkill_mngr.rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN); + if (!priv->rfkill_mngr.rfkill) { + 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_mngr.rfkill->dev.class->suspend = NULL; + priv->rfkill_mngr.rfkill->dev.class->resume = NULL; + + priv->rfkill_mngr.input_dev = input_allocate_device(); + if (!priv->rfkill_mngr.input_dev) { + ret = -ENOMEM; + goto freed_rfkill; + } + + 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); + if (ret) + goto free_input_dev; + + ret = input_register_device(priv->rfkill_mngr.input_dev); + if (ret) + goto unregister_rfkill; + + return ret; + +unregister_rfkill: + rfkill_unregister(priv->rfkill_mngr.rfkill); + +free_input_dev: + input_free_device(priv->rfkill_mngr.input_dev); + priv->rfkill_mngr.input_dev = NULL; + +freed_rfkill: + rfkill_free(priv->rfkill_mngr.rfkill); + priv->rfkill_mngr.rfkill = NULL; + +error: + return ret; +} +EXPORT_SYMBOL(iwl_rfkill_init); + +void iwl_rfkill_unregister(struct iwl_priv *priv) +{ + + 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); +} +EXPORT_SYMBOL(iwl_rfkill_unregister); + + +void iwl_rfkill_free(struct iwl_priv *priv) +{ + if (priv->rfkill_mngr.input_dev) + input_free_device(priv->rfkill_mngr.input_dev); + + if (priv->rfkill_mngr.rfkill) + rfkill_free(priv->rfkill_mngr.rfkill); +} +EXPORT_SYMBOL(iwl_rfkill_free); + +/* set rf-kill to the right state. */ +void iwl_rfkill_set_hw_state(struct iwl_priv *priv) +{ + + if (!priv->rfkill_mngr.rfkill) + return; + + if (!iwl_is_rfkill(priv)) + priv->rfkill_mngr.rfkill->state = RFKILL_STATE_ON; + else + priv->rfkill_mngr.rfkill->state = RFKILL_STATE_OFF; +} +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 new file mode 100644 index 000000000000..a5cbc5ab45d9 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.h @@ -0,0 +1,56 @@ +/****************************************************************************** + * + * Copyright(c) 2007 - 2008 Intel Corporation. All rights reserved. + * + * Portions of this file are derived from the ipw3945 project, as well + * as portions of the ieee80211 subsystem header files. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * James P. Ketrenos + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + *****************************************************************************/ +#ifndef __iwl_rf_kill_h__ +#define __iwl_rf_kill_h__ + +struct iwl_priv; + +#include +#include + + +#ifdef CONFIG_IWLCORE_RFKILL +struct iwl_rfkill_mngr { + struct rfkill *rfkill; + struct input_dev *input_dev; +}; + +void iwl_rfkill_set_hw_state(struct iwl_priv *priv); +void iwl_rfkill_free(struct iwl_priv *priv); +void iwl_rfkill_unregister(struct iwl_priv *priv); +int iwl_rfkill_init(struct iwl_priv *priv); +#else +static inline void iwl_rfkill_set_hw_state(struct iwl_priv *priv) {} +static inline void iwl_rfkill_free(struct iwl_priv *priv) {} +static inline void iwl_rfkill_unregister(struct iwl_priv *priv) {} +static inline int iwl_rfkill_init(struct iwl_priv *priv) { return 0; } +#endif + + + +#endif /* __iwl_rf_kill_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 5261b6179a86..7f56565b4002 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -2607,7 +2607,7 @@ static void iwl4965_set_rate(struct iwl_priv *priv) (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; } -static void iwl4965_radio_kill_sw(struct iwl_priv *priv, int disable_radio) +void iwl4965_radio_kill_sw(struct iwl_priv *priv, int disable_radio) { unsigned long flags; @@ -2625,8 +2625,16 @@ static void iwl4965_radio_kill_sw(struct iwl_priv *priv, int disable_radio) iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, CSR_UCODE_SW_BIT_RFKILL); spin_unlock_irqrestore(&priv->lock, flags); - iwl4965_send_card_state(priv, CARD_STATE_CMD_DISABLE, 0); + /* call the host command only if no hw rf-kill set */ + if (!test_bit(STATUS_RF_KILL_HW, &priv->status)) + iwl4965_send_card_state(priv, + CARD_STATE_CMD_DISABLE, + 0); set_bit(STATUS_RF_KILL_SW, &priv->status); + + /* make sure mac80211 stop sending Tx frame */ + if (priv->mac80211_registered) + ieee80211_stop_queues(priv->hw); } return; } @@ -5852,6 +5860,7 @@ static int __iwl4965_up(struct iwl_priv *priv) if (test_bit(STATUS_RF_KILL_SW, &priv->status)) { IWL_WARNING("Radio disabled by SW RF kill (module " "parameter)\n"); + iwl_rfkill_set_hw_state(priv); return -ENODEV; } @@ -5867,11 +5876,13 @@ static int __iwl4965_up(struct iwl_priv *priv) else { set_bit(STATUS_RF_KILL_HW, &priv->status); if (!test_bit(STATUS_IN_SUSPEND, &priv->status)) { + iwl_rfkill_set_hw_state(priv); IWL_WARNING("Radio disabled by HW RF Kill switch\n"); return -ENODEV; } } + iwl_rfkill_set_hw_state(priv); iwl_write32(priv, CSR_INT, 0xFFFFFFFF); rc = iwl4965_hw_nic_init(priv); @@ -5985,6 +5996,9 @@ static void iwl4965_bg_rf_kill(struct work_struct *work) if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) queue_work(priv->workqueue, &priv->restart); } else { + /* make sure mac80211 stop sending Tx frame */ + if (priv->mac80211_registered) + ieee80211_stop_queues(priv->hw); if (!test_bit(STATUS_RF_KILL_HW, &priv->status)) IWL_DEBUG_RF_KILL("Can not turn radio back on - " @@ -5994,6 +6008,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); } @@ -6674,7 +6690,8 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co } #endif - iwl4965_radio_kill_sw(priv, !conf->radio_enabled); + if (priv->cfg->ops->lib->radio_kill_sw) + priv->cfg->ops->lib->radio_kill_sw(priv, !conf->radio_enabled); if (!conf->radio_enabled) { IWL_DEBUG_MAC80211("leave - radio disabled\n"); @@ -7449,36 +7466,6 @@ static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO, #endif /* CONFIG_IWLWIFI_DEBUG */ -static ssize_t show_rf_kill(struct device *d, - struct device_attribute *attr, char *buf) -{ - /* - * 0 - RF kill not enabled - * 1 - SW based RF kill active (sysfs) - * 2 - HW based RF kill active - * 3 - Both HW and SW based RF kill active - */ - struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; - int val = (test_bit(STATUS_RF_KILL_SW, &priv->status) ? 0x1 : 0x0) | - (test_bit(STATUS_RF_KILL_HW, &priv->status) ? 0x2 : 0x0); - - return sprintf(buf, "%i\n", val); -} - -static ssize_t store_rf_kill(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; - - mutex_lock(&priv->mutex); - iwl4965_radio_kill_sw(priv, buf[0] == '1'); - mutex_unlock(&priv->mutex); - - return count; -} - -static DEVICE_ATTR(rf_kill, S_IWUSR | S_IRUGO, show_rf_kill, store_rf_kill); static ssize_t show_temperature(struct device *d, struct device_attribute *attr, char *buf) @@ -7964,7 +7951,6 @@ static struct attribute *iwl4965_sysfs_entries[] = { #endif &dev_attr_power_level.attr, &dev_attr_retry_rate.attr, - &dev_attr_rf_kill.attr, &dev_attr_rs_window.attr, &dev_attr_statistics.attr, &dev_attr_status.attr, -- cgit v1.2.1 From 0359facc7b7a37fd1223ac60649c80cd8daeaf73 Mon Sep 17 00:00:00 2001 From: Mohamed Abbas Date: Fri, 28 Mar 2008 16:21:08 -0700 Subject: iwlwifi: fix race condition during driver unload This patch fixed the OOPS when load the driver while rf-kill is on then unload the driver right after load. a race condition caused the interupt handler to schedule the tasklet which will run right after the driver pci_remove causing invalid poiter OOPS. Signed-off-by: Mohamed Abbas Signed-off-by: Joonwoo Park Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl3945-base.c | 34 +++++++++++++++++++++++++++-- drivers/net/wireless/iwlwifi/iwl4965-base.c | 32 +++++++++++++++++++++++++-- 2 files changed, 62 insertions(+), 4 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index ab635dcfd5d1..2a5245b63e32 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -4153,6 +4153,16 @@ static void iwl3945_enable_interrupts(struct iwl3945_priv *priv) iwl3945_write32(priv, CSR_INT_MASK, CSR_INI_SET_MASK); } + +/* call this function to flush any scheduled tasklet */ +static inline void iwl_synchronize_irq(struct iwl3945_priv *priv) +{ + /* wait to make sure we flush pedding tasklet*/ + synchronize_irq(priv->pci_dev->irq); + tasklet_kill(&priv->irq_tasklet); +} + + static inline void iwl3945_disable_interrupts(struct iwl3945_priv *priv) { clear_bit(STATUS_INT_ENABLED, &priv->status); @@ -4552,7 +4562,9 @@ static void iwl3945_irq_tasklet(struct iwl3945_priv *priv) } /* Re-enable all interrupts */ - iwl3945_enable_interrupts(priv); + /* only Re-enable if disabled by irq */ + if (test_bit(STATUS_INT_ENABLED, &priv->status)) + iwl3945_enable_interrupts(priv); #ifdef CONFIG_IWL3945_DEBUG if (iwl3945_debug_level & (IWL_DL_ISR)) { @@ -4616,7 +4628,9 @@ unplugged: none: /* re-enable interrupts here since we don't have anything to service. */ - iwl3945_enable_interrupts(priv); + /* only Re-enable if disabled by irq */ + if (test_bit(STATUS_INT_ENABLED, &priv->status)) + iwl3945_enable_interrupts(priv); spin_unlock(&priv->lock); return IRQ_NONE; } @@ -5905,7 +5919,10 @@ static void __iwl3945_down(struct iwl3945_priv *priv) iwl3945_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); /* tell the device to stop sending interrupts */ + spin_lock_irqsave(&priv->lock, flags); iwl3945_disable_interrupts(priv); + spin_unlock_irqrestore(&priv->lock, flags); + iwl_synchronize_irq(priv); if (priv->mac80211_registered) ieee80211_stop_queues(priv->hw); @@ -7943,6 +7960,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e struct ieee80211_hw *hw; struct iwl_3945_cfg *cfg = (struct iwl_3945_cfg *)(ent->driver_data); int i; + unsigned long flags; DECLARE_MAC_BUF(mac); /* Disabling hardware scan means that mac80211 will perform scans @@ -8093,7 +8111,9 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e priv->power_mode = IWL_POWER_AC; priv->user_txpower_limit = IWL_DEFAULT_TX_POWER; + spin_lock_irqsave(&priv->lock, flags); iwl3945_disable_interrupts(priv); + spin_unlock_irqrestore(&priv->lock, flags); err = sysfs_create_group(&pdev->dev.kobj, &iwl3945_attribute_group); if (err) { @@ -8180,6 +8200,7 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) struct iwl3945_priv *priv = pci_get_drvdata(pdev); struct list_head *p, *q; int i; + unsigned long flags; if (!priv) return; @@ -8190,6 +8211,15 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) iwl3945_down(priv); + /* make sure we flush any pending irq or + * tasklet for the driver + */ + spin_lock_irqsave(&priv->lock, flags); + iwl3945_disable_interrupts(priv); + spin_unlock_irqrestore(&priv->lock, flags); + + iwl_synchronize_irq(priv); + /* Free MAC hash list for ADHOC */ for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++) { list_for_each_safe(p, q, &priv->ibss_mac_hash[i]) { diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 7f56565b4002..29e843108e9f 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -4285,6 +4285,14 @@ static void iwl4965_enable_interrupts(struct iwl_priv *priv) iwl_write32(priv, CSR_INT_MASK, CSR_INI_SET_MASK); } +/* call this function to flush any scheduled tasklet */ +static inline void iwl_synchronize_irq(struct iwl_priv *priv) +{ + /* wait to make sure we flush pedding tasklet*/ + synchronize_irq(priv->pci_dev->irq); + tasklet_kill(&priv->irq_tasklet); +} + static inline void iwl4965_disable_interrupts(struct iwl_priv *priv) { clear_bit(STATUS_INT_ENABLED, &priv->status); @@ -4668,7 +4676,9 @@ static void iwl4965_irq_tasklet(struct iwl_priv *priv) } /* Re-enable all interrupts */ - iwl4965_enable_interrupts(priv); + /* only Re-enable if diabled by irq */ + if (test_bit(STATUS_INT_ENABLED, &priv->status)) + iwl4965_enable_interrupts(priv); #ifdef CONFIG_IWLWIFI_DEBUG if (iwl_debug_level & (IWL_DL_ISR)) { @@ -4733,7 +4743,9 @@ static irqreturn_t iwl4965_isr(int irq, void *data) none: /* re-enable interrupts here since we don't have anything to service. */ - iwl4965_enable_interrupts(priv); + /* only Re-enable if diabled by irq */ + if (test_bit(STATUS_INT_ENABLED, &priv->status)) + iwl4965_enable_interrupts(priv); spin_unlock(&priv->lock); return IRQ_NONE; } @@ -5772,7 +5784,10 @@ static void __iwl4965_down(struct iwl_priv *priv) iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); /* tell the device to stop sending interrupts */ + spin_lock_irqsave(&priv->lock, flags); iwl4965_disable_interrupts(priv); + spin_unlock_irqrestore(&priv->lock, flags); + iwl_synchronize_irq(priv); if (priv->mac80211_registered) ieee80211_stop_queues(priv->hw); @@ -7996,6 +8011,7 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e struct iwl_priv *priv; struct ieee80211_hw *hw; struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); + unsigned long flags; DECLARE_MAC_BUF(mac); /************************ @@ -8133,7 +8149,9 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e /******************** * 8. Setup services ********************/ + spin_lock_irqsave(&priv->lock, flags); iwl4965_disable_interrupts(priv); + spin_unlock_irqrestore(&priv->lock, flags); err = sysfs_create_group(&pdev->dev.kobj, &iwl4965_attribute_group); if (err) { @@ -8182,6 +8200,7 @@ static void __devexit iwl4965_pci_remove(struct pci_dev *pdev) struct iwl_priv *priv = pci_get_drvdata(pdev); struct list_head *p, *q; int i; + unsigned long flags; if (!priv) return; @@ -8192,6 +8211,15 @@ static void __devexit iwl4965_pci_remove(struct pci_dev *pdev) iwl4965_down(priv); + /* make sure we flush any pending irq or + * tasklet for the driver + */ + spin_lock_irqsave(&priv->lock, flags); + iwl4965_disable_interrupts(priv); + spin_unlock_irqrestore(&priv->lock, flags); + + iwl_synchronize_irq(priv); + /* Free MAC hash list for ADHOC */ for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++) { list_for_each_safe(p, q, &priv->ibss_mac_hash[i]) { -- cgit v1.2.1 From 897e1cf29e05e3373bf380a417d085cd3389a3c0 Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Fri, 28 Mar 2008 16:21:09 -0700 Subject: iwlwifi: move rate registration to module load Having rate registration during module load enables the use of error checking as well as reliable registration/unregistration pairing. Previously this was not possible as rate registration was done during _probe where _probe could be run for more than one device on the system. Signed-off-by: Reinette Chatre Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 6 +++--- drivers/net/wireless/iwlwifi/iwl-3945-rs.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-4965-rs.c | 6 +++--- drivers/net/wireless/iwlwifi/iwl-4965-rs.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-4965.c | 1 - drivers/net/wireless/iwlwifi/iwl3945-base.c | 23 ++++++++++++++++++----- drivers/net/wireless/iwlwifi/iwl4965-base.c | 22 ++++++++++++++++++---- 7 files changed, 46 insertions(+), 20 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index 157e572ebc83..8559f252a55f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -976,12 +976,12 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) iwl3945_rates[rs_sta->start_rate].plcp); } -void iwl3945_rate_control_register(struct ieee80211_hw *hw) +int iwl3945_rate_control_register(void) { - ieee80211_rate_control_register(&rs_ops); + return ieee80211_rate_control_register(&rs_ops); } -void iwl3945_rate_control_unregister(struct ieee80211_hw *hw) +void iwl3945_rate_control_unregister(void) { ieee80211_rate_control_unregister(&rs_ops); } diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.h b/drivers/net/wireless/iwlwifi/iwl-3945-rs.h index e88b1d31f56f..f085d330bdcf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.h @@ -202,7 +202,7 @@ extern void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id); * ieee80211_register_hw * */ -extern void iwl3945_rate_control_register(struct ieee80211_hw *hw); +extern int iwl3945_rate_control_register(void); /** * iwl3945_rate_control_unregister - Unregister the rate control callbacks @@ -210,6 +210,6 @@ extern void iwl3945_rate_control_register(struct ieee80211_hw *hw); * This should be called after calling ieee80211_unregister_hw, but before * the driver is unloaded. */ -extern void iwl3945_rate_control_unregister(struct ieee80211_hw *hw); +extern void iwl3945_rate_control_unregister(void); #endif diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c index 735eadd57d18..90ecf26af280 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c @@ -2822,12 +2822,12 @@ void iwl4965_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) priv->lq_mngr.lq_ready = 1; } -void iwl4965_rate_control_register(struct ieee80211_hw *hw) +int iwl4965_rate_control_register(void) { - ieee80211_rate_control_register(&rs_ops); + return ieee80211_rate_control_register(&rs_ops); } -void iwl4965_rate_control_unregister(struct ieee80211_hw *hw) +void iwl4965_rate_control_unregister(void) { ieee80211_rate_control_unregister(&rs_ops); } diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.h b/drivers/net/wireless/iwlwifi/iwl-4965-rs.h index ae827e1fb0fb..866e378aa385 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.h @@ -288,7 +288,7 @@ extern void iwl4965_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id); * ieee80211_register_hw * */ -extern void iwl4965_rate_control_register(struct ieee80211_hw *hw); +extern int iwl4965_rate_control_register(void); /** * iwl4965_rate_control_unregister - Unregister the rate control callbacks @@ -296,6 +296,6 @@ extern void iwl4965_rate_control_register(struct ieee80211_hw *hw); * This should be called after calling ieee80211_unregister_hw, but before * the driver is unloaded. */ -extern void iwl4965_rate_control_unregister(struct ieee80211_hw *hw); +extern void iwl4965_rate_control_unregister(void); #endif diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 3ab5d8292502..add6311393d3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -177,7 +177,6 @@ static int iwl4965_init_drv(struct iwl_priv *priv) goto err_free_channel_map; } - iwl4965_rate_control_register(priv->hw); ret = ieee80211_register_hw(priv->hw); if (ret) { IWL_ERROR("Failed to register network device (error %d)\n", diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 2a5245b63e32..8c2036850c89 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -8156,7 +8156,6 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e goto out_free_channel_map; } - iwl3945_rate_control_register(priv->hw); err = ieee80211_register_hw(priv->hw); if (err) { IWL_ERROR("Failed to register network device (error %d)\n", err); @@ -8241,7 +8240,6 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) if (priv->mac80211_registered) { ieee80211_unregister_hw(priv->hw); - iwl3945_rate_control_unregister(priv->hw); } /*netif_stop_queue(dev); */ @@ -8322,21 +8320,35 @@ static int __init iwl3945_init(void) int ret; printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n"); printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n"); + + ret = iwl3945_rate_control_register(); + if (ret) { + IWL_ERROR("Unable to register rate control algorithm: %d\n", ret); + return ret; + } + ret = pci_register_driver(&iwl3945_driver); if (ret) { IWL_ERROR("Unable to initialize PCI module\n"); - return ret; + goto error_register; } #ifdef CONFIG_IWL3945_DEBUG ret = driver_create_file(&iwl3945_driver.driver, &driver_attr_debug_level); if (ret) { IWL_ERROR("Unable to create driver sysfs file\n"); - pci_unregister_driver(&iwl3945_driver); - return ret; + goto error_debug; } #endif return ret; + +#ifdef CONFIG_IWL3945_DEBUG +error_debug: + pci_unregister_driver(&iwl3945_driver); +#endif +error_register: + iwl3945_rate_control_unregister(); + return ret; } static void __exit iwl3945_exit(void) @@ -8345,6 +8357,7 @@ static void __exit iwl3945_exit(void) driver_remove_file(&iwl3945_driver.driver, &driver_attr_debug_level); #endif pci_unregister_driver(&iwl3945_driver); + iwl3945_rate_control_unregister(); } module_param_named(antenna, iwl3945_param_antenna, int, 0444); diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 29e843108e9f..ae4e53f5bedd 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -8243,7 +8243,6 @@ static void __devexit iwl4965_pci_remove(struct pci_dev *pdev) if (priv->mac80211_registered) { ieee80211_unregister_hw(priv->hw); - iwl4965_rate_control_unregister(priv->hw); } /*netif_stop_queue(dev); */ @@ -8324,21 +8323,35 @@ static int __init iwl4965_init(void) int ret; printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n"); printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n"); + + ret = iwl4965_rate_control_register(); + if (ret) { + IWL_ERROR("Unable to register rate control algorithm: %d\n", ret); + return ret; + } + ret = pci_register_driver(&iwl4965_driver); if (ret) { IWL_ERROR("Unable to initialize PCI module\n"); - return ret; + goto error_register; } #ifdef CONFIG_IWLWIFI_DEBUG ret = driver_create_file(&iwl4965_driver.driver, &driver_attr_debug_level); if (ret) { IWL_ERROR("Unable to create driver sysfs file\n"); - pci_unregister_driver(&iwl4965_driver); - return ret; + goto error_debug; } #endif return ret; + +#ifdef CONFIG_IWLWIFI_DEBUG +error_debug: + pci_unregister_driver(&iwl4965_driver); +#endif +error_register: + iwl4965_rate_control_unregister(); + return ret; } static void __exit iwl4965_exit(void) @@ -8347,6 +8360,7 @@ static void __exit iwl4965_exit(void) driver_remove_file(&iwl4965_driver.driver, &driver_attr_debug_level); #endif pci_unregister_driver(&iwl4965_driver); + iwl4965_rate_control_unregister(); } module_exit(iwl4965_exit); -- cgit v1.2.1 From c4f552321fa2cfe1d6b1846138d2aa8254308f96 Mon Sep 17 00:00:00 2001 From: Ron Rindjunsky Date: Fri, 28 Mar 2008 16:21:10 -0700 Subject: iwlwifi: unregister to upper stack before releasing resources This patch fixes an early release of driver's resources before upper stack was notified that low-level driver shuts down. Signed-off-by: Ron Rindjunsky Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl4965-base.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index ae4e53f5bedd..e98695f7f14c 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -8207,6 +8207,11 @@ static void __devexit iwl4965_pci_remove(struct pci_dev *pdev) IWL_DEBUG_INFO("*** UNLOAD DRIVER ***\n"); + if (priv->mac80211_registered) { + ieee80211_unregister_hw(priv->hw); + priv->mac80211_registered = 0; + } + set_bit(STATUS_EXIT_PENDING, &priv->status); iwl4965_down(priv); @@ -8241,9 +8246,6 @@ static void __devexit iwl4965_pci_remove(struct pci_dev *pdev) iwl4965_unset_hw_setting(priv); iwlcore_clear_stations_table(priv); - if (priv->mac80211_registered) { - ieee80211_unregister_hw(priv->hw); - } /*netif_stop_queue(dev); */ flush_workqueue(priv->workqueue); -- cgit v1.2.1 From a571ea4eb34adbf33bbaf4bdc6db6037b1a93e0f Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Fri, 28 Mar 2008 16:21:11 -0700 Subject: iwlwifi: LED initialize before registering This patch initialize all fields in led before registering it This fixes oops on initialization Signed-off-by: Tomas Winkler Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-led.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index d59ad1844e25..4fe5ee2ba545 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c @@ -238,18 +238,20 @@ static int iwl_leds_register_led(struct iwl_priv *priv, led->led_dev.brightness_set = iwl4965_led_brightness_set; led->led_dev.default_trigger = trigger; + led->priv = priv; + led->type = type; + ret = led_classdev_register(device, &led->led_dev); if (ret) { IWL_ERROR("Error: failed to register led handler.\n"); return ret; } - led->priv = priv; - led->type = type; led->registered = 1; if (set_led && led->led_on) led->led_on(priv, IWL_LED_LINK); + return 0; } -- cgit v1.2.1 From e5472978ef16051337913f57b2f22982f3e9e4c2 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Fri, 28 Mar 2008 16:21:12 -0700 Subject: iwlwifi: Fix synchronous host command This patch replaces static variable from send_cmd_sync with flag in priv->status. It was used for reentrance protection but clearly made it impossible to stuck more cards into the same machine In addition it force check of return values of synchronous commands commands that doesn't requires return value async commands have to be used Signed-off-by: Tomas Winkler Signed-off-by: Yi Zhu Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.h | 35 +++++++++++++++-------------- drivers/net/wireless/iwlwifi/iwl-4965.c | 8 +++---- drivers/net/wireless/iwlwifi/iwl-4965.h | 35 +++++++++++++++-------------- drivers/net/wireless/iwlwifi/iwl-core.h | 6 +++-- drivers/net/wireless/iwlwifi/iwl-hcmd.c | 8 +++---- drivers/net/wireless/iwlwifi/iwl3945-base.c | 8 +++---- 6 files changed, 52 insertions(+), 48 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index d7ccf13b875d..ac1226946aa6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -401,23 +401,24 @@ struct iwl3945_rx_queue { #define MIN_B_CHANNELS 1 #define STATUS_HCMD_ACTIVE 0 /* host command in progress */ -#define STATUS_INT_ENABLED 1 -#define STATUS_RF_KILL_HW 2 -#define STATUS_RF_KILL_SW 3 -#define STATUS_INIT 4 -#define STATUS_ALIVE 5 -#define STATUS_READY 6 -#define STATUS_TEMPERATURE 7 -#define STATUS_GEO_CONFIGURED 8 -#define STATUS_EXIT_PENDING 9 -#define STATUS_IN_SUSPEND 10 -#define STATUS_STATISTICS 11 -#define STATUS_SCANNING 12 -#define STATUS_SCAN_ABORTING 13 -#define STATUS_SCAN_HW 14 -#define STATUS_POWER_PMI 15 -#define STATUS_FW_ERROR 16 -#define STATUS_CONF_PENDING 17 +#define STATUS_HCMD_SYNC_ACTIVE 1 /* sync host command in progress */ +#define STATUS_INT_ENABLED 2 +#define STATUS_RF_KILL_HW 3 +#define STATUS_RF_KILL_SW 4 +#define STATUS_INIT 5 +#define STATUS_ALIVE 6 +#define STATUS_READY 7 +#define STATUS_TEMPERATURE 8 +#define STATUS_GEO_CONFIGURED 9 +#define STATUS_EXIT_PENDING 10 +#define STATUS_IN_SUSPEND 11 +#define STATUS_STATISTICS 12 +#define STATUS_SCANNING 13 +#define STATUS_SCAN_ABORTING 14 +#define STATUS_SCAN_HW 15 +#define STATUS_POWER_PMI 16 +#define STATUS_FW_ERROR 17 +#define STATUS_CONF_PENDING 18 #define MAX_TID_COUNT 9 diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index add6311393d3..51a144914cfa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -1314,8 +1314,8 @@ void iwl4965_chain_noise_reset(struct iwl_priv *priv) cmd.diff_gain_a = 0; cmd.diff_gain_b = 0; cmd.diff_gain_c = 0; - iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD, - sizeof(cmd), &cmd); + iwl_send_cmd_pdu_async(priv, REPLY_PHY_CALIBRATION_CMD, + sizeof(cmd), &cmd, NULL); msleep(4); data->state = IWL_CHAIN_NOISE_ACCUMULATE; IWL_DEBUG_CALIB("Run chain_noise_calibrate\n"); @@ -4563,8 +4563,8 @@ void iwl4965_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap) /* Update the rate scaling for control frame Tx to AP */ link_cmd.sta_id = is_ap ? IWL_AP_ID : priv->hw_setting.bcast_sta_id; - iwl_send_cmd_pdu(priv, REPLY_TX_LINK_QUALITY_CMD, sizeof(link_cmd), - &link_cmd); + iwl_send_cmd_pdu_async(priv, REPLY_TX_LINK_QUALITY_CMD, + sizeof(link_cmd), &link_cmd, NULL); } #ifdef CONFIG_IWL4965_HT diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index ca864fa65ca4..8c14e9a87c14 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -415,23 +415,24 @@ struct iwl4965_rx_queue { #define MIN_B_CHANNELS 1 #define STATUS_HCMD_ACTIVE 0 /* host command in progress */ -#define STATUS_INT_ENABLED 1 -#define STATUS_RF_KILL_HW 2 -#define STATUS_RF_KILL_SW 3 -#define STATUS_INIT 4 -#define STATUS_ALIVE 5 -#define STATUS_READY 6 -#define STATUS_TEMPERATURE 7 -#define STATUS_GEO_CONFIGURED 8 -#define STATUS_EXIT_PENDING 9 -#define STATUS_IN_SUSPEND 10 -#define STATUS_STATISTICS 11 -#define STATUS_SCANNING 12 -#define STATUS_SCAN_ABORTING 13 -#define STATUS_SCAN_HW 14 -#define STATUS_POWER_PMI 15 -#define STATUS_FW_ERROR 16 -#define STATUS_CONF_PENDING 17 +#define STATUS_HCMD_SYNC_ACTIVE 1 /* sync host command in progress */ +#define STATUS_INT_ENABLED 2 +#define STATUS_RF_KILL_HW 3 +#define STATUS_RF_KILL_SW 4 +#define STATUS_INIT 5 +#define STATUS_ALIVE 6 +#define STATUS_READY 7 +#define STATUS_TEMPERATURE 8 +#define STATUS_GEO_CONFIGURED 9 +#define STATUS_EXIT_PENDING 10 +#define STATUS_IN_SUSPEND 11 +#define STATUS_STATISTICS 12 +#define STATUS_SCANNING 13 +#define STATUS_SCAN_ABORTING 14 +#define STATUS_SCAN_HW 15 +#define STATUS_POWER_PMI 16 +#define STATUS_FW_ERROR 17 +#define STATUS_CONF_PENDING 18 #define MAX_TID_COUNT 9 diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 5efafe1a1d86..64f4df53986c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -138,9 +138,11 @@ int iwl_setup(struct iwl_priv *priv); *****************************************************/ const char *get_cmd_string(u8 cmd); -int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd); +int __must_check iwl_send_cmd_sync(struct iwl_priv *priv, + struct iwl_host_cmd *cmd); int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd); -int iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u16 len, const void *data); +int __must_check iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, + u16 len, const void *data); int iwl_send_cmd_pdu_async(struct iwl_priv *priv, u8 id, u16 len, const void *data, int (*callback)(struct iwl_priv *priv, diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c index 51c9949633e3..1f8c2999805b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c @@ -151,17 +151,17 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) { int cmd_idx; int ret; - static atomic_t entry = ATOMIC_INIT(0); /* reentrance protection */ BUG_ON(cmd->meta.flags & CMD_ASYNC); /* A synchronous command can not have a callback set. */ BUG_ON(cmd->meta.u.callback != NULL); - if (atomic_xchg(&entry, 1)) { + if (test_and_set_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status)) { IWL_ERROR("Error sending %s: Already sending a host command\n", get_cmd_string(cmd->id)); - return -EBUSY; + ret = -EBUSY; + goto out; } set_bit(STATUS_HCMD_ACTIVE, &priv->status); @@ -231,7 +231,7 @@ fail: cmd->meta.u.skb = NULL; } out: - atomic_set(&entry, 0); + clear_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status); return ret; } EXPORT_SYMBOL(iwl_send_cmd_sync); diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 8c2036850c89..51480a4920e8 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -733,17 +733,17 @@ static int iwl3945_send_cmd_sync(struct iwl3945_priv *priv, struct iwl3945_host_ { int cmd_idx; int ret; - static atomic_t entry = ATOMIC_INIT(0); /* reentrance protection */ BUG_ON(cmd->meta.flags & CMD_ASYNC); /* A synchronous command can not have a callback set. */ BUG_ON(cmd->meta.u.callback != NULL); - if (atomic_xchg(&entry, 1)) { + if (test_and_set_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status)) { IWL_ERROR("Error sending %s: Already sending a host command\n", get_cmd_string(cmd->id)); - return -EBUSY; + ret = -EBUSY; + goto out; } set_bit(STATUS_HCMD_ACTIVE, &priv->status); @@ -813,7 +813,7 @@ fail: cmd->meta.u.skb = NULL; } out: - atomic_set(&entry, 0); + clear_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status); return ret; } -- cgit v1.2.1 From bc5213f468b4d0520a06e27ea2cc9724bc5b896c Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Sat, 29 Mar 2008 15:59:01 +0100 Subject: rt2x00: Invert scheduled packet_filter check Invert the check for scheduling the packet_filter configuration. When DRIVER_REQUIRE_SCHEDULED is not set we should immediately configure the the filter. This fixes the 'infinite calls to rt2x00mc_configure_filter' bug reported by Bas Hulsken. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00mac.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 17b6bb034ebf..a0adf5a04aa0 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -418,9 +418,9 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw, rt2x00dev->packet_filter = *total_flags; if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags)) - queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->filter_work); - else rt2x00dev->ops->lib->config_filter(rt2x00dev, *total_flags); + else + queue_work(rt2x00dev->hw->workqueue, &rt2x00dev->filter_work); } EXPORT_SYMBOL_GPL(rt2x00mac_configure_filter); -- cgit v1.2.1 From e0b005fa1479045fe879944036268af3ebcd1835 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 31 Mar 2008 15:24:53 +0200 Subject: rt2x00: TO_DS filter depends on intf_ap_count The TO_DS filter does not only depend on the FIF_PROMISC_IN_BSS flag provided by mac80211, but also on the intf_ap_count count. This makes sense, since when Master mode is active, we should all frames that are send to the active AP (the device itself). This means that when an interface is added we should force the packet filter to be updated during the next mac80211 call of configure_filter() to make sure the intf_ap_count field is checked. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 3 ++- drivers/net/wireless/rt2x00/rt2500pci.c | 3 ++- drivers/net/wireless/rt2x00/rt2500usb.c | 3 ++- drivers/net/wireless/rt2x00/rt2x00mac.c | 7 +++++++ drivers/net/wireless/rt2x00/rt61pci.c | 3 ++- drivers/net/wireless/rt2x00/rt73usb.c | 3 ++- 6 files changed, 17 insertions(+), 5 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index a6e9c89c802a..9abdfb84697c 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -290,7 +290,8 @@ static void rt2400pci_config_filter(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(®, RXCSR0_DROP_NOT_TO_ME, !(filter_flags & FIF_PROMISC_IN_BSS)); rt2x00_set_field32(®, RXCSR0_DROP_TODS, - !(filter_flags & FIF_PROMISC_IN_BSS)); + !(filter_flags & FIF_PROMISC_IN_BSS) && + !rt2x00dev->intf_ap_count); rt2x00_set_field32(®, RXCSR0_DROP_VERSION_ERROR, 1); rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); } diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 1bdb873b65f2..54c9a75b549b 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -291,7 +291,8 @@ static void rt2500pci_config_filter(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(®, RXCSR0_DROP_NOT_TO_ME, !(filter_flags & FIF_PROMISC_IN_BSS)); rt2x00_set_field32(®, RXCSR0_DROP_TODS, - !(filter_flags & FIF_PROMISC_IN_BSS)); + !(filter_flags & FIF_PROMISC_IN_BSS) && + !rt2x00dev->intf_ap_count); rt2x00_set_field32(®, RXCSR0_DROP_VERSION_ERROR, 1); rt2x00_set_field32(®, RXCSR0_DROP_MCAST, !(filter_flags & FIF_ALLMULTI)); diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index f5c18f011e93..28fdf191e956 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -337,7 +337,8 @@ static void rt2500usb_config_filter(struct rt2x00_dev *rt2x00dev, rt2x00_set_field16(®, TXRX_CSR2_DROP_NOT_TO_ME, !(filter_flags & FIF_PROMISC_IN_BSS)); rt2x00_set_field16(®, TXRX_CSR2_DROP_TODS, - !(filter_flags & FIF_PROMISC_IN_BSS)); + !(filter_flags & FIF_PROMISC_IN_BSS) && + !rt2x00dev->intf_ap_count); rt2x00_set_field16(®, TXRX_CSR2_DROP_VERSION_ERROR, 1); rt2x00_set_field16(®, TXRX_CSR2_DROP_MULTICAST, !(filter_flags & FIF_ALLMULTI)); diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index a0adf5a04aa0..dc70e7aedfff 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -253,6 +253,13 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, */ rt2x00lib_config_intf(rt2x00dev, intf, conf->type, intf->mac, NULL); + /* + * Some filters depend on the current working mode. We can force + * an update during the next configure_filter() run by mac80211 by + * resetting the current packet_filter state. + */ + rt2x00dev->packet_filter = 0; + return 0; } EXPORT_SYMBOL_GPL(rt2x00mac_add_interface); diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 0d2e6f7dd692..c5c625143335 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -342,7 +342,8 @@ static void rt61pci_config_filter(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(®, TXRX_CSR0_DROP_NOT_TO_ME, !(filter_flags & FIF_PROMISC_IN_BSS)); rt2x00_set_field32(®, TXRX_CSR0_DROP_TO_DS, - !(filter_flags & FIF_PROMISC_IN_BSS)); + !(filter_flags & FIF_PROMISC_IN_BSS) && + !rt2x00dev->intf_ap_count); rt2x00_set_field32(®, TXRX_CSR0_DROP_VERSION_ERROR, 1); rt2x00_set_field32(®, TXRX_CSR0_DROP_MULTICAST, !(filter_flags & FIF_ALLMULTI)); diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index b3c846223432..796cf2990b72 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -354,7 +354,8 @@ static void rt73usb_config_filter(struct rt2x00_dev *rt2x00dev, rt2x00_set_field32(®, TXRX_CSR0_DROP_NOT_TO_ME, !(filter_flags & FIF_PROMISC_IN_BSS)); rt2x00_set_field32(®, TXRX_CSR0_DROP_TO_DS, - !(filter_flags & FIF_PROMISC_IN_BSS)); + !(filter_flags & FIF_PROMISC_IN_BSS) && + !rt2x00dev->intf_ap_count); rt2x00_set_field32(®, TXRX_CSR0_DROP_VERSION_ERROR, 1); rt2x00_set_field32(®, TXRX_CSR0_DROP_MULTICAST, !(filter_flags & FIF_ALLMULTI)); -- cgit v1.2.1 From a2e1d52a32eab53f8ab03c4023310f65aaa054a7 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 31 Mar 2008 15:53:44 +0200 Subject: rt2x00: Remove MAC80211_LEDS dependency Implement triggers inside rt2x00 itself based on input from mac80211. This replaces the method of using the mac80211 trigger events which do not work for USB drivers due to the scheduling requirement. After this patch RT2500USB_LEDS and RT73USB_LEDS no longer need to be tagged as broken since they now support LED handling again without having to check for in_atomic(). Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/Kconfig | 14 ++-- drivers/net/wireless/rt2x00/rt2400pci.c | 63 ++++++++------- drivers/net/wireless/rt2x00/rt2500pci.c | 63 ++++++++------- drivers/net/wireless/rt2x00/rt2500usb.c | 85 ++++++++++---------- drivers/net/wireless/rt2x00/rt2x00.h | 5 +- drivers/net/wireless/rt2x00/rt2x00dev.c | 10 ++- drivers/net/wireless/rt2x00/rt2x00leds.c | 131 ++++++++++++++++--------------- drivers/net/wireless/rt2x00/rt2x00leds.h | 21 +---- drivers/net/wireless/rt2x00/rt2x00lib.h | 12 +++ drivers/net/wireless/rt2x00/rt2x00mac.c | 6 ++ drivers/net/wireless/rt2x00/rt61pci.c | 64 +++++++++------ drivers/net/wireless/rt2x00/rt73usb.c | 70 ++++++++++------- 12 files changed, 297 insertions(+), 247 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index ad1549592c00..a1e3938cba9b 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig @@ -38,10 +38,6 @@ config RT2X00_LIB_RFKILL config RT2X00_LIB_LEDS boolean depends on RT2X00_LIB - select NEW_LEDS - select LEDS_CLASS - select LEDS_TRIGGERS - select MAC80211_LEDS config RT2400PCI tristate "Ralink rt2400 pci/pcmcia support" @@ -64,7 +60,7 @@ config RT2400PCI_RFKILL config RT2400PCI_LEDS bool "RT2400 leds support" - depends on RT2400PCI + depends on RT2400PCI && LEDS_CLASS select RT2X00_LIB_LEDS ---help--- This adds support for led triggers provided my mac80211. @@ -90,7 +86,7 @@ config RT2500PCI_RFKILL config RT2500PCI_LEDS bool "RT2500 leds support" - depends on RT2500PCI + depends on RT2500PCI && LEDS_CLASS select RT2X00_LIB_LEDS ---help--- This adds support for led triggers provided my mac80211. @@ -118,7 +114,7 @@ config RT61PCI_RFKILL config RT61PCI_LEDS bool "RT61 leds support" - depends on RT61PCI + depends on RT61PCI && LEDS_CLASS select RT2X00_LIB_LEDS ---help--- This adds support for led triggers provided my mac80211. @@ -134,7 +130,7 @@ config RT2500USB config RT2500USB_LEDS bool "RT2500 leds support" - depends on RT2500USB && BROKEN + depends on RT2500USB && LEDS_CLASS select RT2X00_LIB_LEDS ---help--- This adds support for led triggers provided my mac80211. @@ -152,7 +148,7 @@ config RT73USB config RT73USB_LEDS bool "RT73 leds support" - depends on RT73USB && BROKEN + depends on RT73USB && LEDS_CLASS select RT2X00_LIB_LEDS ---help--- This adds support for led triggers provided my mac80211. diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 9abdfb84697c..b41187af1306 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -244,27 +244,39 @@ static int rt2400pci_rfkill_poll(struct rt2x00_dev *rt2x00dev) #endif /* CONFIG_RT2400PCI_RFKILL */ #ifdef CONFIG_RT2400PCI_LEDS -static void rt2400pci_led_brightness(struct led_classdev *led_cdev, +static void rt2400pci_brightness_set(struct led_classdev *led_cdev, enum led_brightness brightness) { struct rt2x00_led *led = container_of(led_cdev, struct rt2x00_led, led_dev); unsigned int enabled = brightness != LED_OFF; - unsigned int activity = - led->rt2x00dev->led_flags & LED_SUPPORT_ACTIVITY; u32 reg; rt2x00pci_register_read(led->rt2x00dev, LEDCSR, ®); - if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC) { + if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC) rt2x00_set_field32(®, LEDCSR_LINK, enabled); - rt2x00_set_field32(®, LEDCSR_ACTIVITY, enabled && activity); - } + else if (led->type == LED_TYPE_ACTIVITY) + rt2x00_set_field32(®, LEDCSR_ACTIVITY, enabled); rt2x00pci_register_write(led->rt2x00dev, LEDCSR, reg); } -#else -#define rt2400pci_led_brightness NULL + +static int rt2400pci_blink_set(struct led_classdev *led_cdev, + unsigned long *delay_on, + unsigned long *delay_off) +{ + struct rt2x00_led *led = + container_of(led_cdev, struct rt2x00_led, led_dev); + u32 reg; + + rt2x00pci_register_read(led->rt2x00dev, LEDCSR, ®); + rt2x00_set_field32(®, LEDCSR_ON_PERIOD, *delay_on); + rt2x00_set_field32(®, LEDCSR_OFF_PERIOD, *delay_off); + rt2x00pci_register_write(led->rt2x00dev, LEDCSR, reg); + + return 0; +} #endif /* CONFIG_RT2400PCI_LEDS */ /* @@ -719,11 +731,6 @@ static int rt2400pci_init_registers(struct rt2x00_dev *rt2x00dev) (rt2x00dev->rx->data_size / 128)); rt2x00pci_register_write(rt2x00dev, CSR9, reg); - rt2x00pci_register_read(rt2x00dev, LEDCSR, ®); - rt2x00_set_field32(®, LEDCSR_ON_PERIOD, 70); - rt2x00_set_field32(®, LEDCSR_OFF_PERIOD, 30); - rt2x00pci_register_write(rt2x00dev, LEDCSR, reg); - rt2x00pci_register_write(rt2x00dev, CNT3, 0x3f080000); rt2x00pci_register_read(rt2x00dev, ARCSR0, ®); @@ -1291,19 +1298,22 @@ static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev) #ifdef CONFIG_RT2400PCI_LEDS value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE); - switch (value) { - case LED_MODE_ASUS: - case LED_MODE_ALPHA: - case LED_MODE_DEFAULT: - rt2x00dev->led_flags = LED_SUPPORT_RADIO; - break; - case LED_MODE_TXRX_ACTIVITY: - rt2x00dev->led_flags = - LED_SUPPORT_RADIO | LED_SUPPORT_ACTIVITY; - break; - case LED_MODE_SIGNAL_STRENGTH: - rt2x00dev->led_flags = LED_SUPPORT_RADIO; - break; + rt2x00dev->led_radio.rt2x00dev = rt2x00dev; + rt2x00dev->led_radio.type = LED_TYPE_RADIO; + rt2x00dev->led_radio.led_dev.brightness_set = + rt2400pci_brightness_set; + rt2x00dev->led_radio.led_dev.blink_set = + rt2400pci_blink_set; + rt2x00dev->led_radio.flags = LED_INITIALIZED; + + if (value == LED_MODE_TXRX_ACTIVITY) { + rt2x00dev->led_qual.rt2x00dev = rt2x00dev; + rt2x00dev->led_radio.type = LED_TYPE_ACTIVITY; + rt2x00dev->led_qual.led_dev.brightness_set = + rt2400pci_brightness_set; + rt2x00dev->led_qual.led_dev.blink_set = + rt2400pci_blink_set; + rt2x00dev->led_qual.flags = LED_INITIALIZED; } #endif /* CONFIG_RT2400PCI_LEDS */ @@ -1569,7 +1579,6 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { .link_stats = rt2400pci_link_stats, .reset_tuner = rt2400pci_reset_tuner, .link_tuner = rt2400pci_link_tuner, - .led_brightness = rt2400pci_led_brightness, .write_tx_desc = rt2400pci_write_tx_desc, .write_tx_data = rt2x00pci_write_tx_data, .kick_tx_queue = rt2400pci_kick_tx_queue, diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 54c9a75b549b..5ade097ed45e 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -244,27 +244,39 @@ static int rt2500pci_rfkill_poll(struct rt2x00_dev *rt2x00dev) #endif /* CONFIG_RT2500PCI_RFKILL */ #ifdef CONFIG_RT2500PCI_LEDS -static void rt2500pci_led_brightness(struct led_classdev *led_cdev, +static void rt2500pci_brightness_set(struct led_classdev *led_cdev, enum led_brightness brightness) { struct rt2x00_led *led = container_of(led_cdev, struct rt2x00_led, led_dev); unsigned int enabled = brightness != LED_OFF; - unsigned int activity = - led->rt2x00dev->led_flags & LED_SUPPORT_ACTIVITY; u32 reg; rt2x00pci_register_read(led->rt2x00dev, LEDCSR, ®); - if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC) { + if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC) rt2x00_set_field32(®, LEDCSR_LINK, enabled); - rt2x00_set_field32(®, LEDCSR_ACTIVITY, enabled && activity); - } + else if (led->type == LED_TYPE_ACTIVITY) + rt2x00_set_field32(®, LEDCSR_ACTIVITY, enabled); rt2x00pci_register_write(led->rt2x00dev, LEDCSR, reg); } -#else -#define rt2500pci_led_brightness NULL + +static int rt2500pci_blink_set(struct led_classdev *led_cdev, + unsigned long *delay_on, + unsigned long *delay_off) +{ + struct rt2x00_led *led = + container_of(led_cdev, struct rt2x00_led, led_dev); + u32 reg; + + rt2x00pci_register_read(led->rt2x00dev, LEDCSR, ®); + rt2x00_set_field32(®, LEDCSR_ON_PERIOD, *delay_on); + rt2x00_set_field32(®, LEDCSR_OFF_PERIOD, *delay_off); + rt2x00pci_register_write(led->rt2x00dev, LEDCSR, reg); + + return 0; +} #endif /* CONFIG_RT2500PCI_LEDS */ /* @@ -812,11 +824,6 @@ static int rt2500pci_init_registers(struct rt2x00_dev *rt2x00dev) rt2x00_set_field32(®, CSR11_CW_SELECT, 0); rt2x00pci_register_write(rt2x00dev, CSR11, reg); - rt2x00pci_register_read(rt2x00dev, LEDCSR, ®); - rt2x00_set_field32(®, LEDCSR_ON_PERIOD, 70); - rt2x00_set_field32(®, LEDCSR_OFF_PERIOD, 30); - rt2x00pci_register_write(rt2x00dev, LEDCSR, reg); - rt2x00pci_register_write(rt2x00dev, CNT3, 0); rt2x00pci_register_read(rt2x00dev, TXCSR8, ®); @@ -1468,19 +1475,22 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev) #ifdef CONFIG_RT2500PCI_LEDS value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE); - switch (value) { - case LED_MODE_ASUS: - case LED_MODE_ALPHA: - case LED_MODE_DEFAULT: - rt2x00dev->led_flags = LED_SUPPORT_RADIO; - break; - case LED_MODE_TXRX_ACTIVITY: - rt2x00dev->led_flags = - LED_SUPPORT_RADIO | LED_SUPPORT_ACTIVITY; - break; - case LED_MODE_SIGNAL_STRENGTH: - rt2x00dev->led_flags = LED_SUPPORT_RADIO; - break; + rt2x00dev->led_radio.rt2x00dev = rt2x00dev; + rt2x00dev->led_radio.type = LED_TYPE_RADIO; + rt2x00dev->led_radio.led_dev.brightness_set = + rt2500pci_brightness_set; + rt2x00dev->led_radio.led_dev.blink_set = + rt2500pci_blink_set; + rt2x00dev->led_radio.flags = LED_INITIALIZED; + + if (value == LED_MODE_TXRX_ACTIVITY) { + rt2x00dev->led_qual.rt2x00dev = rt2x00dev; + rt2x00dev->led_radio.type = LED_TYPE_ACTIVITY; + rt2x00dev->led_qual.led_dev.brightness_set = + rt2500pci_brightness_set; + rt2x00dev->led_qual.led_dev.blink_set = + rt2500pci_blink_set; + rt2x00dev->led_qual.flags = LED_INITIALIZED; } #endif /* CONFIG_RT2500PCI_LEDS */ @@ -1882,7 +1892,6 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = { .link_stats = rt2500pci_link_stats, .reset_tuner = rt2500pci_reset_tuner, .link_tuner = rt2500pci_link_tuner, - .led_brightness = rt2500pci_led_brightness, .write_tx_desc = rt2500pci_write_tx_desc, .write_tx_data = rt2x00pci_write_tx_data, .kick_tx_queue = rt2500pci_kick_tx_queue, diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 28fdf191e956..6bb07b339325 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -283,34 +283,39 @@ static const struct rt2x00debug rt2500usb_rt2x00debug = { #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ #ifdef CONFIG_RT2500USB_LEDS -static void rt2500usb_led_brightness(struct led_classdev *led_cdev, +static void rt2500usb_brightness_set(struct led_classdev *led_cdev, enum led_brightness brightness) { struct rt2x00_led *led = container_of(led_cdev, struct rt2x00_led, led_dev); unsigned int enabled = brightness != LED_OFF; - unsigned int activity = - led->rt2x00dev->led_flags & LED_SUPPORT_ACTIVITY; + u16 reg; - if (in_atomic()) { - NOTICE(led->rt2x00dev, - "Ignoring LED brightness command for led %d\n", - led->type); - return; - } + rt2500usb_register_read(led->rt2x00dev, MAC_CSR20, ®); - if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC) { - rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg, - MAC_CSR20_LINK, enabled); - rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg, - MAC_CSR20_ACTIVITY, enabled && activity); - } + if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC) + rt2x00_set_field16(®, MAC_CSR20_LINK, enabled); + else if (led->type == LED_TYPE_ACTIVITY) + rt2x00_set_field16(®, MAC_CSR20_ACTIVITY, enabled); + + rt2500usb_register_write(led->rt2x00dev, MAC_CSR20, reg); +} + +static int rt2500usb_blink_set(struct led_classdev *led_cdev, + unsigned long *delay_on, + unsigned long *delay_off) +{ + struct rt2x00_led *led = + container_of(led_cdev, struct rt2x00_led, led_dev); + u16 reg; + + rt2500usb_register_read(led->rt2x00dev, MAC_CSR21, ®); + rt2x00_set_field16(®, MAC_CSR21_ON_PERIOD, *delay_on); + rt2x00_set_field16(®, MAC_CSR21_OFF_PERIOD, *delay_off); + rt2500usb_register_write(led->rt2x00dev, MAC_CSR21, reg); - rt2500usb_register_write(led->rt2x00dev, MAC_CSR20, - led->rt2x00dev->led_mcu_reg); + return 0; } -#else -#define rt2500usb_led_brightness NULL #endif /* CONFIG_RT2500USB_LEDS */ /* @@ -762,11 +767,6 @@ static int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev) rt2x00_set_field16(®, MAC_CSR1_HOST_READY, 0); rt2500usb_register_write(rt2x00dev, MAC_CSR1, reg); - rt2500usb_register_read(rt2x00dev, MAC_CSR21, ®); - rt2x00_set_field16(®, MAC_CSR21_ON_PERIOD, 70); - rt2x00_set_field16(®, MAC_CSR21_OFF_PERIOD, 30); - rt2500usb_register_write(rt2x00dev, MAC_CSR21, reg); - rt2500usb_register_read(rt2x00dev, TXRX_CSR5, ®); rt2x00_set_field16(®, TXRX_CSR5_BBP_ID0, 13); rt2x00_set_field16(®, TXRX_CSR5_BBP_ID0_VALID, 1); @@ -1384,27 +1384,23 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev) #ifdef CONFIG_RT2500USB_LEDS value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE); - switch (value) { - case LED_MODE_ASUS: - case LED_MODE_ALPHA: - case LED_MODE_DEFAULT: - rt2x00dev->led_flags = LED_SUPPORT_RADIO; - break; - case LED_MODE_TXRX_ACTIVITY: - rt2x00dev->led_flags = - LED_SUPPORT_RADIO | LED_SUPPORT_ACTIVITY; - break; - case LED_MODE_SIGNAL_STRENGTH: - rt2x00dev->led_flags = LED_SUPPORT_RADIO; - break; + rt2x00dev->led_radio.rt2x00dev = rt2x00dev; + rt2x00dev->led_radio.type = LED_TYPE_RADIO; + rt2x00dev->led_radio.led_dev.brightness_set = + rt2500usb_brightness_set; + rt2x00dev->led_radio.led_dev.blink_set = + rt2500usb_blink_set; + rt2x00dev->led_radio.flags = LED_INITIALIZED; + + if (value == LED_MODE_TXRX_ACTIVITY) { + rt2x00dev->led_qual.rt2x00dev = rt2x00dev; + rt2x00dev->led_radio.type = LED_TYPE_ACTIVITY; + rt2x00dev->led_qual.led_dev.brightness_set = + rt2500usb_brightness_set; + rt2x00dev->led_qual.led_dev.blink_set = + rt2500usb_blink_set; + rt2x00dev->led_qual.flags = LED_INITIALIZED; } - - /* - * Store the current led register value, we need it later - * in set_brightness but that is called in irq context which - * means we can't use rt2500usb_register_read() at that time. - */ - rt2500usb_register_read(rt2x00dev, MAC_CSR20, &rt2x00dev->led_mcu_reg); #endif /* CONFIG_RT2500USB_LEDS */ /* @@ -1792,7 +1788,6 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { .link_stats = rt2500usb_link_stats, .reset_tuner = rt2500usb_reset_tuner, .link_tuner = rt2500usb_link_tuner, - .led_brightness = rt2500usb_led_brightness, .write_tx_desc = rt2500usb_write_tx_desc, .write_tx_data = rt2x00usb_write_tx_data, .get_tx_data_len = rt2500usb_get_tx_data_len, diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 30f9f3afdaef..57bdc153952f 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -385,6 +385,7 @@ struct rt2x00_intf { unsigned int delayed_flags; #define DELAYED_UPDATE_BEACON 0x00000001 #define DELAYED_CONFIG_ERP 0x00000002 +#define DELAYED_LED_ASSOC 0x00000004 }; static inline struct rt2x00_intf* vif_to_intf(struct ieee80211_vif *vif) @@ -533,8 +534,6 @@ struct rt2x00lib_ops { struct link_qual *qual); void (*reset_tuner) (struct rt2x00_dev *rt2x00dev); void (*link_tuner) (struct rt2x00_dev *rt2x00dev); - void (*led_brightness) (struct led_classdev *led_cdev, - enum led_brightness brightness); /* * TX control handlers @@ -694,8 +693,6 @@ struct rt2x00_dev { * by mac8011 or the kernel. */ #ifdef CONFIG_RT2X00_LIB_LEDS - unsigned int led_flags; - struct rt2x00_trigger trigger_qual; struct rt2x00_led led_radio; struct rt2x00_led led_assoc; struct rt2x00_led led_qual; diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index d2c096708e8c..62b58a6261fe 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -108,11 +108,13 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev) /* * Enable radio. */ - status = rt2x00dev->ops->lib->set_device_state(rt2x00dev, - STATE_RADIO_ON); + status = + rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_ON); if (status) return status; + rt2x00leds_led_radio(rt2x00dev, true); + __set_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags); /* @@ -155,6 +157,7 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev) * Disable radio. */ rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_OFF); + rt2x00leds_led_radio(rt2x00dev, false); } void rt2x00lib_toggle_rx(struct rt2x00_dev *rt2x00dev, enum dev_state state) @@ -449,6 +452,9 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac, if (delayed_flags & DELAYED_CONFIG_ERP) rt2x00lib_config_erp(rt2x00dev, intf, &intf->conf); + + if (delayed_flags & DELAYED_LED_ASSOC) + rt2x00leds_led_assoc(rt2x00dev, !!rt2x00dev->intf_associated); } static void rt2x00lib_intf_scheduled(struct work_struct *work) diff --git a/drivers/net/wireless/rt2x00/rt2x00leds.c b/drivers/net/wireless/rt2x00/rt2x00leds.c index ca2d282a9f75..40c1f5c1b805 100644 --- a/drivers/net/wireless/rt2x00/rt2x00leds.c +++ b/drivers/net/wireless/rt2x00/rt2x00leds.c @@ -31,7 +31,10 @@ void rt2x00leds_led_quality(struct rt2x00_dev *rt2x00dev, int rssi) { - if (!rt2x00dev->trigger_qual.registered) + struct rt2x00_led *led = &rt2x00dev->led_qual; + unsigned int brightness; + + if ((led->type != LED_TYPE_QUALITY) || !(led->flags & LED_REGISTERED)) return; /* @@ -62,39 +65,51 @@ void rt2x00leds_led_quality(struct rt2x00_dev *rt2x00dev, int rssi) * is going to calculate the value and might use it in a * division. */ - led_trigger_event(&rt2x00dev->trigger_qual.trigger, - ((LED_FULL / 6) * rssi) + 1); + brightness = ((LED_FULL / 6) * rssi) + 1; + if (brightness != led->led_dev.brightness) { + led->led_dev.brightness_set(&led->led_dev, brightness); + led->led_dev.brightness = brightness; + } } -static int rt2x00leds_register_trigger(struct rt2x00_dev *rt2x00dev, - struct rt2x00_trigger *trigger, - const char *name) +void rt2x00leds_led_assoc(struct rt2x00_dev *rt2x00dev, bool enabled) { - int retval; + struct rt2x00_led *led = &rt2x00dev->led_assoc; + unsigned int brightness; - trigger->trigger.name = name; - retval = led_trigger_register(&trigger->trigger); - if (retval) { - ERROR(rt2x00dev, "Failed to register led trigger.\n"); - return retval; + if ((led->type != LED_TYPE_ASSOC) || !(led->flags & LED_REGISTERED)) + return; + + brightness = enabled ? LED_FULL : LED_OFF; + if (brightness != led->led_dev.brightness) { + led->led_dev.brightness_set(&led->led_dev, brightness); + led->led_dev.brightness = brightness; } +} - trigger->registered = 1; +void rt2x00leds_led_radio(struct rt2x00_dev *rt2x00dev, bool enabled) +{ + struct rt2x00_led *led = &rt2x00dev->led_radio; + unsigned int brightness; - return 0; + if ((led->type != LED_TYPE_RADIO) || !(led->flags & LED_REGISTERED)) + return; + + brightness = enabled ? LED_FULL : LED_OFF; + if (brightness != led->led_dev.brightness) { + led->led_dev.brightness_set(&led->led_dev, brightness); + led->led_dev.brightness = brightness; + } } static int rt2x00leds_register_led(struct rt2x00_dev *rt2x00dev, struct rt2x00_led *led, - enum led_type type, - const char *name, char *trigger) + const char *name) { struct device *device = wiphy_dev(rt2x00dev->hw->wiphy); int retval; led->led_dev.name = name; - led->led_dev.brightness_set = rt2x00dev->ops->lib->led_brightness; - led->led_dev.default_trigger = trigger; retval = led_classdev_register(device, &led->led_dev); if (retval) { @@ -102,115 +117,103 @@ static int rt2x00leds_register_led(struct rt2x00_dev *rt2x00dev, return retval; } - led->rt2x00dev = rt2x00dev; - led->type = type; - led->registered = 1; + led->flags |= LED_REGISTERED; return 0; } void rt2x00leds_register(struct rt2x00_dev *rt2x00dev) { - char *trigger; char dev_name[16]; char name[32]; int retval; - - if (!rt2x00dev->ops->lib->led_brightness) - return; + unsigned long on_period; + unsigned long off_period; snprintf(dev_name, sizeof(dev_name), "%s-%s", rt2x00dev->ops->name, wiphy_name(rt2x00dev->hw->wiphy)); - if (rt2x00dev->led_flags & LED_SUPPORT_RADIO) { - trigger = ieee80211_get_radio_led_name(rt2x00dev->hw); + if (rt2x00dev->led_radio.flags & LED_INITIALIZED) { snprintf(name, sizeof(name), "%s:radio", dev_name); retval = rt2x00leds_register_led(rt2x00dev, &rt2x00dev->led_radio, - LED_TYPE_RADIO, - name, trigger); + name); if (retval) goto exit_fail; } - if (rt2x00dev->led_flags & LED_SUPPORT_ASSOC) { - trigger = ieee80211_get_assoc_led_name(rt2x00dev->hw); + if (rt2x00dev->led_assoc.flags & LED_INITIALIZED) { snprintf(name, sizeof(name), "%s:assoc", dev_name); retval = rt2x00leds_register_led(rt2x00dev, &rt2x00dev->led_assoc, - LED_TYPE_ASSOC, - name, trigger); + name); if (retval) goto exit_fail; } - if (rt2x00dev->led_flags & LED_SUPPORT_QUALITY) { + if (rt2x00dev->led_qual.flags & LED_INITIALIZED) { snprintf(name, sizeof(name), "%s:quality", dev_name); - retval = rt2x00leds_register_trigger(rt2x00dev, - &rt2x00dev->trigger_qual, - name); - retval = rt2x00leds_register_led(rt2x00dev, &rt2x00dev->led_qual, - LED_TYPE_QUALITY, - name, name); + name); if (retval) goto exit_fail; } + /* + * Initialize blink time to default value: + * On period: 70ms + * Off period: 30ms + */ + if (rt2x00dev->led_radio.led_dev.blink_set) { + on_period = 70; + off_period = 30; + rt2x00dev->led_radio.led_dev.blink_set( + &rt2x00dev->led_radio.led_dev, &on_period, &off_period); + } + return; exit_fail: rt2x00leds_unregister(rt2x00dev); } -static void rt2x00leds_unregister_trigger(struct rt2x00_trigger *trigger) -{ - if (!trigger->registered) - return; - - led_trigger_unregister(&trigger->trigger); - trigger->registered = 0; -} - static void rt2x00leds_unregister_led(struct rt2x00_led *led) { - if (!led->registered) - return; - led_classdev_unregister(&led->led_dev); - led->led_dev.brightness_set(&led->led_dev, LED_OFF); - led->registered = 0; + led->flags &= ~LED_REGISTERED; } void rt2x00leds_unregister(struct rt2x00_dev *rt2x00dev) { - rt2x00leds_unregister_trigger(&rt2x00dev->trigger_qual); - rt2x00leds_unregister_led(&rt2x00dev->led_qual); - rt2x00leds_unregister_led(&rt2x00dev->led_assoc); - rt2x00leds_unregister_led(&rt2x00dev->led_radio); + if (rt2x00dev->led_qual.flags & LED_REGISTERED) + rt2x00leds_unregister_led(&rt2x00dev->led_qual); + if (rt2x00dev->led_assoc.flags & LED_REGISTERED) + rt2x00leds_unregister_led(&rt2x00dev->led_assoc); + if (rt2x00dev->led_radio.flags & LED_REGISTERED) + rt2x00leds_unregister_led(&rt2x00dev->led_radio); } void rt2x00leds_suspend(struct rt2x00_dev *rt2x00dev) { - if (rt2x00dev->led_qual.registered) + if (rt2x00dev->led_qual.flags & LED_REGISTERED) led_classdev_suspend(&rt2x00dev->led_qual.led_dev); - if (rt2x00dev->led_assoc.registered) + if (rt2x00dev->led_assoc.flags & LED_REGISTERED) led_classdev_suspend(&rt2x00dev->led_assoc.led_dev); - if (rt2x00dev->led_radio.registered) + if (rt2x00dev->led_radio.flags & LED_REGISTERED) led_classdev_suspend(&rt2x00dev->led_radio.led_dev); } void rt2x00leds_resume(struct rt2x00_dev *rt2x00dev) { - if (rt2x00dev->led_radio.registered) + if (rt2x00dev->led_radio.flags & LED_REGISTERED) led_classdev_resume(&rt2x00dev->led_radio.led_dev); - if (rt2x00dev->led_assoc.registered) + if (rt2x00dev->led_assoc.flags & LED_REGISTERED) led_classdev_resume(&rt2x00dev->led_assoc.led_dev); - if (rt2x00dev->led_qual.registered) + if (rt2x00dev->led_qual.flags & LED_REGISTERED) led_classdev_resume(&rt2x00dev->led_qual.led_dev); } diff --git a/drivers/net/wireless/rt2x00/rt2x00leds.h b/drivers/net/wireless/rt2x00/rt2x00leds.h index 11e71e9ce853..9df4a49bdcad 100644 --- a/drivers/net/wireless/rt2x00/rt2x00leds.h +++ b/drivers/net/wireless/rt2x00/rt2x00leds.h @@ -26,18 +26,10 @@ #ifndef RT2X00LEDS_H #define RT2X00LEDS_H -/* -* Flags used by driver to indicate which - * which led types are supported. - */ -#define LED_SUPPORT_RADIO 0x000001 -#define LED_SUPPORT_ASSOC 0x000002 -#define LED_SUPPORT_ACTIVITY 0x000004 -#define LED_SUPPORT_QUALITY 0x000008 - enum led_type { LED_TYPE_RADIO, LED_TYPE_ASSOC, + LED_TYPE_ACTIVITY, LED_TYPE_QUALITY, }; @@ -48,14 +40,9 @@ struct rt2x00_led { struct led_classdev led_dev; enum led_type type; - unsigned int registered; -}; - -struct rt2x00_trigger { - struct led_trigger trigger; - - enum led_type type; - unsigned int registered; + unsigned int flags; +#define LED_INITIALIZED ( 1 << 0 ) +#define LED_REGISTERED ( 1 << 1 ) }; #endif /* CONFIG_RT2X00_LIB_LEDS */ diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index 64fae7e3f73b..5be32fffc74c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -185,6 +185,8 @@ static inline void rt2x00rfkill_resume(struct rt2x00_dev *rt2x00dev) */ #ifdef CONFIG_RT2X00_LIB_LEDS void rt2x00leds_led_quality(struct rt2x00_dev *rt2x00dev, int rssi); +void rt2x00leds_led_assoc(struct rt2x00_dev *rt2x00dev, bool enabled); +void rt2x00leds_led_radio(struct rt2x00_dev *rt2x00dev, bool enabled); void rt2x00leds_register(struct rt2x00_dev *rt2x00dev); void rt2x00leds_unregister(struct rt2x00_dev *rt2x00dev); void rt2x00leds_suspend(struct rt2x00_dev *rt2x00dev); @@ -195,6 +197,16 @@ static inline void rt2x00leds_led_quality(struct rt2x00_dev *rt2x00dev, { } +static inline void rt2x00leds_led_assoc(struct rt2x00_dev *rt2x00dev, + bool enabled) +{ +} + +static inline void rt2x00leds_led_radio(struct rt2x00_dev *rt2x00dev, + bool enabled) +{ +} + static inline void rt2x00leds_register(struct rt2x00_dev *rt2x00dev) { } diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index dc70e7aedfff..c206b5092070 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -485,6 +485,12 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, rt2x00dev->intf_associated++; else rt2x00dev->intf_associated--; + + if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags)) + rt2x00leds_led_assoc(rt2x00dev, + !!rt2x00dev->intf_associated); + else + delayed |= DELAYED_LED_ASSOC; } /* diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index c5c625143335..1cb056be4489 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -277,7 +277,7 @@ static int rt61pci_rfkill_poll(struct rt2x00_dev *rt2x00dev) #endif /* CONFIG_RT61PCI_RFKILL */ #ifdef CONFIG_RT61PCI_LEDS -static void rt61pci_led_brightness(struct led_classdev *led_cdev, +static void rt61pci_brightness_set(struct led_classdev *led_cdev, enum led_brightness brightness) { struct rt2x00_led *led = @@ -314,8 +314,22 @@ static void rt61pci_led_brightness(struct led_classdev *led_cdev, brightness / (LED_FULL / 6), 0); } } -#else -#define rt61pci_led_brightness NULL + +static int rt61pci_blink_set(struct led_classdev *led_cdev, + unsigned long *delay_on, + unsigned long *delay_off) +{ + struct rt2x00_led *led = + container_of(led_cdev, struct rt2x00_led, led_dev); + u32 reg; + + rt2x00pci_register_read(led->rt2x00dev, MAC_CSR14, ®); + rt2x00_set_field32(®, MAC_CSR14_ON_PERIOD, *delay_on); + rt2x00_set_field32(®, MAC_CSR14_OFF_PERIOD, *delay_off); + rt2x00pci_register_write(led->rt2x00dev, MAC_CSR14, reg); + + return 0; +} #endif /* CONFIG_RT61PCI_LEDS */ /* @@ -1202,11 +1216,6 @@ static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev) rt2x00pci_register_write(rt2x00dev, MAC_CSR13, 0x0000e000); - rt2x00pci_register_read(rt2x00dev, MAC_CSR14, ®); - rt2x00_set_field32(®, MAC_CSR14_ON_PERIOD, 70); - rt2x00_set_field32(®, MAC_CSR14_OFF_PERIOD, 30); - rt2x00pci_register_write(rt2x00dev, MAC_CSR14, reg); - /* * Invalidate all Shared Keys (SEC_CSR0), * and clear the Shared key Cipher algorithms (SEC_CSR1 & SEC_CSR5) @@ -2058,22 +2067,32 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev) */ #ifdef CONFIG_RT61PCI_LEDS rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &eeprom); - value = rt2x00_get_field16(eeprom, EEPROM_LED_LED_MODE); - switch (value) { - case LED_MODE_TXRX_ACTIVITY: - case LED_MODE_ASUS: - case LED_MODE_ALPHA: - case LED_MODE_DEFAULT: - rt2x00dev->led_flags = - LED_SUPPORT_RADIO | LED_SUPPORT_ASSOC; - break; - case LED_MODE_SIGNAL_STRENGTH: - rt2x00dev->led_flags = - LED_SUPPORT_RADIO | LED_SUPPORT_ASSOC | - LED_SUPPORT_QUALITY; - break; + rt2x00dev->led_radio.rt2x00dev = rt2x00dev; + rt2x00dev->led_radio.type = LED_TYPE_RADIO; + rt2x00dev->led_radio.led_dev.brightness_set = + rt61pci_brightness_set; + rt2x00dev->led_radio.led_dev.blink_set = + rt61pci_blink_set; + rt2x00dev->led_radio.flags = LED_INITIALIZED; + + rt2x00dev->led_assoc.rt2x00dev = rt2x00dev; + rt2x00dev->led_assoc.type = LED_TYPE_ASSOC; + rt2x00dev->led_assoc.led_dev.brightness_set = + rt61pci_brightness_set; + rt2x00dev->led_assoc.led_dev.blink_set = + rt61pci_blink_set; + rt2x00dev->led_assoc.flags = LED_INITIALIZED; + + if (value == LED_MODE_SIGNAL_STRENGTH) { + rt2x00dev->led_qual.rt2x00dev = rt2x00dev; + rt2x00dev->led_radio.type = LED_TYPE_QUALITY; + rt2x00dev->led_qual.led_dev.brightness_set = + rt61pci_brightness_set; + rt2x00dev->led_qual.led_dev.blink_set = + rt61pci_blink_set; + rt2x00dev->led_qual.flags = LED_INITIALIZED; } rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_LED_MODE, value); @@ -2447,7 +2466,6 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { .link_stats = rt61pci_link_stats, .reset_tuner = rt61pci_reset_tuner, .link_tuner = rt61pci_link_tuner, - .led_brightness = rt61pci_led_brightness, .write_tx_desc = rt61pci_write_tx_desc, .write_tx_data = rt2x00pci_write_tx_data, .kick_tx_queue = rt61pci_kick_tx_queue, diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 796cf2990b72..a9efe25f1ea7 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -280,7 +280,7 @@ static const struct rt2x00debug rt73usb_rt2x00debug = { #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ #ifdef CONFIG_RT73USB_LEDS -static void rt73usb_led_brightness(struct led_classdev *led_cdev, +static void rt73usb_brightness_set(struct led_classdev *led_cdev, enum led_brightness brightness) { struct rt2x00_led *led = @@ -291,13 +291,6 @@ static void rt73usb_led_brightness(struct led_classdev *led_cdev, unsigned int bg_mode = (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_2GHZ); - if (in_atomic()) { - NOTICE(led->rt2x00dev, - "Ignoring LED brightness command for led %d\n", - led->type); - return; - } - if (led->type == LED_TYPE_RADIO) { rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg, MCU_LEDCS_RADIO_STATUS, enabled); @@ -326,8 +319,22 @@ static void rt73usb_led_brightness(struct led_classdev *led_cdev, REGISTER_TIMEOUT); } } -#else -#define rt73usb_led_brightness NULL + +static int rt73usb_blink_set(struct led_classdev *led_cdev, + unsigned long *delay_on, + unsigned long *delay_off) +{ + struct rt2x00_led *led = + container_of(led_cdev, struct rt2x00_led, led_dev); + u32 reg; + + rt73usb_register_read(led->rt2x00dev, MAC_CSR14, ®); + rt2x00_set_field32(®, MAC_CSR14_ON_PERIOD, *delay_on); + rt2x00_set_field32(®, MAC_CSR14_OFF_PERIOD, *delay_off); + rt73usb_register_write(led->rt2x00dev, MAC_CSR14, reg); + + return 0; +} #endif /* CONFIG_RT73USB_LEDS */ /* @@ -1006,11 +1013,6 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev) rt73usb_register_write(rt2x00dev, MAC_CSR13, 0x00007f00); - rt73usb_register_read(rt2x00dev, MAC_CSR14, ®); - rt2x00_set_field32(®, MAC_CSR14_ON_PERIOD, 70); - rt2x00_set_field32(®, MAC_CSR14_OFF_PERIOD, 30); - rt73usb_register_write(rt2x00dev, MAC_CSR14, reg); - /* * Invalidate all Shared Keys (SEC_CSR0), * and clear the Shared key Cipher algorithms (SEC_CSR1 & SEC_CSR5) @@ -1627,19 +1629,30 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev) #ifdef CONFIG_RT73USB_LEDS rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &eeprom); - switch (value) { - case LED_MODE_TXRX_ACTIVITY: - case LED_MODE_ASUS: - case LED_MODE_ALPHA: - case LED_MODE_DEFAULT: - rt2x00dev->led_flags = - LED_SUPPORT_RADIO | LED_SUPPORT_ASSOC; - break; - case LED_MODE_SIGNAL_STRENGTH: - rt2x00dev->led_flags = - LED_SUPPORT_RADIO | LED_SUPPORT_ASSOC | - LED_SUPPORT_QUALITY; - break; + rt2x00dev->led_radio.rt2x00dev = rt2x00dev; + rt2x00dev->led_radio.type = LED_TYPE_RADIO; + rt2x00dev->led_radio.led_dev.brightness_set = + rt73usb_brightness_set; + rt2x00dev->led_radio.led_dev.blink_set = + rt73usb_blink_set; + rt2x00dev->led_radio.flags = LED_INITIALIZED; + + rt2x00dev->led_assoc.rt2x00dev = rt2x00dev; + rt2x00dev->led_assoc.type = LED_TYPE_ASSOC; + rt2x00dev->led_assoc.led_dev.brightness_set = + rt73usb_brightness_set; + rt2x00dev->led_assoc.led_dev.blink_set = + rt73usb_blink_set; + rt2x00dev->led_assoc.flags = LED_INITIALIZED; + + if (value == LED_MODE_SIGNAL_STRENGTH) { + rt2x00dev->led_qual.rt2x00dev = rt2x00dev; + rt2x00dev->led_radio.type = LED_TYPE_QUALITY; + rt2x00dev->led_qual.led_dev.brightness_set = + rt73usb_brightness_set; + rt2x00dev->led_qual.led_dev.blink_set = + rt73usb_blink_set; + rt2x00dev->led_qual.flags = LED_INITIALIZED; } rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_LED_MODE, value); @@ -2040,7 +2053,6 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { .link_stats = rt73usb_link_stats, .reset_tuner = rt73usb_reset_tuner, .link_tuner = rt73usb_link_tuner, - .led_brightness = rt73usb_led_brightness, .write_tx_desc = rt73usb_write_tx_desc, .write_tx_data = rt2x00usb_write_tx_data, .get_tx_data_len = rt73usb_get_tx_data_len, -- cgit v1.2.1 From 06501d29ada4457349f4f4427bbf0bbb7c59b8f6 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Tue, 1 Apr 2008 17:38:47 -0400 Subject: wireless: fix various printk warnings on ia64 (and others) drivers/net/wireless/ath5k/base.c: In function `ath5k_check_ibss_tsf': drivers/net/wireless/ath5k/base.c:1740: warning: long long unsigned int format, u64 arg (arg 5) drivers/net/wireless/ath5k/base.c:1740: warning: long long unsigned int format, u64 arg (arg 6) drivers/net/wireless/ath5k/base.c:1740: warning: long long int format, u64 arg (arg 7) drivers/net/wireless/ath5k/base.c:1740: warning: long long unsigned int format, u64 arg (arg 8) drivers/net/wireless/ath5k/base.c:1757: warning: long long unsigned int format, u64 arg (arg 5) drivers/net/wireless/ath5k/base.c:1757: warning: long long unsigned int format, u64 arg (arg 6) drivers/net/wireless/iwlwifi/iwl4965-base.c: In function `iwl4965_tx_status_reply_tx': drivers/net/wireless/iwlwifi/iwl4965-base.c:3105: warning: long long unsigned int format, u64 arg (arg 6) drivers/net/wireless/iwlwifi/iwl-4965.c: In function `iwl4965_rx_reply_rx': drivers/net/wireless/iwlwifi/iwl-4965.c:3978: warning: long long unsigned int format, u64 arg (arg 7) Cc: Andrew Morton Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/base.c | 9 ++++++--- drivers/net/wireless/iwlwifi/iwl-4965.c | 2 +- drivers/net/wireless/iwlwifi/iwl4965-base.c | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index b5c0a0d7a81c..8862d245c82b 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -1739,8 +1739,10 @@ ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb, ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "beacon %llx mactime %llx (diff %lld) tsf now %llx\n", - bc_tstamp, rxs->mactime, - (rxs->mactime - bc_tstamp), tsf); + (unsigned long long)bc_tstamp, + (unsigned long long)rxs->mactime, + (unsigned long long)(rxs->mactime - bc_tstamp), + (unsigned long long)tsf); /* * Sometimes the HW will give us a wrong tstamp in the rx @@ -1756,7 +1758,8 @@ ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb, if (bc_tstamp > rxs->mactime) { ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "fixing mactime from %llx to %llx\n", - rxs->mactime, tsf); + (unsigned long long)rxs->mactime, + (unsigned long long)tsf); rxs->mactime = tsf; } diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 51a144914cfa..89d600cfb846 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -3971,7 +3971,7 @@ static void iwl4965_rx_reply_rx(struct iwl_priv *priv, IWL_DEBUG_STATS_LIMIT("Rssi %d, noise %d, qual %d, TSF %llu\n", rx_status.ssi, rx_status.noise, rx_status.signal, - rx_status.mactime); + (unsigned long long)rx_status.mactime); network_packet = iwl4965_is_network_packet(priv, header); if (network_packet) { diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index e98695f7f14c..8d49ff4bd4db 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -3119,7 +3119,7 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv, agg->rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags); IWL_DEBUG_TX_REPLY("Frames %d start_idx=%d bitmap=0x%llx\n", agg->frame_count, agg->start_idx, - agg->bitmap); + (unsigned long long)agg->bitmap); if (bitmap) agg->wait_for_ba = 1; -- cgit v1.2.1 From 98952d5decf8195b2cbb96d47572278335a8a8d8 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Fri, 28 Mar 2008 16:33:33 -0700 Subject: iwlwifi: eliminate conf_ht This patch eliminates the use of conf_ht in iwlwifi driver, replacing it with bss_info_changed. Signed-off-by: Tomas Winkler Signed-off-by: Ron Rindjunsky Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl4965-base.c | 146 ++++++++++++---------------- 1 file changed, 63 insertions(+), 83 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 8d49ff4bd4db..826c912aea9a 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -6941,6 +6941,64 @@ static void iwl4965_mac_remove_interface(struct ieee80211_hw *hw, } + +#ifdef CONFIG_IWL4965_HT +static void iwl4965_ht_conf(struct iwl_priv *priv, + struct ieee80211_bss_conf *bss_conf) +{ + struct ieee80211_ht_info *ht_conf = bss_conf->ht_conf; + struct ieee80211_ht_bss_info *ht_bss_conf = bss_conf->ht_bss_conf; + struct iwl_ht_info *iwl_conf = &priv->current_ht_config; + + IWL_DEBUG_MAC80211("enter: \n"); + + iwl_conf->is_ht = bss_conf->assoc_ht; + + if (!iwl_conf->is_ht) + return; + + priv->ps_mode = (u8)((ht_conf->cap & IEEE80211_HT_CAP_MIMO_PS) >> 2); + + if (ht_conf->cap & IEEE80211_HT_CAP_SGI_20) + iwl_conf->sgf |= 0x1; + if (ht_conf->cap & IEEE80211_HT_CAP_SGI_40) + iwl_conf->sgf |= 0x2; + + iwl_conf->is_green_field = !!(ht_conf->cap & IEEE80211_HT_CAP_GRN_FLD); + iwl_conf->max_amsdu_size = + !!(ht_conf->cap & IEEE80211_HT_CAP_MAX_AMSDU); + + iwl_conf->supported_chan_width = + !!(ht_conf->cap & IEEE80211_HT_CAP_SUP_WIDTH); + iwl_conf->extension_chan_offset = + ht_bss_conf->bss_cap & IEEE80211_HT_IE_CHA_SEC_OFFSET; + /* If no above or below channel supplied disable FAT channel */ + if (iwl_conf->extension_chan_offset != IWL_EXT_CHANNEL_OFFSET_ABOVE && + iwl_conf->extension_chan_offset != IWL_EXT_CHANNEL_OFFSET_BELOW) + iwl_conf->supported_chan_width = 0; + + iwl_conf->tx_mimo_ps_mode = + (u8)((ht_conf->cap & IEEE80211_HT_CAP_MIMO_PS) >> 2); + memcpy(iwl_conf->supp_mcs_set, ht_conf->supp_mcs_set, 16); + + iwl_conf->control_channel = ht_bss_conf->primary_channel; + iwl_conf->tx_chan_width = + !!(ht_bss_conf->bss_cap & IEEE80211_HT_IE_CHA_WIDTH); + iwl_conf->ht_protection = + ht_bss_conf->bss_op_mode & IEEE80211_HT_IE_HT_PROTECTION; + iwl_conf->non_GF_STA_present = + !!(ht_bss_conf->bss_op_mode & IEEE80211_HT_IE_NON_GF_STA_PRSNT); + + IWL_DEBUG_MAC80211("control channel %d\n", iwl_conf->control_channel); + IWL_DEBUG_MAC80211("leave\n"); +} +#else +static inline void iwl4965_ht_conf(struct iwl_priv *priv, + struct ieee80211_bss_conf *bss_conf) +{ +} +#endif + static void iwl4965_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf, @@ -6962,6 +7020,11 @@ static void iwl4965_bss_info_changed(struct ieee80211_hw *hw, priv->staging_rxon.flags &= ~RXON_FLG_TGG_PROTECT_MSK; } + if (changes & BSS_CHANGED_HT) { + iwl4965_ht_conf(priv, bss_conf); + iwl4965_set_rxon_chain(priv); + } + if (changes & BSS_CHANGED_ASSOC) { /* * TODO: @@ -7358,88 +7421,6 @@ static int iwl4965_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk return 0; } -#ifdef CONFIG_IWL4965_HT - -static void iwl4965_ht_info_fill(struct ieee80211_conf *conf, - struct iwl_priv *priv) -{ - struct iwl_ht_info *iwl_conf = &priv->current_ht_config; - struct ieee80211_ht_info *ht_conf = &conf->ht_conf; - struct ieee80211_ht_bss_info *ht_bss_conf = &conf->ht_bss_conf; - - IWL_DEBUG_MAC80211("enter: \n"); - - if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE)) { - iwl_conf->is_ht = 0; - return; - } - - iwl_conf->is_ht = 1; - priv->ps_mode = (u8)((ht_conf->cap & IEEE80211_HT_CAP_MIMO_PS) >> 2); - - if (ht_conf->cap & IEEE80211_HT_CAP_SGI_20) - iwl_conf->sgf |= 0x1; - if (ht_conf->cap & IEEE80211_HT_CAP_SGI_40) - iwl_conf->sgf |= 0x2; - - iwl_conf->is_green_field = !!(ht_conf->cap & IEEE80211_HT_CAP_GRN_FLD); - iwl_conf->max_amsdu_size = - !!(ht_conf->cap & IEEE80211_HT_CAP_MAX_AMSDU); - - iwl_conf->supported_chan_width = - !!(ht_conf->cap & IEEE80211_HT_CAP_SUP_WIDTH); - iwl_conf->extension_chan_offset = - ht_bss_conf->bss_cap & IEEE80211_HT_IE_CHA_SEC_OFFSET; - /* If no above or below channel supplied disable FAT channel */ - if (iwl_conf->extension_chan_offset != IWL_EXT_CHANNEL_OFFSET_ABOVE && - iwl_conf->extension_chan_offset != IWL_EXT_CHANNEL_OFFSET_BELOW) - iwl_conf->supported_chan_width = 0; - - iwl_conf->tx_mimo_ps_mode = - (u8)((ht_conf->cap & IEEE80211_HT_CAP_MIMO_PS) >> 2); - memcpy(iwl_conf->supp_mcs_set, ht_conf->supp_mcs_set, 16); - - iwl_conf->control_channel = ht_bss_conf->primary_channel; - iwl_conf->tx_chan_width = - !!(ht_bss_conf->bss_cap & IEEE80211_HT_IE_CHA_WIDTH); - iwl_conf->ht_protection = - ht_bss_conf->bss_op_mode & IEEE80211_HT_IE_HT_PROTECTION; - iwl_conf->non_GF_STA_present = - !!(ht_bss_conf->bss_op_mode & IEEE80211_HT_IE_NON_GF_STA_PRSNT); - - IWL_DEBUG_MAC80211("control channel %d\n", - iwl_conf->control_channel); - IWL_DEBUG_MAC80211("leave\n"); -} - -static int iwl4965_mac_conf_ht(struct ieee80211_hw *hw, - struct ieee80211_conf *conf) -{ - struct iwl_priv *priv = hw->priv; - - IWL_DEBUG_MAC80211("enter: \n"); - - iwl4965_ht_info_fill(conf, priv); - iwl4965_set_rxon_chain(priv); - - if (priv && priv->assoc_id && - (priv->iw_mode == IEEE80211_IF_TYPE_STA)) { - unsigned long flags; - - spin_lock_irqsave(&priv->lock, flags); - if (priv->beacon_int) - queue_work(priv->workqueue, &priv->post_associate.work); - else - priv->call_post_assoc_from_beacon = 1; - spin_unlock_irqrestore(&priv->lock, flags); - } - - IWL_DEBUG_MAC80211("leave:\n"); - return 0; -} - -#endif /*CONFIG_IWL4965_HT*/ - /***************************************************************************** * * sysfs attributes @@ -7999,7 +7980,6 @@ static struct ieee80211_ops iwl4965_hw_ops = { .beacon_update = iwl4965_mac_beacon_update, .bss_info_changed = iwl4965_bss_info_changed, #ifdef CONFIG_IWL4965_HT - .conf_ht = iwl4965_mac_conf_ht, .ampdu_action = iwl4965_mac_ampdu_action, #endif /* CONFIG_IWL4965_HT */ .hw_scan = iwl4965_mac_hw_scan -- cgit v1.2.1 From 3109ece1114293b8201d9c140d02d7ce9a9fa387 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Fri, 28 Mar 2008 16:33:35 -0700 Subject: iwlwifi: Eliminate association from beacon This patch removes association from beacon using bss_info_change handler for association Signed-off-by: Tomas Winkler Signed-off-by: Gregory Greenman Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965-rs.c | 2 +- drivers/net/wireless/iwlwifi/iwl-4965.c | 174 +--------------------------- drivers/net/wireless/iwlwifi/iwl-4965.h | 6 +- drivers/net/wireless/iwlwifi/iwl4965-base.c | 73 +++++++----- 4 files changed, 51 insertions(+), 204 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c index 90ecf26af280..32eb414899d6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c @@ -275,7 +275,7 @@ static int rs_send_lq_cmd(struct iwl_priv *priv, if (flags & CMD_ASYNC) cmd.meta.u.callback = iwl4965_lq_sync_callback; - if (iwl4965_is_associated(priv) && priv->assoc_station_added && + if (iwl_is_associated(priv) && priv->assoc_station_added && priv->lq_mngr.lq_ready) return iwl_send_cmd(priv, &cmd); diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 89d600cfb846..0171bb8cbbc6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -1306,7 +1306,7 @@ void iwl4965_chain_noise_reset(struct iwl_priv *priv) struct iwl4965_chain_noise_data *data = NULL; data = &(priv->chain_noise_data); - if ((data->state == IWL_CHAIN_NOISE_ALIVE) && iwl4965_is_associated(priv)) { + if ((data->state == IWL_CHAIN_NOISE_ALIVE) && iwl_is_associated(priv)) { struct iwl4965_calibration_cmd cmd; memset(&cmd, 0, sizeof(cmd)); @@ -1581,7 +1581,7 @@ static void iwl4965_sensitivity_calibration(struct iwl_priv *priv, data = &(priv->sensitivity_data); - if (!iwl4965_is_associated(priv)) { + if (!iwl_is_associated(priv)) { IWL_DEBUG_CALIB("<< - not associated\n"); return; } @@ -3575,77 +3575,6 @@ static int iwl4965_calc_rssi(struct iwl4965_rx_phy_res *rx_resp) #ifdef CONFIG_IWL4965_HT -/* Parsed Information Elements */ -struct ieee802_11_elems { - u8 *ds_params; - u8 ds_params_len; - u8 *tim; - u8 tim_len; - u8 *ibss_params; - u8 ibss_params_len; - u8 *erp_info; - u8 erp_info_len; - u8 *ht_cap_param; - u8 ht_cap_param_len; - u8 *ht_extra_param; - u8 ht_extra_param_len; -}; - -static int parse_elems(u8 *start, size_t len, struct ieee802_11_elems *elems) -{ - size_t left = len; - u8 *pos = start; - int unknown = 0; - - memset(elems, 0, sizeof(*elems)); - - while (left >= 2) { - u8 id, elen; - - id = *pos++; - elen = *pos++; - left -= 2; - - if (elen > left) - return -1; - - switch (id) { - case WLAN_EID_DS_PARAMS: - elems->ds_params = pos; - elems->ds_params_len = elen; - break; - case WLAN_EID_TIM: - elems->tim = pos; - elems->tim_len = elen; - break; - case WLAN_EID_IBSS_PARAMS: - elems->ibss_params = pos; - elems->ibss_params_len = elen; - break; - case WLAN_EID_ERP_INFO: - elems->erp_info = pos; - elems->erp_info_len = elen; - break; - case WLAN_EID_HT_CAPABILITY: - elems->ht_cap_param = pos; - elems->ht_cap_param_len = elen; - break; - case WLAN_EID_HT_EXTRA_INFO: - elems->ht_extra_param = pos; - elems->ht_extra_param_len = elen; - break; - default: - unknown++; - break; - } - - left -= elen; - pos += elen; - } - - return 0; -} - void iwl4965_init_ht_hw_capab(struct iwl_priv *priv, struct ieee80211_ht_info *ht_info, enum ieee80211_band band) @@ -3862,7 +3791,6 @@ static inline void iwl4965_dbg_report_frame(struct iwl_priv *priv, #endif -#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6) /* Called for REPLY_RX (legacy ABG frames), or * REPLY_RX_MPDU_CMD (HT high-throughput N frames). */ @@ -3951,7 +3879,7 @@ static void iwl4965_rx_reply_rx(struct iwl_priv *priv, * which are gathered only when associated, and indicate noise * only for the associated network channel ... * Ignore these noise values while scanning (other channels) */ - if (iwl4965_is_associated(priv) && + if (iwl_is_associated(priv) && !test_bit(STATUS_SCANNING, &priv->status)) { rx_status.noise = priv->last_rx_noise; rx_status.signal = iwl4965_calc_sig_qual(rx_status.ssi, @@ -3962,7 +3890,7 @@ static void iwl4965_rx_reply_rx(struct iwl_priv *priv, } /* Reset beacon noise level if not associated. */ - if (!iwl4965_is_associated(priv)) + if (!iwl_is_associated(priv)) priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE; /* Set "1" to report good data frames in groups of 100 */ @@ -3983,101 +3911,9 @@ static void iwl4965_rx_reply_rx(struct iwl_priv *priv, fc = le16_to_cpu(header->frame_control); switch (fc & IEEE80211_FCTL_FTYPE) { case IEEE80211_FTYPE_MGMT: - if (priv->iw_mode == IEEE80211_IF_TYPE_AP) iwl4965_update_ps_mode(priv, fc & IEEE80211_FCTL_PM, header->addr2); - switch (fc & IEEE80211_FCTL_STYPE) { - case IEEE80211_STYPE_PROBE_RESP: - case IEEE80211_STYPE_BEACON: - if ((priv->iw_mode == IEEE80211_IF_TYPE_STA && - !compare_ether_addr(header->addr2, priv->bssid)) || - (priv->iw_mode == IEEE80211_IF_TYPE_IBSS && - !compare_ether_addr(header->addr3, priv->bssid))) { - struct ieee80211_mgmt *mgmt = - (struct ieee80211_mgmt *)header; - u64 timestamp = - le64_to_cpu(mgmt->u.beacon.timestamp); - - priv->timestamp0 = timestamp & 0xFFFFFFFF; - priv->timestamp1 = - (timestamp >> 32) & 0xFFFFFFFF; - priv->beacon_int = le16_to_cpu( - mgmt->u.beacon.beacon_int); - if (priv->call_post_assoc_from_beacon && - (priv->iw_mode == IEEE80211_IF_TYPE_STA)) { - priv->call_post_assoc_from_beacon = 0; - queue_work(priv->workqueue, - &priv->post_associate.work); - } - } - break; - - case IEEE80211_STYPE_ACTION: - break; - - /* - * TODO: Use the new callback function from - * mac80211 instead of sniffing these packets. - */ - case IEEE80211_STYPE_ASSOC_RESP: - case IEEE80211_STYPE_REASSOC_RESP: - if (network_packet) { -#ifdef CONFIG_IWL4965_HT - u8 *pos = NULL; - struct ieee802_11_elems elems; -#endif /*CONFIG_IWL4965_HT */ - struct ieee80211_mgmt *mgnt = - (struct ieee80211_mgmt *)header; - - /* We have just associated, give some - * time for the 4-way handshake if - * any. Don't start scan too early. */ - priv->next_scan_jiffies = jiffies + - IWL_DELAY_NEXT_SCAN_AFTER_ASSOC; - - priv->assoc_id = (~((1 << 15) | (1 << 14)) - & le16_to_cpu(mgnt->u.assoc_resp.aid)); - priv->assoc_capability = - le16_to_cpu( - mgnt->u.assoc_resp.capab_info); -#ifdef CONFIG_IWL4965_HT - pos = mgnt->u.assoc_resp.variable; - if (!parse_elems(pos, - len - (pos - (u8 *) mgnt), - &elems)) { - if (elems.ht_extra_param && - elems.ht_cap_param) - break; - } -#endif /*CONFIG_IWL4965_HT */ - /* assoc_id is 0 no association */ - if (!priv->assoc_id) - break; - if (priv->beacon_int) - queue_work(priv->workqueue, - &priv->post_associate.work); - else - priv->call_post_assoc_from_beacon = 1; - } - - break; - - case IEEE80211_STYPE_PROBE_REQ: - if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) && - !iwl4965_is_associated(priv)) { - DECLARE_MAC_BUF(mac1); - DECLARE_MAC_BUF(mac2); - DECLARE_MAC_BUF(mac3); - - IWL_DEBUG_DROP("Dropping (non network): " - "%s, %s, %s\n", - print_mac(mac1, header->addr1), - print_mac(mac2, header->addr2), - print_mac(mac3, header->addr3)); - return; - } - } iwl4965_handle_data_packet(priv, 0, include_phy, rxb, &rx_status); break; @@ -4136,7 +3972,6 @@ static void iwl4965_rx_reply_rx_phy(struct iwl_priv *priv, memcpy(&priv->last_phy_res[1], &(pkt->u.raw[0]), sizeof(struct iwl4965_rx_phy_res)); } - static void iwl4965_rx_missed_beacon_notif(struct iwl_priv *priv, struct iwl4965_rx_mem_buffer *rxb) @@ -4158,7 +3993,6 @@ static void iwl4965_rx_missed_beacon_notif(struct iwl_priv *priv, } #endif /*CONFIG_IWL4965_SENSITIVITY*/ } - #ifdef CONFIG_IWL4965_HT /** diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index 8c14e9a87c14..c8e7028cdf2a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -1068,7 +1068,6 @@ struct iwl_priv { u16 active_rate; u16 active_rate_basic; - u8 call_post_assoc_from_beacon; u8 assoc_station_added; u8 use_ant_b_for_management_frame; /* Tx antenna selection */ u8 valid_antenna; /* Bit mask of antennas actually connected */ @@ -1161,8 +1160,7 @@ struct iwl_priv { struct sk_buff *ibss_beacon; /* Last Rx'd beacon timestamp */ - u32 timestamp0; - u32 timestamp1; + u64 timestamp; u16 beacon_int; struct iwl4965_driver_hw_info hw_setting; struct ieee80211_vif *vif; @@ -1226,7 +1224,7 @@ struct iwl_priv { struct timer_list statistics_periodic; }; /*iwl_priv */ -static inline int iwl4965_is_associated(struct iwl_priv *priv) +static inline int iwl_is_associated(struct iwl_priv *priv) { return (priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0; } diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 826c912aea9a..f995af682233 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -901,7 +901,7 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv) * an RXON_ASSOC and the new config wants the associated mask enabled, * we must clear the associated from the active configuration * before we apply the new config */ - if (iwl4965_is_associated(priv) && + if (iwl_is_associated(priv) && (priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK)) { IWL_DEBUG_INFO("Toggling associated bit on current RXON\n"); active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; @@ -967,7 +967,7 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv) /* If we have set the ASSOC_MSK and we are in BSS mode then * add the IWL_AP_ID to the station rate table */ - if (iwl4965_is_associated(priv) && + if (iwl_is_associated(priv) && (priv->iw_mode == IEEE80211_IF_TYPE_STA)) { if (iwl4965_rxon_add_station(priv, priv->active_rxon.bssid_addr, 1) == IWL_INVALID_STATION) { @@ -1319,7 +1319,7 @@ unsigned int iwl4965_fill_beacon_frame(struct iwl_priv *priv, const u8 *dest, int left) { - if (!iwl4965_is_associated(priv) || !priv->ibss_beacon || + if (!iwl_is_associated(priv) || !priv->ibss_beacon || ((priv->iw_mode != IEEE80211_IF_TYPE_IBSS) && (priv->iw_mode != IEEE80211_IF_TYPE_AP))) return 0; @@ -1582,7 +1582,7 @@ static void iwl4965_activate_qos(struct iwl_priv *priv, u8 force) spin_unlock_irqrestore(&priv->lock, flags); - if (force || iwl4965_is_associated(priv)) { + if (force || iwl_is_associated(priv)) { IWL_DEBUG_QOS("send QoS cmd with Qos active=%d FLAGS=0x%X\n", priv->qos_data.qos_active, priv->qos_data.def_qos_parm.qos_flags); @@ -1921,13 +1921,13 @@ static void iwl4965_setup_rxon_timing(struct iwl_priv *priv) conf = ieee80211_get_hw_conf(priv->hw); spin_lock_irqsave(&priv->lock, flags); - priv->rxon_timing.timestamp.dw[1] = cpu_to_le32(priv->timestamp1); - priv->rxon_timing.timestamp.dw[0] = cpu_to_le32(priv->timestamp0); + priv->rxon_timing.timestamp.dw[1] = cpu_to_le32(priv->timestamp >> 32); + priv->rxon_timing.timestamp.dw[0] = + cpu_to_le32(priv->timestamp & 0xFFFFFFFF); priv->rxon_timing.listen_interval = INTEL_CONN_LISTEN_INTERVAL; - tsf = priv->timestamp1; - tsf = ((tsf << 32) | priv->timestamp0); + tsf = priv->timestamp; beacon_int = priv->beacon_int; spin_unlock_irqrestore(&priv->lock, flags); @@ -2374,10 +2374,10 @@ static int iwl4965_tx_skb(struct iwl_priv *priv, /* drop all data frame if we are not associated */ if (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) && - (!iwl4965_is_associated(priv) || + (!iwl_is_associated(priv) || ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && !priv->assoc_id) || !priv->assoc_station_added)) { - IWL_DEBUG_DROP("Dropping - !iwl4965_is_associated\n"); + IWL_DEBUG_DROP("Dropping - !iwl_is_associated\n"); goto drop_unlock; } @@ -2838,7 +2838,7 @@ static int iwl4965_get_measurement(struct iwl_priv *priv, int spectrum_resp_status; int duration = le16_to_cpu(params->duration); - if (iwl4965_is_associated(priv)) + if (iwl_is_associated(priv)) add_time = iwl4965_usecs_to_beacons( le64_to_cpu(params->start_time) - priv->last_tsf, @@ -2853,7 +2853,7 @@ static int iwl4965_get_measurement(struct iwl_priv *priv, cmd.len = sizeof(spectrum); spectrum.len = cpu_to_le16(cmd.len - sizeof(spectrum.len)); - if (iwl4965_is_associated(priv)) + if (iwl_is_associated(priv)) spectrum.start_time = iwl4965_add_beacon_time(priv->last_beacon_time, add_time, @@ -4504,7 +4504,7 @@ static void iwl4965_irq_handle_error(struct iwl_priv *priv) IWL_DEBUG(IWL_DL_INFO | IWL_DL_FW_ERRORS, "Restarting adapter due to uCode error.\n"); - if (iwl4965_is_associated(priv)) { + if (iwl_is_associated(priv)) { memcpy(&priv->recovery_rxon, &priv->active_rxon, sizeof(priv->recovery_rxon)); priv->error_recovering = 1; @@ -4790,7 +4790,7 @@ static u16 iwl4965_get_passive_dwell_time(struct iwl_priv *priv, IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 : IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52; - if (iwl4965_is_associated(priv)) { + if (iwl_is_associated(priv)) { /* If we're associated, we clamp the maximum passive * dwell time to be 98% of the beacon interval (minus * 2 * channel tune time) */ @@ -4830,7 +4830,7 @@ static int iwl4965_get_channels_for_scan(struct iwl_priv *priv, for (i = 0, added = 0; i < sband->n_channels; i++) { if (ieee80211_frequency_to_channel(channels[i].center_freq) == le16_to_cpu(priv->active_rxon.channel)) { - if (iwl4965_is_associated(priv)) { + if (iwl_is_associated(priv)) { IWL_DEBUG_SCAN ("Skipping current channel %d\n", le16_to_cpu(priv->active_rxon.channel)); @@ -5711,7 +5711,7 @@ static void iwl4965_alive_start(struct iwl_priv *priv) iwl4965_send_power_mode(priv, IWL_POWER_LEVEL(priv->power_mode)); - if (iwl4965_is_associated(priv)) { + if (iwl_is_associated(priv)) { struct iwl4965_rxon_cmd *active_rxon = (struct iwl4965_rxon_cmd *)(&priv->active_rxon); @@ -6129,7 +6129,7 @@ static void iwl4965_bg_request_scan(struct work_struct *data) scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH; scan->quiet_time = IWL_ACTIVE_QUIET_TIME; - if (iwl4965_is_associated(priv)) { + if (iwl_is_associated(priv)) { u16 interval = 0; u32 extra; u32 suspend_time = 100; @@ -6166,7 +6166,7 @@ static void iwl4965_bg_request_scan(struct work_struct *data) memcpy(scan->direct_scan[0].ssid, priv->direct_ssid, priv->direct_ssid_len); direct_mask = 1; - } else if (!iwl4965_is_associated(priv) && priv->essid_len) { + } else if (!iwl_is_associated(priv) && priv->essid_len) { scan->direct_scan[0].id = WLAN_EID_SSID; scan->direct_scan[0].len = priv->essid_len; memcpy(scan->direct_scan[0].ssid, priv->essid, priv->essid_len); @@ -6999,6 +6999,7 @@ static inline void iwl4965_ht_conf(struct iwl_priv *priv, } #endif +#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6) static void iwl4965_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf, @@ -7006,7 +7007,11 @@ static void iwl4965_bss_info_changed(struct ieee80211_hw *hw, { struct iwl_priv *priv = hw->priv; + IWL_DEBUG_MAC80211("changes = 0x%X\n", changes); + if (changes & BSS_CHANGED_ERP_PREAMBLE) { + IWL_DEBUG_MAC80211("ERP_PREAMBLE %d\n", + bss_conf->use_short_preamble); if (bss_conf->use_short_preamble) priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; else @@ -7014,6 +7019,7 @@ static void iwl4965_bss_info_changed(struct ieee80211_hw *hw, } if (changes & BSS_CHANGED_ERP_CTS_PROT) { + IWL_DEBUG_MAC80211("ERP_CTS %d\n", bss_conf->use_cts_prot); if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ)) priv->staging_rxon.flags |= RXON_FLG_TGG_PROTECT_MSK; else @@ -7021,19 +7027,30 @@ static void iwl4965_bss_info_changed(struct ieee80211_hw *hw, } if (changes & BSS_CHANGED_HT) { + IWL_DEBUG_MAC80211("HT %d\n", bss_conf->assoc_ht); iwl4965_ht_conf(priv, bss_conf); iwl4965_set_rxon_chain(priv); } if (changes & BSS_CHANGED_ASSOC) { - /* - * TODO: - * do stuff instead of sniffing assoc resp - */ + IWL_DEBUG_MAC80211("ASSOC %d\n", bss_conf->assoc); + if (bss_conf->assoc) { + priv->assoc_id = bss_conf->aid; + priv->beacon_int = bss_conf->beacon_int; + priv->timestamp = bss_conf->timestamp; + priv->assoc_capability = bss_conf->assoc_capability; + priv->next_scan_jiffies = jiffies + + IWL_DELAY_NEXT_SCAN_AFTER_ASSOC; + queue_work(priv->workqueue, &priv->post_associate.work); + } else { + priv->assoc_id = 0; + IWL_DEBUG_MAC80211("DISASSOC %d\n", bss_conf->assoc); + } + } else if (changes && iwl_is_associated(priv) && priv->assoc_id) { + IWL_DEBUG_MAC80211("Associated Changes %d\n", changes); + iwl4965_send_rxon_assoc(priv); } - if (iwl4965_is_associated(priv)) - iwl4965_send_rxon_assoc(priv); } static int iwl4965_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len) @@ -7166,7 +7183,7 @@ static int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, /* FIXME: need to differenciate between static and dynamic key * in the level of mac80211 */ - static_key = !iwl4965_is_associated(priv); + static_key = !iwl_is_associated(priv); if (!static_key) { sta_id = iwl4965_hw_find_station(priv, addr); @@ -7247,7 +7264,7 @@ static int iwl4965_mac_conf_tx(struct ieee80211_hw *hw, int queue, mutex_lock(&priv->mutex); if (priv->iw_mode == IEEE80211_IF_TYPE_AP) iwl4965_activate_qos(priv, 1); - else if (priv->assoc_id && iwl4965_is_associated(priv)) + else if (priv->assoc_id && iwl_is_associated(priv)) iwl4965_activate_qos(priv, 0); mutex_unlock(&priv->mutex); @@ -7330,7 +7347,6 @@ static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw) spin_lock_irqsave(&priv->lock, flags); priv->assoc_id = 0; priv->assoc_capability = 0; - priv->call_post_assoc_from_beacon = 0; priv->assoc_station_added = 0; /* new association get rid of ibss beacon skb */ @@ -7340,8 +7356,7 @@ static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw) priv->ibss_beacon = NULL; priv->beacon_int = priv->hw->conf.beacon_int; - priv->timestamp1 = 0; - priv->timestamp0 = 0; + priv->timestamp = 0; if ((priv->iw_mode == IEEE80211_IF_TYPE_STA)) priv->beacon_int = 0; -- cgit v1.2.1 From 5100d5ac81b9330dc57e35adbe50923ba6107b8f Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sat, 29 Mar 2008 21:01:16 +0100 Subject: b43: Add PIO support for PCMCIA devices This adds PIO support back (D'oh!) for PCMCIA devices. This is a complete rewrite of the old PIO code. It does actually work and we get reasonable performance out of it on a modern machine. On a PowerBook G4 I get a few MBit for TX and a few more for RX. So it doesn't work as well as DMA (of course), but it's a _lot_ faster than the old PIO code (only got a few kBit with that). The limiting factor is the host CPU speed. So it will generate 100% CPU usage when the network interface is heavily loaded. A voluntary preemption point in the RX path makes sure Desktop Latency isn't hurt. PIO is needed for 16bit PCMCIA devices, as we really don't want to poke with the braindead DMA mechanisms on PCMCIA sockets. Additionally, not all PCMCIA sockets do actually support DMA in 16bit mode (mine doesn't). Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/Kconfig | 17 + drivers/net/wireless/b43/Makefile | 1 + drivers/net/wireless/b43/b43.h | 59 ++- drivers/net/wireless/b43/dma.c | 120 +++--- drivers/net/wireless/b43/dma.h | 3 + drivers/net/wireless/b43/main.c | 37 +- drivers/net/wireless/b43/pio.c | 835 ++++++++++++++++++++++++++++++++++++++ drivers/net/wireless/b43/pio.h | 220 ++++++++++ drivers/net/wireless/b43/xmit.c | 61 +-- drivers/net/wireless/b43/xmit.h | 17 +- 10 files changed, 1267 insertions(+), 103 deletions(-) create mode 100644 drivers/net/wireless/b43/pio.c create mode 100644 drivers/net/wireless/b43/pio.h (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig index 8bc4bc4c330e..94f04559028b 100644 --- a/drivers/net/wireless/b43/Kconfig +++ b/drivers/net/wireless/b43/Kconfig @@ -62,6 +62,13 @@ config B43_PCMCIA If unsure, say N. +# Data transfers to the device via PIO +# This is only needed on PCMCIA devices. All others can do DMA properly. +config B43_PIO + bool + depends on B43 && (B43_PCMCIA || B43_FORCE_PIO) + default y + config B43_NPHY bool "Pre IEEE 802.11n support (BROKEN)" depends on B43 && EXPERIMENTAL && BROKEN @@ -94,3 +101,13 @@ config B43_DEBUG Say Y, if you want to find out why the driver does not work for you. + +config B43_FORCE_PIO + bool "Force usage of PIO instead of DMA" + depends on B43 && B43_DEBUG + ---help--- + This will disable DMA and always enable PIO instead. + + Say N! + This is only for debugging the PIO engine code. You do + _NOT_ want to enable this. diff --git a/drivers/net/wireless/b43/Makefile b/drivers/net/wireless/b43/Makefile index ae11fe4c0be6..8c52b0b9862a 100644 --- a/drivers/net/wireless/b43/Makefile +++ b/drivers/net/wireless/b43/Makefile @@ -8,6 +8,7 @@ b43-y += xmit.o b43-y += lo.o b43-y += wa.o b43-y += dma.o +b43-$(CONFIG_B43_PIO) += pio.o b43-$(CONFIG_B43_RFKILL) += rfkill.o b43-$(CONFIG_B43_LEDS) += leds.o b43-$(CONFIG_B43_PCMCIA) += pcmcia.o diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index d40be1568517..ef8ae385835a 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -75,6 +75,23 @@ #define B43_MMIO_DMA64_BASE4 0x300 #define B43_MMIO_DMA64_BASE5 0x340 +/* PIO on core rev < 11 */ +#define B43_MMIO_PIO_BASE0 0x300 +#define B43_MMIO_PIO_BASE1 0x310 +#define B43_MMIO_PIO_BASE2 0x320 +#define B43_MMIO_PIO_BASE3 0x330 +#define B43_MMIO_PIO_BASE4 0x340 +#define B43_MMIO_PIO_BASE5 0x350 +#define B43_MMIO_PIO_BASE6 0x360 +#define B43_MMIO_PIO_BASE7 0x370 +/* PIO on core rev >= 11 */ +#define B43_MMIO_PIO11_BASE0 0x200 +#define B43_MMIO_PIO11_BASE1 0x240 +#define B43_MMIO_PIO11_BASE2 0x280 +#define B43_MMIO_PIO11_BASE3 0x2C0 +#define B43_MMIO_PIO11_BASE4 0x300 +#define B43_MMIO_PIO11_BASE5 0x340 + #define B43_MMIO_PHY_VER 0x3E0 #define B43_MMIO_PHY_RADIO 0x3E2 #define B43_MMIO_PHY0 0x3E6 @@ -442,7 +459,6 @@ enum { }; struct b43_dmaring; -struct b43_pioqueue; /* The firmware file header */ #define B43_FW_TYPE_UCODE 'u' @@ -598,6 +614,20 @@ struct b43_dma { struct b43_dmaring *rx_ring; }; +struct b43_pio_txqueue; +struct b43_pio_rxqueue; + +/* Data structures for PIO transmission, per 80211 core. */ +struct b43_pio { + struct b43_pio_txqueue *tx_queue_AC_BK; /* Background */ + struct b43_pio_txqueue *tx_queue_AC_BE; /* Best Effort */ + struct b43_pio_txqueue *tx_queue_AC_VI; /* Video */ + struct b43_pio_txqueue *tx_queue_AC_VO; /* Voice */ + struct b43_pio_txqueue *tx_queue_mcast; /* Multicast */ + + struct b43_pio_rxqueue *rx_queue; +}; + /* Context information for a noise calculation (Link Quality). */ struct b43_noise_calculation { u8 channel_at_start; @@ -773,8 +803,15 @@ struct b43_wldev { /* PHY/Radio device. */ struct b43_phy phy; - /* DMA engines. */ - struct b43_dma dma; + union { + /* DMA engines. */ + struct b43_dma dma; + /* PIO engines. */ + struct b43_pio pio; + }; + /* Use b43_using_pio_transfers() to check whether we are using + * DMA or PIO data transfers. */ + bool __using_pio_transfers; /* Various statistics about the physical device. */ struct b43_stats stats; @@ -858,6 +895,22 @@ static inline void b43_write32(struct b43_wldev *dev, u16 offset, u32 value) ssb_write32(dev->dev, offset, value); } +static inline bool b43_using_pio_transfers(struct b43_wldev *dev) +{ +#ifdef CONFIG_B43_PIO + return dev->__using_pio_transfers; +#else + return 0; +#endif +} + +#ifdef CONFIG_B43_FORCE_PIO +# define B43_FORCE_PIO 1 +#else +# define B43_FORCE_PIO 0 +#endif + + /* Message printing */ void b43info(struct b43_wl *wl, const char *fmt, ...) __attribute__ ((format(printf, 2, 3))); diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index 70db0570adc5..f1b983cb9c1f 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c @@ -550,7 +550,6 @@ static int setup_rx_descbuffer(struct b43_dmaring *ring, struct b43_dmadesc_meta *meta, gfp_t gfp_flags) { struct b43_rxhdr_fw4 *rxhdr; - struct b43_hwtxstatus *txstat; dma_addr_t dmaaddr; struct sk_buff *skb; @@ -586,8 +585,6 @@ static int setup_rx_descbuffer(struct b43_dmaring *ring, rxhdr = (struct b43_rxhdr_fw4 *)(skb->data); rxhdr->frame_len = 0; - txstat = (struct b43_hwtxstatus *)(skb->data); - txstat->cookie = 0; return 0; } @@ -776,6 +773,18 @@ static u64 supported_dma_mask(struct b43_wldev *dev) return DMA_30BIT_MASK; } +static enum b43_dmatype dma_mask_to_engine_type(u64 dmamask) +{ + if (dmamask == DMA_30BIT_MASK) + return B43_DMA_30BIT; + if (dmamask == DMA_32BIT_MASK) + return B43_DMA_32BIT; + if (dmamask == DMA_64BIT_MASK) + return B43_DMA_64BIT; + B43_WARN_ON(1); + return B43_DMA_30BIT; +} + /* Main initialization function. */ static struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, @@ -956,7 +965,11 @@ static void b43_destroy_dmaring(struct b43_dmaring *ring, void b43_dma_free(struct b43_wldev *dev) { - struct b43_dma *dma = &dev->dma; + struct b43_dma *dma; + + if (b43_using_pio_transfers(dev)) + return; + dma = &dev->dma; destroy_ring(dma, rx_ring); destroy_ring(dma, tx_ring_AC_BK); @@ -974,19 +987,7 @@ int b43_dma_init(struct b43_wldev *dev) enum b43_dmatype type; dmamask = supported_dma_mask(dev); - switch (dmamask) { - default: - B43_WARN_ON(1); - case DMA_30BIT_MASK: - type = B43_DMA_30BIT; - break; - case DMA_32BIT_MASK: - type = B43_DMA_32BIT; - break; - case DMA_64BIT_MASK: - type = B43_DMA_64BIT; - break; - } + type = dma_mask_to_engine_type(dmamask); err = ssb_dma_set_mask(dev->dev, dmamask); if (err) { b43err(dev->wl, "The machine/kernel does not support " @@ -1113,7 +1114,6 @@ static int dma_tx_fragment(struct b43_dmaring *ring, size_t hdrsize = b43_txhdr_size(ring->dev); #define SLOTS_PER_PACKET 2 - B43_WARN_ON(skb_shinfo(skb)->nr_frags); old_top_slot = ring->current_slot; old_used_slots = ring->used_slots; @@ -1257,11 +1257,6 @@ int b43_dma_tx(struct b43_wldev *dev, int err = 0; unsigned long flags; - if (unlikely(skb->len < 2 + 2 + 6)) { - /* Too short, this can't be a valid frame. */ - return -EINVAL; - } - hdr = (struct ieee80211_hdr *)skb->data; if (ctl->flags & IEEE80211_TXCTL_SEND_AFTER_DTIM) { /* The multicast ring will be sent after the DTIM */ @@ -1319,38 +1314,6 @@ out_unlock: return err; } -static void b43_fill_txstatus_report(struct b43_dmaring *ring, - struct ieee80211_tx_status *report, - const struct b43_txstatus *status) -{ - bool frame_failed = 0; - - if (status->acked) { - /* The frame was ACKed. */ - report->flags |= IEEE80211_TX_STATUS_ACK; - } else { - /* The frame was not ACKed... */ - if (!(report->control.flags & IEEE80211_TXCTL_NO_ACK)) { - /* ...but we expected an ACK. */ - frame_failed = 1; - report->excessive_retries = 1; - } - } - if (status->frame_count == 0) { - /* The frame was not transmitted at all. */ - report->retry_count = 0; - } else { - report->retry_count = status->frame_count - 1; -#ifdef CONFIG_B43_DEBUG - if (frame_failed) - ring->nr_failed_tx_packets++; - else - ring->nr_succeed_tx_packets++; - ring->nr_total_packet_tries += status->frame_count; -#endif /* DEBUG */ - } -} - /* Called with IRQs disabled. */ void b43_dma_handle_txstatus(struct b43_wldev *dev, const struct b43_txstatus *status) @@ -1360,6 +1323,7 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev, struct b43_dmadesc_generic *desc; struct b43_dmadesc_meta *meta; int slot; + bool frame_succeed; ring = parse_cookie(dev, status->cookie, &slot); if (unlikely(!ring)) @@ -1386,7 +1350,15 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev, * status of the transmission. * Some fields of txstat are already filled in dma_tx(). */ - b43_fill_txstatus_report(ring, &(meta->txstat), status); + frame_succeed = b43_fill_txstatus_report( + &(meta->txstat), status); +#ifdef CONFIG_B43_DEBUG + if (frame_succeed) + ring->nr_succeed_tx_packets++; + else + ring->nr_failed_tx_packets++; + ring->nr_total_packet_tries += status->frame_count; +#endif /* DEBUG */ ieee80211_tx_status_irqsafe(dev->wl->hw, meta->skb, &(meta->txstat)); /* skb is freed by ieee80211_tx_status_irqsafe() */ @@ -1573,3 +1545,39 @@ void b43_dma_tx_resume(struct b43_wldev *dev) b43_dma_tx_resume_ring(dev->dma.tx_ring_AC_BK); b43_power_saving_ctl_bits(dev, 0); } + +#ifdef CONFIG_B43_PIO +static void direct_fifo_rx(struct b43_wldev *dev, enum b43_dmatype type, + u16 mmio_base, bool enable) +{ + u32 ctl; + + if (type == B43_DMA_64BIT) { + ctl = b43_read32(dev, mmio_base + B43_DMA64_RXCTL); + ctl &= ~B43_DMA64_RXDIRECTFIFO; + if (enable) + ctl |= B43_DMA64_RXDIRECTFIFO; + b43_write32(dev, mmio_base + B43_DMA64_RXCTL, ctl); + } else { + ctl = b43_read32(dev, mmio_base + B43_DMA32_RXCTL); + ctl &= ~B43_DMA32_RXDIRECTFIFO; + if (enable) + ctl |= B43_DMA32_RXDIRECTFIFO; + b43_write32(dev, mmio_base + B43_DMA32_RXCTL, ctl); + } +} + +/* Enable/Disable Direct FIFO Receive Mode (PIO) on a RX engine. + * This is called from PIO code, so DMA structures are not available. */ +void b43_dma_direct_fifo_rx(struct b43_wldev *dev, + unsigned int engine_index, bool enable) +{ + enum b43_dmatype type; + u16 mmio_base; + + type = dma_mask_to_engine_type(supported_dma_mask(dev)); + + mmio_base = b43_dmacontroller_base(type, engine_index); + direct_fifo_rx(dev, type, mmio_base, enable); +} +#endif /* CONFIG_B43_PIO */ diff --git a/drivers/net/wireless/b43/dma.h b/drivers/net/wireless/b43/dma.h index ea27085dec0e..20acf885dba5 100644 --- a/drivers/net/wireless/b43/dma.h +++ b/drivers/net/wireless/b43/dma.h @@ -291,4 +291,7 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev, void b43_dma_rx(struct b43_dmaring *ring); +void b43_dma_direct_fifo_rx(struct b43_wldev *dev, + unsigned int engine_index, bool enable); + #endif /* B43_DMA_H_ */ diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index a4e6a59ccac8..355f28a2f7f5 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -47,6 +47,7 @@ #include "debugfs.h" #include "phy.h" #include "dma.h" +#include "pio.h" #include "sysfs.h" #include "xmit.h" #include "lo.h" @@ -1593,8 +1594,12 @@ static void b43_interrupt_tasklet(struct b43_wldev *dev) handle_irq_noise(dev); /* Check the DMA reason registers for received data. */ - if (dma_reason[0] & B43_DMAIRQ_RX_DONE) - b43_dma_rx(dev->dma.rx_ring); + if (dma_reason[0] & B43_DMAIRQ_RX_DONE) { + if (b43_using_pio_transfers(dev)) + b43_pio_rx(dev->pio.rx_queue); + else + b43_dma_rx(dev->dma.rx_ring); + } B43_WARN_ON(dma_reason[1] & B43_DMAIRQ_RX_DONE); B43_WARN_ON(dma_reason[2] & B43_DMAIRQ_RX_DONE); B43_WARN_ON(dma_reason[3] & B43_DMAIRQ_RX_DONE); @@ -2698,12 +2703,21 @@ static int b43_op_tx(struct ieee80211_hw *hw, struct b43_wldev *dev = wl->current_dev; int err = -ENODEV; + if (unlikely(skb->len < 2 + 2 + 6)) { + /* Too short, this can't be a valid frame. */ + return -EINVAL; + } + B43_WARN_ON(skb_shinfo(skb)->nr_frags); + if (unlikely(!dev)) goto out; if (unlikely(b43_status(dev) < B43_STAT_STARTED)) goto out; - /* DMA-TX is done without a global lock. */ - err = b43_dma_tx(dev, skb, ctl); + /* TX is done without a global lock. */ + if (b43_using_pio_transfers(dev)) + err = b43_pio_tx(dev, skb, ctl); + else + err = b43_dma_tx(dev, skb, ctl); out: if (unlikely(err)) return NETDEV_TX_BUSY; @@ -2897,7 +2911,10 @@ static int b43_op_get_tx_stats(struct ieee80211_hw *hw, goto out; spin_lock_irqsave(&wl->irq_lock, flags); if (likely(b43_status(dev) >= B43_STAT_STARTED)) { - b43_dma_get_tx_stats(dev, stats); + if (b43_using_pio_transfers(dev)) + b43_pio_get_tx_stats(dev, stats); + else + b43_dma_get_tx_stats(dev, stats); err = 0; } spin_unlock_irqrestore(&wl->irq_lock, flags); @@ -3366,6 +3383,7 @@ static void b43_wireless_core_stop(struct b43_wldev *dev) b43_set_status(dev, B43_STAT_INITIALIZED); + b43_pio_stop(dev); mutex_unlock(&wl->mutex); /* Must unlock as it would otherwise deadlock. No races here. * Cancel the possibly running self-rearming periodic work. */ @@ -3683,6 +3701,7 @@ static void b43_wireless_core_exit(struct b43_wldev *dev) b43_rng_exit(dev->wl, false); } b43_dma_free(dev); + b43_pio_free(dev); b43_chip_exit(dev); b43_radio_turn_off(dev, 1); b43_switch_analog(dev, 0); @@ -3780,7 +3799,13 @@ static int b43_wireless_core_init(struct b43_wldev *dev) /* Maximum Contention Window */ b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MAXCONT, 0x3FF); - err = b43_dma_init(dev); + if ((dev->dev->bus->bustype == SSB_BUSTYPE_PCMCIA) || B43_FORCE_PIO) { + dev->__using_pio_transfers = 1; + err = b43_pio_init(dev); + } else { + dev->__using_pio_transfers = 0; + err = b43_dma_init(dev); + } if (err) goto err_chip_exit; b43_qos_init(dev); diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c new file mode 100644 index 000000000000..e73769ac027f --- /dev/null +++ b/drivers/net/wireless/b43/pio.c @@ -0,0 +1,835 @@ +/* + + Broadcom B43 wireless driver + + PIO data transfer + + Copyright (c) 2005-2008 Michael Buesch + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, + Boston, MA 02110-1301, USA. + +*/ + +#include "b43.h" +#include "pio.h" +#include "dma.h" +#include "main.h" +#include "xmit.h" + +#include + + +static void b43_pio_rx_work(struct work_struct *work); + + +static u16 generate_cookie(struct b43_pio_txqueue *q, + struct b43_pio_txpacket *pack) +{ + u16 cookie; + + /* Use the upper 4 bits of the cookie as + * PIO controller ID and store the packet index number + * in the lower 12 bits. + * Note that the cookie must never be 0, as this + * is a special value used in RX path. + * It can also not be 0xFFFF because that is special + * for multicast frames. + */ + cookie = (((u16)q->index + 1) << 12); + cookie |= pack->index; + + return cookie; +} + +static +struct b43_pio_txqueue * parse_cookie(struct b43_wldev *dev, + u16 cookie, + struct b43_pio_txpacket **pack) +{ + struct b43_pio *pio = &dev->pio; + struct b43_pio_txqueue *q = NULL; + unsigned int pack_index; + + switch (cookie & 0xF000) { + case 0x1000: + q = pio->tx_queue_AC_BK; + break; + case 0x2000: + q = pio->tx_queue_AC_BE; + break; + case 0x3000: + q = pio->tx_queue_AC_VI; + break; + case 0x4000: + q = pio->tx_queue_AC_VO; + break; + case 0x5000: + q = pio->tx_queue_mcast; + break; + } + if (B43_WARN_ON(!q)) + return NULL; + pack_index = (cookie & 0x0FFF); + if (B43_WARN_ON(pack_index >= ARRAY_SIZE(q->packets))) + return NULL; + *pack = &q->packets[pack_index]; + + return q; +} + +static u16 index_to_pioqueue_base(struct b43_wldev *dev, + unsigned int index) +{ + static const u16 bases[] = { + B43_MMIO_PIO_BASE0, + B43_MMIO_PIO_BASE1, + B43_MMIO_PIO_BASE2, + B43_MMIO_PIO_BASE3, + B43_MMIO_PIO_BASE4, + B43_MMIO_PIO_BASE5, + B43_MMIO_PIO_BASE6, + B43_MMIO_PIO_BASE7, + }; + static const u16 bases_rev11[] = { + B43_MMIO_PIO11_BASE0, + B43_MMIO_PIO11_BASE1, + B43_MMIO_PIO11_BASE2, + B43_MMIO_PIO11_BASE3, + B43_MMIO_PIO11_BASE4, + B43_MMIO_PIO11_BASE5, + }; + + if (dev->dev->id.revision >= 11) { + B43_WARN_ON(index >= ARRAY_SIZE(bases_rev11)); + return bases_rev11[index]; + } + B43_WARN_ON(index >= ARRAY_SIZE(bases)); + return bases[index]; +} + +static u16 pio_txqueue_offset(struct b43_wldev *dev) +{ + if (dev->dev->id.revision >= 11) + return 0x18; + return 0; +} + +static u16 pio_rxqueue_offset(struct b43_wldev *dev) +{ + if (dev->dev->id.revision >= 11) + return 0x38; + return 8; +} + +static struct b43_pio_txqueue * b43_setup_pioqueue_tx(struct b43_wldev *dev, + unsigned int index) +{ + struct b43_pio_txqueue *q; + struct b43_pio_txpacket *p; + unsigned int i; + + q = kzalloc(sizeof(*q), GFP_KERNEL); + if (!q) + return NULL; + spin_lock_init(&q->lock); + q->dev = dev; + q->rev = dev->dev->id.revision; + q->mmio_base = index_to_pioqueue_base(dev, index) + + pio_txqueue_offset(dev); + q->index = index; + + q->free_packet_slots = B43_PIO_MAX_NR_TXPACKETS; + if (q->rev >= 8) { + q->buffer_size = 1920; //FIXME this constant is wrong. + } else { + q->buffer_size = b43_piotx_read16(q, B43_PIO_TXQBUFSIZE); + q->buffer_size -= 80; + } + + INIT_LIST_HEAD(&q->packets_list); + for (i = 0; i < ARRAY_SIZE(q->packets); i++) { + p = &(q->packets[i]); + INIT_LIST_HEAD(&p->list); + p->index = i; + p->queue = q; + list_add(&p->list, &q->packets_list); + } + + return q; +} + +static struct b43_pio_rxqueue * b43_setup_pioqueue_rx(struct b43_wldev *dev, + unsigned int index) +{ + struct b43_pio_rxqueue *q; + + q = kzalloc(sizeof(*q), GFP_KERNEL); + if (!q) + return NULL; + spin_lock_init(&q->lock); + q->dev = dev; + q->rev = dev->dev->id.revision; + q->mmio_base = index_to_pioqueue_base(dev, index) + + pio_rxqueue_offset(dev); + INIT_WORK(&q->rx_work, b43_pio_rx_work); + + /* Enable Direct FIFO RX (PIO) on the engine. */ + b43_dma_direct_fifo_rx(dev, index, 1); + + return q; +} + +static void b43_pio_cancel_tx_packets(struct b43_pio_txqueue *q) +{ + struct b43_pio_txpacket *pack; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(q->packets); i++) { + pack = &(q->packets[i]); + if (pack->skb) { + dev_kfree_skb_any(pack->skb); + pack->skb = NULL; + } + } +} + +static void b43_destroy_pioqueue_tx(struct b43_pio_txqueue *q, + const char *name) +{ + if (!q) + return; + b43_pio_cancel_tx_packets(q); + kfree(q); +} + +static void b43_destroy_pioqueue_rx(struct b43_pio_rxqueue *q, + const char *name) +{ + if (!q) + return; + kfree(q); +} + +#define destroy_queue_tx(pio, queue) do { \ + b43_destroy_pioqueue_tx((pio)->queue, __stringify(queue)); \ + (pio)->queue = NULL; \ + } while (0) + +#define destroy_queue_rx(pio, queue) do { \ + b43_destroy_pioqueue_rx((pio)->queue, __stringify(queue)); \ + (pio)->queue = NULL; \ + } while (0) + +void b43_pio_free(struct b43_wldev *dev) +{ + struct b43_pio *pio; + + if (!b43_using_pio_transfers(dev)) + return; + pio = &dev->pio; + + destroy_queue_rx(pio, rx_queue); + destroy_queue_tx(pio, tx_queue_mcast); + destroy_queue_tx(pio, tx_queue_AC_VO); + destroy_queue_tx(pio, tx_queue_AC_VI); + destroy_queue_tx(pio, tx_queue_AC_BE); + destroy_queue_tx(pio, tx_queue_AC_BK); +} + +void b43_pio_stop(struct b43_wldev *dev) +{ + if (!b43_using_pio_transfers(dev)) + return; + cancel_work_sync(&dev->pio.rx_queue->rx_work); +} + +int b43_pio_init(struct b43_wldev *dev) +{ + struct b43_pio *pio = &dev->pio; + int err = -ENOMEM; + + b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL) + & ~B43_MACCTL_BE); + b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_RXPADOFF, 0); + + pio->tx_queue_AC_BK = b43_setup_pioqueue_tx(dev, 0); + if (!pio->tx_queue_AC_BK) + goto out; + + pio->tx_queue_AC_BE = b43_setup_pioqueue_tx(dev, 1); + if (!pio->tx_queue_AC_BE) + goto err_destroy_bk; + + pio->tx_queue_AC_VI = b43_setup_pioqueue_tx(dev, 2); + if (!pio->tx_queue_AC_VI) + goto err_destroy_be; + + pio->tx_queue_AC_VO = b43_setup_pioqueue_tx(dev, 3); + if (!pio->tx_queue_AC_VO) + goto err_destroy_vi; + + pio->tx_queue_mcast = b43_setup_pioqueue_tx(dev, 4); + if (!pio->tx_queue_mcast) + goto err_destroy_vo; + + pio->rx_queue = b43_setup_pioqueue_rx(dev, 0); + if (!pio->rx_queue) + goto err_destroy_mcast; + + b43dbg(dev->wl, "PIO initialized\n"); + err = 0; +out: + return err; + +err_destroy_mcast: + destroy_queue_tx(pio, tx_queue_mcast); +err_destroy_vo: + destroy_queue_tx(pio, tx_queue_AC_VO); +err_destroy_vi: + destroy_queue_tx(pio, tx_queue_AC_VI); +err_destroy_be: + destroy_queue_tx(pio, tx_queue_AC_BE); +err_destroy_bk: + destroy_queue_tx(pio, tx_queue_AC_BK); + return err; +} + +/* Static mapping of mac80211's queues (priorities) to b43 PIO queues. */ +static struct b43_pio_txqueue * select_queue_by_priority(struct b43_wldev *dev, + u8 queue_prio) +{ + struct b43_pio_txqueue *q; + + if (b43_modparam_qos) { + /* 0 = highest priority */ + switch (queue_prio) { + default: + B43_WARN_ON(1); + /* fallthrough */ + case 0: + q = dev->pio.tx_queue_AC_VO; + break; + case 1: + q = dev->pio.tx_queue_AC_VI; + break; + case 2: + q = dev->pio.tx_queue_AC_BE; + break; + case 3: + q = dev->pio.tx_queue_AC_BK; + break; + } + } else + q = dev->pio.tx_queue_AC_BE; + + return q; +} + +static inline void tx_write_2byte_queue(struct b43_pio_txqueue *q, + u16 *ctl, + const void *_data, + unsigned int data_len) +{ + const u8 *data = _data; + unsigned int i; + u16 value; + + *ctl |= B43_PIO_TXCTL_WRITELO | B43_PIO_TXCTL_WRITEHI; + b43_piotx_write16(q, B43_PIO_TXCTL, *ctl); + for (i = 0; i < data_len; i += 2) { + value = data[i]; + if (i + 1 < data_len) { + value |= (u16)(data[i + 1]) << 8; + } else { + *ctl &= ~B43_PIO_TXCTL_WRITEHI; + b43_piotx_write16(q, B43_PIO_TXCTL, *ctl); + } + b43_piotx_write16(q, B43_PIO_TXDATA, value); + } +} + +static void pio_tx_frame_2byte_queue(struct b43_pio_txpacket *pack, + const u8 *hdr, unsigned int hdrlen) +{ + struct b43_pio_txqueue *q = pack->queue; + const char *frame = pack->skb->data; + unsigned int frame_len = pack->skb->len; + u16 ctl; + + ctl = b43_piotx_read16(q, B43_PIO_TXCTL); + ctl |= B43_PIO_TXCTL_FREADY; + ctl &= ~B43_PIO_TXCTL_EOF; + + /* Transfer the header data. */ + tx_write_2byte_queue(q, &ctl, hdr, hdrlen); + /* Transfer the frame data. */ + tx_write_2byte_queue(q, &ctl, frame, frame_len); + + ctl |= B43_PIO_TXCTL_EOF; + b43_piotx_write16(q, B43_PIO_TXCTL, ctl); +} + +static inline void tx_write_4byte_queue(struct b43_pio_txqueue *q, + u32 *ctl, + const void *_data, + unsigned int data_len) +{ + const u8 *data = _data; + unsigned int i; + u32 value; + bool ctl_changed = 0; + + *ctl |= B43_PIO8_TXCTL_0_7 | B43_PIO8_TXCTL_8_15 | + B43_PIO8_TXCTL_16_23 | B43_PIO8_TXCTL_24_31; + b43_piotx_write32(q, B43_PIO8_TXCTL, *ctl); + for (i = 0; i < data_len; i += 4) { + value = data[i]; + if (i + 1 < data_len) { + value |= (u32)(data[i + 1]) << 8; + } else { + *ctl &= ~B43_PIO8_TXCTL_8_15; + ctl_changed = 1; + } + if (i + 2 < data_len) { + value |= (u32)(data[i + 2]) << 16; + } else { + *ctl &= ~B43_PIO8_TXCTL_16_23; + ctl_changed = 1; + } + if (i + 3 < data_len) { + value |= (u32)(data[i + 3]) << 24; + } else { + *ctl &= ~B43_PIO8_TXCTL_24_31; + ctl_changed = 1; + } + if (ctl_changed) + b43_piotx_write32(q, B43_PIO8_TXCTL, *ctl); + b43_piotx_write32(q, B43_PIO8_TXDATA, value); + } +} + +static void pio_tx_frame_4byte_queue(struct b43_pio_txpacket *pack, + const u8 *hdr, unsigned int hdrlen) +{ + struct b43_pio_txqueue *q = pack->queue; + const char *frame = pack->skb->data; + unsigned int frame_len = pack->skb->len; + u32 ctl; + + ctl = b43_piotx_read32(q, B43_PIO8_TXCTL); + ctl |= B43_PIO8_TXCTL_FREADY; + ctl &= ~B43_PIO8_TXCTL_EOF; + + /* Transfer the header data. */ + tx_write_4byte_queue(q, &ctl, hdr, hdrlen); + /* Transfer the frame data. */ + tx_write_4byte_queue(q, &ctl, frame, frame_len); + + ctl |= B43_PIO8_TXCTL_EOF; + b43_piotx_write32(q, B43_PIO_TXCTL, ctl); +} + +static int pio_tx_frame(struct b43_pio_txqueue *q, + struct sk_buff *skb, + struct ieee80211_tx_control *ctl) +{ + struct b43_pio_txpacket *pack; + struct b43_txhdr txhdr; + u16 cookie; + int err; + unsigned int hdrlen; + + B43_WARN_ON(list_empty(&q->packets_list)); + pack = list_entry(q->packets_list.next, + struct b43_pio_txpacket, list); + memset(&pack->txstat, 0, sizeof(pack->txstat)); + memcpy(&pack->txstat.control, ctl, sizeof(*ctl)); + + cookie = generate_cookie(q, pack); + hdrlen = b43_txhdr_size(q->dev); + err = b43_generate_txhdr(q->dev, (u8 *)&txhdr, skb->data, + skb->len, ctl, cookie); + if (err) + return err; + + if (ctl->flags & IEEE80211_TXCTL_SEND_AFTER_DTIM) { + /* Tell the firmware about the cookie of the last + * mcast frame, so it can clear the more-data bit in it. */ + b43_shm_write16(q->dev, B43_SHM_SHARED, + B43_SHM_SH_MCASTCOOKIE, cookie); + } + + pack->skb = skb; + if (q->rev >= 8) + pio_tx_frame_4byte_queue(pack, (const u8 *)&txhdr, hdrlen); + else + pio_tx_frame_2byte_queue(pack, (const u8 *)&txhdr, hdrlen); + + /* Remove it from the list of available packet slots. + * It will be put back when we receive the status report. */ + list_del(&pack->list); + + /* Update the queue statistics. */ + q->buffer_used += roundup(skb->len + hdrlen, 4); + q->free_packet_slots -= 1; + + return 0; +} + +int b43_pio_tx(struct b43_wldev *dev, + struct sk_buff *skb, struct ieee80211_tx_control *ctl) +{ + struct b43_pio_txqueue *q; + struct ieee80211_hdr *hdr; + unsigned long flags; + unsigned int hdrlen, total_len; + int err = 0; + + hdr = (struct ieee80211_hdr *)skb->data; + if (ctl->flags & IEEE80211_TXCTL_SEND_AFTER_DTIM) { + /* The multicast queue will be sent after the DTIM. */ + q = dev->pio.tx_queue_mcast; + /* Set the frame More-Data bit. Ucode will clear it + * for us on the last frame. */ + hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA); + } else { + /* Decide by priority where to put this frame. */ + q = select_queue_by_priority(dev, ctl->queue); + } + + spin_lock_irqsave(&q->lock, flags); + + hdrlen = b43_txhdr_size(dev); + total_len = roundup(skb->len + hdrlen, 4); + + if (unlikely(total_len > q->buffer_size)) { + err = -ENOBUFS; + b43dbg(dev->wl, "PIO: TX packet longer than queue.\n"); + goto out_unlock; + } + if (unlikely(q->free_packet_slots == 0)) { + err = -ENOBUFS; + b43warn(dev->wl, "PIO: TX packet overflow.\n"); + goto out_unlock; + } + B43_WARN_ON(q->buffer_used > q->buffer_size); + + if (total_len > (q->buffer_size - q->buffer_used)) { + /* Not enough memory on the queue. */ + err = -EBUSY; + ieee80211_stop_queue(dev->wl->hw, ctl->queue); + q->stopped = 1; + goto out_unlock; + } + + /* Assign the queue number to the ring (if not already done before) + * so TX status handling can use it. The mac80211-queue to b43-queue + * mapping is static, so we don't need to store it per frame. */ + q->queue_prio = ctl->queue; + + err = pio_tx_frame(q, skb, ctl); + if (unlikely(err == -ENOKEY)) { + /* Drop this packet, as we don't have the encryption key + * anymore and must not transmit it unencrypted. */ + dev_kfree_skb_any(skb); + err = 0; + goto out_unlock; + } + if (unlikely(err)) { + b43err(dev->wl, "PIO transmission failure\n"); + goto out_unlock; + } + q->nr_tx_packets++; + + B43_WARN_ON(q->buffer_used > q->buffer_size); + if (((q->buffer_size - q->buffer_used) < roundup(2 + 2 + 6, 4)) || + (q->free_packet_slots == 0)) { + /* The queue is full. */ + ieee80211_stop_queue(dev->wl->hw, ctl->queue); + q->stopped = 1; + } + +out_unlock: + spin_unlock_irqrestore(&q->lock, flags); + + return err; +} + +/* Called with IRQs disabled. */ +void b43_pio_handle_txstatus(struct b43_wldev *dev, + const struct b43_txstatus *status) +{ + struct b43_pio_txqueue *q; + struct b43_pio_txpacket *pack = NULL; + unsigned int total_len; + + q = parse_cookie(dev, status->cookie, &pack); + if (unlikely(!q)) + return; + B43_WARN_ON(!pack); + + spin_lock(&q->lock); /* IRQs are already disabled. */ + + b43_fill_txstatus_report(&(pack->txstat), status); + + total_len = pack->skb->len + b43_txhdr_size(dev); + total_len = roundup(total_len, 4); + q->buffer_used -= total_len; + q->free_packet_slots += 1; + + ieee80211_tx_status_irqsafe(dev->wl->hw, pack->skb, + &(pack->txstat)); + pack->skb = NULL; + list_add(&pack->list, &q->packets_list); + + if (q->stopped) { + ieee80211_wake_queue(dev->wl->hw, q->queue_prio); + q->stopped = 0; + } + + spin_unlock(&q->lock); +} + +void b43_pio_get_tx_stats(struct b43_wldev *dev, + struct ieee80211_tx_queue_stats *stats) +{ + const int nr_queues = dev->wl->hw->queues; + struct b43_pio_txqueue *q; + struct ieee80211_tx_queue_stats_data *data; + unsigned long flags; + int i; + + for (i = 0; i < nr_queues; i++) { + data = &(stats->data[i]); + q = select_queue_by_priority(dev, i); + + spin_lock_irqsave(&q->lock, flags); + data->len = B43_PIO_MAX_NR_TXPACKETS - q->free_packet_slots; + data->limit = B43_PIO_MAX_NR_TXPACKETS; + data->count = q->nr_tx_packets; + spin_unlock_irqrestore(&q->lock, flags); + } +} + +/* Returns whether we should fetch another frame. */ +static bool pio_rx_frame(struct b43_pio_rxqueue *q) +{ + struct b43_rxhdr_fw4 rxhdr; + u16 len; + u32 macstat; + unsigned int i, padding; + struct sk_buff *skb; + const char *err_msg = NULL; + + memset(&rxhdr, 0, sizeof(rxhdr)); + + /* Check if we have data and wait for it to get ready. */ + if (q->rev >= 8) { + u32 ctl; + + ctl = b43_piorx_read32(q, B43_PIO8_RXCTL); + if (!(ctl & B43_PIO8_RXCTL_FRAMERDY)) + return 0; + b43_piorx_write32(q, B43_PIO8_RXCTL, + B43_PIO8_RXCTL_FRAMERDY); + for (i = 0; i < 10; i++) { + ctl = b43_piorx_read32(q, B43_PIO8_RXCTL); + if (ctl & B43_PIO8_RXCTL_DATARDY) + goto data_ready; + udelay(10); + } + } else { + u16 ctl; + + ctl = b43_piorx_read16(q, B43_PIO_RXCTL); + if (!(ctl & B43_PIO_RXCTL_FRAMERDY)) + return 0; + b43_piorx_write16(q, B43_PIO_RXCTL, + B43_PIO_RXCTL_FRAMERDY); + for (i = 0; i < 10; i++) { + ctl = b43_piorx_read16(q, B43_PIO_RXCTL); + if (ctl & B43_PIO_RXCTL_DATARDY) + goto data_ready; + udelay(10); + } + } + b43dbg(q->dev->wl, "PIO RX timed out\n"); + return 1; +data_ready: + + /* Get the preamble (RX header) */ + if (q->rev >= 8) { + u32 *preamble = (u32 *)&rxhdr; + u32 value; + + for (i = 0; i < sizeof(rxhdr); i += 4) { + value = b43_piorx_read32(q, B43_PIO8_RXDATA); + preamble[i / 4] = cpu_to_le32(value); + } + } else { + u16 *preamble = (u16 *)&rxhdr; + u16 value; + + for (i = 0; i < sizeof(rxhdr); i += 2) { + value = b43_piorx_read16(q, B43_PIO_RXDATA); + preamble[i / 2] = cpu_to_le16(value); + } + } + /* Sanity checks. */ + len = le16_to_cpu(rxhdr.frame_len); + if (unlikely(len > 0x700)) { + err_msg = "len > 0x700"; + goto rx_error; + } + if (unlikely(len == 0)) { + err_msg = "len == 0"; + goto rx_error; + } + + macstat = le32_to_cpu(rxhdr.mac_status); + if (macstat & B43_RX_MAC_FCSERR) { + if (!(q->dev->wl->filter_flags & FIF_FCSFAIL)) { + /* Drop frames with failed FCS. */ + err_msg = "Frame FCS error"; + goto rx_error; + } + } + + /* We always pad 2 bytes, as that's what upstream code expects + * due to the RX-header being 30 bytes. In case the frame is + * unaligned, we pad another 2 bytes. */ + padding = (macstat & B43_RX_MAC_PADDING) ? 2 : 0; + skb = dev_alloc_skb(len + padding + 2); + if (unlikely(!skb)) { + err_msg = "Out of memory"; + goto rx_error; + } + skb_reserve(skb, 2); + skb_put(skb, len + padding); + if (q->rev >= 8) { + u32 value; + + for (i = padding; i < len + padding; i += 4) { + value = b43_piorx_read32(q, B43_PIO8_RXDATA); + skb->data[i] = value; + if ((i + 1) < (len + padding)) + skb->data[i + 1] = value >> 8; + if ((i + 2) < (len + padding)) + skb->data[i + 2] = value >> 16; + if ((i + 3) < (len + padding)) + skb->data[i + 3] = value >> 24; + } + } else { + u16 value; + + for (i = padding; i < len + padding; i += 2) { + value = b43_piorx_read16(q, B43_PIO_RXDATA); + skb->data[i] = value; + if ((i + 1) < (len + padding)) + skb->data[i + 1] = value >> 8; + } + } + + b43_rx(q->dev, skb, &rxhdr); + + return 1; + +rx_error: + if (err_msg) + b43dbg(q->dev->wl, "PIO RX error: %s\n", err_msg); + b43_piorx_write16(q, B43_PIO_RXCTL, B43_PIO_RXCTL_DATARDY); + return 1; +} + +/* RX workqueue. We can sleep, yay! */ +static void b43_pio_rx_work(struct work_struct *work) +{ + struct b43_pio_rxqueue *q = container_of(work, struct b43_pio_rxqueue, + rx_work); + unsigned int budget = 50; + bool stop; + + do { + spin_lock_irq(&q->lock); + stop = (pio_rx_frame(q) == 0); + spin_unlock_irq(&q->lock); + cond_resched(); + if (stop) + break; + } while (--budget); +} + +/* Called with IRQs disabled. */ +void b43_pio_rx(struct b43_pio_rxqueue *q) +{ + /* Due to latency issues we must run the RX path in + * a workqueue to be able to schedule between packets. */ + queue_work(q->dev->wl->hw->workqueue, &q->rx_work); +} + +static void b43_pio_tx_suspend_queue(struct b43_pio_txqueue *q) +{ + unsigned long flags; + + spin_lock_irqsave(&q->lock, flags); + if (q->rev >= 8) { + b43_piotx_write32(q, B43_PIO8_TXCTL, + b43_piotx_read32(q, B43_PIO8_TXCTL) + | B43_PIO8_TXCTL_SUSPREQ); + } else { + b43_piotx_write16(q, B43_PIO_TXCTL, + b43_piotx_read16(q, B43_PIO_TXCTL) + | B43_PIO_TXCTL_SUSPREQ); + } + spin_unlock_irqrestore(&q->lock, flags); +} + +static void b43_pio_tx_resume_queue(struct b43_pio_txqueue *q) +{ + unsigned long flags; + + spin_lock_irqsave(&q->lock, flags); + if (q->rev >= 8) { + b43_piotx_write32(q, B43_PIO8_TXCTL, + b43_piotx_read32(q, B43_PIO8_TXCTL) + & ~B43_PIO8_TXCTL_SUSPREQ); + } else { + b43_piotx_write16(q, B43_PIO_TXCTL, + b43_piotx_read16(q, B43_PIO_TXCTL) + & ~B43_PIO_TXCTL_SUSPREQ); + } + spin_unlock_irqrestore(&q->lock, flags); +} + +void b43_pio_tx_suspend(struct b43_wldev *dev) +{ + b43_power_saving_ctl_bits(dev, B43_PS_AWAKE); + b43_pio_tx_suspend_queue(dev->pio.tx_queue_AC_BK); + b43_pio_tx_suspend_queue(dev->pio.tx_queue_AC_BE); + b43_pio_tx_suspend_queue(dev->pio.tx_queue_AC_VI); + b43_pio_tx_suspend_queue(dev->pio.tx_queue_AC_VO); + b43_pio_tx_suspend_queue(dev->pio.tx_queue_mcast); +} + +void b43_pio_tx_resume(struct b43_wldev *dev) +{ + b43_pio_tx_resume_queue(dev->pio.tx_queue_mcast); + b43_pio_tx_resume_queue(dev->pio.tx_queue_AC_VO); + b43_pio_tx_resume_queue(dev->pio.tx_queue_AC_VI); + b43_pio_tx_resume_queue(dev->pio.tx_queue_AC_BE); + b43_pio_tx_resume_queue(dev->pio.tx_queue_AC_BK); + b43_power_saving_ctl_bits(dev, 0); +} diff --git a/drivers/net/wireless/b43/pio.h b/drivers/net/wireless/b43/pio.h new file mode 100644 index 000000000000..e2ec676cc9e4 --- /dev/null +++ b/drivers/net/wireless/b43/pio.h @@ -0,0 +1,220 @@ +#ifndef B43_PIO_H_ +#define B43_PIO_H_ + +#include "b43.h" + +#include +#include +#include +#include + + +/*** Registers for PIO queues up to revision 7. ***/ +/* TX queue. */ +#define B43_PIO_TXCTL 0x00 +#define B43_PIO_TXCTL_WRITELO 0x0001 +#define B43_PIO_TXCTL_WRITEHI 0x0002 +#define B43_PIO_TXCTL_EOF 0x0004 +#define B43_PIO_TXCTL_FREADY 0x0008 +#define B43_PIO_TXCTL_FLUSHREQ 0x0020 +#define B43_PIO_TXCTL_FLUSHPEND 0x0040 +#define B43_PIO_TXCTL_SUSPREQ 0x0080 +#define B43_PIO_TXCTL_QSUSP 0x0100 +#define B43_PIO_TXCTL_COMMCNT 0xFC00 +#define B43_PIO_TXCTL_COMMCNT_SHIFT 10 +#define B43_PIO_TXDATA 0x02 +#define B43_PIO_TXQBUFSIZE 0x04 +/* RX queue. */ +#define B43_PIO_RXCTL 0x00 +#define B43_PIO_RXCTL_FRAMERDY 0x0001 +#define B43_PIO_RXCTL_DATARDY 0x0002 +#define B43_PIO_RXDATA 0x02 + +/*** Registers for PIO queues revision 8 and later. ***/ +/* TX queue */ +#define B43_PIO8_TXCTL 0x00 +#define B43_PIO8_TXCTL_0_7 0x00000001 +#define B43_PIO8_TXCTL_8_15 0x00000002 +#define B43_PIO8_TXCTL_16_23 0x00000004 +#define B43_PIO8_TXCTL_24_31 0x00000008 +#define B43_PIO8_TXCTL_EOF 0x00000010 +#define B43_PIO8_TXCTL_FREADY 0x00000080 +#define B43_PIO8_TXCTL_SUSPREQ 0x00000100 +#define B43_PIO8_TXCTL_QSUSP 0x00000200 +#define B43_PIO8_TXCTL_FLUSHREQ 0x00000400 +#define B43_PIO8_TXCTL_FLUSHPEND 0x00000800 +#define B43_PIO8_TXDATA 0x04 +/* RX queue */ +#define B43_PIO8_RXCTL 0x00 +#define B43_PIO8_RXCTL_FRAMERDY 0x00000001 +#define B43_PIO8_RXCTL_DATARDY 0x00000002 +#define B43_PIO8_RXDATA 0x04 + + +/* The maximum number of TX-packets the HW can handle. */ +#define B43_PIO_MAX_NR_TXPACKETS 32 + + +#ifdef CONFIG_B43_PIO + +struct b43_pio_txpacket { + /* Pointer to the TX queue we belong to. */ + struct b43_pio_txqueue *queue; + /* The TX data packet. */ + struct sk_buff *skb; + /* The status meta data. */ + struct ieee80211_tx_status txstat; + /* Index in the (struct b43_pio_txqueue)->packets array. */ + u8 index; + + struct list_head list; +}; + +struct b43_pio_txqueue { + struct b43_wldev *dev; + spinlock_t lock; + u16 mmio_base; + + /* The device queue buffer size in bytes. */ + u16 buffer_size; + /* The number of used bytes in the device queue buffer. */ + u16 buffer_used; + /* The number of packets that can still get queued. + * This is decremented on queueing a packet and incremented + * after receiving the transmit status. */ + u16 free_packet_slots; + + /* True, if the mac80211 queue was stopped due to overflow at TX. */ + bool stopped; + /* Our b43 queue index number */ + u8 index; + /* The mac80211 QoS queue priority. */ + u8 queue_prio; + + /* Buffer for TX packet meta data. */ + struct b43_pio_txpacket packets[B43_PIO_MAX_NR_TXPACKETS]; + struct list_head packets_list; + + /* Total number of transmitted packets. */ + unsigned int nr_tx_packets; + + /* Shortcut to the 802.11 core revision. This is to + * avoid horrible pointer dereferencing in the fastpaths. */ + u8 rev; +}; + +struct b43_pio_rxqueue { + struct b43_wldev *dev; + spinlock_t lock; + u16 mmio_base; + + /* Work to reduce latency issues on RX. */ + struct work_struct rx_work; + + /* Shortcut to the 802.11 core revision. This is to + * avoid horrible pointer dereferencing in the fastpaths. */ + u8 rev; +}; + + +static inline u16 b43_piotx_read16(struct b43_pio_txqueue *q, u16 offset) +{ + return b43_read16(q->dev, q->mmio_base + offset); +} + +static inline u32 b43_piotx_read32(struct b43_pio_txqueue *q, u16 offset) +{ + return b43_read32(q->dev, q->mmio_base + offset); +} + +static inline void b43_piotx_write16(struct b43_pio_txqueue *q, + u16 offset, u16 value) +{ + b43_write16(q->dev, q->mmio_base + offset, value); +} + +static inline void b43_piotx_write32(struct b43_pio_txqueue *q, + u16 offset, u32 value) +{ + b43_write32(q->dev, q->mmio_base + offset, value); +} + + +static inline u16 b43_piorx_read16(struct b43_pio_rxqueue *q, u16 offset) +{ + return b43_read16(q->dev, q->mmio_base + offset); +} + +static inline u32 b43_piorx_read32(struct b43_pio_rxqueue *q, u16 offset) +{ + return b43_read32(q->dev, q->mmio_base + offset); +} + +static inline void b43_piorx_write16(struct b43_pio_rxqueue *q, + u16 offset, u16 value) +{ + b43_write16(q->dev, q->mmio_base + offset, value); +} + +static inline void b43_piorx_write32(struct b43_pio_rxqueue *q, + u16 offset, u32 value) +{ + b43_write32(q->dev, q->mmio_base + offset, value); +} + + +int b43_pio_init(struct b43_wldev *dev); +void b43_pio_stop(struct b43_wldev *dev); +void b43_pio_free(struct b43_wldev *dev); + +int b43_pio_tx(struct b43_wldev *dev, + struct sk_buff *skb, struct ieee80211_tx_control *ctl); +void b43_pio_handle_txstatus(struct b43_wldev *dev, + const struct b43_txstatus *status); +void b43_pio_get_tx_stats(struct b43_wldev *dev, + struct ieee80211_tx_queue_stats *stats); +void b43_pio_rx(struct b43_pio_rxqueue *q); + +void b43_pio_tx_suspend(struct b43_wldev *dev); +void b43_pio_tx_resume(struct b43_wldev *dev); + + +#else /* CONFIG_B43_PIO */ + + +static inline int b43_pio_init(struct b43_wldev *dev) +{ + return 0; +} +static inline void b43_pio_free(struct b43_wldev *dev) +{ +} +static inline void b43_pio_stop(struct b43_wldev *dev) +{ +} +static inline int b43_pio_tx(struct b43_wldev *dev, + struct sk_buff *skb, + struct ieee80211_tx_control *ctl) +{ + return 0; +} +static inline void b43_pio_handle_txstatus(struct b43_wldev *dev, + const struct b43_txstatus *status) +{ +} +static inline void b43_pio_get_tx_stats(struct b43_wldev *dev, + struct ieee80211_tx_queue_stats *stats) +{ +} +static inline void b43_pio_rx(struct b43_pio_rxqueue *q) +{ +} +static inline void b43_pio_tx_suspend(struct b43_wldev *dev) +{ +} +static inline void b43_pio_tx_resume(struct b43_wldev *dev) +{ +} + +#endif /* CONFIG_B43_PIO */ +#endif /* B43_PIO_H_ */ diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index ec10a8e182f9..b2a3123f42db 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c @@ -30,6 +30,7 @@ #include "xmit.h" #include "phy.h" #include "dma.h" +#include "pio.h" /* Extract the bitrate index out of a CCK PLCP header. */ @@ -668,40 +669,54 @@ void b43_handle_txstatus(struct b43_wldev *dev, dev->wl->ieee_stats.dot11RTSSuccessCount++; } - b43_dma_handle_txstatus(dev, status); + if (b43_using_pio_transfers(dev)) + b43_pio_handle_txstatus(dev, status); + else + b43_dma_handle_txstatus(dev, status); } -/* Handle TX status report as received through DMA/PIO queues */ -void b43_handle_hwtxstatus(struct b43_wldev *dev, - const struct b43_hwtxstatus *hw) +/* Fill out the mac80211 TXstatus report based on the b43-specific + * txstatus report data. This returns a boolean whether the frame was + * successfully transmitted. */ +bool b43_fill_txstatus_report(struct ieee80211_tx_status *report, + const struct b43_txstatus *status) { - struct b43_txstatus status; - u8 tmp; - - status.cookie = le16_to_cpu(hw->cookie); - status.seq = le16_to_cpu(hw->seq); - status.phy_stat = hw->phy_stat; - tmp = hw->count; - status.frame_count = (tmp >> 4); - status.rts_count = (tmp & 0x0F); - tmp = hw->flags; - status.supp_reason = ((tmp & 0x1C) >> 2); - status.pm_indicated = !!(tmp & 0x80); - status.intermediate = !!(tmp & 0x40); - status.for_ampdu = !!(tmp & 0x20); - status.acked = !!(tmp & 0x02); - - b43_handle_txstatus(dev, &status); + bool frame_success = 1; + + if (status->acked) { + /* The frame was ACKed. */ + report->flags |= IEEE80211_TX_STATUS_ACK; + } else { + /* The frame was not ACKed... */ + if (!(report->control.flags & IEEE80211_TXCTL_NO_ACK)) { + /* ...but we expected an ACK. */ + frame_success = 0; + report->excessive_retries = 1; + } + } + if (status->frame_count == 0) { + /* The frame was not transmitted at all. */ + report->retry_count = 0; + } else + report->retry_count = status->frame_count - 1; + + return frame_success; } /* Stop any TX operation on the device (suspend the hardware queues) */ void b43_tx_suspend(struct b43_wldev *dev) { - b43_dma_tx_suspend(dev); + if (b43_using_pio_transfers(dev)) + b43_pio_tx_suspend(dev); + else + b43_dma_tx_suspend(dev); } /* Resume any TX operation on the device (resume the hardware queues) */ void b43_tx_resume(struct b43_wldev *dev) { - b43_dma_tx_resume(dev); + if (b43_using_pio_transfers(dev)) + b43_pio_tx_resume(dev); + else + b43_dma_tx_resume(dev); } diff --git a/drivers/net/wireless/b43/xmit.h b/drivers/net/wireless/b43/xmit.h index bf58a8a85258..4f26988a5132 100644 --- a/drivers/net/wireless/b43/xmit.h +++ b/drivers/net/wireless/b43/xmit.h @@ -207,18 +207,6 @@ enum { B43_TXST_SUPP_ABNACK, /* Afterburner NACK */ }; -/* Transmit Status as received through DMA/PIO on old chips */ -struct b43_hwtxstatus { - PAD_BYTES(4); - __le16 cookie; - u8 flags; - u8 count; - PAD_BYTES(2); - __le16 seq; - u8 phy_stat; - PAD_BYTES(1); -} __attribute__ ((__packed__)); - /* Receive header for v4 firmware. */ struct b43_rxhdr_fw4 { __le16 frame_len; /* Frame length */ @@ -295,9 +283,8 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr); void b43_handle_txstatus(struct b43_wldev *dev, const struct b43_txstatus *status); - -void b43_handle_hwtxstatus(struct b43_wldev *dev, - const struct b43_hwtxstatus *hw); +bool b43_fill_txstatus_report(struct ieee80211_tx_status *report, + const struct b43_txstatus *status); void b43_tx_suspend(struct b43_wldev *dev); void b43_tx_resume(struct b43_wldev *dev); -- cgit v1.2.1 From 8fe2b65a18e49bfde56a59ed4ab3fc7aa0c2f325 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sun, 30 Mar 2008 00:10:50 +0100 Subject: ssb: Turn suspend/resume upside down Turn the SSB bus suspend mechanism upside down. Instead of deciding by an internal reference count when to suspend/resume, let the parent bus call us in their suspend/resume routine. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/pcmcia.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/b43/pcmcia.c b/drivers/net/wireless/b43/pcmcia.c index 371e4a119511..b8aa16307f79 100644 --- a/drivers/net/wireless/b43/pcmcia.c +++ b/drivers/net/wireless/b43/pcmcia.c @@ -43,14 +43,16 @@ MODULE_DEVICE_TABLE(pcmcia, b43_pcmcia_tbl); #ifdef CONFIG_PM static int b43_pcmcia_suspend(struct pcmcia_device *dev) { - //TODO - return 0; + struct ssb_bus *ssb = dev->priv; + + return ssb_bus_suspend(ssb); } static int b43_pcmcia_resume(struct pcmcia_device *dev) { - //TODO - return 0; + struct ssb_bus *ssb = dev->priv; + + return ssb_bus_resume(ssb); } #else /* CONFIG_PM */ # define b43_pcmcia_suspend NULL -- cgit v1.2.1 From 7b463ced635231dd1d4ca6d8b1d93f9353b9dc3a Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 1 Apr 2008 15:17:36 -0400 Subject: prism54: set carrier flags correctly > prism54 should set the carrier flags correctly when it thinks the > link can be used. Agreed, so sure, this is OK but I rather we turn the carrier on or off *before* sending an event, like this. Signed-off-by: Roy Marples Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/prism54/isl_ioctl.c | 5 ++++- drivers/net/wireless/prism54/islpci_dev.c | 4 +++- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c index 2e25e190f334..e5b3c282009c 100644 --- a/drivers/net/wireless/prism54/isl_ioctl.c +++ b/drivers/net/wireless/prism54/isl_ioctl.c @@ -2081,6 +2081,7 @@ link_changed(struct net_device *ndev, u32 bitrate) islpci_private *priv = netdev_priv(ndev); if (bitrate) { + netif_carrier_on(ndev); if (priv->iw_mode == IW_MODE_INFRA) { union iwreq_data uwrq; prism54_get_wap(ndev, NULL, (struct sockaddr *) &uwrq, @@ -2089,8 +2090,10 @@ link_changed(struct net_device *ndev, u32 bitrate) } else send_simple_event(netdev_priv(ndev), "Link established"); - } else + } else { + netif_carrier_off(ndev); send_simple_event(netdev_priv(ndev), "Link lost"); + } } /* Beacon/ProbeResp payload header */ diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c index eb7c1c6bcd8a..04c2638d75ad 100644 --- a/drivers/net/wireless/prism54/islpci_dev.c +++ b/drivers/net/wireless/prism54/islpci_dev.c @@ -387,7 +387,9 @@ islpci_open(struct net_device *ndev) } netif_start_queue(ndev); -/* netif_mark_up( ndev ); */ + + /* Turn off carrier unless we know we have associated */ + netif_carrier_off(ndev); return 0; } -- cgit v1.2.1 From 2aee82de5238625a7664f88d6ebff9de467bb685 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 1 Apr 2008 02:56:32 +0200 Subject: wavelan_cs: stop inlining largish static functions Hi John, Can you please take a look at this patch? drivers/net/wireless/wavelan_cs.c has unusually large number of static inline functions - 27. I looked through them and 20 of them do not seem to warrant inlining. Some are really big; others call mdelay(1) or busy-wait for a bit to be set in a hardware register - it's pointless to optimize such functions for speed. This patch removes "inline" from these static function (regardless of number of callsites - gcc nowadays auto-inlines statics with one callsite). Size difference for 32bit x86: text data bss dec hex filename 17020 372 8 17400 43f8 linux-2.6-ALLYES/drivers/net/wireless/wavelan_cs.o 14032 356 8 14396 383c linux-2.6.inline-ALLYES/drivers/net/wireless/wavelan_cs.o Signed-off-by: Denys Vlasenko -- vda Signed-off-by: John W. Linville --- drivers/net/wireless/wavelan_cs.c | 47 ++++++++++++++++++------------------- drivers/net/wireless/wavelan_cs.p.h | 26 ++++++++++---------- 2 files changed, 36 insertions(+), 37 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c index 06eea6ab7bf0..baf74015751c 100644 --- a/drivers/net/wireless/wavelan_cs.c +++ b/drivers/net/wireless/wavelan_cs.c @@ -102,7 +102,7 @@ hacr_write(u_long base, * Write to card's Host Adapter Command Register. Include a delay for * those times when it is needed. */ -static inline void +static void hacr_write_slow(u_long base, u_char hacr) { @@ -255,7 +255,7 @@ update_psa_checksum(struct net_device * dev) /* * Write 1 byte to the MMC. */ -static inline void +static void mmc_out(u_long base, u_short o, u_char d) @@ -275,7 +275,7 @@ mmc_out(u_long base, * Routine to write bytes to the Modem Management Controller. * We start by the end because it is the way it should be ! */ -static inline void +static void mmc_write(u_long base, u_char o, u_char * b, @@ -293,7 +293,7 @@ mmc_write(u_long base, * Read 1 byte from the MMC. * Optimised version for 1 byte, avoid using memory... */ -static inline u_char +static u_char mmc_in(u_long base, u_short o) { @@ -318,7 +318,7 @@ mmc_in(u_long base, * (code has just been moved in the above function) * We start by the end because it is the way it should be ! */ -static inline void +static void mmc_read(u_long base, u_char o, u_char * b, @@ -350,9 +350,8 @@ mmc_encr(u_long base) /* i/o port of the card */ /*------------------------------------------------------------------*/ /* * Wait for the frequency EEprom to complete a command... - * I hope this one will be optimally inlined... */ -static inline void +static void fee_wait(u_long base, /* i/o port of the card */ int delay, /* Base delay to wait for */ int number) /* Number of time to wait */ @@ -738,9 +737,9 @@ static void wv_roam_handover(wavepoint_history *wavepoint, net_local *lp) } /* Called when a WavePoint beacon is received */ -static inline void wl_roam_gather(struct net_device * dev, - u_char * hdr, /* Beacon header */ - u_char * stats) /* SNR, Signal quality +static void wl_roam_gather(struct net_device * dev, + u_char * hdr, /* Beacon header */ + u_char * stats) /* SNR, Signal quality of packet */ { wavepoint_beacon *beacon= (wavepoint_beacon *)hdr; /* Rcvd. Beacon */ @@ -794,7 +793,7 @@ out: static inline int WAVELAN_BEACON(unsigned char *data) { wavepoint_beacon *beacon= (wavepoint_beacon *)data; - static wavepoint_beacon beacon_template={0xaa,0xaa,0x03,0x08,0x00,0x0e,0x20,0x03,0x00}; + static const wavepoint_beacon beacon_template={0xaa,0xaa,0x03,0x08,0x00,0x0e,0x20,0x03,0x00}; if(memcmp(beacon,&beacon_template,9)==0) return 1; @@ -980,7 +979,7 @@ read_ringbuf(struct net_device * dev, * wavelan_interrupt is not an option...), so you may experience * some delay sometime... */ -static inline void +static void wv_82593_reconfig(struct net_device * dev) { net_local * lp = netdev_priv(dev); @@ -1233,7 +1232,7 @@ wv_local_show(struct net_device * dev) /* * Dump packet header (and content if necessary) on the screen */ -static inline void +static void wv_packet_info(u_char * p, /* Packet to dump */ int length, /* Length of the packet */ char * msg1, /* Name of the device */ @@ -1272,7 +1271,7 @@ wv_packet_info(u_char * p, /* Packet to dump */ * This is the information which is displayed by the driver at startup * There is a lot of flag to configure it at your will... */ -static inline void +static void wv_init_info(struct net_device * dev) { unsigned int base = dev->base_addr; @@ -1509,7 +1508,7 @@ wavelan_set_mac_address(struct net_device * dev, * Frequency setting (for hardware able of it) * It's a bit complicated and you don't really want to look into it... */ -static inline int +static int wv_set_frequency(u_long base, /* i/o port of the card */ iw_freq * frequency) { @@ -1706,7 +1705,7 @@ wv_set_frequency(u_long base, /* i/o port of the card */ /* * Give the list of available frequencies */ -static inline int +static int wv_frequency_list(u_long base, /* i/o port of the card */ iw_freq * list, /* List of frequency to fill */ int max) /* Maximum number of frequencies */ @@ -2759,7 +2758,7 @@ wavelan_get_wireless_stats(struct net_device * dev) * frame pointer and verify that the frame seem correct * (called by wv_packet_rcv()) */ -static inline int +static int wv_start_of_frame(struct net_device * dev, int rfp, /* end of frame */ int wrap) /* start of buffer */ @@ -2821,7 +2820,7 @@ wv_start_of_frame(struct net_device * dev, * Note: if any errors occur, the packet is "dropped on the floor" * (called by wv_packet_rcv()) */ -static inline void +static void wv_packet_read(struct net_device * dev, int fd_p, int sksize) @@ -2922,7 +2921,7 @@ wv_packet_read(struct net_device * dev, * (called by wavelan_interrupt()) * Note : the spinlock is already grabbed for us and irq are disabled. */ -static inline void +static void wv_packet_rcv(struct net_device * dev) { unsigned int base = dev->base_addr; @@ -3056,7 +3055,7 @@ wv_packet_rcv(struct net_device * dev) * the transmit. * (called in wavelan_packet_xmit()) */ -static inline void +static void wv_packet_write(struct net_device * dev, void * buf, short length) @@ -3180,7 +3179,7 @@ wavelan_packet_xmit(struct sk_buff * skb, * Routine to initialize the Modem Management Controller. * (called by wv_hw_config()) */ -static inline int +static int wv_mmc_init(struct net_device * dev) { unsigned int base = dev->base_addr; @@ -3699,7 +3698,7 @@ wv_82593_config(struct net_device * dev) * wavelan. * (called by wv_config()) */ -static inline int +static int wv_pcmcia_reset(struct net_device * dev) { int i; @@ -3864,7 +3863,7 @@ wv_hw_config(struct net_device * dev) * 2. Start the LAN controller's receive unit * (called by wavelan_event(), wavelan_watchdog() and wavelan_open()) */ -static inline void +static void wv_hw_reset(struct net_device * dev) { net_local * lp = netdev_priv(dev); @@ -3895,7 +3894,7 @@ wv_hw_reset(struct net_device * dev) * device available to the system. * (called by wavelan_event()) */ -static inline int +static int wv_pcmcia_config(struct pcmcia_device * link) { struct net_device * dev = (struct net_device *) link->priv; diff --git a/drivers/net/wireless/wavelan_cs.p.h b/drivers/net/wireless/wavelan_cs.p.h index 33dd97094227..628192d7248f 100644 --- a/drivers/net/wireless/wavelan_cs.p.h +++ b/drivers/net/wireless/wavelan_cs.p.h @@ -637,7 +637,7 @@ struct net_local /* ----------------- MODEM MANAGEMENT SUBROUTINES ----------------- */ static inline u_char /* data */ hasr_read(u_long); /* Read the host interface : base address */ -static inline void +static void hacr_write(u_long, /* Write to host interface : base address */ u_char), /* data */ hacr_write_slow(u_long, @@ -651,7 +651,7 @@ static void int, /* Offset in psa */ u_char *, /* Buffer in memory */ int); /* Length of buffer */ -static inline void +static void mmc_out(u_long, /* Write 1 byte to the Modem Manag Control */ u_short, u_char), @@ -659,10 +659,10 @@ static inline void u_char, u_char *, int); -static inline u_char /* Read 1 byte from the MMC */ +static u_char /* Read 1 byte from the MMC */ mmc_in(u_long, u_short); -static inline void +static void mmc_read(u_long, /* Read n bytes from the MMC */ u_char, u_char *, @@ -688,10 +688,10 @@ static int int, char *, int); -static inline void +static void wv_82593_reconfig(struct net_device *); /* Reconfigure the controller */ /* ------------------- DEBUG & INFO SUBROUTINES ------------------- */ -static inline void +static void wv_init_info(struct net_device *); /* display startup info */ /* ------------------- IOCTL, STATS & RECONFIG ------------------- */ static en_stats * @@ -699,17 +699,17 @@ static en_stats * static iw_stats * wavelan_get_wireless_stats(struct net_device *); /* ----------------------- PACKET RECEPTION ----------------------- */ -static inline int +static int wv_start_of_frame(struct net_device *, /* Seek beggining of current frame */ int, /* end of frame */ int); /* start of buffer */ -static inline void +static void wv_packet_read(struct net_device *, /* Read a packet from a frame */ int, int), wv_packet_rcv(struct net_device *); /* Read all packets waiting */ /* --------------------- PACKET TRANSMISSION --------------------- */ -static inline void +static void wv_packet_write(struct net_device *, /* Write a packet to the Tx buffer */ void *, short); @@ -717,20 +717,20 @@ static int wavelan_packet_xmit(struct sk_buff *, /* Send a packet */ struct net_device *); /* -------------------- HARDWARE CONFIGURATION -------------------- */ -static inline int +static int wv_mmc_init(struct net_device *); /* Initialize the modem */ static int wv_ru_stop(struct net_device *), /* Stop the i82593 receiver unit */ wv_ru_start(struct net_device *); /* Start the i82593 receiver unit */ static int wv_82593_config(struct net_device *); /* Configure the i82593 */ -static inline int +static int wv_pcmcia_reset(struct net_device *); /* Reset the pcmcia interface */ static int wv_hw_config(struct net_device *); /* Reset & configure the whole hardware */ -static inline void +static void wv_hw_reset(struct net_device *); /* Same, + start receiver unit */ -static inline int +static int wv_pcmcia_config(struct pcmcia_device *); /* Configure the pcmcia interface */ static void wv_pcmcia_release(struct pcmcia_device *);/* Remove a device */ -- cgit v1.2.1 From 16788599a9601cbba6ad7b58b3b52227ea59c013 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Tue, 1 Apr 2008 20:59:32 -0400 Subject: drivers/net/wireless/iwlwifi/iwl-debugfs.c: fix another '%llu' warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/net/wireless/iwlwifi/iwl-debugfs.c: In function ‘iwl_dbgfs_stations_read’: drivers/net/wireless/iwlwifi/iwl-debugfs.c:247: warning: format ‘%llu’ expects type ‘long long unsigned int’, but argument 4 has type ‘u64’ Cc: Reinette Chatre Cc: Andrew Morton Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index b2cc552de738..447ff2ca4137 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -243,7 +243,7 @@ static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf, station->tid[j].agg.wait_for_ba); pos += sprintf(buf+pos, "%u\t%llu\t%u\n", station->tid[j].agg.start_idx, - station->tid[j].agg.bitmap, + (unsigned long long)station->tid[j].agg.bitmap, station->tid[j].agg.rate_n_flags); } pos += sprintf(buf+pos, "\n"); -- cgit v1.2.1 From a0b484fee72fc18eb9145011a5edec922fafbc15 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 1 Apr 2008 17:51:47 +0200 Subject: iwlwifi: fix some warnings This fixes all kinds of warnings in iwlwifi. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 6 +++--- drivers/net/wireless/iwlwifi/iwl-3945.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-4965.c | 5 +++-- drivers/net/wireless/iwlwifi/iwl-4965.h | 4 ++-- 4 files changed, 10 insertions(+), 9 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index eb30819cddc4..0d3cc3559039 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -524,7 +524,7 @@ static void iwl3945_add_radiotap(struct iwl3945_priv *priv, s8 noise = 0; int rate = stats->rate_idx; u64 tsf = stats->mactime; - __le16 phy_flags_hw = rx_hdr->phy_flags; + __le16 phy_flags_hw = rx_hdr->phy_flags, antenna; struct iwl3945_rt_rx_hdr { struct ieee80211_radiotap_header rt_hdr; @@ -596,8 +596,8 @@ static void iwl3945_add_radiotap(struct iwl3945_priv *priv, iwl3945_rt->rt_rate = iwl3945_rates[rate].ieee; /* antenna number */ - iwl3945_rt->rt_antenna = - le16_to_cpu(phy_flags_hw & RX_RES_PHY_FLAGS_ANTENNA_MSK) >> 4; + antenna = phy_flags_hw & RX_RES_PHY_FLAGS_ANTENNA_MSK; + iwl3945_rt->rt_antenna = le16_to_cpu(antenna) >> 4; /* set the preamble flag if we have it */ if (phy_flags_hw & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index ac1226946aa6..333c85077211 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -280,8 +280,8 @@ struct iwl3945_frame { #define SEQ_TO_QUEUE(x) ((x >> 8) & 0xbf) #define QUEUE_TO_SEQ(x) ((x & 0xbf) << 8) -#define SEQ_TO_INDEX(x) (x & 0xff) -#define INDEX_TO_SEQ(x) (x & 0xff) +#define SEQ_TO_INDEX(x) ((u8)(x & 0xff)) +#define INDEX_TO_SEQ(x) ((u8)(x & 0xff)) #define SEQ_HUGE_FRAME (0x4000) #define SEQ_RX_FRAME __constant_cpu_to_le16(0x8000) #define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 0171bb8cbbc6..73e8a24eb9ce 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -3296,6 +3296,7 @@ static void iwl4965_add_radiotap(struct iwl_priv *priv, s8 noise = 0; int rate = stats->rate_idx; u64 tsf = stats->mactime; + __le16 antenna; __le16 phy_flags_hw = rx_start->phy_flags; struct iwl4965_rt_rx_hdr { struct ieee80211_radiotap_header rt_hdr; @@ -3380,8 +3381,8 @@ static void iwl4965_add_radiotap(struct iwl_priv *priv, * new 802.11n radiotap field "RX chains" that is defined * as a bitmask. */ - iwl4965_rt->rt_antenna = - le16_to_cpu(phy_flags_hw & RX_RES_PHY_FLAGS_ANTENNA_MSK) >> 4; + antenna = phy_flags_hw & RX_RES_PHY_FLAGS_ANTENNA_MSK; + iwl4965_rt->rt_antenna = le16_to_cpu(antenna) >> 4; /* set the preamble flag if appropriate */ if (phy_flags_hw & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index c8e7028cdf2a..0ec217da48d4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -294,8 +294,8 @@ struct iwl4965_frame { #define SEQ_TO_QUEUE(x) ((x >> 8) & 0xbf) #define QUEUE_TO_SEQ(x) ((x & 0xbf) << 8) -#define SEQ_TO_INDEX(x) (x & 0xff) -#define INDEX_TO_SEQ(x) (x & 0xff) +#define SEQ_TO_INDEX(x) ((u8)(x & 0xff)) +#define INDEX_TO_SEQ(x) ((u8)(x & 0xff)) #define SEQ_HUGE_FRAME (0x4000) #define SEQ_RX_FRAME __constant_cpu_to_le16(0x8000) #define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4) -- cgit v1.2.1 From 53f36d70f072403d9aef68b332b72eb8c559b4ae Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Wed, 2 Apr 2008 12:10:04 -0400 Subject: iwlwifi/Kconfg: make IWLWIFI_LEDS invisible Select IWLWIFI_LEDS automatically when either IWL3945_LEDS or IWL4965_LEDS is selected. This avoids potential misconfigurations which lead to build failures for iwl-led.c. Cc: Miles Lane Cc: reinette.chatre@intel.com Signed-off-by: John w. Linville Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/Kconfig | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index 4a5c8c0d007d..bcaa61b7c563 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig @@ -3,11 +3,8 @@ config IWLCORE depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL config IWLWIFI_LEDS - bool "Enable LEDS features in iwlwifi driver" - depends on IWLCORE && MAC80211_LEDS && LEDS_CLASS - ---help--- - This option enables LEDS for the iwlwifi drivers - + bool + default n config IWLCORE_RFKILL boolean "IWLWIFI RF kill support" @@ -52,7 +49,8 @@ config IWL4965_HT config IWL4965_LEDS bool "Enable LEDS features in iwl4965 driver" - depends on IWL4965 && IWLWIFI_LEDS + depends on IWL4965 && MAC80211_LEDS && LEDS_CLASS + select IWLWIFI_LEDS ---help--- This option enables LEDS for the iwlwifi drivers -- cgit v1.2.1 From 697900ac14528e985b66f471ecb81082fc00baa9 Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Wed, 2 Apr 2008 16:27:10 +0200 Subject: libertas: move association code from join.c into scan.c Besides code moving, I did the following changes: * made some functions static * removed some unneeded #include's * made patch checkpatch.pl clean Signed-off-by: Holger Schurig Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/Makefile | 2 +- drivers/net/wireless/libertas/assoc.c | 862 ++++++++++++++++++++++++++++++- drivers/net/wireless/libertas/assoc.h | 28 + drivers/net/wireless/libertas/cmd.c | 2 +- drivers/net/wireless/libertas/cmdresp.c | 2 +- drivers/net/wireless/libertas/ethtool.c | 1 - drivers/net/wireless/libertas/join.c | 872 -------------------------------- drivers/net/wireless/libertas/join.h | 48 -- drivers/net/wireless/libertas/main.c | 1 - drivers/net/wireless/libertas/scan.c | 2 +- drivers/net/wireless/libertas/wext.c | 1 - 11 files changed, 890 insertions(+), 931 deletions(-) delete mode 100644 drivers/net/wireless/libertas/join.c delete mode 100644 drivers/net/wireless/libertas/join.h (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/libertas/Makefile b/drivers/net/wireless/libertas/Makefile index 0e2787691f96..f0724e31adfd 100644 --- a/drivers/net/wireless/libertas/Makefile +++ b/drivers/net/wireless/libertas/Makefile @@ -1,7 +1,7 @@ libertas-objs := main.o wext.o \ rx.o tx.o cmd.o \ cmdresp.o scan.o \ - join.o 11d.o \ + 11d.o \ debugfs.o \ ethtool.o assoc.o diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c index 95d98203eb4e..e794e93a2297 100644 --- a/drivers/net/wireless/libertas/assoc.c +++ b/drivers/net/wireless/libertas/assoc.c @@ -1,13 +1,9 @@ /* Copyright (C) 2006, Red Hat, Inc. */ -#include -#include #include #include "assoc.h" -#include "join.h" #include "decl.h" -#include "hostcmd.h" #include "host.h" #include "cmd.h" @@ -17,6 +13,162 @@ static const u8 bssid_any[ETH_ALEN] __attribute__ ((aligned (2))) = static const u8 bssid_off[ETH_ALEN] __attribute__ ((aligned (2))) = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +/* The firmware needs certain bits masked out of the beacon-derviced capability + * field when associating/joining to BSSs. + */ +#define CAPINFO_MASK (~(0xda00)) + + + +/** + * @brief Associate to a specific BSS discovered in a scan + * + * @param priv A pointer to struct lbs_private structure + * @param pbssdesc Pointer to the BSS descriptor to associate with. + * + * @return 0-success, otherwise fail + */ +static int lbs_associate(struct lbs_private *priv, + struct assoc_request *assoc_req) +{ + int ret; + + lbs_deb_enter(LBS_DEB_ASSOC); + + ret = lbs_prepare_and_send_command(priv, CMD_802_11_AUTHENTICATE, + 0, CMD_OPTION_WAITFORRSP, + 0, assoc_req->bss.bssid); + + if (ret) + goto done; + + /* set preamble to firmware */ + if ((priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) && + (assoc_req->bss.capability & WLAN_CAPABILITY_SHORT_PREAMBLE)) + priv->preamble = CMD_TYPE_SHORT_PREAMBLE; + else + priv->preamble = CMD_TYPE_LONG_PREAMBLE; + + lbs_set_radio_control(priv); + + ret = lbs_prepare_and_send_command(priv, CMD_802_11_ASSOCIATE, + 0, CMD_OPTION_WAITFORRSP, 0, assoc_req); + +done: + lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); + return ret; +} + +/** + * @brief Join an adhoc network found in a previous scan + * + * @param priv A pointer to struct lbs_private structure + * @param pbssdesc Pointer to a BSS descriptor found in a previous scan + * to attempt to join + * + * @return 0--success, -1--fail + */ +static int lbs_join_adhoc_network(struct lbs_private *priv, + struct assoc_request *assoc_req) +{ + struct bss_descriptor *bss = &assoc_req->bss; + int ret = 0; + + lbs_deb_join("current SSID '%s', ssid length %u\n", + escape_essid(priv->curbssparams.ssid, + priv->curbssparams.ssid_len), + priv->curbssparams.ssid_len); + lbs_deb_join("requested ssid '%s', ssid length %u\n", + escape_essid(bss->ssid, bss->ssid_len), + bss->ssid_len); + + /* check if the requested SSID is already joined */ + if (priv->curbssparams.ssid_len && + !lbs_ssid_cmp(priv->curbssparams.ssid, + priv->curbssparams.ssid_len, + bss->ssid, bss->ssid_len) && + (priv->mode == IW_MODE_ADHOC) && + (priv->connect_status == LBS_CONNECTED)) { + union iwreq_data wrqu; + + lbs_deb_join("ADHOC_J_CMD: New ad-hoc SSID is the same as " + "current, not attempting to re-join"); + + /* Send the re-association event though, because the association + * request really was successful, even if just a null-op. + */ + memset(&wrqu, 0, sizeof(wrqu)); + memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, + ETH_ALEN); + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); + goto out; + } + + /* Use shortpreamble only when both creator and card supports + short preamble */ + if (!(bss->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) || + !(priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)) { + lbs_deb_join("AdhocJoin: Long preamble\n"); + priv->preamble = CMD_TYPE_LONG_PREAMBLE; + } else { + lbs_deb_join("AdhocJoin: Short preamble\n"); + priv->preamble = CMD_TYPE_SHORT_PREAMBLE; + } + + lbs_set_radio_control(priv); + + lbs_deb_join("AdhocJoin: channel = %d\n", assoc_req->channel); + lbs_deb_join("AdhocJoin: band = %c\n", assoc_req->band); + + priv->adhoccreate = 0; + + ret = lbs_prepare_and_send_command(priv, CMD_802_11_AD_HOC_JOIN, + 0, CMD_OPTION_WAITFORRSP, + OID_802_11_SSID, assoc_req); + +out: + return ret; +} + +/** + * @brief Start an Adhoc Network + * + * @param priv A pointer to struct lbs_private structure + * @param adhocssid The ssid of the Adhoc Network + * @return 0--success, -1--fail + */ +static int lbs_start_adhoc_network(struct lbs_private *priv, + struct assoc_request *assoc_req) +{ + int ret = 0; + + priv->adhoccreate = 1; + + if (priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) { + lbs_deb_join("AdhocStart: Short preamble\n"); + priv->preamble = CMD_TYPE_SHORT_PREAMBLE; + } else { + lbs_deb_join("AdhocStart: Long preamble\n"); + priv->preamble = CMD_TYPE_LONG_PREAMBLE; + } + + lbs_set_radio_control(priv); + + lbs_deb_join("AdhocStart: channel = %d\n", assoc_req->channel); + lbs_deb_join("AdhocStart: band = %d\n", assoc_req->band); + + ret = lbs_prepare_and_send_command(priv, CMD_802_11_AD_HOC_START, + 0, CMD_OPTION_WAITFORRSP, 0, assoc_req); + + return ret; +} + +int lbs_stop_adhoc_network(struct lbs_private *priv) +{ + return lbs_prepare_and_send_command(priv, CMD_802_11_AD_HOC_STOP, + 0, CMD_OPTION_WAITFORRSP, 0, NULL); +} static int assoc_helper_essid(struct lbs_private *priv, struct assoc_request * assoc_req) @@ -722,3 +874,705 @@ struct assoc_request *lbs_get_association_request(struct lbs_private *priv) lbs_deb_leave(LBS_DEB_ASSOC); return assoc_req; } + + +/** + * @brief This function finds common rates between rate1 and card rates. + * + * It will fill common rates in rate1 as output if found. + * + * NOTE: Setting the MSB of the basic rates need to be taken + * care, either before or after calling this function + * + * @param priv A pointer to struct lbs_private structure + * @param rate1 the buffer which keeps input and output + * @param rate1_size the size of rate1 buffer; new size of buffer on return + * + * @return 0 or -1 + */ +static int get_common_rates(struct lbs_private *priv, + u8 *rates, + u16 *rates_size) +{ + u8 *card_rates = lbs_bg_rates; + size_t num_card_rates = sizeof(lbs_bg_rates); + int ret = 0, i, j; + u8 tmp[30]; + size_t tmp_size = 0; + + /* For each rate in card_rates that exists in rate1, copy to tmp */ + for (i = 0; card_rates[i] && (i < num_card_rates); i++) { + for (j = 0; rates[j] && (j < *rates_size); j++) { + if (rates[j] == card_rates[i]) + tmp[tmp_size++] = card_rates[i]; + } + } + + lbs_deb_hex(LBS_DEB_JOIN, "AP rates ", rates, *rates_size); + lbs_deb_hex(LBS_DEB_JOIN, "card rates ", card_rates, num_card_rates); + lbs_deb_hex(LBS_DEB_JOIN, "common rates", tmp, tmp_size); + lbs_deb_join("TX data rate 0x%02x\n", priv->cur_rate); + + if (!priv->auto_rate) { + for (i = 0; i < tmp_size; i++) { + if (tmp[i] == priv->cur_rate) + goto done; + } + lbs_pr_alert("Previously set fixed data rate %#x isn't " + "compatible with the network.\n", priv->cur_rate); + ret = -1; + goto done; + } + ret = 0; + +done: + memset(rates, 0, *rates_size); + *rates_size = min_t(int, tmp_size, *rates_size); + memcpy(rates, tmp, *rates_size); + return ret; +} + + +/** + * @brief Sets the MSB on basic rates as the firmware requires + * + * Scan through an array and set the MSB for basic data rates. + * + * @param rates buffer of data rates + * @param len size of buffer + */ +static void lbs_set_basic_rate_flags(u8 *rates, size_t len) +{ + int i; + + for (i = 0; i < len; i++) { + if (rates[i] == 0x02 || rates[i] == 0x04 || + rates[i] == 0x0b || rates[i] == 0x16) + rates[i] |= 0x80; + } +} + +/** + * @brief Send Deauthentication Request + * + * @param priv A pointer to struct lbs_private structure + * @return 0--success, -1--fail + */ +int lbs_send_deauthentication(struct lbs_private *priv) +{ + return lbs_prepare_and_send_command(priv, CMD_802_11_DEAUTHENTICATE, + 0, CMD_OPTION_WAITFORRSP, 0, NULL); +} + +/** + * @brief This function prepares command of authenticate. + * + * @param priv A pointer to struct lbs_private structure + * @param cmd A pointer to cmd_ds_command structure + * @param pdata_buf Void cast of pointer to a BSSID to authenticate with + * + * @return 0 or -1 + */ +int lbs_cmd_80211_authenticate(struct lbs_private *priv, + struct cmd_ds_command *cmd, + void *pdata_buf) +{ + struct cmd_ds_802_11_authenticate *pauthenticate = &cmd->params.auth; + int ret = -1; + u8 *bssid = pdata_buf; + DECLARE_MAC_BUF(mac); + + lbs_deb_enter(LBS_DEB_JOIN); + + cmd->command = cpu_to_le16(CMD_802_11_AUTHENTICATE); + cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_authenticate) + + S_DS_GEN); + + /* translate auth mode to 802.11 defined wire value */ + switch (priv->secinfo.auth_mode) { + case IW_AUTH_ALG_OPEN_SYSTEM: + pauthenticate->authtype = 0x00; + break; + case IW_AUTH_ALG_SHARED_KEY: + pauthenticate->authtype = 0x01; + break; + case IW_AUTH_ALG_LEAP: + pauthenticate->authtype = 0x80; + break; + default: + lbs_deb_join("AUTH_CMD: invalid auth alg 0x%X\n", + priv->secinfo.auth_mode); + goto out; + } + + memcpy(pauthenticate->macaddr, bssid, ETH_ALEN); + + lbs_deb_join("AUTH_CMD: BSSID %s, auth 0x%x\n", + print_mac(mac, bssid), pauthenticate->authtype); + ret = 0; + +out: + lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret); + return ret; +} + +int lbs_cmd_80211_deauthenticate(struct lbs_private *priv, + struct cmd_ds_command *cmd) +{ + struct cmd_ds_802_11_deauthenticate *dauth = &cmd->params.deauth; + + lbs_deb_enter(LBS_DEB_JOIN); + + cmd->command = cpu_to_le16(CMD_802_11_DEAUTHENTICATE); + cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_deauthenticate) + + S_DS_GEN); + + /* set AP MAC address */ + memmove(dauth->macaddr, priv->curbssparams.bssid, ETH_ALEN); + + /* Reason code 3 = Station is leaving */ +#define REASON_CODE_STA_LEAVING 3 + dauth->reasoncode = cpu_to_le16(REASON_CODE_STA_LEAVING); + + lbs_deb_leave(LBS_DEB_JOIN); + return 0; +} + +int lbs_cmd_80211_associate(struct lbs_private *priv, + struct cmd_ds_command *cmd, void *pdata_buf) +{ + struct cmd_ds_802_11_associate *passo = &cmd->params.associate; + int ret = 0; + struct assoc_request *assoc_req = pdata_buf; + struct bss_descriptor *bss = &assoc_req->bss; + u8 *pos; + u16 tmpcap, tmplen; + struct mrvlietypes_ssidparamset *ssid; + struct mrvlietypes_phyparamset *phy; + struct mrvlietypes_ssparamset *ss; + struct mrvlietypes_ratesparamset *rates; + struct mrvlietypes_rsnparamset *rsn; + + lbs_deb_enter(LBS_DEB_ASSOC); + + pos = (u8 *) passo; + + if (!priv) { + ret = -1; + goto done; + } + + cmd->command = cpu_to_le16(CMD_802_11_ASSOCIATE); + + memcpy(passo->peerstaaddr, bss->bssid, sizeof(passo->peerstaaddr)); + pos += sizeof(passo->peerstaaddr); + + /* set the listen interval */ + passo->listeninterval = cpu_to_le16(MRVDRV_DEFAULT_LISTEN_INTERVAL); + + pos += sizeof(passo->capability); + pos += sizeof(passo->listeninterval); + pos += sizeof(passo->bcnperiod); + pos += sizeof(passo->dtimperiod); + + ssid = (struct mrvlietypes_ssidparamset *) pos; + ssid->header.type = cpu_to_le16(TLV_TYPE_SSID); + tmplen = bss->ssid_len; + ssid->header.len = cpu_to_le16(tmplen); + memcpy(ssid->ssid, bss->ssid, tmplen); + pos += sizeof(ssid->header) + tmplen; + + phy = (struct mrvlietypes_phyparamset *) pos; + phy->header.type = cpu_to_le16(TLV_TYPE_PHY_DS); + tmplen = sizeof(phy->fh_ds.dsparamset); + phy->header.len = cpu_to_le16(tmplen); + memcpy(&phy->fh_ds.dsparamset, + &bss->phyparamset.dsparamset.currentchan, + tmplen); + pos += sizeof(phy->header) + tmplen; + + ss = (struct mrvlietypes_ssparamset *) pos; + ss->header.type = cpu_to_le16(TLV_TYPE_CF); + tmplen = sizeof(ss->cf_ibss.cfparamset); + ss->header.len = cpu_to_le16(tmplen); + pos += sizeof(ss->header) + tmplen; + + rates = (struct mrvlietypes_ratesparamset *) pos; + rates->header.type = cpu_to_le16(TLV_TYPE_RATES); + memcpy(&rates->rates, &bss->rates, MAX_RATES); + tmplen = MAX_RATES; + if (get_common_rates(priv, rates->rates, &tmplen)) { + ret = -1; + goto done; + } + pos += sizeof(rates->header) + tmplen; + rates->header.len = cpu_to_le16(tmplen); + lbs_deb_assoc("ASSOC_CMD: num rates %u\n", tmplen); + + /* Copy the infra. association rates into Current BSS state structure */ + memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates)); + memcpy(&priv->curbssparams.rates, &rates->rates, tmplen); + + /* Set MSB on basic rates as the firmware requires, but _after_ + * copying to current bss rates. + */ + lbs_set_basic_rate_flags(rates->rates, tmplen); + + if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) { + rsn = (struct mrvlietypes_rsnparamset *) pos; + /* WPA_IE or WPA2_IE */ + rsn->header.type = cpu_to_le16((u16) assoc_req->wpa_ie[0]); + tmplen = (u16) assoc_req->wpa_ie[1]; + rsn->header.len = cpu_to_le16(tmplen); + memcpy(rsn->rsnie, &assoc_req->wpa_ie[2], tmplen); + lbs_deb_hex(LBS_DEB_JOIN, "ASSOC_CMD: RSN IE", (u8 *) rsn, + sizeof(rsn->header) + tmplen); + pos += sizeof(rsn->header) + tmplen; + } + + /* update curbssparams */ + priv->curbssparams.channel = bss->phyparamset.dsparamset.currentchan; + + if (lbs_parse_dnld_countryinfo_11d(priv, bss)) { + ret = -1; + goto done; + } + + cmd->size = cpu_to_le16((u16) (pos - (u8 *) passo) + S_DS_GEN); + + /* set the capability info */ + tmpcap = (bss->capability & CAPINFO_MASK); + if (bss->mode == IW_MODE_INFRA) + tmpcap |= WLAN_CAPABILITY_ESS; + passo->capability = cpu_to_le16(tmpcap); + lbs_deb_assoc("ASSOC_CMD: capability 0x%04x\n", tmpcap); + +done: + lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); + return ret; +} + +int lbs_cmd_80211_ad_hoc_start(struct lbs_private *priv, + struct cmd_ds_command *cmd, void *pdata_buf) +{ + struct cmd_ds_802_11_ad_hoc_start *adhs = &cmd->params.ads; + int ret = 0; + int cmdappendsize = 0; + struct assoc_request *assoc_req = pdata_buf; + u16 tmpcap = 0; + size_t ratesize = 0; + + lbs_deb_enter(LBS_DEB_JOIN); + + if (!priv) { + ret = -1; + goto done; + } + + cmd->command = cpu_to_le16(CMD_802_11_AD_HOC_START); + + /* + * Fill in the parameters for 2 data structures: + * 1. cmd_ds_802_11_ad_hoc_start command + * 2. priv->scantable[i] + * + * Driver will fill up SSID, bsstype,IBSS param, Physical Param, + * probe delay, and cap info. + * + * Firmware will fill up beacon period, DTIM, Basic rates + * and operational rates. + */ + + memset(adhs->ssid, 0, IW_ESSID_MAX_SIZE); + memcpy(adhs->ssid, assoc_req->ssid, assoc_req->ssid_len); + + lbs_deb_join("ADHOC_S_CMD: SSID '%s', ssid length %u\n", + escape_essid(assoc_req->ssid, assoc_req->ssid_len), + assoc_req->ssid_len); + + /* set the BSS type */ + adhs->bsstype = CMD_BSS_TYPE_IBSS; + priv->mode = IW_MODE_ADHOC; + if (priv->beacon_period == 0) + priv->beacon_period = MRVDRV_BEACON_INTERVAL; + adhs->beaconperiod = cpu_to_le16(priv->beacon_period); + + /* set Physical param set */ +#define DS_PARA_IE_ID 3 +#define DS_PARA_IE_LEN 1 + + adhs->phyparamset.dsparamset.elementid = DS_PARA_IE_ID; + adhs->phyparamset.dsparamset.len = DS_PARA_IE_LEN; + + WARN_ON(!assoc_req->channel); + + lbs_deb_join("ADHOC_S_CMD: Creating ADHOC on channel %d\n", + assoc_req->channel); + + adhs->phyparamset.dsparamset.currentchan = assoc_req->channel; + + /* set IBSS param set */ +#define IBSS_PARA_IE_ID 6 +#define IBSS_PARA_IE_LEN 2 + + adhs->ssparamset.ibssparamset.elementid = IBSS_PARA_IE_ID; + adhs->ssparamset.ibssparamset.len = IBSS_PARA_IE_LEN; + adhs->ssparamset.ibssparamset.atimwindow = 0; + + /* set capability info */ + tmpcap = WLAN_CAPABILITY_IBSS; + if (assoc_req->secinfo.wep_enabled) { + lbs_deb_join("ADHOC_S_CMD: WEP enabled, " + "setting privacy on\n"); + tmpcap |= WLAN_CAPABILITY_PRIVACY; + } else { + lbs_deb_join("ADHOC_S_CMD: WEP disabled, " + "setting privacy off\n"); + } + adhs->capability = cpu_to_le16(tmpcap); + + /* probedelay */ + adhs->probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME); + + memset(adhs->rates, 0, sizeof(adhs->rates)); + ratesize = min(sizeof(adhs->rates), sizeof(lbs_bg_rates)); + memcpy(adhs->rates, lbs_bg_rates, ratesize); + + /* Copy the ad-hoc creating rates into Current BSS state structure */ + memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates)); + memcpy(&priv->curbssparams.rates, &adhs->rates, ratesize); + + /* Set MSB on basic rates as the firmware requires, but _after_ + * copying to current bss rates. + */ + lbs_set_basic_rate_flags(adhs->rates, ratesize); + + lbs_deb_join("ADHOC_S_CMD: rates=%02x %02x %02x %02x \n", + adhs->rates[0], adhs->rates[1], adhs->rates[2], adhs->rates[3]); + + lbs_deb_join("ADHOC_S_CMD: AD HOC Start command is ready\n"); + + if (lbs_create_dnld_countryinfo_11d(priv)) { + lbs_deb_join("ADHOC_S_CMD: dnld_countryinfo_11d failed\n"); + ret = -1; + goto done; + } + + cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_start) + + S_DS_GEN + cmdappendsize); + + ret = 0; +done: + lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret); + return ret; +} + +int lbs_cmd_80211_ad_hoc_stop(struct cmd_ds_command *cmd) +{ + cmd->command = cpu_to_le16(CMD_802_11_AD_HOC_STOP); + cmd->size = cpu_to_le16(S_DS_GEN); + + return 0; +} + +int lbs_cmd_80211_ad_hoc_join(struct lbs_private *priv, + struct cmd_ds_command *cmd, void *pdata_buf) +{ + struct cmd_ds_802_11_ad_hoc_join *join_cmd = &cmd->params.adj; + struct assoc_request *assoc_req = pdata_buf; + struct bss_descriptor *bss = &assoc_req->bss; + int cmdappendsize = 0; + int ret = 0; + u16 ratesize = 0; + DECLARE_MAC_BUF(mac); + + lbs_deb_enter(LBS_DEB_JOIN); + + cmd->command = cpu_to_le16(CMD_802_11_AD_HOC_JOIN); + + join_cmd->bss.type = CMD_BSS_TYPE_IBSS; + join_cmd->bss.beaconperiod = cpu_to_le16(bss->beaconperiod); + + memcpy(&join_cmd->bss.bssid, &bss->bssid, ETH_ALEN); + memcpy(&join_cmd->bss.ssid, &bss->ssid, bss->ssid_len); + + memcpy(&join_cmd->bss.phyparamset, &bss->phyparamset, + sizeof(union ieeetypes_phyparamset)); + + memcpy(&join_cmd->bss.ssparamset, &bss->ssparamset, + sizeof(union IEEEtypes_ssparamset)); + + join_cmd->bss.capability = cpu_to_le16(bss->capability & CAPINFO_MASK); + lbs_deb_join("ADHOC_J_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n", + bss->capability, CAPINFO_MASK); + + /* information on BSSID descriptor passed to FW */ + lbs_deb_join( + "ADHOC_J_CMD: BSSID = %s, SSID = '%s'\n", + print_mac(mac, join_cmd->bss.bssid), + join_cmd->bss.ssid); + + /* failtimeout */ + join_cmd->failtimeout = cpu_to_le16(MRVDRV_ASSOCIATION_TIME_OUT); + + /* probedelay */ + join_cmd->probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME); + + priv->curbssparams.channel = bss->channel; + + /* Copy Data rates from the rates recorded in scan response */ + memset(join_cmd->bss.rates, 0, sizeof(join_cmd->bss.rates)); + ratesize = min_t(u16, sizeof(join_cmd->bss.rates), MAX_RATES); + memcpy(join_cmd->bss.rates, bss->rates, ratesize); + if (get_common_rates(priv, join_cmd->bss.rates, &ratesize)) { + lbs_deb_join("ADHOC_J_CMD: get_common_rates returns error.\n"); + ret = -1; + goto done; + } + + /* Copy the ad-hoc creating rates into Current BSS state structure */ + memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates)); + memcpy(&priv->curbssparams.rates, join_cmd->bss.rates, ratesize); + + /* Set MSB on basic rates as the firmware requires, but _after_ + * copying to current bss rates. + */ + lbs_set_basic_rate_flags(join_cmd->bss.rates, ratesize); + + join_cmd->bss.ssparamset.ibssparamset.atimwindow = + cpu_to_le16(bss->atimwindow); + + if (assoc_req->secinfo.wep_enabled) { + u16 tmp = le16_to_cpu(join_cmd->bss.capability); + tmp |= WLAN_CAPABILITY_PRIVACY; + join_cmd->bss.capability = cpu_to_le16(tmp); + } + + if (priv->psmode == LBS802_11POWERMODEMAX_PSP) { + /* wake up first */ + __le32 Localpsmode; + + Localpsmode = cpu_to_le32(LBS802_11POWERMODECAM); + ret = lbs_prepare_and_send_command(priv, + CMD_802_11_PS_MODE, + CMD_ACT_SET, + 0, 0, &Localpsmode); + + if (ret) { + ret = -1; + goto done; + } + } + + if (lbs_parse_dnld_countryinfo_11d(priv, bss)) { + ret = -1; + goto done; + } + + cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_join) + + S_DS_GEN + cmdappendsize); + +done: + lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret); + return ret; +} + +int lbs_ret_80211_associate(struct lbs_private *priv, + struct cmd_ds_command *resp) +{ + int ret = 0; + union iwreq_data wrqu; + struct ieeetypes_assocrsp *passocrsp; + struct bss_descriptor *bss; + u16 status_code; + + lbs_deb_enter(LBS_DEB_ASSOC); + + if (!priv->in_progress_assoc_req) { + lbs_deb_assoc("ASSOC_RESP: no in-progress assoc request\n"); + ret = -1; + goto done; + } + bss = &priv->in_progress_assoc_req->bss; + + passocrsp = (struct ieeetypes_assocrsp *) &resp->params; + + /* + * Older FW versions map the IEEE 802.11 Status Code in the association + * response to the following values returned in passocrsp->statuscode: + * + * IEEE Status Code Marvell Status Code + * 0 -> 0x0000 ASSOC_RESULT_SUCCESS + * 13 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED + * 14 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED + * 15 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED + * 16 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED + * others -> 0x0003 ASSOC_RESULT_REFUSED + * + * Other response codes: + * 0x0001 -> ASSOC_RESULT_INVALID_PARAMETERS (unused) + * 0x0002 -> ASSOC_RESULT_TIMEOUT (internal timer expired waiting for + * association response from the AP) + */ + + status_code = le16_to_cpu(passocrsp->statuscode); + switch (status_code) { + case 0x00: + break; + case 0x01: + lbs_deb_assoc("ASSOC_RESP: invalid parameters\n"); + break; + case 0x02: + lbs_deb_assoc("ASSOC_RESP: internal timer " + "expired while waiting for the AP\n"); + break; + case 0x03: + lbs_deb_assoc("ASSOC_RESP: association " + "refused by AP\n"); + break; + case 0x04: + lbs_deb_assoc("ASSOC_RESP: authentication " + "refused by AP\n"); + break; + default: + lbs_deb_assoc("ASSOC_RESP: failure reason 0x%02x " + " unknown\n", status_code); + break; + } + + if (status_code) { + lbs_mac_event_disconnected(priv); + ret = -1; + goto done; + } + + lbs_deb_hex(LBS_DEB_ASSOC, "ASSOC_RESP", (void *)&resp->params, + le16_to_cpu(resp->size) - S_DS_GEN); + + /* Send a Media Connected event, according to the Spec */ + priv->connect_status = LBS_CONNECTED; + + /* Update current SSID and BSSID */ + memcpy(&priv->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE); + priv->curbssparams.ssid_len = bss->ssid_len; + memcpy(priv->curbssparams.bssid, bss->bssid, ETH_ALEN); + + priv->SNR[TYPE_RXPD][TYPE_AVG] = 0; + priv->NF[TYPE_RXPD][TYPE_AVG] = 0; + + memset(priv->rawSNR, 0x00, sizeof(priv->rawSNR)); + memset(priv->rawNF, 0x00, sizeof(priv->rawNF)); + priv->nextSNRNF = 0; + priv->numSNRNF = 0; + + netif_carrier_on(priv->dev); + if (!priv->tx_pending_len) + netif_wake_queue(priv->dev); + + memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN); + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); + +done: + lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); + return ret; +} + +int lbs_ret_80211_disassociate(struct lbs_private *priv) +{ + lbs_deb_enter(LBS_DEB_JOIN); + + lbs_mac_event_disconnected(priv); + + lbs_deb_leave(LBS_DEB_JOIN); + return 0; +} + +int lbs_ret_80211_ad_hoc_start(struct lbs_private *priv, + struct cmd_ds_command *resp) +{ + int ret = 0; + u16 command = le16_to_cpu(resp->command); + u16 result = le16_to_cpu(resp->result); + struct cmd_ds_802_11_ad_hoc_result *padhocresult; + union iwreq_data wrqu; + struct bss_descriptor *bss; + DECLARE_MAC_BUF(mac); + + lbs_deb_enter(LBS_DEB_JOIN); + + padhocresult = &resp->params.result; + + lbs_deb_join("ADHOC_RESP: size = %d\n", le16_to_cpu(resp->size)); + lbs_deb_join("ADHOC_RESP: command = %x\n", command); + lbs_deb_join("ADHOC_RESP: result = %x\n", result); + + if (!priv->in_progress_assoc_req) { + lbs_deb_join("ADHOC_RESP: no in-progress association " + "request\n"); + ret = -1; + goto done; + } + bss = &priv->in_progress_assoc_req->bss; + + /* + * Join result code 0 --> SUCCESS + */ + if (result) { + lbs_deb_join("ADHOC_RESP: failed\n"); + if (priv->connect_status == LBS_CONNECTED) + lbs_mac_event_disconnected(priv); + ret = -1; + goto done; + } + + /* + * Now the join cmd should be successful + * If BSSID has changed use SSID to compare instead of BSSID + */ + lbs_deb_join("ADHOC_RESP: associated to '%s'\n", + escape_essid(bss->ssid, bss->ssid_len)); + + /* Send a Media Connected event, according to the Spec */ + priv->connect_status = LBS_CONNECTED; + + if (command == CMD_RET(CMD_802_11_AD_HOC_START)) { + /* Update the created network descriptor with the new BSSID */ + memcpy(bss->bssid, padhocresult->bssid, ETH_ALEN); + } + + /* Set the BSSID from the joined/started descriptor */ + memcpy(&priv->curbssparams.bssid, bss->bssid, ETH_ALEN); + + /* Set the new SSID to current SSID */ + memcpy(&priv->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE); + priv->curbssparams.ssid_len = bss->ssid_len; + + netif_carrier_on(priv->dev); + if (!priv->tx_pending_len) + netif_wake_queue(priv->dev); + + memset(&wrqu, 0, sizeof(wrqu)); + memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN); + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); + + lbs_deb_join("ADHOC_RESP: - Joined/Started Ad Hoc\n"); + lbs_deb_join("ADHOC_RESP: channel = %d\n", priv->curbssparams.channel); + lbs_deb_join("ADHOC_RESP: BSSID = %s\n", + print_mac(mac, padhocresult->bssid)); + +done: + lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret); + return ret; +} + +int lbs_ret_80211_ad_hoc_stop(struct lbs_private *priv) +{ + lbs_deb_enter(LBS_DEB_JOIN); + + lbs_mac_event_disconnected(priv); + + lbs_deb_leave(LBS_DEB_JOIN); + return 0; +} diff --git a/drivers/net/wireless/libertas/assoc.h b/drivers/net/wireless/libertas/assoc.h index d489cf4cc1e2..c516fbe518fd 100644 --- a/drivers/net/wireless/libertas/assoc.h +++ b/drivers/net/wireless/libertas/assoc.h @@ -8,4 +8,32 @@ void lbs_association_worker(struct work_struct *work); struct assoc_request *lbs_get_association_request(struct lbs_private *priv); +struct cmd_ds_command; +int lbs_cmd_80211_authenticate(struct lbs_private *priv, + struct cmd_ds_command *cmd, + void *pdata_buf); +int lbs_cmd_80211_ad_hoc_join(struct lbs_private *priv, + struct cmd_ds_command *cmd, + void *pdata_buf); +int lbs_cmd_80211_ad_hoc_stop(struct cmd_ds_command *cmd); +int lbs_cmd_80211_ad_hoc_start(struct lbs_private *priv, + struct cmd_ds_command *cmd, + void *pdata_buf); +int lbs_cmd_80211_deauthenticate(struct lbs_private *priv, + struct cmd_ds_command *cmd); +int lbs_cmd_80211_associate(struct lbs_private *priv, + struct cmd_ds_command *cmd, + void *pdata_buf); + +int lbs_ret_80211_ad_hoc_start(struct lbs_private *priv, + struct cmd_ds_command *resp); +int lbs_ret_80211_ad_hoc_stop(struct lbs_private *priv); +int lbs_ret_80211_disassociate(struct lbs_private *priv); +int lbs_ret_80211_associate(struct lbs_private *priv, + struct cmd_ds_command *resp); + +int lbs_stop_adhoc_network(struct lbs_private *priv); + +int lbs_send_deauthentication(struct lbs_private *priv); + #endif /* _LBS_ASSOC_H */ diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index dbaf8b9e47d5..4e6d01948372 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -9,7 +9,7 @@ #include "decl.h" #include "defs.h" #include "dev.h" -#include "join.h" +#include "assoc.h" #include "wext.h" #include "cmd.h" diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c index e60d03bf8d11..245d3c3a9274 100644 --- a/drivers/net/wireless/libertas/cmdresp.c +++ b/drivers/net/wireless/libertas/cmdresp.c @@ -12,7 +12,7 @@ #include "decl.h" #include "defs.h" #include "dev.h" -#include "join.h" +#include "assoc.h" #include "wext.h" /** diff --git a/drivers/net/wireless/libertas/ethtool.c b/drivers/net/wireless/libertas/ethtool.c index 7c8ce7d0f23a..be226c1885a9 100644 --- a/drivers/net/wireless/libertas/ethtool.c +++ b/drivers/net/wireless/libertas/ethtool.c @@ -6,7 +6,6 @@ #include "decl.h" #include "defs.h" #include "dev.h" -#include "join.h" #include "wext.h" #include "cmd.h" diff --git a/drivers/net/wireless/libertas/join.c b/drivers/net/wireless/libertas/join.c deleted file mode 100644 index 3e5026ff2ffa..000000000000 --- a/drivers/net/wireless/libertas/join.c +++ /dev/null @@ -1,872 +0,0 @@ -/** - * Functions implementing wlan infrastructure and adhoc join routines, - * IOCTL handlers as well as command preperation and response routines - * for sending adhoc start, adhoc join, and association commands - * to the firmware. - */ -#include -#include -#include -#include - -#include - -#include "host.h" -#include "decl.h" -#include "join.h" -#include "dev.h" -#include "assoc.h" - -/* The firmware needs certain bits masked out of the beacon-derviced capability - * field when associating/joining to BSSs. - */ -#define CAPINFO_MASK (~(0xda00)) - -/** - * @brief This function finds common rates between rate1 and card rates. - * - * It will fill common rates in rate1 as output if found. - * - * NOTE: Setting the MSB of the basic rates need to be taken - * care, either before or after calling this function - * - * @param priv A pointer to struct lbs_private structure - * @param rate1 the buffer which keeps input and output - * @param rate1_size the size of rate1 buffer; new size of buffer on return - * - * @return 0 or -1 - */ -static int get_common_rates(struct lbs_private *priv, - u8 *rates, - u16 *rates_size) -{ - u8 *card_rates = lbs_bg_rates; - size_t num_card_rates = sizeof(lbs_bg_rates); - int ret = 0, i, j; - u8 tmp[30]; - size_t tmp_size = 0; - - /* For each rate in card_rates that exists in rate1, copy to tmp */ - for (i = 0; card_rates[i] && (i < num_card_rates); i++) { - for (j = 0; rates[j] && (j < *rates_size); j++) { - if (rates[j] == card_rates[i]) - tmp[tmp_size++] = card_rates[i]; - } - } - - lbs_deb_hex(LBS_DEB_JOIN, "AP rates ", rates, *rates_size); - lbs_deb_hex(LBS_DEB_JOIN, "card rates ", card_rates, num_card_rates); - lbs_deb_hex(LBS_DEB_JOIN, "common rates", tmp, tmp_size); - lbs_deb_join("TX data rate 0x%02x\n", priv->cur_rate); - - if (!priv->auto_rate) { - for (i = 0; i < tmp_size; i++) { - if (tmp[i] == priv->cur_rate) - goto done; - } - lbs_pr_alert("Previously set fixed data rate %#x isn't " - "compatible with the network.\n", priv->cur_rate); - ret = -1; - goto done; - } - ret = 0; - -done: - memset(rates, 0, *rates_size); - *rates_size = min_t(int, tmp_size, *rates_size); - memcpy(rates, tmp, *rates_size); - return ret; -} - - -/** - * @brief Sets the MSB on basic rates as the firmware requires - * - * Scan through an array and set the MSB for basic data rates. - * - * @param rates buffer of data rates - * @param len size of buffer - */ -static void lbs_set_basic_rate_flags(u8 *rates, size_t len) -{ - int i; - - for (i = 0; i < len; i++) { - if (rates[i] == 0x02 || rates[i] == 0x04 || - rates[i] == 0x0b || rates[i] == 0x16) - rates[i] |= 0x80; - } -} - -/** - * @brief Associate to a specific BSS discovered in a scan - * - * @param priv A pointer to struct lbs_private structure - * @param pbssdesc Pointer to the BSS descriptor to associate with. - * - * @return 0-success, otherwise fail - */ -int lbs_associate(struct lbs_private *priv, struct assoc_request *assoc_req) -{ - int ret; - - lbs_deb_enter(LBS_DEB_ASSOC); - - ret = lbs_prepare_and_send_command(priv, CMD_802_11_AUTHENTICATE, - 0, CMD_OPTION_WAITFORRSP, - 0, assoc_req->bss.bssid); - - if (ret) - goto done; - - /* set preamble to firmware */ - if ( (priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) - && (assoc_req->bss.capability & WLAN_CAPABILITY_SHORT_PREAMBLE)) - priv->preamble = CMD_TYPE_SHORT_PREAMBLE; - else - priv->preamble = CMD_TYPE_LONG_PREAMBLE; - - lbs_set_radio_control(priv); - - ret = lbs_prepare_and_send_command(priv, CMD_802_11_ASSOCIATE, - 0, CMD_OPTION_WAITFORRSP, 0, assoc_req); - -done: - lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); - return ret; -} - -/** - * @brief Start an Adhoc Network - * - * @param priv A pointer to struct lbs_private structure - * @param adhocssid The ssid of the Adhoc Network - * @return 0--success, -1--fail - */ -int lbs_start_adhoc_network(struct lbs_private *priv, - struct assoc_request *assoc_req) -{ - int ret = 0; - - priv->adhoccreate = 1; - - if (priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) { - lbs_deb_join("AdhocStart: Short preamble\n"); - priv->preamble = CMD_TYPE_SHORT_PREAMBLE; - } else { - lbs_deb_join("AdhocStart: Long preamble\n"); - priv->preamble = CMD_TYPE_LONG_PREAMBLE; - } - - lbs_set_radio_control(priv); - - lbs_deb_join("AdhocStart: channel = %d\n", assoc_req->channel); - lbs_deb_join("AdhocStart: band = %d\n", assoc_req->band); - - ret = lbs_prepare_and_send_command(priv, CMD_802_11_AD_HOC_START, - 0, CMD_OPTION_WAITFORRSP, 0, assoc_req); - - return ret; -} - -/** - * @brief Join an adhoc network found in a previous scan - * - * @param priv A pointer to struct lbs_private structure - * @param pbssdesc Pointer to a BSS descriptor found in a previous scan - * to attempt to join - * - * @return 0--success, -1--fail - */ -int lbs_join_adhoc_network(struct lbs_private *priv, - struct assoc_request *assoc_req) -{ - struct bss_descriptor * bss = &assoc_req->bss; - int ret = 0; - - lbs_deb_join("%s: Current SSID '%s', ssid length %u\n", - __func__, - escape_essid(priv->curbssparams.ssid, - priv->curbssparams.ssid_len), - priv->curbssparams.ssid_len); - lbs_deb_join("%s: requested ssid '%s', ssid length %u\n", - __func__, escape_essid(bss->ssid, bss->ssid_len), - bss->ssid_len); - - /* check if the requested SSID is already joined */ - if ( priv->curbssparams.ssid_len - && !lbs_ssid_cmp(priv->curbssparams.ssid, - priv->curbssparams.ssid_len, - bss->ssid, bss->ssid_len) - && (priv->mode == IW_MODE_ADHOC) - && (priv->connect_status == LBS_CONNECTED)) { - union iwreq_data wrqu; - - lbs_deb_join("ADHOC_J_CMD: New ad-hoc SSID is the same as " - "current, not attempting to re-join"); - - /* Send the re-association event though, because the association - * request really was successful, even if just a null-op. - */ - memset(&wrqu, 0, sizeof(wrqu)); - memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, - ETH_ALEN); - wrqu.ap_addr.sa_family = ARPHRD_ETHER; - wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); - goto out; - } - - /* Use shortpreamble only when both creator and card supports - short preamble */ - if ( !(bss->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) - || !(priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)) { - lbs_deb_join("AdhocJoin: Long preamble\n"); - priv->preamble = CMD_TYPE_LONG_PREAMBLE; - } else { - lbs_deb_join("AdhocJoin: Short preamble\n"); - priv->preamble = CMD_TYPE_SHORT_PREAMBLE; - } - - lbs_set_radio_control(priv); - - lbs_deb_join("AdhocJoin: channel = %d\n", assoc_req->channel); - lbs_deb_join("AdhocJoin: band = %c\n", assoc_req->band); - - priv->adhoccreate = 0; - - ret = lbs_prepare_and_send_command(priv, CMD_802_11_AD_HOC_JOIN, - 0, CMD_OPTION_WAITFORRSP, - OID_802_11_SSID, assoc_req); - -out: - return ret; -} - -int lbs_stop_adhoc_network(struct lbs_private *priv) -{ - return lbs_prepare_and_send_command(priv, CMD_802_11_AD_HOC_STOP, - 0, CMD_OPTION_WAITFORRSP, 0, NULL); -} - -/** - * @brief Send Deauthentication Request - * - * @param priv A pointer to struct lbs_private structure - * @return 0--success, -1--fail - */ -int lbs_send_deauthentication(struct lbs_private *priv) -{ - return lbs_prepare_and_send_command(priv, CMD_802_11_DEAUTHENTICATE, - 0, CMD_OPTION_WAITFORRSP, 0, NULL); -} - -/** - * @brief This function prepares command of authenticate. - * - * @param priv A pointer to struct lbs_private structure - * @param cmd A pointer to cmd_ds_command structure - * @param pdata_buf Void cast of pointer to a BSSID to authenticate with - * - * @return 0 or -1 - */ -int lbs_cmd_80211_authenticate(struct lbs_private *priv, - struct cmd_ds_command *cmd, - void *pdata_buf) -{ - struct cmd_ds_802_11_authenticate *pauthenticate = &cmd->params.auth; - int ret = -1; - u8 *bssid = pdata_buf; - DECLARE_MAC_BUF(mac); - - lbs_deb_enter(LBS_DEB_JOIN); - - cmd->command = cpu_to_le16(CMD_802_11_AUTHENTICATE); - cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_authenticate) - + S_DS_GEN); - - /* translate auth mode to 802.11 defined wire value */ - switch (priv->secinfo.auth_mode) { - case IW_AUTH_ALG_OPEN_SYSTEM: - pauthenticate->authtype = 0x00; - break; - case IW_AUTH_ALG_SHARED_KEY: - pauthenticate->authtype = 0x01; - break; - case IW_AUTH_ALG_LEAP: - pauthenticate->authtype = 0x80; - break; - default: - lbs_deb_join("AUTH_CMD: invalid auth alg 0x%X\n", - priv->secinfo.auth_mode); - goto out; - } - - memcpy(pauthenticate->macaddr, bssid, ETH_ALEN); - - lbs_deb_join("AUTH_CMD: BSSID %s, auth 0x%x\n", - print_mac(mac, bssid), pauthenticate->authtype); - ret = 0; - -out: - lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret); - return ret; -} - -int lbs_cmd_80211_deauthenticate(struct lbs_private *priv, - struct cmd_ds_command *cmd) -{ - struct cmd_ds_802_11_deauthenticate *dauth = &cmd->params.deauth; - - lbs_deb_enter(LBS_DEB_JOIN); - - cmd->command = cpu_to_le16(CMD_802_11_DEAUTHENTICATE); - cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_deauthenticate) + - S_DS_GEN); - - /* set AP MAC address */ - memmove(dauth->macaddr, priv->curbssparams.bssid, ETH_ALEN); - - /* Reason code 3 = Station is leaving */ -#define REASON_CODE_STA_LEAVING 3 - dauth->reasoncode = cpu_to_le16(REASON_CODE_STA_LEAVING); - - lbs_deb_leave(LBS_DEB_JOIN); - return 0; -} - -int lbs_cmd_80211_associate(struct lbs_private *priv, - struct cmd_ds_command *cmd, void *pdata_buf) -{ - struct cmd_ds_802_11_associate *passo = &cmd->params.associate; - int ret = 0; - struct assoc_request * assoc_req = pdata_buf; - struct bss_descriptor * bss = &assoc_req->bss; - u8 *pos; - u16 tmpcap, tmplen; - struct mrvlietypes_ssidparamset *ssid; - struct mrvlietypes_phyparamset *phy; - struct mrvlietypes_ssparamset *ss; - struct mrvlietypes_ratesparamset *rates; - struct mrvlietypes_rsnparamset *rsn; - - lbs_deb_enter(LBS_DEB_ASSOC); - - pos = (u8 *) passo; - - if (!priv) { - ret = -1; - goto done; - } - - cmd->command = cpu_to_le16(CMD_802_11_ASSOCIATE); - - memcpy(passo->peerstaaddr, bss->bssid, sizeof(passo->peerstaaddr)); - pos += sizeof(passo->peerstaaddr); - - /* set the listen interval */ - passo->listeninterval = cpu_to_le16(MRVDRV_DEFAULT_LISTEN_INTERVAL); - - pos += sizeof(passo->capability); - pos += sizeof(passo->listeninterval); - pos += sizeof(passo->bcnperiod); - pos += sizeof(passo->dtimperiod); - - ssid = (struct mrvlietypes_ssidparamset *) pos; - ssid->header.type = cpu_to_le16(TLV_TYPE_SSID); - tmplen = bss->ssid_len; - ssid->header.len = cpu_to_le16(tmplen); - memcpy(ssid->ssid, bss->ssid, tmplen); - pos += sizeof(ssid->header) + tmplen; - - phy = (struct mrvlietypes_phyparamset *) pos; - phy->header.type = cpu_to_le16(TLV_TYPE_PHY_DS); - tmplen = sizeof(phy->fh_ds.dsparamset); - phy->header.len = cpu_to_le16(tmplen); - memcpy(&phy->fh_ds.dsparamset, - &bss->phyparamset.dsparamset.currentchan, - tmplen); - pos += sizeof(phy->header) + tmplen; - - ss = (struct mrvlietypes_ssparamset *) pos; - ss->header.type = cpu_to_le16(TLV_TYPE_CF); - tmplen = sizeof(ss->cf_ibss.cfparamset); - ss->header.len = cpu_to_le16(tmplen); - pos += sizeof(ss->header) + tmplen; - - rates = (struct mrvlietypes_ratesparamset *) pos; - rates->header.type = cpu_to_le16(TLV_TYPE_RATES); - memcpy(&rates->rates, &bss->rates, MAX_RATES); - tmplen = MAX_RATES; - if (get_common_rates(priv, rates->rates, &tmplen)) { - ret = -1; - goto done; - } - pos += sizeof(rates->header) + tmplen; - rates->header.len = cpu_to_le16(tmplen); - lbs_deb_assoc("ASSOC_CMD: num rates %u\n", tmplen); - - /* Copy the infra. association rates into Current BSS state structure */ - memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates)); - memcpy(&priv->curbssparams.rates, &rates->rates, tmplen); - - /* Set MSB on basic rates as the firmware requires, but _after_ - * copying to current bss rates. - */ - lbs_set_basic_rate_flags(rates->rates, tmplen); - - if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) { - rsn = (struct mrvlietypes_rsnparamset *) pos; - /* WPA_IE or WPA2_IE */ - rsn->header.type = cpu_to_le16((u16) assoc_req->wpa_ie[0]); - tmplen = (u16) assoc_req->wpa_ie[1]; - rsn->header.len = cpu_to_le16(tmplen); - memcpy(rsn->rsnie, &assoc_req->wpa_ie[2], tmplen); - lbs_deb_hex(LBS_DEB_JOIN, "ASSOC_CMD: RSN IE", (u8 *) rsn, - sizeof(rsn->header) + tmplen); - pos += sizeof(rsn->header) + tmplen; - } - - /* update curbssparams */ - priv->curbssparams.channel = bss->phyparamset.dsparamset.currentchan; - - if (lbs_parse_dnld_countryinfo_11d(priv, bss)) { - ret = -1; - goto done; - } - - cmd->size = cpu_to_le16((u16) (pos - (u8 *) passo) + S_DS_GEN); - - /* set the capability info */ - tmpcap = (bss->capability & CAPINFO_MASK); - if (bss->mode == IW_MODE_INFRA) - tmpcap |= WLAN_CAPABILITY_ESS; - passo->capability = cpu_to_le16(tmpcap); - lbs_deb_assoc("ASSOC_CMD: capability 0x%04x\n", tmpcap); - -done: - lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); - return ret; -} - -int lbs_cmd_80211_ad_hoc_start(struct lbs_private *priv, - struct cmd_ds_command *cmd, void *pdata_buf) -{ - struct cmd_ds_802_11_ad_hoc_start *adhs = &cmd->params.ads; - int ret = 0; - int cmdappendsize = 0; - struct assoc_request * assoc_req = pdata_buf; - u16 tmpcap = 0; - size_t ratesize = 0; - - lbs_deb_enter(LBS_DEB_JOIN); - - if (!priv) { - ret = -1; - goto done; - } - - cmd->command = cpu_to_le16(CMD_802_11_AD_HOC_START); - - /* - * Fill in the parameters for 2 data structures: - * 1. cmd_ds_802_11_ad_hoc_start command - * 2. priv->scantable[i] - * - * Driver will fill up SSID, bsstype,IBSS param, Physical Param, - * probe delay, and cap info. - * - * Firmware will fill up beacon period, DTIM, Basic rates - * and operational rates. - */ - - memset(adhs->ssid, 0, IW_ESSID_MAX_SIZE); - memcpy(adhs->ssid, assoc_req->ssid, assoc_req->ssid_len); - - lbs_deb_join("ADHOC_S_CMD: SSID '%s', ssid length %u\n", - escape_essid(assoc_req->ssid, assoc_req->ssid_len), - assoc_req->ssid_len); - - /* set the BSS type */ - adhs->bsstype = CMD_BSS_TYPE_IBSS; - priv->mode = IW_MODE_ADHOC; - if (priv->beacon_period == 0) - priv->beacon_period = MRVDRV_BEACON_INTERVAL; - adhs->beaconperiod = cpu_to_le16(priv->beacon_period); - - /* set Physical param set */ -#define DS_PARA_IE_ID 3 -#define DS_PARA_IE_LEN 1 - - adhs->phyparamset.dsparamset.elementid = DS_PARA_IE_ID; - adhs->phyparamset.dsparamset.len = DS_PARA_IE_LEN; - - WARN_ON(!assoc_req->channel); - - lbs_deb_join("ADHOC_S_CMD: Creating ADHOC on channel %d\n", - assoc_req->channel); - - adhs->phyparamset.dsparamset.currentchan = assoc_req->channel; - - /* set IBSS param set */ -#define IBSS_PARA_IE_ID 6 -#define IBSS_PARA_IE_LEN 2 - - adhs->ssparamset.ibssparamset.elementid = IBSS_PARA_IE_ID; - adhs->ssparamset.ibssparamset.len = IBSS_PARA_IE_LEN; - adhs->ssparamset.ibssparamset.atimwindow = 0; - - /* set capability info */ - tmpcap = WLAN_CAPABILITY_IBSS; - if (assoc_req->secinfo.wep_enabled) { - lbs_deb_join("ADHOC_S_CMD: WEP enabled, setting privacy on\n"); - tmpcap |= WLAN_CAPABILITY_PRIVACY; - } else { - lbs_deb_join("ADHOC_S_CMD: WEP disabled, setting privacy off\n"); - } - adhs->capability = cpu_to_le16(tmpcap); - - /* probedelay */ - adhs->probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME); - - memset(adhs->rates, 0, sizeof(adhs->rates)); - ratesize = min(sizeof(adhs->rates), sizeof(lbs_bg_rates)); - memcpy(adhs->rates, lbs_bg_rates, ratesize); - - /* Copy the ad-hoc creating rates into Current BSS state structure */ - memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates)); - memcpy(&priv->curbssparams.rates, &adhs->rates, ratesize); - - /* Set MSB on basic rates as the firmware requires, but _after_ - * copying to current bss rates. - */ - lbs_set_basic_rate_flags(adhs->rates, ratesize); - - lbs_deb_join("ADHOC_S_CMD: rates=%02x %02x %02x %02x \n", - adhs->rates[0], adhs->rates[1], adhs->rates[2], adhs->rates[3]); - - lbs_deb_join("ADHOC_S_CMD: AD HOC Start command is ready\n"); - - if (lbs_create_dnld_countryinfo_11d(priv)) { - lbs_deb_join("ADHOC_S_CMD: dnld_countryinfo_11d failed\n"); - ret = -1; - goto done; - } - - cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_start) + - S_DS_GEN + cmdappendsize); - - ret = 0; -done: - lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret); - return ret; -} - -int lbs_cmd_80211_ad_hoc_stop(struct cmd_ds_command *cmd) -{ - cmd->command = cpu_to_le16(CMD_802_11_AD_HOC_STOP); - cmd->size = cpu_to_le16(S_DS_GEN); - - return 0; -} - -int lbs_cmd_80211_ad_hoc_join(struct lbs_private *priv, - struct cmd_ds_command *cmd, void *pdata_buf) -{ - struct cmd_ds_802_11_ad_hoc_join *join_cmd = &cmd->params.adj; - struct assoc_request * assoc_req = pdata_buf; - struct bss_descriptor *bss = &assoc_req->bss; - int cmdappendsize = 0; - int ret = 0; - u16 ratesize = 0; - DECLARE_MAC_BUF(mac); - - lbs_deb_enter(LBS_DEB_JOIN); - - cmd->command = cpu_to_le16(CMD_802_11_AD_HOC_JOIN); - - join_cmd->bss.type = CMD_BSS_TYPE_IBSS; - join_cmd->bss.beaconperiod = cpu_to_le16(bss->beaconperiod); - - memcpy(&join_cmd->bss.bssid, &bss->bssid, ETH_ALEN); - memcpy(&join_cmd->bss.ssid, &bss->ssid, bss->ssid_len); - - memcpy(&join_cmd->bss.phyparamset, &bss->phyparamset, - sizeof(union ieeetypes_phyparamset)); - - memcpy(&join_cmd->bss.ssparamset, &bss->ssparamset, - sizeof(union IEEEtypes_ssparamset)); - - join_cmd->bss.capability = cpu_to_le16(bss->capability & CAPINFO_MASK); - lbs_deb_join("ADHOC_J_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n", - bss->capability, CAPINFO_MASK); - - /* information on BSSID descriptor passed to FW */ - lbs_deb_join( - "ADHOC_J_CMD: BSSID = %s, SSID = '%s'\n", - print_mac(mac, join_cmd->bss.bssid), - join_cmd->bss.ssid); - - /* failtimeout */ - join_cmd->failtimeout = cpu_to_le16(MRVDRV_ASSOCIATION_TIME_OUT); - - /* probedelay */ - join_cmd->probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME); - - priv->curbssparams.channel = bss->channel; - - /* Copy Data rates from the rates recorded in scan response */ - memset(join_cmd->bss.rates, 0, sizeof(join_cmd->bss.rates)); - ratesize = min_t(u16, sizeof(join_cmd->bss.rates), MAX_RATES); - memcpy(join_cmd->bss.rates, bss->rates, ratesize); - if (get_common_rates(priv, join_cmd->bss.rates, &ratesize)) { - lbs_deb_join("ADHOC_J_CMD: get_common_rates returns error.\n"); - ret = -1; - goto done; - } - - /* Copy the ad-hoc creating rates into Current BSS state structure */ - memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates)); - memcpy(&priv->curbssparams.rates, join_cmd->bss.rates, ratesize); - - /* Set MSB on basic rates as the firmware requires, but _after_ - * copying to current bss rates. - */ - lbs_set_basic_rate_flags(join_cmd->bss.rates, ratesize); - - join_cmd->bss.ssparamset.ibssparamset.atimwindow = - cpu_to_le16(bss->atimwindow); - - if (assoc_req->secinfo.wep_enabled) { - u16 tmp = le16_to_cpu(join_cmd->bss.capability); - tmp |= WLAN_CAPABILITY_PRIVACY; - join_cmd->bss.capability = cpu_to_le16(tmp); - } - - if (priv->psmode == LBS802_11POWERMODEMAX_PSP) { - /* wake up first */ - __le32 Localpsmode; - - Localpsmode = cpu_to_le32(LBS802_11POWERMODECAM); - ret = lbs_prepare_and_send_command(priv, - CMD_802_11_PS_MODE, - CMD_ACT_SET, - 0, 0, &Localpsmode); - - if (ret) { - ret = -1; - goto done; - } - } - - if (lbs_parse_dnld_countryinfo_11d(priv, bss)) { - ret = -1; - goto done; - } - - cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ad_hoc_join) + - S_DS_GEN + cmdappendsize); - -done: - lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret); - return ret; -} - -int lbs_ret_80211_associate(struct lbs_private *priv, - struct cmd_ds_command *resp) -{ - int ret = 0; - union iwreq_data wrqu; - struct ieeetypes_assocrsp *passocrsp; - struct bss_descriptor * bss; - u16 status_code; - - lbs_deb_enter(LBS_DEB_ASSOC); - - if (!priv->in_progress_assoc_req) { - lbs_deb_assoc("ASSOC_RESP: no in-progress assoc request\n"); - ret = -1; - goto done; - } - bss = &priv->in_progress_assoc_req->bss; - - passocrsp = (struct ieeetypes_assocrsp *) & resp->params; - - /* - * Older FW versions map the IEEE 802.11 Status Code in the association - * response to the following values returned in passocrsp->statuscode: - * - * IEEE Status Code Marvell Status Code - * 0 -> 0x0000 ASSOC_RESULT_SUCCESS - * 13 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED - * 14 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED - * 15 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED - * 16 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED - * others -> 0x0003 ASSOC_RESULT_REFUSED - * - * Other response codes: - * 0x0001 -> ASSOC_RESULT_INVALID_PARAMETERS (unused) - * 0x0002 -> ASSOC_RESULT_TIMEOUT (internal timer expired waiting for - * association response from the AP) - */ - - status_code = le16_to_cpu(passocrsp->statuscode); - switch (status_code) { - case 0x00: - break; - case 0x01: - lbs_deb_assoc("ASSOC_RESP: invalid parameters\n"); - break; - case 0x02: - lbs_deb_assoc("ASSOC_RESP: internal timer " - "expired while waiting for the AP\n"); - break; - case 0x03: - lbs_deb_assoc("ASSOC_RESP: association " - "refused by AP\n"); - break; - case 0x04: - lbs_deb_assoc("ASSOC_RESP: authentication " - "refused by AP\n"); - break; - default: - lbs_deb_assoc("ASSOC_RESP: failure reason 0x%02x " - " unknown\n", status_code); - break; - } - - if (status_code) { - lbs_mac_event_disconnected(priv); - ret = -1; - goto done; - } - - lbs_deb_hex(LBS_DEB_ASSOC, "ASSOC_RESP", (void *)&resp->params, - le16_to_cpu(resp->size) - S_DS_GEN); - - /* Send a Media Connected event, according to the Spec */ - priv->connect_status = LBS_CONNECTED; - - /* Update current SSID and BSSID */ - memcpy(&priv->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE); - priv->curbssparams.ssid_len = bss->ssid_len; - memcpy(priv->curbssparams.bssid, bss->bssid, ETH_ALEN); - - priv->SNR[TYPE_RXPD][TYPE_AVG] = 0; - priv->NF[TYPE_RXPD][TYPE_AVG] = 0; - - memset(priv->rawSNR, 0x00, sizeof(priv->rawSNR)); - memset(priv->rawNF, 0x00, sizeof(priv->rawNF)); - priv->nextSNRNF = 0; - priv->numSNRNF = 0; - - netif_carrier_on(priv->dev); - if (!priv->tx_pending_len) - netif_wake_queue(priv->dev); - - memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN); - wrqu.ap_addr.sa_family = ARPHRD_ETHER; - wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); - -done: - lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); - return ret; -} - -int lbs_ret_80211_disassociate(struct lbs_private *priv) -{ - lbs_deb_enter(LBS_DEB_JOIN); - - lbs_mac_event_disconnected(priv); - - lbs_deb_leave(LBS_DEB_JOIN); - return 0; -} - -int lbs_ret_80211_ad_hoc_start(struct lbs_private *priv, - struct cmd_ds_command *resp) -{ - int ret = 0; - u16 command = le16_to_cpu(resp->command); - u16 result = le16_to_cpu(resp->result); - struct cmd_ds_802_11_ad_hoc_result *padhocresult; - union iwreq_data wrqu; - struct bss_descriptor *bss; - DECLARE_MAC_BUF(mac); - - lbs_deb_enter(LBS_DEB_JOIN); - - padhocresult = &resp->params.result; - - lbs_deb_join("ADHOC_RESP: size = %d\n", le16_to_cpu(resp->size)); - lbs_deb_join("ADHOC_RESP: command = %x\n", command); - lbs_deb_join("ADHOC_RESP: result = %x\n", result); - - if (!priv->in_progress_assoc_req) { - lbs_deb_join("ADHOC_RESP: no in-progress association request\n"); - ret = -1; - goto done; - } - bss = &priv->in_progress_assoc_req->bss; - - /* - * Join result code 0 --> SUCCESS - */ - if (result) { - lbs_deb_join("ADHOC_RESP: failed\n"); - if (priv->connect_status == LBS_CONNECTED) { - lbs_mac_event_disconnected(priv); - } - ret = -1; - goto done; - } - - /* - * Now the join cmd should be successful - * If BSSID has changed use SSID to compare instead of BSSID - */ - lbs_deb_join("ADHOC_RESP: associated to '%s'\n", - escape_essid(bss->ssid, bss->ssid_len)); - - /* Send a Media Connected event, according to the Spec */ - priv->connect_status = LBS_CONNECTED; - - if (command == CMD_RET(CMD_802_11_AD_HOC_START)) { - /* Update the created network descriptor with the new BSSID */ - memcpy(bss->bssid, padhocresult->bssid, ETH_ALEN); - } - - /* Set the BSSID from the joined/started descriptor */ - memcpy(&priv->curbssparams.bssid, bss->bssid, ETH_ALEN); - - /* Set the new SSID to current SSID */ - memcpy(&priv->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE); - priv->curbssparams.ssid_len = bss->ssid_len; - - netif_carrier_on(priv->dev); - if (!priv->tx_pending_len) - netif_wake_queue(priv->dev); - - memset(&wrqu, 0, sizeof(wrqu)); - memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN); - wrqu.ap_addr.sa_family = ARPHRD_ETHER; - wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); - - lbs_deb_join("ADHOC_RESP: - Joined/Started Ad Hoc\n"); - lbs_deb_join("ADHOC_RESP: channel = %d\n", priv->curbssparams.channel); - lbs_deb_join("ADHOC_RESP: BSSID = %s\n", - print_mac(mac, padhocresult->bssid)); - -done: - lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret); - return ret; -} - -int lbs_ret_80211_ad_hoc_stop(struct lbs_private *priv) -{ - lbs_deb_enter(LBS_DEB_JOIN); - - lbs_mac_event_disconnected(priv); - - lbs_deb_leave(LBS_DEB_JOIN); - return 0; -} diff --git a/drivers/net/wireless/libertas/join.h b/drivers/net/wireless/libertas/join.h deleted file mode 100644 index bfc3a10a2f39..000000000000 --- a/drivers/net/wireless/libertas/join.h +++ /dev/null @@ -1,48 +0,0 @@ -/** - * Interface for the wlan infrastructure and adhoc join routines - * - * Driver interface functions and type declarations for the join module - * implemented in join.c. Process all start/join requests for - * both adhoc and infrastructure networks - */ -#ifndef _LBS_JOIN_H -#define _LBS_JOIN_H - -#include "defs.h" -#include "dev.h" - -struct cmd_ds_command; -int lbs_cmd_80211_authenticate(struct lbs_private *priv, - struct cmd_ds_command *cmd, - void *pdata_buf); -int lbs_cmd_80211_ad_hoc_join(struct lbs_private *priv, - struct cmd_ds_command *cmd, - void *pdata_buf); -int lbs_cmd_80211_ad_hoc_stop(struct cmd_ds_command *cmd); -int lbs_cmd_80211_ad_hoc_start(struct lbs_private *priv, - struct cmd_ds_command *cmd, - void *pdata_buf); -int lbs_cmd_80211_deauthenticate(struct lbs_private *priv, - struct cmd_ds_command *cmd); -int lbs_cmd_80211_associate(struct lbs_private *priv, - struct cmd_ds_command *cmd, - void *pdata_buf); - -int lbs_ret_80211_ad_hoc_start(struct lbs_private *priv, - struct cmd_ds_command *resp); -int lbs_ret_80211_ad_hoc_stop(struct lbs_private *priv); -int lbs_ret_80211_disassociate(struct lbs_private *priv); -int lbs_ret_80211_associate(struct lbs_private *priv, - struct cmd_ds_command *resp); - -int lbs_start_adhoc_network(struct lbs_private *priv, - struct assoc_request * assoc_req); -int lbs_join_adhoc_network(struct lbs_private *priv, - struct assoc_request * assoc_req); -int lbs_stop_adhoc_network(struct lbs_private *priv); - -int lbs_send_deauthentication(struct lbs_private *priv); - -int lbs_associate(struct lbs_private *priv, struct assoc_request *assoc_req); - -#endif diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 6c2af176da20..15c9cc8bab48 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -20,7 +20,6 @@ #include "wext.h" #include "debugfs.h" #include "assoc.h" -#include "join.h" #include "cmd.h" #define DRIVER_RELEASE_VERSION "323.p0" diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c index 3825b7979fc4..1c7003d7de43 100644 --- a/drivers/net/wireless/libertas/scan.c +++ b/drivers/net/wireless/libertas/scan.c @@ -19,7 +19,7 @@ #include "decl.h" #include "dev.h" #include "scan.h" -#include "join.h" +#include "assoc.h" #include "cmd.h" //! Approximate amount of data needed to pass a scan result back to iwlist diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c index 738142e802d4..375072130221 100644 --- a/drivers/net/wireless/libertas/wext.c +++ b/drivers/net/wireless/libertas/wext.c @@ -16,7 +16,6 @@ #include "decl.h" #include "defs.h" #include "dev.h" -#include "join.h" #include "wext.h" #include "assoc.h" #include "cmd.h" -- cgit v1.2.1 From 245bf20f9c159f8d35befbc038997096b759459c Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Wed, 2 Apr 2008 16:27:42 +0200 Subject: libertas: move association code from scan.c into assoc.c Besides code moving, I did the following changes: * made some functions static * removed some unneeded #include's * made patch checkpatch.pl clean Signed-off-by: Holger Schurig Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/assoc.c | 352 ++++++++++++++++++++++++++++++++ drivers/net/wireless/libertas/dev.h | 41 +++- drivers/net/wireless/libertas/main.c | 1 + drivers/net/wireless/libertas/scan.c | 364 +--------------------------------- drivers/net/wireless/libertas/scan.h | 62 +----- drivers/net/wireless/libertas/wext.c | 1 + 6 files changed, 397 insertions(+), 424 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c index e794e93a2297..319b4f931a62 100644 --- a/drivers/net/wireless/libertas/assoc.c +++ b/drivers/net/wireless/libertas/assoc.c @@ -5,6 +5,7 @@ #include "assoc.h" #include "decl.h" #include "host.h" +#include "scan.h" #include "cmd.h" @@ -170,6 +171,272 @@ int lbs_stop_adhoc_network(struct lbs_private *priv) 0, CMD_OPTION_WAITFORRSP, 0, NULL); } +static inline int match_bss_no_security(struct lbs_802_11_security *secinfo, + struct bss_descriptor *match_bss) +{ + if (!secinfo->wep_enabled && !secinfo->WPAenabled + && !secinfo->WPA2enabled + && match_bss->wpa_ie[0] != MFIE_TYPE_GENERIC + && match_bss->rsn_ie[0] != MFIE_TYPE_RSN + && !(match_bss->capability & WLAN_CAPABILITY_PRIVACY)) + return 1; + else + return 0; +} + +static inline int match_bss_static_wep(struct lbs_802_11_security *secinfo, + struct bss_descriptor *match_bss) +{ + if (secinfo->wep_enabled && !secinfo->WPAenabled + && !secinfo->WPA2enabled + && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) + return 1; + else + return 0; +} + +static inline int match_bss_wpa(struct lbs_802_11_security *secinfo, + struct bss_descriptor *match_bss) +{ + if (!secinfo->wep_enabled && secinfo->WPAenabled + && (match_bss->wpa_ie[0] == MFIE_TYPE_GENERIC) + /* privacy bit may NOT be set in some APs like LinkSys WRT54G + && (match_bss->capability & WLAN_CAPABILITY_PRIVACY) */ + ) + return 1; + else + return 0; +} + +static inline int match_bss_wpa2(struct lbs_802_11_security *secinfo, + struct bss_descriptor *match_bss) +{ + if (!secinfo->wep_enabled && secinfo->WPA2enabled && + (match_bss->rsn_ie[0] == MFIE_TYPE_RSN) + /* privacy bit may NOT be set in some APs like LinkSys WRT54G + (match_bss->capability & WLAN_CAPABILITY_PRIVACY) */ + ) + return 1; + else + return 0; +} + +static inline int match_bss_dynamic_wep(struct lbs_802_11_security *secinfo, + struct bss_descriptor *match_bss) +{ + if (!secinfo->wep_enabled && !secinfo->WPAenabled + && !secinfo->WPA2enabled + && (match_bss->wpa_ie[0] != MFIE_TYPE_GENERIC) + && (match_bss->rsn_ie[0] != MFIE_TYPE_RSN) + && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) + return 1; + else + return 0; +} + +/** + * @brief Check if a scanned network compatible with the driver settings + * + * WEP WPA WPA2 ad-hoc encrypt Network + * enabled enabled enabled AES mode privacy WPA WPA2 Compatible + * 0 0 0 0 NONE 0 0 0 yes No security + * 1 0 0 0 NONE 1 0 0 yes Static WEP + * 0 1 0 0 x 1x 1 x yes WPA + * 0 0 1 0 x 1x x 1 yes WPA2 + * 0 0 0 1 NONE 1 0 0 yes Ad-hoc AES + * 0 0 0 0 !=NONE 1 0 0 yes Dynamic WEP + * + * + * @param priv A pointer to struct lbs_private + * @param index Index in scantable to check against current driver settings + * @param mode Network mode: Infrastructure or IBSS + * + * @return Index in scantable, or error code if negative + */ +static int is_network_compatible(struct lbs_private *priv, + struct bss_descriptor *bss, uint8_t mode) +{ + int matched = 0; + + lbs_deb_enter(LBS_DEB_SCAN); + + if (bss->mode != mode) + goto done; + + matched = match_bss_no_security(&priv->secinfo, bss); + if (matched) + goto done; + matched = match_bss_static_wep(&priv->secinfo, bss); + if (matched) + goto done; + matched = match_bss_wpa(&priv->secinfo, bss); + if (matched) { + lbs_deb_scan("is_network_compatible() WPA: wpa_ie 0x%x " + "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s " + "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0], + priv->secinfo.wep_enabled ? "e" : "d", + priv->secinfo.WPAenabled ? "e" : "d", + priv->secinfo.WPA2enabled ? "e" : "d", + (bss->capability & WLAN_CAPABILITY_PRIVACY)); + goto done; + } + matched = match_bss_wpa2(&priv->secinfo, bss); + if (matched) { + lbs_deb_scan("is_network_compatible() WPA2: wpa_ie 0x%x " + "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s " + "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0], + priv->secinfo.wep_enabled ? "e" : "d", + priv->secinfo.WPAenabled ? "e" : "d", + priv->secinfo.WPA2enabled ? "e" : "d", + (bss->capability & WLAN_CAPABILITY_PRIVACY)); + goto done; + } + matched = match_bss_dynamic_wep(&priv->secinfo, bss); + if (matched) { + lbs_deb_scan("is_network_compatible() dynamic WEP: " + "wpa_ie 0x%x wpa2_ie 0x%x privacy 0x%x\n", + bss->wpa_ie[0], bss->rsn_ie[0], + (bss->capability & WLAN_CAPABILITY_PRIVACY)); + goto done; + } + + /* bss security settings don't match those configured on card */ + lbs_deb_scan("is_network_compatible() FAILED: wpa_ie 0x%x " + "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s privacy 0x%x\n", + bss->wpa_ie[0], bss->rsn_ie[0], + priv->secinfo.wep_enabled ? "e" : "d", + priv->secinfo.WPAenabled ? "e" : "d", + priv->secinfo.WPA2enabled ? "e" : "d", + (bss->capability & WLAN_CAPABILITY_PRIVACY)); + +done: + lbs_deb_leave_args(LBS_DEB_SCAN, "matched: %d", matched); + return matched; +} + +/** + * @brief This function finds a specific compatible BSSID in the scan list + * + * Used in association code + * + * @param priv A pointer to struct lbs_private + * @param bssid BSSID to find in the scan list + * @param mode Network mode: Infrastructure or IBSS + * + * @return index in BSSID list, or error return code (< 0) + */ +static struct bss_descriptor *lbs_find_bssid_in_list(struct lbs_private *priv, + uint8_t *bssid, uint8_t mode) +{ + struct bss_descriptor *iter_bss; + struct bss_descriptor *found_bss = NULL; + + lbs_deb_enter(LBS_DEB_SCAN); + + if (!bssid) + goto out; + + lbs_deb_hex(LBS_DEB_SCAN, "looking for", bssid, ETH_ALEN); + + /* Look through the scan table for a compatible match. The loop will + * continue past a matched bssid that is not compatible in case there + * is an AP with multiple SSIDs assigned to the same BSSID + */ + mutex_lock(&priv->lock); + list_for_each_entry(iter_bss, &priv->network_list, list) { + if (compare_ether_addr(iter_bss->bssid, bssid)) + continue; /* bssid doesn't match */ + switch (mode) { + case IW_MODE_INFRA: + case IW_MODE_ADHOC: + if (!is_network_compatible(priv, iter_bss, mode)) + break; + found_bss = iter_bss; + break; + default: + found_bss = iter_bss; + break; + } + } + mutex_unlock(&priv->lock); + +out: + lbs_deb_leave_args(LBS_DEB_SCAN, "found_bss %p", found_bss); + return found_bss; +} + +/** + * @brief This function finds ssid in ssid list. + * + * Used in association code + * + * @param priv A pointer to struct lbs_private + * @param ssid SSID to find in the list + * @param bssid BSSID to qualify the SSID selection (if provided) + * @param mode Network mode: Infrastructure or IBSS + * + * @return index in BSSID list + */ +static struct bss_descriptor *lbs_find_ssid_in_list(struct lbs_private *priv, + uint8_t *ssid, uint8_t ssid_len, + uint8_t *bssid, uint8_t mode, + int channel) +{ + u32 bestrssi = 0; + struct bss_descriptor *iter_bss = NULL; + struct bss_descriptor *found_bss = NULL; + struct bss_descriptor *tmp_oldest = NULL; + + lbs_deb_enter(LBS_DEB_SCAN); + + mutex_lock(&priv->lock); + + list_for_each_entry(iter_bss, &priv->network_list, list) { + if (!tmp_oldest || + (iter_bss->last_scanned < tmp_oldest->last_scanned)) + tmp_oldest = iter_bss; + + if (lbs_ssid_cmp(iter_bss->ssid, iter_bss->ssid_len, + ssid, ssid_len) != 0) + continue; /* ssid doesn't match */ + if (bssid && compare_ether_addr(iter_bss->bssid, bssid) != 0) + continue; /* bssid doesn't match */ + if ((channel > 0) && (iter_bss->channel != channel)) + continue; /* channel doesn't match */ + + switch (mode) { + case IW_MODE_INFRA: + case IW_MODE_ADHOC: + if (!is_network_compatible(priv, iter_bss, mode)) + break; + + if (bssid) { + /* Found requested BSSID */ + found_bss = iter_bss; + goto out; + } + + if (SCAN_RSSI(iter_bss->rssi) > bestrssi) { + bestrssi = SCAN_RSSI(iter_bss->rssi); + found_bss = iter_bss; + } + break; + case IW_MODE_AUTO: + default: + if (SCAN_RSSI(iter_bss->rssi) > bestrssi) { + bestrssi = SCAN_RSSI(iter_bss->rssi); + found_bss = iter_bss; + } + break; + } + } + +out: + mutex_unlock(&priv->lock); + lbs_deb_leave_args(LBS_DEB_SCAN, "found_bss %p", found_bss); + return found_bss; +} + static int assoc_helper_essid(struct lbs_private *priv, struct assoc_request * assoc_req) { @@ -617,6 +884,91 @@ static int should_stop_adhoc(struct lbs_private *priv, } +/** + * @brief This function finds the best SSID in the Scan List + * + * Search the scan table for the best SSID that also matches the current + * adapter network preference (infrastructure or adhoc) + * + * @param priv A pointer to struct lbs_private + * + * @return index in BSSID list + */ +static struct bss_descriptor *lbs_find_best_ssid_in_list( + struct lbs_private *priv, uint8_t mode) +{ + uint8_t bestrssi = 0; + struct bss_descriptor *iter_bss; + struct bss_descriptor *best_bss = NULL; + + lbs_deb_enter(LBS_DEB_SCAN); + + mutex_lock(&priv->lock); + + list_for_each_entry(iter_bss, &priv->network_list, list) { + switch (mode) { + case IW_MODE_INFRA: + case IW_MODE_ADHOC: + if (!is_network_compatible(priv, iter_bss, mode)) + break; + if (SCAN_RSSI(iter_bss->rssi) <= bestrssi) + break; + bestrssi = SCAN_RSSI(iter_bss->rssi); + best_bss = iter_bss; + break; + case IW_MODE_AUTO: + default: + if (SCAN_RSSI(iter_bss->rssi) <= bestrssi) + break; + bestrssi = SCAN_RSSI(iter_bss->rssi); + best_bss = iter_bss; + break; + } + } + + mutex_unlock(&priv->lock); + lbs_deb_leave_args(LBS_DEB_SCAN, "best_bss %p", best_bss); + return best_bss; +} + +/** + * @brief Find the best AP + * + * Used from association worker. + * + * @param priv A pointer to struct lbs_private structure + * @param pSSID A pointer to AP's ssid + * + * @return 0--success, otherwise--fail + */ +static int lbs_find_best_network_ssid(struct lbs_private *priv, + uint8_t *out_ssid, uint8_t *out_ssid_len, uint8_t preferred_mode, + uint8_t *out_mode) +{ + int ret = -1; + struct bss_descriptor *found; + + lbs_deb_enter(LBS_DEB_SCAN); + + priv->scan_ssid_len = 0; + lbs_scan_networks(priv, 1); + if (priv->surpriseremoved) + goto out; + + found = lbs_find_best_ssid_in_list(priv, preferred_mode); + if (found && (found->ssid_len > 0)) { + memcpy(out_ssid, &found->ssid, IW_ESSID_MAX_SIZE); + *out_ssid_len = found->ssid_len; + *out_mode = found->mode; + ret = 0; + } + +out: + lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); + return ret; +} + + void lbs_association_worker(struct work_struct *work) { struct lbs_private *priv = container_of(work, struct lbs_private, diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index 3f3e7f6e68b3..1e6bae80396b 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h @@ -10,9 +10,10 @@ #include #include #include +#include #include "defs.h" -#include "scan.h" +#include "hostcmd.h" extern struct ethtool_ops lbs_ethtool_ops; @@ -325,6 +326,44 @@ struct lbs_private { extern struct cmd_confirm_sleep confirm_sleep; +/** + * @brief Structure used to store information for each beacon/probe response + */ +struct bss_descriptor { + u8 bssid[ETH_ALEN]; + + u8 ssid[IW_ESSID_MAX_SIZE + 1]; + u8 ssid_len; + + u16 capability; + u32 rssi; + u32 channel; + u16 beaconperiod; + u32 atimwindow; + + /* IW_MODE_AUTO, IW_MODE_ADHOC, IW_MODE_INFRA */ + u8 mode; + + /* zero-terminated array of supported data rates */ + u8 rates[MAX_RATES + 1]; + + unsigned long last_scanned; + + union ieeetypes_phyparamset phyparamset; + union IEEEtypes_ssparamset ssparamset; + + struct ieeetypes_countryinfofullset countryinfo; + + u8 wpa_ie[MAX_WPA_IE_LEN]; + size_t wpa_ie_len; + u8 rsn_ie[MAX_WPA_IE_LEN]; + size_t rsn_ie_len; + + u8 mesh; + + struct list_head list; +}; + /** Association request * * Encapsulates all the options that describe a specific assocation request diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 15c9cc8bab48..8f1122610974 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -19,6 +19,7 @@ #include "dev.h" #include "wext.h" #include "debugfs.h" +#include "scan.h" #include "assoc.h" #include "cmd.h" diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c index 1c7003d7de43..e72c97a0d6c1 100644 --- a/drivers/net/wireless/libertas/scan.c +++ b/drivers/net/wireless/libertas/scan.c @@ -4,22 +4,13 @@ * IOCTL handlers as well as command preperation and response routines * for sending scan commands to the firmware. */ -#include -#include -#include -#include #include - -#include -#include - #include #include "host.h" #include "decl.h" #include "dev.h" #include "scan.h" -#include "assoc.h" #include "cmd.h" //! Approximate amount of data needed to pass a scan result back to iwlist @@ -110,69 +101,6 @@ int lbs_ssid_cmp(uint8_t *ssid1, uint8_t ssid1_len, uint8_t *ssid2, return memcmp(ssid1, ssid2, ssid1_len); } -static inline int match_bss_no_security(struct lbs_802_11_security *secinfo, - struct bss_descriptor *match_bss) -{ - if (!secinfo->wep_enabled && !secinfo->WPAenabled - && !secinfo->WPA2enabled - && match_bss->wpa_ie[0] != MFIE_TYPE_GENERIC - && match_bss->rsn_ie[0] != MFIE_TYPE_RSN - && !(match_bss->capability & WLAN_CAPABILITY_PRIVACY)) - return 1; - else - return 0; -} - -static inline int match_bss_static_wep(struct lbs_802_11_security *secinfo, - struct bss_descriptor *match_bss) -{ - if (secinfo->wep_enabled && !secinfo->WPAenabled - && !secinfo->WPA2enabled - && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) - return 1; - else - return 0; -} - -static inline int match_bss_wpa(struct lbs_802_11_security *secinfo, - struct bss_descriptor *match_bss) -{ - if (!secinfo->wep_enabled && secinfo->WPAenabled - && (match_bss->wpa_ie[0] == MFIE_TYPE_GENERIC) - /* privacy bit may NOT be set in some APs like LinkSys WRT54G - && (match_bss->capability & WLAN_CAPABILITY_PRIVACY) */ - ) - return 1; - else - return 0; -} - -static inline int match_bss_wpa2(struct lbs_802_11_security *secinfo, - struct bss_descriptor *match_bss) -{ - if (!secinfo->wep_enabled && secinfo->WPA2enabled - && (match_bss->rsn_ie[0] == MFIE_TYPE_RSN) - /* privacy bit may NOT be set in some APs like LinkSys WRT54G - && (match_bss->capability & WLAN_CAPABILITY_PRIVACY) */ - ) - return 1; - else - return 0; -} - -static inline int match_bss_dynamic_wep(struct lbs_802_11_security *secinfo, - struct bss_descriptor *match_bss) -{ - if (!secinfo->wep_enabled && !secinfo->WPAenabled - && !secinfo->WPA2enabled - && (match_bss->wpa_ie[0] != MFIE_TYPE_GENERIC) - && (match_bss->rsn_ie[0] != MFIE_TYPE_RSN) - && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) - return 1; - else - return 0; -} - static inline int is_same_network(struct bss_descriptor *src, struct bss_descriptor *dst) { @@ -185,78 +113,6 @@ static inline int is_same_network(struct bss_descriptor *src, !memcmp(src->ssid, dst->ssid, src->ssid_len)); } -/** - * @brief Check if a scanned network compatible with the driver settings - * - * WEP WPA WPA2 ad-hoc encrypt Network - * enabled enabled enabled AES mode privacy WPA WPA2 Compatible - * 0 0 0 0 NONE 0 0 0 yes No security - * 1 0 0 0 NONE 1 0 0 yes Static WEP - * 0 1 0 0 x 1x 1 x yes WPA - * 0 0 1 0 x 1x x 1 yes WPA2 - * 0 0 0 1 NONE 1 0 0 yes Ad-hoc AES - * 0 0 0 0 !=NONE 1 0 0 yes Dynamic WEP - * - * - * @param priv A pointer to struct lbs_private - * @param index Index in scantable to check against current driver settings - * @param mode Network mode: Infrastructure or IBSS - * - * @return Index in scantable, or error code if negative - */ -static int is_network_compatible(struct lbs_private *priv, - struct bss_descriptor *bss, uint8_t mode) -{ - int matched = 0; - - lbs_deb_enter(LBS_DEB_SCAN); - - if (bss->mode != mode) - goto done; - - if ((matched = match_bss_no_security(&priv->secinfo, bss))) { - goto done; - } else if ((matched = match_bss_static_wep(&priv->secinfo, bss))) { - goto done; - } else if ((matched = match_bss_wpa(&priv->secinfo, bss))) { - lbs_deb_scan("is_network_compatible() WPA: wpa_ie 0x%x " - "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s " - "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0], - priv->secinfo.wep_enabled ? "e" : "d", - priv->secinfo.WPAenabled ? "e" : "d", - priv->secinfo.WPA2enabled ? "e" : "d", - (bss->capability & WLAN_CAPABILITY_PRIVACY)); - goto done; - } else if ((matched = match_bss_wpa2(&priv->secinfo, bss))) { - lbs_deb_scan("is_network_compatible() WPA2: wpa_ie 0x%x " - "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s " - "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0], - priv->secinfo.wep_enabled ? "e" : "d", - priv->secinfo.WPAenabled ? "e" : "d", - priv->secinfo.WPA2enabled ? "e" : "d", - (bss->capability & WLAN_CAPABILITY_PRIVACY)); - goto done; - } else if ((matched = match_bss_dynamic_wep(&priv->secinfo, bss))) { - lbs_deb_scan("is_network_compatible() dynamic WEP: " - "wpa_ie 0x%x wpa2_ie 0x%x privacy 0x%x\n", - bss->wpa_ie[0], bss->rsn_ie[0], - (bss->capability & WLAN_CAPABILITY_PRIVACY)); - goto done; - } - - /* bss security settings don't match those configured on card */ - lbs_deb_scan("is_network_compatible() FAILED: wpa_ie 0x%x " - "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s privacy 0x%x\n", - bss->wpa_ie[0], bss->rsn_ie[0], - priv->secinfo.wep_enabled ? "e" : "d", - priv->secinfo.WPAenabled ? "e" : "d", - priv->secinfo.WPA2enabled ? "e" : "d", - (bss->capability & WLAN_CAPABILITY_PRIVACY)); - -done: - lbs_deb_leave_args(LBS_DEB_SCAN, "matched: %d", matched); - return matched; -} @@ -341,7 +197,6 @@ static int lbs_scan_create_channel_list(struct lbs_private *priv, return chanidx; } - /* * Add SSID TLV of the form: * @@ -359,7 +214,6 @@ static int lbs_scan_add_ssid_tlv(struct lbs_private *priv, u8 *tlv) return sizeof(ssid_tlv->header) + priv->scan_ssid_len; } - /* * Add CHANLIST TLV of the form * @@ -398,7 +252,6 @@ static int lbs_scan_add_chanlist_tlv(uint8_t *tlv, return sizeof(chan_tlv->header) + size; } - /* * Add RATES TLV of the form * @@ -433,7 +286,6 @@ static int lbs_scan_add_rates_tlv(uint8_t *tlv) return sizeof(rate_tlv->header) + i; } - /* * Generate the CMD_802_11_SCAN command with the proper tlv * for a bunch of channels. @@ -482,12 +334,9 @@ out: return ret; } - /** * @brief Internal function used to start a scan based on an input config * - * Also used from debugfs - * * Use the input user scan configuration information when provided in * order to send the appropriate scan commands to firmware to populate or * update the internal driver scan table @@ -497,7 +346,7 @@ out: * * @return 0 or < 0 if error */ -static int lbs_scan_networks(struct lbs_private *priv, int full_scan) +int lbs_scan_networks(struct lbs_private *priv, int full_scan) { int ret = -ENOMEM; struct chanscanparamset *chan_list; @@ -627,9 +476,6 @@ out: return ret; } - - - void lbs_scan_worker(struct work_struct *work) { struct lbs_private *priv = @@ -880,214 +726,6 @@ done: return ret; } -/** - * @brief This function finds a specific compatible BSSID in the scan list - * - * Used in association code - * - * @param priv A pointer to struct lbs_private - * @param bssid BSSID to find in the scan list - * @param mode Network mode: Infrastructure or IBSS - * - * @return index in BSSID list, or error return code (< 0) - */ -struct bss_descriptor *lbs_find_bssid_in_list(struct lbs_private *priv, - uint8_t *bssid, uint8_t mode) -{ - struct bss_descriptor *iter_bss; - struct bss_descriptor *found_bss = NULL; - - lbs_deb_enter(LBS_DEB_SCAN); - - if (!bssid) - goto out; - - lbs_deb_hex(LBS_DEB_SCAN, "looking for", bssid, ETH_ALEN); - - /* Look through the scan table for a compatible match. The loop will - * continue past a matched bssid that is not compatible in case there - * is an AP with multiple SSIDs assigned to the same BSSID - */ - mutex_lock(&priv->lock); - list_for_each_entry (iter_bss, &priv->network_list, list) { - if (compare_ether_addr(iter_bss->bssid, bssid)) - continue; /* bssid doesn't match */ - switch (mode) { - case IW_MODE_INFRA: - case IW_MODE_ADHOC: - if (!is_network_compatible(priv, iter_bss, mode)) - break; - found_bss = iter_bss; - break; - default: - found_bss = iter_bss; - break; - } - } - mutex_unlock(&priv->lock); - -out: - lbs_deb_leave_args(LBS_DEB_SCAN, "found_bss %p", found_bss); - return found_bss; -} - -/** - * @brief This function finds ssid in ssid list. - * - * Used in association code - * - * @param priv A pointer to struct lbs_private - * @param ssid SSID to find in the list - * @param bssid BSSID to qualify the SSID selection (if provided) - * @param mode Network mode: Infrastructure or IBSS - * - * @return index in BSSID list - */ -struct bss_descriptor *lbs_find_ssid_in_list(struct lbs_private *priv, - uint8_t *ssid, uint8_t ssid_len, - uint8_t *bssid, uint8_t mode, - int channel) -{ - u32 bestrssi = 0; - struct bss_descriptor * iter_bss = NULL; - struct bss_descriptor * found_bss = NULL; - struct bss_descriptor * tmp_oldest = NULL; - - lbs_deb_enter(LBS_DEB_SCAN); - - mutex_lock(&priv->lock); - - list_for_each_entry (iter_bss, &priv->network_list, list) { - if ( !tmp_oldest - || (iter_bss->last_scanned < tmp_oldest->last_scanned)) - tmp_oldest = iter_bss; - - if (lbs_ssid_cmp(iter_bss->ssid, iter_bss->ssid_len, - ssid, ssid_len) != 0) - continue; /* ssid doesn't match */ - if (bssid && compare_ether_addr(iter_bss->bssid, bssid) != 0) - continue; /* bssid doesn't match */ - if ((channel > 0) && (iter_bss->channel != channel)) - continue; /* channel doesn't match */ - - switch (mode) { - case IW_MODE_INFRA: - case IW_MODE_ADHOC: - if (!is_network_compatible(priv, iter_bss, mode)) - break; - - if (bssid) { - /* Found requested BSSID */ - found_bss = iter_bss; - goto out; - } - - if (SCAN_RSSI(iter_bss->rssi) > bestrssi) { - bestrssi = SCAN_RSSI(iter_bss->rssi); - found_bss = iter_bss; - } - break; - case IW_MODE_AUTO: - default: - if (SCAN_RSSI(iter_bss->rssi) > bestrssi) { - bestrssi = SCAN_RSSI(iter_bss->rssi); - found_bss = iter_bss; - } - break; - } - } - -out: - mutex_unlock(&priv->lock); - lbs_deb_leave_args(LBS_DEB_SCAN, "found_bss %p", found_bss); - return found_bss; -} - -/** - * @brief This function finds the best SSID in the Scan List - * - * Search the scan table for the best SSID that also matches the current - * adapter network preference (infrastructure or adhoc) - * - * @param priv A pointer to struct lbs_private - * - * @return index in BSSID list - */ -static struct bss_descriptor *lbs_find_best_ssid_in_list(struct lbs_private *priv, - uint8_t mode) -{ - uint8_t bestrssi = 0; - struct bss_descriptor *iter_bss; - struct bss_descriptor *best_bss = NULL; - - lbs_deb_enter(LBS_DEB_SCAN); - - mutex_lock(&priv->lock); - - list_for_each_entry (iter_bss, &priv->network_list, list) { - switch (mode) { - case IW_MODE_INFRA: - case IW_MODE_ADHOC: - if (!is_network_compatible(priv, iter_bss, mode)) - break; - if (SCAN_RSSI(iter_bss->rssi) <= bestrssi) - break; - bestrssi = SCAN_RSSI(iter_bss->rssi); - best_bss = iter_bss; - break; - case IW_MODE_AUTO: - default: - if (SCAN_RSSI(iter_bss->rssi) <= bestrssi) - break; - bestrssi = SCAN_RSSI(iter_bss->rssi); - best_bss = iter_bss; - break; - } - } - - mutex_unlock(&priv->lock); - lbs_deb_leave_args(LBS_DEB_SCAN, "best_bss %p", best_bss); - return best_bss; -} - -/** - * @brief Find the best AP - * - * Used from association worker. - * - * @param priv A pointer to struct lbs_private structure - * @param pSSID A pointer to AP's ssid - * - * @return 0--success, otherwise--fail - */ -int lbs_find_best_network_ssid(struct lbs_private *priv, uint8_t *out_ssid, - uint8_t *out_ssid_len, uint8_t preferred_mode, - uint8_t *out_mode) -{ - int ret = -1; - struct bss_descriptor *found; - - lbs_deb_enter(LBS_DEB_SCAN); - - priv->scan_ssid_len = 0; - lbs_scan_networks(priv, 1); - if (priv->surpriseremoved) - goto out; - - found = lbs_find_best_ssid_in_list(priv, preferred_mode); - if (found && (found->ssid_len > 0)) { - memcpy(out_ssid, &found->ssid, IW_ESSID_MAX_SIZE); - *out_ssid_len = found->ssid_len; - *out_mode = found->mode; - ret = 0; - } - -out: - lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); - return ret; -} - - /** * @brief Send a scan command for all available channels filtered on a spec * diff --git a/drivers/net/wireless/libertas/scan.h b/drivers/net/wireless/libertas/scan.h index b50cf1415e04..9e07b0464a8e 100644 --- a/drivers/net/wireless/libertas/scan.h +++ b/drivers/net/wireless/libertas/scan.h @@ -7,73 +7,13 @@ #ifndef _LBS_SCAN_H #define _LBS_SCAN_H -#include -#include "hostcmd.h" - /** * @brief Maximum number of channels that can be sent in a setuserscan ioctl */ #define LBS_IOCTL_USER_SCAN_CHAN_MAX 50 -//! Infrastructure BSS scan type in cmd_ds_802_11_scan -#define LBS_SCAN_BSS_TYPE_BSS 1 - -//! Adhoc BSS scan type in cmd_ds_802_11_scan -#define LBS_SCAN_BSS_TYPE_IBSS 2 - -//! Adhoc or Infrastructure BSS scan type in cmd_ds_802_11_scan, no filter -#define LBS_SCAN_BSS_TYPE_ANY 3 - -/** - * @brief Structure used to store information for each beacon/probe response - */ -struct bss_descriptor { - u8 bssid[ETH_ALEN]; - - u8 ssid[IW_ESSID_MAX_SIZE + 1]; - u8 ssid_len; - - u16 capability; - u32 rssi; - u32 channel; - u16 beaconperiod; - u32 atimwindow; - - /* IW_MODE_AUTO, IW_MODE_ADHOC, IW_MODE_INFRA */ - u8 mode; - - /* zero-terminated array of supported data rates */ - u8 rates[MAX_RATES + 1]; - - unsigned long last_scanned; - - union ieeetypes_phyparamset phyparamset; - union IEEEtypes_ssparamset ssparamset; - - struct ieeetypes_countryinfofullset countryinfo; - - u8 wpa_ie[MAX_WPA_IE_LEN]; - size_t wpa_ie_len; - u8 rsn_ie[MAX_WPA_IE_LEN]; - size_t rsn_ie_len; - - u8 mesh; - - struct list_head list; -}; - int lbs_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len); -struct bss_descriptor *lbs_find_ssid_in_list(struct lbs_private *priv, - u8 *ssid, u8 ssid_len, u8 *bssid, u8 mode, - int channel); - -struct bss_descriptor *lbs_find_bssid_in_list(struct lbs_private *priv, - u8 *bssid, u8 mode); - -int lbs_find_best_network_ssid(struct lbs_private *priv, u8 *out_ssid, - u8 *out_ssid_len, u8 preferred_mode, u8 *out_mode); - int lbs_send_specific_ssid_scan(struct lbs_private *priv, u8 *ssid, u8 ssid_len); @@ -82,6 +22,8 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info, int lbs_set_scan(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra); +int lbs_scan_networks(struct lbs_private *priv, int full_scan); + void lbs_scan_worker(struct work_struct *work); #endif diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c index 375072130221..4ab5b8523ed9 100644 --- a/drivers/net/wireless/libertas/wext.c +++ b/drivers/net/wireless/libertas/wext.c @@ -17,6 +17,7 @@ #include "defs.h" #include "dev.h" #include "wext.h" +#include "scan.h" #include "assoc.h" #include "cmd.h" -- cgit v1.2.1 From 73ab1f25d4a3a22a1547d44199c2171c04e59cb8 Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Wed, 2 Apr 2008 16:52:19 +0200 Subject: libertas: move lbs_update_channel out of assoc.c ... as it has nothing to do with pure association Signed-off-by: Holger Schurig Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/assoc.c | 17 ----------------- drivers/net/wireless/libertas/cmd.c | 16 ++++++++++++++++ 2 files changed, 16 insertions(+), 17 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c index 319b4f931a62..f353419acd02 100644 --- a/drivers/net/wireless/libertas/assoc.c +++ b/drivers/net/wireless/libertas/assoc.c @@ -583,23 +583,6 @@ done: return ret; } - -int lbs_update_channel(struct lbs_private *priv) -{ - int ret; - - /* the channel in f/w could be out of sync; get the current channel */ - lbs_deb_enter(LBS_DEB_ASSOC); - - ret = lbs_get_channel(priv); - if (ret > 0) { - priv->curbssparams.channel = ret; - ret = 0; - } - lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); - return ret; -} - static int assoc_helper_channel(struct lbs_private *priv, struct assoc_request * assoc_req) { diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index 4e6d01948372..4a82f5114ca0 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -825,6 +825,22 @@ out: return ret; } +int lbs_update_channel(struct lbs_private *priv) +{ + int ret; + + /* the channel in f/w could be out of sync; get the current channel */ + lbs_deb_enter(LBS_DEB_ASSOC); + + ret = lbs_get_channel(priv); + if (ret > 0) { + priv->curbssparams.channel = ret; + ret = 0; + } + lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); + return ret; +} + /** * @brief Set the radio channel * -- cgit v1.2.1 From fb14a7e0860ef8b19d0dd61be96e23eacb4da129 Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Wed, 2 Apr 2008 18:04:35 +0200 Subject: libertas: remove lbs_get_fwversion() It was used only at one place anyway. Signed-off-by: Holger Schurig Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/decl.h | 3 --- drivers/net/wireless/libertas/ethtool.c | 9 +++++---- drivers/net/wireless/libertas/wext.c | 17 ----------------- 3 files changed, 5 insertions(+), 24 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h index 1ca747b28ef5..4aea421f07ce 100644 --- a/drivers/net/wireless/libertas/decl.h +++ b/drivers/net/wireless/libertas/decl.h @@ -35,9 +35,6 @@ void lbs_interrupt(struct lbs_private *priv); int lbs_set_radio_control(struct lbs_private *priv); u32 lbs_fw_index_to_data_rate(u8 index); u8 lbs_data_rate_to_fw_index(u32 rate); -void lbs_get_fwversion(struct lbs_private *priv, - char *fwversion, - int maxlen); /** The proc fs interface */ int lbs_process_rx_command(struct lbs_private *priv); diff --git a/drivers/net/wireless/libertas/ethtool.c b/drivers/net/wireless/libertas/ethtool.c index be226c1885a9..dcfdb404678b 100644 --- a/drivers/net/wireless/libertas/ethtool.c +++ b/drivers/net/wireless/libertas/ethtool.c @@ -24,13 +24,14 @@ static void lbs_ethtool_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { struct lbs_private *priv = (struct lbs_private *) dev->priv; - char fwver[32]; - - lbs_get_fwversion(priv, fwver, sizeof(fwver) - 1); + snprintf(info->fw_version, 32, "%u.%u.%u.p%u", + priv->fwrelease >> 24 & 0xff, + priv->fwrelease >> 16 & 0xff, + priv->fwrelease >> 8 & 0xff, + priv->fwrelease & 0xff); strcpy(info->driver, "libertas"); strcpy(info->version, lbs_driver_version); - strcpy(info->fw_version, fwver); } /* All 8388 parts have 16KiB EEPROM size at the time of writing. diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c index 4ab5b8523ed9..0973d015a520 100644 --- a/drivers/net/wireless/libertas/wext.c +++ b/drivers/net/wireless/libertas/wext.c @@ -2060,23 +2060,6 @@ static int lbs_set_wap(struct net_device *dev, struct iw_request_info *info, return ret; } -void lbs_get_fwversion(struct lbs_private *priv, char *fwversion, int maxlen) -{ - char fwver[32]; - - mutex_lock(&priv->lock); - - sprintf(fwver, "%u.%u.%u.p%u", - priv->fwrelease >> 24 & 0xff, - priv->fwrelease >> 16 & 0xff, - priv->fwrelease >> 8 & 0xff, - priv->fwrelease & 0xff); - - mutex_unlock(&priv->lock); - snprintf(fwversion, maxlen, fwver); -} - - /* * iwconfig settable callbacks */ -- cgit v1.2.1 From 93af2614513103216038afa708718295e7016dbb Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Wed, 2 Apr 2008 11:35:32 -0400 Subject: drivers/net/wireless/iwlwifi/iwl-3945.h: correct CONFIG_IWL4965_LEDS typo Thakns to Winfried Tilanus for identifying the problem! Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 333c85077211..3dc7f0fbf02f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -779,7 +779,7 @@ struct iwl3945_priv { struct iwl3945_init_alive_resp card_alive_init; struct iwl3945_alive_resp card_alive; -#ifdef CONFIG_IWL4965_LEDS +#ifdef CONFIG_IWL3945_LEDS struct iwl3945_led led[IWL_LED_TRG_MAX]; unsigned long last_blink_time; u8 last_blink_rate; -- cgit v1.2.1 From 36316126e90b058ad7bd5b9e3d6079814e0a17e2 Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Wed, 2 Apr 2008 10:50:35 -0700 Subject: iwl4965: use IWLWIFI_LEDS config variable Fix error reported by Miles Lane Signed-off-by: Reinette Chatre CC: Miles Lane Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index 0ec217da48d4..baeafd45180b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -1057,7 +1057,7 @@ struct iwl_priv { struct iwl_rfkill_mngr rfkill_mngr; #endif -#ifdef CONFIG_IWL4965_LEDS +#ifdef CONFIG_IWLWIFI_LEDS struct iwl4965_led led[IWL_LED_TRG_MAX]; unsigned long last_blink_time; u8 last_blink_rate; -- cgit v1.2.1 From d8c17e159758c2a4f8c3319fe8a6cf313f7a6733 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Wed, 2 Apr 2008 19:58:20 +0200 Subject: b43: Use SSB block-I/O to do PIO This changes the b43-PIO code to use the new SSB block-I/O. This reduces the overhead by removing lots of function calls, pointer dereferencing, if-conditionals any byteswapping for each packet data word. This also fixes a harmless sparse endianness warning. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/Kconfig | 1 + drivers/net/wireless/b43/pio.c | 173 ++++++++++++++++++++------------------- 2 files changed, 91 insertions(+), 83 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig index 94f04559028b..f51b2d9b085b 100644 --- a/drivers/net/wireless/b43/Kconfig +++ b/drivers/net/wireless/b43/Kconfig @@ -67,6 +67,7 @@ config B43_PCMCIA config B43_PIO bool depends on B43 && (B43_PCMCIA || B43_FORCE_PIO) + select SSB_BLOCKIO default y config B43_NPHY diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c index e73769ac027f..fcacafb04346 100644 --- a/drivers/net/wireless/b43/pio.c +++ b/drivers/net/wireless/b43/pio.c @@ -338,27 +338,28 @@ static struct b43_pio_txqueue * select_queue_by_priority(struct b43_wldev *dev, return q; } -static inline void tx_write_2byte_queue(struct b43_pio_txqueue *q, - u16 *ctl, - const void *_data, - unsigned int data_len) +static u16 tx_write_2byte_queue(struct b43_pio_txqueue *q, + u16 ctl, + const void *_data, + unsigned int data_len) { + struct b43_wldev *dev = q->dev; const u8 *data = _data; - unsigned int i; - u16 value; - - *ctl |= B43_PIO_TXCTL_WRITELO | B43_PIO_TXCTL_WRITEHI; - b43_piotx_write16(q, B43_PIO_TXCTL, *ctl); - for (i = 0; i < data_len; i += 2) { - value = data[i]; - if (i + 1 < data_len) { - value |= (u16)(data[i + 1]) << 8; - } else { - *ctl &= ~B43_PIO_TXCTL_WRITEHI; - b43_piotx_write16(q, B43_PIO_TXCTL, *ctl); - } - b43_piotx_write16(q, B43_PIO_TXDATA, value); + + ctl |= B43_PIO_TXCTL_WRITELO | B43_PIO_TXCTL_WRITEHI; + b43_piotx_write16(q, B43_PIO_TXCTL, ctl); + + ssb_block_write(dev->dev, data, (data_len & ~1), + q->mmio_base + B43_PIO_TXDATA, + sizeof(u16)); + if (data_len & 1) { + /* Write the last byte. */ + ctl &= ~B43_PIO_TXCTL_WRITEHI; + b43_piotx_write16(q, B43_PIO_TXCTL, ctl); + b43_piotx_write16(q, B43_PIO_TXDATA, data[data_len - 1]); } + + return ctl; } static void pio_tx_frame_2byte_queue(struct b43_pio_txpacket *pack, @@ -374,51 +375,53 @@ static void pio_tx_frame_2byte_queue(struct b43_pio_txpacket *pack, ctl &= ~B43_PIO_TXCTL_EOF; /* Transfer the header data. */ - tx_write_2byte_queue(q, &ctl, hdr, hdrlen); + ctl = tx_write_2byte_queue(q, ctl, hdr, hdrlen); /* Transfer the frame data. */ - tx_write_2byte_queue(q, &ctl, frame, frame_len); + ctl = tx_write_2byte_queue(q, ctl, frame, frame_len); ctl |= B43_PIO_TXCTL_EOF; b43_piotx_write16(q, B43_PIO_TXCTL, ctl); } -static inline void tx_write_4byte_queue(struct b43_pio_txqueue *q, - u32 *ctl, - const void *_data, - unsigned int data_len) +static u32 tx_write_4byte_queue(struct b43_pio_txqueue *q, + u32 ctl, + const void *_data, + unsigned int data_len) { + struct b43_wldev *dev = q->dev; const u8 *data = _data; - unsigned int i; - u32 value; - bool ctl_changed = 0; - - *ctl |= B43_PIO8_TXCTL_0_7 | B43_PIO8_TXCTL_8_15 | - B43_PIO8_TXCTL_16_23 | B43_PIO8_TXCTL_24_31; - b43_piotx_write32(q, B43_PIO8_TXCTL, *ctl); - for (i = 0; i < data_len; i += 4) { - value = data[i]; - if (i + 1 < data_len) { - value |= (u32)(data[i + 1]) << 8; - } else { - *ctl &= ~B43_PIO8_TXCTL_8_15; - ctl_changed = 1; - } - if (i + 2 < data_len) { - value |= (u32)(data[i + 2]) << 16; - } else { - *ctl &= ~B43_PIO8_TXCTL_16_23; - ctl_changed = 1; - } - if (i + 3 < data_len) { - value |= (u32)(data[i + 3]) << 24; - } else { - *ctl &= ~B43_PIO8_TXCTL_24_31; - ctl_changed = 1; + + ctl |= B43_PIO8_TXCTL_0_7 | B43_PIO8_TXCTL_8_15 | + B43_PIO8_TXCTL_16_23 | B43_PIO8_TXCTL_24_31; + b43_piotx_write32(q, B43_PIO8_TXCTL, ctl); + + ssb_block_write(dev->dev, data, (data_len & ~3), + q->mmio_base + B43_PIO8_TXDATA, + sizeof(u32)); + if (data_len & 3) { + u32 value = 0; + + /* Write the last few bytes. */ + ctl &= ~(B43_PIO8_TXCTL_8_15 | B43_PIO8_TXCTL_16_23 | + B43_PIO8_TXCTL_24_31); + data = &(data[data_len - 1]); + switch (data_len & 3) { + case 3: + ctl |= B43_PIO8_TXCTL_16_23; + value |= (u32)(*data) << 16; + data--; + case 2: + ctl |= B43_PIO8_TXCTL_8_15; + value |= (u32)(*data) << 8; + data--; + case 1: + value |= (u32)(*data); } - if (ctl_changed) - b43_piotx_write32(q, B43_PIO8_TXCTL, *ctl); + b43_piotx_write32(q, B43_PIO8_TXCTL, ctl); b43_piotx_write32(q, B43_PIO8_TXDATA, value); } + + return ctl; } static void pio_tx_frame_4byte_queue(struct b43_pio_txpacket *pack, @@ -434,9 +437,9 @@ static void pio_tx_frame_4byte_queue(struct b43_pio_txpacket *pack, ctl &= ~B43_PIO8_TXCTL_EOF; /* Transfer the header data. */ - tx_write_4byte_queue(q, &ctl, hdr, hdrlen); + ctl = tx_write_4byte_queue(q, ctl, hdr, hdrlen); /* Transfer the frame data. */ - tx_write_4byte_queue(q, &ctl, frame, frame_len); + ctl = tx_write_4byte_queue(q, ctl, frame, frame_len); ctl |= B43_PIO8_TXCTL_EOF; b43_piotx_write32(q, B43_PIO_TXCTL, ctl); @@ -627,6 +630,7 @@ void b43_pio_get_tx_stats(struct b43_wldev *dev, /* Returns whether we should fetch another frame. */ static bool pio_rx_frame(struct b43_pio_rxqueue *q) { + struct b43_wldev *dev = q->dev; struct b43_rxhdr_fw4 rxhdr; u16 len; u32 macstat; @@ -672,21 +676,13 @@ data_ready: /* Get the preamble (RX header) */ if (q->rev >= 8) { - u32 *preamble = (u32 *)&rxhdr; - u32 value; - - for (i = 0; i < sizeof(rxhdr); i += 4) { - value = b43_piorx_read32(q, B43_PIO8_RXDATA); - preamble[i / 4] = cpu_to_le32(value); - } + ssb_block_read(dev->dev, &rxhdr, sizeof(rxhdr), + q->mmio_base + B43_PIO8_RXDATA, + sizeof(u32)); } else { - u16 *preamble = (u16 *)&rxhdr; - u16 value; - - for (i = 0; i < sizeof(rxhdr); i += 2) { - value = b43_piorx_read16(q, B43_PIO_RXDATA); - preamble[i / 2] = cpu_to_le16(value); - } + ssb_block_read(dev->dev, &rxhdr, sizeof(rxhdr), + q->mmio_base + B43_PIO_RXDATA, + sizeof(u16)); } /* Sanity checks. */ len = le16_to_cpu(rxhdr.frame_len); @@ -720,26 +716,37 @@ data_ready: skb_reserve(skb, 2); skb_put(skb, len + padding); if (q->rev >= 8) { - u32 value; - - for (i = padding; i < len + padding; i += 4) { + ssb_block_read(dev->dev, skb->data + padding, (len & ~3), + q->mmio_base + B43_PIO8_RXDATA, + sizeof(u32)); + if (len & 3) { + u32 value; + char *data; + + /* Read the last few bytes. */ value = b43_piorx_read32(q, B43_PIO8_RXDATA); - skb->data[i] = value; - if ((i + 1) < (len + padding)) - skb->data[i + 1] = value >> 8; - if ((i + 2) < (len + padding)) - skb->data[i + 2] = value >> 16; - if ((i + 3) < (len + padding)) - skb->data[i + 3] = value >> 24; + data = &(skb->data[len + padding - 1]); + switch (len & 3) { + case 3: + *data = (value >> 16); + data--; + case 2: + *data = (value >> 8); + data--; + case 1: + *data = value; + } } } else { - u16 value; + ssb_block_read(dev->dev, skb->data + padding, (len & ~1), + q->mmio_base + B43_PIO_RXDATA, + sizeof(u16)); + if (len & 1) { + u16 value; - for (i = padding; i < len + padding; i += 2) { + /* Read the last byte. */ value = b43_piorx_read16(q, B43_PIO_RXDATA); - skb->data[i] = value; - if ((i + 1) < (len + padding)) - skb->data[i + 1] = value >> 8; + skb->data[len + padding - 1] = value; } } -- cgit v1.2.1 From 7b584163979a9fe2ebfdd57a9d64cbe27166ab70 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Thu, 3 Apr 2008 18:01:12 +0200 Subject: b43: Add more N-PHY stuff This adds some minor stuff for N-PHY support. Nothing special. Adds Analog switching and some TODOs for RSSI processing. Just a patch I had floating around for quite some time now. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 14 +++++++++++++- drivers/net/wireless/b43/nphy.c | 1 - drivers/net/wireless/b43/xmit.c | 23 +++++++++++++++-------- drivers/net/wireless/b43/xmit.h | 15 +++++++++++++-- 4 files changed, 41 insertions(+), 12 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 355f28a2f7f5..3fb4ef816842 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -46,6 +46,7 @@ #include "main.h" #include "debugfs.h" #include "phy.h" +#include "nphy.h" #include "dma.h" #include "pio.h" #include "sysfs.h" @@ -1019,7 +1020,18 @@ void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags) /* Turn the Analog ON/OFF */ static void b43_switch_analog(struct b43_wldev *dev, int on) { - b43_write16(dev, B43_MMIO_PHY0, on ? 0 : 0xF4); + switch (dev->phy.type) { + case B43_PHYTYPE_A: + case B43_PHYTYPE_G: + b43_write16(dev, B43_MMIO_PHY0, on ? 0 : 0xF4); + break; + case B43_PHYTYPE_N: + b43_phy_write(dev, B43_NPHY_AFECTL_OVER, + on ? 0 : 0x7FFF); + break; + default: + B43_WARN_ON(1); + } } void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags) diff --git a/drivers/net/wireless/b43/nphy.c b/drivers/net/wireless/b43/nphy.c index 705131ef4bfa..8695eb223476 100644 --- a/drivers/net/wireless/b43/nphy.c +++ b/drivers/net/wireless/b43/nphy.c @@ -240,7 +240,6 @@ static void b43_nphy_workarounds(struct b43_wldev *dev) b43_phy_set(dev, B43_NPHY_IQFLIP, B43_NPHY_IQFLIP_ADC1 | B43_NPHY_IQFLIP_ADC2); - //FIXME the following condition is different in the specs. if (1 /* FIXME band is 2.4GHz */) { b43_phy_set(dev, B43_NPHY_CLASSCTL, B43_NPHY_CLASSCTL_CCKEN); diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index b2a3123f42db..19aefbfb2c93 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c @@ -513,7 +513,6 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) u32 macstat; u16 chanid; u16 phytype; - u8 jssi; int padding; memset(&status, 0, sizeof(status)); @@ -521,7 +520,6 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) /* Get metadata about the frame from the header. */ phystat0 = le16_to_cpu(rxhdr->phy_status0); phystat3 = le16_to_cpu(rxhdr->phy_status3); - jssi = rxhdr->jssi; macstat = le32_to_cpu(rxhdr->mac_status); mactime = le16_to_cpu(rxhdr->mac_time); chanstat = le16_to_cpu(rxhdr->channel); @@ -575,13 +573,22 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) } } - status.ssi = b43_rssi_postprocess(dev, jssi, - (phystat0 & B43_RX_PHYST0_OFDM), - (phystat0 & B43_RX_PHYST0_GAINCTL), - (phystat3 & B43_RX_PHYST3_TRSTATE)); + /* Link quality statistics */ status.noise = dev->stats.link_noise; - /* the next line looks wrong, but is what mac80211 wants */ - status.signal = (jssi * 100) / B43_RX_MAX_SSI; + if ((chanstat & B43_RX_CHAN_PHYTYPE) == B43_PHYTYPE_N) { +// s8 rssi = max(rxhdr->power0, rxhdr->power1); + //TODO: Find out what the rssi value is (dBm or percentage?) + // and also find out what the maximum possible value is. + // Fill status.ssi and status.signal fields. + } else { + status.ssi = b43_rssi_postprocess(dev, rxhdr->jssi, + (phystat0 & B43_RX_PHYST0_OFDM), + (phystat0 & B43_RX_PHYST0_GAINCTL), + (phystat3 & B43_RX_PHYST3_TRSTATE)); + /* the next line looks wrong, but is what mac80211 wants */ + status.signal = (rxhdr->jssi * 100) / B43_RX_MAX_SSI; + } + if (phystat0 & B43_RX_PHYST0_OFDM) status.rate_idx = b43_plcp_get_bitrate_idx_ofdm(plcp, phytype == B43_PHYTYPE_A); diff --git a/drivers/net/wireless/b43/xmit.h b/drivers/net/wireless/b43/xmit.h index 4f26988a5132..b05f44e0d626 100644 --- a/drivers/net/wireless/b43/xmit.h +++ b/drivers/net/wireless/b43/xmit.h @@ -212,8 +212,19 @@ struct b43_rxhdr_fw4 { __le16 frame_len; /* Frame length */ PAD_BYTES(2); __le16 phy_status0; /* PHY RX Status 0 */ - __u8 jssi; /* PHY RX Status 1: JSSI */ - __u8 sig_qual; /* PHY RX Status 1: Signal Quality */ + union { + /* RSSI for A/B/G-PHYs */ + struct { + __u8 jssi; /* PHY RX Status 1: JSSI */ + __u8 sig_qual; /* PHY RX Status 1: Signal Quality */ + } __attribute__ ((__packed__)); + + /* RSSI for N-PHYs */ + struct { + __s8 power0; /* PHY RX Status 1: Power 0 */ + __s8 power1; /* PHY RX Status 1: Power 1 */ + } __attribute__ ((__packed__)); + } __attribute__ ((__packed__)); __le16 phy_status2; /* PHY RX Status 2 */ __le16 phy_status3; /* PHY RX Status 3 */ __le32 mac_status; /* MAC RX status */ -- cgit v1.2.1 From d59f720d88089f2feabe4335839521b26572dc75 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Thu, 3 Apr 2008 18:56:19 +0200 Subject: b43: Fix TBTT and PU timings This fixes some timings for pre-TBTT and synthetic PU. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/b43.h | 1 + drivers/net/wireless/b43/main.c | 46 ++++++++++++++++++++++++++++++++++------- 2 files changed, 39 insertions(+), 8 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index ef8ae385835a..e478799c09cb 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -111,6 +111,7 @@ #define B43_MMIO_GPIO_MASK 0x49E #define B43_MMIO_TSF_CFP_START_LOW 0x604 #define B43_MMIO_TSF_CFP_START_HIGH 0x606 +#define B43_MMIO_TSF_CFP_PRETBTT 0x612 #define B43_MMIO_TSF_0 0x632 /* core rev < 3 only */ #define B43_MMIO_TSF_1 0x634 /* core rev < 3 only */ #define B43_MMIO_TSF_2 0x636 /* core rev < 3 only */ diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 3fb4ef816842..6ecaf84da2fc 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -3690,6 +3690,41 @@ static void b43_set_retry_limits(struct b43_wldev *dev, long_retry); } +static void b43_set_synth_pu_delay(struct b43_wldev *dev, bool idle) +{ + u16 pu_delay; + + /* The time value is in microseconds. */ + if (dev->phy.type == B43_PHYTYPE_A) + pu_delay = 3700; + else + pu_delay = 1050; + if ((dev->wl->if_type == IEEE80211_IF_TYPE_IBSS) || idle) + pu_delay = 500; + if ((dev->phy.radio_ver == 0x2050) && (dev->phy.radio_rev == 8)) + pu_delay = max(pu_delay, (u16)2400); + + b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_SPUWKUP, pu_delay); +} + +/* Set the TSF CFP pre-TargetBeaconTransmissionTime. */ +static void b43_set_pretbtt(struct b43_wldev *dev) +{ + u16 pretbtt; + + /* The time value is in microseconds. */ + if (dev->wl->if_type == IEEE80211_IF_TYPE_IBSS) { + pretbtt = 2; + } else { + if (dev->phy.type == B43_PHYTYPE_A) + pretbtt = 120; + else + pretbtt = 250; + } + b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_PRETBTT, pretbtt); + b43_write16(dev, B43_MMIO_TSF_CFP_PRETBTT, pretbtt); +} + /* Shutdown a wireless core */ /* Locking: wl->mutex */ static void b43_wireless_core_exit(struct b43_wldev *dev) @@ -3821,14 +3856,7 @@ static int b43_wireless_core_init(struct b43_wldev *dev) if (err) goto err_chip_exit; b43_qos_init(dev); - -//FIXME -#if 1 - b43_write16(dev, 0x0612, 0x0050); - b43_shm_write16(dev, B43_SHM_SHARED, 0x0416, 0x0050); - b43_shm_write16(dev, B43_SHM_SHARED, 0x0414, 0x01F4); -#endif - + b43_set_synth_pu_delay(dev, 1); b43_bluetooth_coext_enable(dev); ssb_bus_powerup(bus, 1); /* Enable dynamic PCTL */ @@ -3888,6 +3916,8 @@ static int b43_op_add_interface(struct ieee80211_hw *hw, spin_lock_irqsave(&wl->irq_lock, flags); b43_adjust_opmode(dev); + b43_set_pretbtt(dev); + b43_set_synth_pu_delay(dev, 0); b43_upload_card_macaddress(dev); spin_unlock_irqrestore(&wl->irq_lock, flags); -- cgit v1.2.1 From 133adf08266740cd886d544aa9fe80b9873cf699 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Fri, 4 Apr 2008 00:01:43 +0200 Subject: rt2x00: Use lib->config_filter() during scheduled packet filter config Now rt2x00lib handles the initial configure_filter() command, we can directly call lib->config_filter() in scheduled context since the called function will no longer check if anything has changed (which is now handled in rt2x00lib as well). This fixes a endless loop with USB drivers where the config_filter command was scheduled time and time again without sending any command to the device. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00dev.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 50ea7bd0c922..0361524d193c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -404,18 +404,8 @@ static void rt2x00lib_packetfilter_scheduled(struct work_struct *work) { struct rt2x00_dev *rt2x00dev = container_of(work, struct rt2x00_dev, filter_work); - unsigned int filter = rt2x00dev->packet_filter; - /* - * Since we had stored the filter inside rt2x00dev->packet_filter, - * we should now clear that field. Otherwise the driver will - * assume nothing has changed (*total_flags will be compared - * to rt2x00dev->packet_filter to determine if any action is required). - */ - rt2x00dev->packet_filter = 0; - - rt2x00dev->ops->hw->configure_filter(rt2x00dev->hw, - filter, &filter, 0, NULL); + rt2x00dev->ops->lib->config_filter(rt2x00dev, rt2x00dev->packet_filter); } static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac, -- cgit v1.2.1 From 12a81f60b98096079d392f8abc284cbd76aa719b Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Thu, 3 Apr 2008 16:05:20 -0700 Subject: iwlwifi: hw names cleanup This patch make some cleanup in HW names Signed-off-by: Tomas Winkler Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965-hw.h | 16 ++++--- drivers/net/wireless/iwlwifi/iwl-4965.c | 28 +++++------ drivers/net/wireless/iwlwifi/iwl-prph.h | 74 ++++++++++++++++-------------- 3 files changed, 62 insertions(+), 56 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h index 1898888e71f2..de7bac149723 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h @@ -126,16 +126,18 @@ /* Sizes and addresses for instruction and data memory (SRAM) in * 4965's embedded processor. Driver access is via HBUS_TARG_MEM_* regs. */ #define RTC_INST_LOWER_BOUND (0x000000) -#define KDR_RTC_INST_UPPER_BOUND (0x018000) +#define IWL49_RTC_INST_UPPER_BOUND (0x018000) #define RTC_DATA_LOWER_BOUND (0x800000) -#define KDR_RTC_DATA_UPPER_BOUND (0x80A000) +#define IWL49_RTC_DATA_UPPER_BOUND (0x80A000) -#define KDR_RTC_INST_SIZE (KDR_RTC_INST_UPPER_BOUND - RTC_INST_LOWER_BOUND) -#define KDR_RTC_DATA_SIZE (KDR_RTC_DATA_UPPER_BOUND - RTC_DATA_LOWER_BOUND) +#define IWL49_RTC_INST_SIZE \ + (IWL49_RTC_INST_UPPER_BOUND - RTC_INST_LOWER_BOUND) +#define IWL49_RTC_DATA_SIZE \ + (IWL49_RTC_DATA_UPPER_BOUND - RTC_DATA_LOWER_BOUND) -#define IWL_MAX_INST_SIZE KDR_RTC_INST_SIZE -#define IWL_MAX_DATA_SIZE KDR_RTC_DATA_SIZE +#define IWL_MAX_INST_SIZE IWL49_RTC_INST_SIZE +#define IWL_MAX_DATA_SIZE IWL49_RTC_DATA_SIZE /* Size of uCode instruction memory in bootstrap state machine */ #define IWL_MAX_BSM_SIZE BSM_SRAM_SIZE @@ -143,7 +145,7 @@ static inline int iwl4965_hw_valid_rtc_data_addr(u32 addr) { return (addr >= RTC_DATA_LOWER_BOUND) && - (addr < KDR_RTC_DATA_UPPER_BOUND); + (addr < IWL49_RTC_DATA_UPPER_BOUND); } /********************* START TEMPERATURE *************************************/ diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 73e8a24eb9ce..e8cff7dbfe87 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -532,7 +532,7 @@ static int iwl4965_txq_ctx_reset(struct iwl_priv *priv) } /* Turn off all Tx DMA channels */ - iwl_write_prph(priv, KDR_SCD_TXFACT, 0); + iwl_write_prph(priv, IWL49_SCD_TXFACT, 0); iwl_release_nic_access(priv); spin_unlock_irqrestore(&priv->lock, flags); @@ -1731,7 +1731,7 @@ static void iwl4965_set_wr_ptrs(struct iwl_priv *priv, int txq_id, u32 index) { iwl_write_direct32(priv, HBUS_TARG_WRPTR, (index & 0xff) | (txq_id << 8)); - iwl_write_prph(priv, KDR_SCD_QUEUE_RDPTR(txq_id), index); + iwl_write_prph(priv, IWL49_SCD_QUEUE_RDPTR(txq_id), index); } /** @@ -1751,7 +1751,7 @@ static void iwl4965_tx_queue_set_status(struct iwl_priv *priv, int active = test_bit(txq_id, &priv->txq_ctx_active_msk)?1:0; /* Set up and activate */ - iwl_write_prph(priv, KDR_SCD_QUEUE_STATUS_BITS(txq_id), + iwl_write_prph(priv, IWL49_SCD_QUEUE_STATUS_BITS(txq_id), (active << SCD_QUEUE_STTS_REG_POS_ACTIVE) | (tx_fifo_id << SCD_QUEUE_STTS_REG_POS_TXF) | (scd_retry << SCD_QUEUE_STTS_REG_POS_WSL) | @@ -1810,7 +1810,7 @@ int iwl4965_alive_notify(struct iwl_priv *priv) } /* Clear 4965's internal Tx Scheduler data base */ - priv->scd_base_addr = iwl_read_prph(priv, KDR_SCD_SRAM_BASE_ADDR); + priv->scd_base_addr = iwl_read_prph(priv, IWL49_SCD_SRAM_BASE_ADDR); a = priv->scd_base_addr + SCD_CONTEXT_DATA_OFFSET; for (; a < priv->scd_base_addr + SCD_TX_STTS_BITMAP_OFFSET; a += 4) iwl_write_targ_mem(priv, a, 0); @@ -1820,18 +1820,18 @@ int iwl4965_alive_notify(struct iwl_priv *priv) iwl_write_targ_mem(priv, a, 0); /* Tel 4965 where to find Tx byte count tables */ - iwl_write_prph(priv, KDR_SCD_DRAM_BASE_ADDR, + iwl_write_prph(priv, IWL49_SCD_DRAM_BASE_ADDR, (priv->hw_setting.shared_phys + offsetof(struct iwl4965_shared, queues_byte_cnt_tbls)) >> 10); /* Disable chain mode for all queues */ - iwl_write_prph(priv, KDR_SCD_QUEUECHAIN_SEL, 0); + iwl_write_prph(priv, IWL49_SCD_QUEUECHAIN_SEL, 0); /* Initialize each Tx queue (including the command queue) */ for (i = 0; i < priv->hw_setting.max_txq_num; i++) { /* TFD circular buffer read/write indexes */ - iwl_write_prph(priv, KDR_SCD_QUEUE_RDPTR(i), 0); + iwl_write_prph(priv, IWL49_SCD_QUEUE_RDPTR(i), 0); iwl_write_direct32(priv, HBUS_TARG_WRPTR, 0 | (i << 8)); /* Max Tx Window size for Scheduler-ACK mode */ @@ -1850,11 +1850,11 @@ int iwl4965_alive_notify(struct iwl_priv *priv) SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK); } - iwl_write_prph(priv, KDR_SCD_INTERRUPT_MASK, + iwl_write_prph(priv, IWL49_SCD_INTERRUPT_MASK, (1 << priv->hw_setting.max_txq_num) - 1); /* Activate all Tx DMA/FIFO channels */ - iwl_write_prph(priv, KDR_SCD_TXFACT, + iwl_write_prph(priv, IWL49_SCD_TXFACT, SCD_TXFACT_REG_TXFIFO_MASK(0, 7)); iwl4965_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0); @@ -4091,7 +4091,7 @@ static void iwl4965_tx_queue_stop_scheduler(struct iwl_priv *priv, /* Simply stop the queue, but don't change any configuration; * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */ iwl_write_prph(priv, - KDR_SCD_QUEUE_STATUS_BITS(txq_id), + IWL49_SCD_QUEUE_STATUS_BITS(txq_id), (0 << SCD_QUEUE_STTS_REG_POS_ACTIVE)| (1 << SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN)); } @@ -4117,14 +4117,14 @@ static int iwl4965_tx_queue_agg_disable(struct iwl_priv *priv, u16 txq_id, iwl4965_tx_queue_stop_scheduler(priv, txq_id); - iwl_clear_bits_prph(priv, KDR_SCD_QUEUECHAIN_SEL, (1 << txq_id)); + iwl_clear_bits_prph(priv, IWL49_SCD_QUEUECHAIN_SEL, (1 << txq_id)); priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff); priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); /* supposes that ssn_idx is valid (!= 0xFFF) */ iwl4965_set_wr_ptrs(priv, txq_id, ssn_idx); - iwl_clear_bits_prph(priv, KDR_SCD_INTERRUPT_MASK, (1 << txq_id)); + iwl_clear_bits_prph(priv, IWL49_SCD_INTERRUPT_MASK, (1 << txq_id)); iwl4965_txq_ctx_deactivate(priv, txq_id); iwl4965_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0); @@ -4313,7 +4313,7 @@ static int iwl4965_tx_queue_agg_enable(struct iwl_priv *priv, int txq_id, iwl4965_tx_queue_set_q2ratid(priv, ra_tid, txq_id); /* Set this queue as a chain-building queue */ - iwl_set_bits_prph(priv, KDR_SCD_QUEUECHAIN_SEL, (1 << txq_id)); + iwl_set_bits_prph(priv, IWL49_SCD_QUEUECHAIN_SEL, (1 << txq_id)); /* Place first TFD at index corresponding to start sequence number. * Assumes that ssn_idx is valid (!= 0xFFF) */ @@ -4332,7 +4332,7 @@ static int iwl4965_tx_queue_agg_enable(struct iwl_priv *priv, int txq_id, (SCD_FRAME_LIMIT << SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK); - iwl_set_bits_prph(priv, KDR_SCD_INTERRUPT_MASK, (1 << txq_id)); + iwl_set_bits_prph(priv, IWL49_SCD_INTERRUPT_MASK, (1 << txq_id)); /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */ iwl4965_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1); diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index ecf651ae2593..c9cf8eef1a90 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h @@ -243,44 +243,48 @@ * 4965 Tx Scheduler registers. * Details are documented in iwl-4965-hw.h */ -#define KDR_SCD_BASE (PRPH_BASE + 0xa02c00) +#define IWL49_SCD_BASE (PRPH_BASE + 0xa02c00) -#define KDR_SCD_SRAM_BASE_ADDR (KDR_SCD_BASE + 0x0) -#define KDR_SCD_EMPTY_BITS (KDR_SCD_BASE + 0x4) -#define KDR_SCD_DRAM_BASE_ADDR (KDR_SCD_BASE + 0x10) -#define KDR_SCD_AIT (KDR_SCD_BASE + 0x18) -#define KDR_SCD_TXFACT (KDR_SCD_BASE + 0x1c) -#define KDR_SCD_QUEUE_WRPTR(x) (KDR_SCD_BASE + 0x24 + (x) * 4) -#define KDR_SCD_QUEUE_RDPTR(x) (KDR_SCD_BASE + 0x64 + (x) * 4) -#define KDR_SCD_SETQUEUENUM (KDR_SCD_BASE + 0xa4) -#define KDR_SCD_SET_TXSTAT_TXED (KDR_SCD_BASE + 0xa8) -#define KDR_SCD_SET_TXSTAT_DONE (KDR_SCD_BASE + 0xac) -#define KDR_SCD_SET_TXSTAT_NOT_SCHD (KDR_SCD_BASE + 0xb0) -#define KDR_SCD_DECREASE_CREDIT (KDR_SCD_BASE + 0xb4) -#define KDR_SCD_DECREASE_SCREDIT (KDR_SCD_BASE + 0xb8) -#define KDR_SCD_LOAD_CREDIT (KDR_SCD_BASE + 0xbc) -#define KDR_SCD_LOAD_SCREDIT (KDR_SCD_BASE + 0xc0) -#define KDR_SCD_BAR (KDR_SCD_BASE + 0xc4) -#define KDR_SCD_BAR_DW0 (KDR_SCD_BASE + 0xc8) -#define KDR_SCD_BAR_DW1 (KDR_SCD_BASE + 0xcc) -#define KDR_SCD_QUEUECHAIN_SEL (KDR_SCD_BASE + 0xd0) -#define KDR_SCD_QUERY_REQ (KDR_SCD_BASE + 0xd8) -#define KDR_SCD_QUERY_RES (KDR_SCD_BASE + 0xdc) -#define KDR_SCD_PENDING_FRAMES (KDR_SCD_BASE + 0xe0) -#define KDR_SCD_INTERRUPT_MASK (KDR_SCD_BASE + 0xe4) -#define KDR_SCD_INTERRUPT_THRESHOLD (KDR_SCD_BASE + 0xe8) -#define KDR_SCD_QUERY_MIN_FRAME_SIZE (KDR_SCD_BASE + 0x100) -#define KDR_SCD_QUEUE_STATUS_BITS(x) (KDR_SCD_BASE + 0x104 + (x) * 4) +#define IWL49_SCD_SRAM_BASE_ADDR (IWL49_SCD_BASE + 0x0) +#define IWL49_SCD_EMPTY_BITS (IWL49_SCD_BASE + 0x4) +#define IWL49_SCD_DRAM_BASE_ADDR (IWL49_SCD_BASE + 0x10) +#define IWL49_SCD_AIT (IWL49_SCD_BASE + 0x18) +#define IWL49_SCD_TXFACT (IWL49_SCD_BASE + 0x1c) +#define IWL49_SCD_QUEUE_WRPTR(x) (IWL49_SCD_BASE + 0x24 + (x) * 4) +#define IWL49_SCD_QUEUE_RDPTR(x) (IWL49_SCD_BASE + 0x64 + (x) * 4) +#define IWL49_SCD_SETQUEUENUM (IWL49_SCD_BASE + 0xa4) +#define IWL49_SCD_SET_TXSTAT_TXED (IWL49_SCD_BASE + 0xa8) +#define IWL49_SCD_SET_TXSTAT_DONE (IWL49_SCD_BASE + 0xac) +#define IWL49_SCD_SET_TXSTAT_NOT_SCHD (IWL49_SCD_BASE + 0xb0) +#define IWL49_SCD_DECREASE_CREDIT (IWL49_SCD_BASE + 0xb4) +#define IWL49_SCD_DECREASE_SCREDIT (IWL49_SCD_BASE + 0xb8) +#define IWL49_SCD_LOAD_CREDIT (IWL49_SCD_BASE + 0xbc) +#define IWL49_SCD_LOAD_SCREDIT (IWL49_SCD_BASE + 0xc0) +#define IWL49_SCD_BAR (IWL49_SCD_BASE + 0xc4) +#define IWL49_SCD_BAR_DW0 (IWL49_SCD_BASE + 0xc8) +#define IWL49_SCD_BAR_DW1 (IWL49_SCD_BASE + 0xcc) +#define IWL49_SCD_QUEUECHAIN_SEL (IWL49_SCD_BASE + 0xd0) +#define IWL49_SCD_QUERY_REQ (IWL49_SCD_BASE + 0xd8) +#define IWL49_SCD_QUERY_RES (IWL49_SCD_BASE + 0xdc) +#define IWL49_SCD_PENDING_FRAMES (IWL49_SCD_BASE + 0xe0) +#define IWL49_SCD_INTERRUPT_MASK (IWL49_SCD_BASE + 0xe4) +#define IWL49_SCD_INTERRUPT_THRESHOLD (IWL49_SCD_BASE + 0xe8) +#define IWL49_SCD_QUERY_MIN_FRAME_SIZE (IWL49_SCD_BASE + 0x100) +#define IWL49_SCD_QUEUE_STATUS_BITS(x) (IWL49_SCD_BASE + 0x104 + (x) * 4) /* SP SCD */ -#define SHL_SCD_BASE (PRPH_BASE + 0xa02c00) +#define IWL50_SCD_BASE (PRPH_BASE + 0xa02c00) -#define SHL_SCD_AIT (SHL_SCD_BASE + 0x0c) -#define SHL_SCD_TXFACT (SHL_SCD_BASE + 0x10) -#define SHL_SCD_QUEUE_WRPTR(x) (SHL_SCD_BASE + 0x18 + (x) * 4) -#define SHL_SCD_QUEUE_RDPTR(x) (SHL_SCD_BASE + 0x68 + (x) * 4) -#define SHL_SCD_QUEUECHAIN_SEL (SHL_SCD_BASE + 0xe8) -#define SHL_SCD_AGGR_SEL (SHL_SCD_BASE + 0x248) -#define SHL_SCD_INTERRUPT_MASK (SHL_SCD_BASE + 0x108) +#define IWL50_SCD_SRAM_BASE_ADDR (IWL50_SCD_BASE + 0x0) +#define IWL50_SCD_DRAM_BASE_ADDR (IWL50_SCD_BASE + 0x8) +#define IWL50_SCD_AIT (IWL50_SCD_BASE + 0x0c) +#define IWL50_SCD_TXFACT (IWL50_SCD_BASE + 0x10) +#define IWL50_SCD_ACTIVE (IWL50_SCD_BASE + 0x14) +#define IWL50_SCD_QUEUE_WRPTR(x) (IWL50_SCD_BASE + 0x18 + (x) * 4) +#define IWL50_SCD_QUEUE_RDPTR(x) (IWL50_SCD_BASE + 0x68 + (x) * 4) +#define IWL50_SCD_QUEUECHAIN_SEL (IWL50_SCD_BASE + 0xe8) +#define IWL50_SCD_AGGR_SEL (IWL50_SCD_BASE + 0x248) +#define IWL50_SCD_INTERRUPT_MASK (IWL50_SCD_BASE + 0x108) +#define IWL50_SCD_QUEUE_STATUS_BITS(x) (IWL50_SCD_BASE + 0x10c + (x) * 4) #endif /* __iwl_prph_h__ */ -- cgit v1.2.1 From fee1247a30e5b3d48fe985b4a935eb6818f3b464 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Thu, 3 Apr 2008 16:05:21 -0700 Subject: iwlwifi: move driver status inliners into iwl-core.h This patch moves inline functions into iwl-core.h Signed-off-by: Tomas Winkler Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965.c | 2 +- drivers/net/wireless/iwlwifi/iwl-4965.h | 20 ------- drivers/net/wireless/iwlwifi/iwl-core.c | 2 +- drivers/net/wireless/iwlwifi/iwl-core.h | 57 ++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-debugfs.c | 1 + drivers/net/wireless/iwlwifi/iwl-led.c | 2 +- drivers/net/wireless/iwlwifi/iwl-rfkill.c | 9 +-- drivers/net/wireless/iwlwifi/iwl4965-base.c | 92 +++++++++-------------------- 8 files changed, 91 insertions(+), 94 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index e8cff7dbfe87..69e92177ad60 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -39,8 +39,8 @@ #include #include "iwl-eeprom.h" -#include "iwl-core.h" #include "iwl-4965.h" +#include "iwl-core.h" #include "iwl-io.h" #include "iwl-helpers.h" diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index baeafd45180b..65e536782706 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -414,26 +414,6 @@ struct iwl4965_rx_queue { #define MAX_B_CHANNELS 14 #define MIN_B_CHANNELS 1 -#define STATUS_HCMD_ACTIVE 0 /* host command in progress */ -#define STATUS_HCMD_SYNC_ACTIVE 1 /* sync host command in progress */ -#define STATUS_INT_ENABLED 2 -#define STATUS_RF_KILL_HW 3 -#define STATUS_RF_KILL_SW 4 -#define STATUS_INIT 5 -#define STATUS_ALIVE 6 -#define STATUS_READY 7 -#define STATUS_TEMPERATURE 8 -#define STATUS_GEO_CONFIGURED 9 -#define STATUS_EXIT_PENDING 10 -#define STATUS_IN_SUSPEND 11 -#define STATUS_STATISTICS 12 -#define STATUS_SCANNING 13 -#define STATUS_SCAN_ABORTING 14 -#define STATUS_SCAN_HW 15 -#define STATUS_POWER_PMI 16 -#define STATUS_FW_ERROR 17 -#define STATUS_CONF_PENDING 18 - #define MAX_TID_COUNT 9 #define IWL_INVALID_RATE 0xFF diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 49fb52f07354..f12230780555 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -34,10 +34,10 @@ struct iwl_priv; /* FIXME: remove */ #include "iwl-debug.h" #include "iwl-eeprom.h" +#include "iwl-4965.h" /* FIXME: remove */ #include "iwl-core.h" #include "iwl-rfkill.h" -#include "iwl-4965.h" /* FIXME: remove */ MODULE_DESCRIPTION("iwl core"); MODULE_VERSION(IWLWIFI_VERSION); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 64f4df53986c..6d82376f43f9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -148,6 +148,63 @@ int iwl_send_cmd_pdu_async(struct iwl_priv *priv, u8 id, u16 len, int (*callback)(struct iwl_priv *priv, struct iwl_cmd *cmd, struct sk_buff *skb)); +/*************** DRIVER STATUS FUNCTIONS *****/ + +#define STATUS_HCMD_ACTIVE 0 /* host command in progress */ +#define STATUS_HCMD_SYNC_ACTIVE 1 /* sync host command in progress */ +#define STATUS_INT_ENABLED 2 +#define STATUS_RF_KILL_HW 3 +#define STATUS_RF_KILL_SW 4 +#define STATUS_INIT 5 +#define STATUS_ALIVE 6 +#define STATUS_READY 7 +#define STATUS_TEMPERATURE 8 +#define STATUS_GEO_CONFIGURED 9 +#define STATUS_EXIT_PENDING 10 +#define STATUS_IN_SUSPEND 11 +#define STATUS_STATISTICS 12 +#define STATUS_SCANNING 13 +#define STATUS_SCAN_ABORTING 14 +#define STATUS_SCAN_HW 15 +#define STATUS_POWER_PMI 16 +#define STATUS_FW_ERROR 17 +#define STATUS_CONF_PENDING 18 + + +static inline int iwl_is_ready(struct iwl_priv *priv) +{ + /* The adapter is 'ready' if READY and GEO_CONFIGURED bits are + * set but EXIT_PENDING is not */ + return test_bit(STATUS_READY, &priv->status) && + test_bit(STATUS_GEO_CONFIGURED, &priv->status) && + !test_bit(STATUS_EXIT_PENDING, &priv->status); +} + +static inline int iwl_is_alive(struct iwl_priv *priv) +{ + return test_bit(STATUS_ALIVE, &priv->status); +} + +static inline int iwl_is_init(struct iwl_priv *priv) +{ + return test_bit(STATUS_INIT, &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); +} + +static inline int iwl_is_ready_rf(struct iwl_priv *priv) +{ + + if (iwl_is_rfkill(priv)) + return 0; + + return iwl_is_ready(priv); +} + enum iwlcore_card_notify { IWLCORE_INIT_EVT = 0, diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 447ff2ca4137..23632e54aab2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -36,6 +36,7 @@ #include "iwl-4965.h" #include "iwl-debug.h" +#include "iwl-core.h" #include "iwl-io.h" diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index 4fe5ee2ba545..03fdf5b434a1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c @@ -40,8 +40,8 @@ #include #include "iwl-4965.h" -#include "iwl-io.h" #include "iwl-core.h" +#include "iwl-io.h" #include "iwl-helpers.h" #define IWL_1MB_RATE (128 * 1024) diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.c b/drivers/net/wireless/iwlwifi/iwl-rfkill.c index 66abf52e8987..308d69b18404 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rfkill.c +++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.c @@ -33,18 +33,11 @@ #include #include "iwl-eeprom.h" -#include "iwl-core.h" #include "iwl-4965.h" +#include "iwl-core.h" #include "iwl-helpers.h" -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); -} - - /* software rf-kill from user */ static int iwl_rfkill_soft_rf_kill(void *data, enum rfkill_state state) { diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index f995af682233..5dfc414792c1 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -46,8 +46,8 @@ #include #include "iwl-eeprom.h" -#include "iwl-core.h" #include "iwl-4965.h" +#include "iwl-core.h" #include "iwl-io.h" #include "iwl-helpers.h" @@ -496,41 +496,7 @@ u8 iwl4965_add_station_flags(struct iwl_priv *priv, const u8 *addr, } -/*************** DRIVER STATUS FUNCTIONS *****/ - -static inline int iwl4965_is_ready(struct iwl_priv *priv) -{ - /* The adapter is 'ready' if READY and GEO_CONFIGURED bits are - * set but EXIT_PENDING is not */ - return test_bit(STATUS_READY, &priv->status) && - test_bit(STATUS_GEO_CONFIGURED, &priv->status) && - !test_bit(STATUS_EXIT_PENDING, &priv->status); -} - -static inline int iwl4965_is_alive(struct iwl_priv *priv) -{ - return test_bit(STATUS_ALIVE, &priv->status); -} -static inline int iwl4965_is_init(struct iwl_priv *priv) -{ - return test_bit(STATUS_INIT, &priv->status); -} - -static inline int iwl4965_is_rfkill(struct iwl_priv *priv) -{ - return test_bit(STATUS_RF_KILL_HW, &priv->status) || - test_bit(STATUS_RF_KILL_SW, &priv->status); -} - -static inline int iwl4965_is_ready_rf(struct iwl_priv *priv) -{ - - if (iwl4965_is_rfkill(priv)) - return 0; - - return iwl4965_is_ready(priv); -} /*************** HOST COMMAND QUEUE FUNCTIONS *****/ @@ -562,7 +528,7 @@ int iwl4965_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) BUG_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) && !(cmd->meta.flags & CMD_SIZE_HUGE)); - if (iwl4965_is_rfkill(priv)) { + if (iwl_is_rfkill(priv)) { IWL_DEBUG_INFO("Not sending command - RF KILL"); return -EIO; } @@ -858,7 +824,7 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv) DECLARE_MAC_BUF(mac); int rc = 0; - if (!iwl4965_is_alive(priv)) + if (!iwl_is_alive(priv)) return -1; /* always get timestamp with Rx frame */ @@ -1973,7 +1939,7 @@ static int iwl4965_scan_initiate(struct iwl_priv *priv) return 0; } - if (!iwl4965_is_ready_rf(priv)) { + if (!iwl_is_ready_rf(priv)) { IWL_DEBUG_SCAN("Aborting scan due to not ready.\n"); return -EIO; } @@ -2127,7 +2093,7 @@ static int iwl4965_set_mode(struct iwl_priv *priv, int mode) iwlcore_clear_stations_table(priv); /* dont commit rxon if rf-kill is on*/ - if (!iwl4965_is_ready_rf(priv)) + if (!iwl_is_ready_rf(priv)) return -EAGAIN; cancel_delayed_work(&priv->scan_check); @@ -2343,7 +2309,7 @@ static int iwl4965_tx_skb(struct iwl_priv *priv, int rc; spin_lock_irqsave(&priv->lock, flags); - if (iwl4965_is_rfkill(priv)) { + if (iwl_is_rfkill(priv)) { IWL_DEBUG_DROP("Dropping - RF KILL\n"); goto drop_unlock; } @@ -5701,7 +5667,7 @@ static void iwl4965_alive_start(struct iwl_priv *priv) /* Clear out the uCode error bit if it is set */ clear_bit(STATUS_FW_ERROR, &priv->status); - if (iwl4965_is_rfkill(priv)) + if (iwl_is_rfkill(priv)) return; ieee80211_start_queues(priv->hw); @@ -5794,7 +5760,7 @@ static void __iwl4965_down(struct iwl_priv *priv) /* If we have not previously called iwl4965_init() then * clear all bits but the RF Kill and SUSPEND bits and return */ - if (!iwl4965_is_init(priv)) { + if (!iwl_is_init(priv)) { priv->status = test_bit(STATUS_RF_KILL_HW, &priv->status) << STATUS_RF_KILL_HW | test_bit(STATUS_RF_KILL_SW, &priv->status) << @@ -6004,7 +5970,7 @@ static void iwl4965_bg_rf_kill(struct work_struct *work) mutex_lock(&priv->mutex); - if (!iwl4965_is_rfkill(priv)) { + if (!iwl_is_rfkill(priv)) { IWL_DEBUG(IWL_DL_INFO | IWL_DL_RF_KILL, "HW and/or SW RF Kill no longer active, restarting " "device\n"); @@ -6071,7 +6037,7 @@ static void iwl4965_bg_request_scan(struct work_struct *data) mutex_lock(&priv->mutex); - if (!iwl4965_is_ready(priv)) { + if (!iwl_is_ready(priv)) { IWL_WARNING("request scan called when driver not ready.\n"); goto done; } @@ -6100,7 +6066,7 @@ static void iwl4965_bg_request_scan(struct work_struct *data) goto done; } - if (iwl4965_is_rfkill(priv)) { + if (iwl_is_rfkill(priv)) { IWL_DEBUG_HC("Aborting scan due to RF Kill activation\n"); goto done; } @@ -6419,7 +6385,7 @@ static void iwl4965_bg_abort_scan(struct work_struct *work) { struct iwl_priv *priv = container_of(work, struct iwl_priv, abort_scan); - if (!iwl4965_is_ready(priv)) + if (!iwl_is_ready(priv)) return; mutex_lock(&priv->mutex); @@ -6552,7 +6518,7 @@ static void iwl4965_mac_stop(struct ieee80211_hw *hw) priv->is_open = 0; - if (iwl4965_is_ready_rf(priv)) { + if (iwl_is_ready_rf(priv)) { /* stop mac, cancel any scan request and clear * RXON_FILTER_ASSOC_MSK BIT */ @@ -6621,7 +6587,7 @@ static int iwl4965_mac_add_interface(struct ieee80211_hw *hw, memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN); } - if (iwl4965_is_ready(priv)) + if (iwl_is_ready(priv)) iwl4965_set_mode(priv, conf->type); mutex_unlock(&priv->mutex); @@ -6649,7 +6615,7 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co priv->add_radiotap = !!(conf->flags & IEEE80211_CONF_RADIOTAP); - if (!iwl4965_is_ready(priv)) { + if (!iwl_is_ready(priv)) { IWL_DEBUG_MAC80211("leave - not ready\n"); ret = -EIO; goto out; @@ -6713,7 +6679,7 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co goto out; } - if (iwl4965_is_rfkill(priv)) { + if (iwl_is_rfkill(priv)) { IWL_DEBUG_MAC80211("leave - RF kill\n"); ret = -EIO; goto out; @@ -6820,7 +6786,7 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw, return 0; } - if (!iwl4965_is_alive(priv)) + if (!iwl_is_alive(priv)) return -EAGAIN; mutex_lock(&priv->mutex); @@ -6849,7 +6815,7 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw, priv->ibss_beacon = conf->beacon; } - if (iwl4965_is_rfkill(priv)) + if (iwl_is_rfkill(priv)) goto done; if (conf->bssid && !is_zero_ether_addr(conf->bssid) && @@ -6923,7 +6889,7 @@ static void iwl4965_mac_remove_interface(struct ieee80211_hw *hw, mutex_lock(&priv->mutex); - if (iwl4965_is_ready_rf(priv)) { + if (iwl_is_ready_rf(priv)) { iwl4965_scan_cancel_timeout(priv, 100); cancel_delayed_work(&priv->post_associate); priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; @@ -7064,7 +7030,7 @@ static int iwl4965_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len) mutex_lock(&priv->mutex); spin_lock_irqsave(&priv->lock, flags); - if (!iwl4965_is_ready_rf(priv)) { + if (!iwl_is_ready_rf(priv)) { rc = -EIO; IWL_DEBUG_MAC80211("leave - not ready or exit pending\n"); goto out_unlock; @@ -7231,7 +7197,7 @@ static int iwl4965_mac_conf_tx(struct ieee80211_hw *hw, int queue, IWL_DEBUG_MAC80211("enter\n"); - if (!iwl4965_is_ready_rf(priv)) { + if (!iwl_is_ready_rf(priv)) { IWL_DEBUG_MAC80211("leave - RF not ready\n"); return -EIO; } @@ -7284,7 +7250,7 @@ static int iwl4965_mac_get_tx_stats(struct ieee80211_hw *hw, IWL_DEBUG_MAC80211("enter\n"); - if (!iwl4965_is_ready_rf(priv)) { + if (!iwl_is_ready_rf(priv)) { IWL_DEBUG_MAC80211("leave - RF not ready\n"); return -EIO; } @@ -7362,7 +7328,7 @@ static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw) spin_unlock_irqrestore(&priv->lock, flags); - if (!iwl4965_is_ready_rf(priv)) { + if (!iwl_is_ready_rf(priv)) { IWL_DEBUG_MAC80211("leave - not ready\n"); mutex_unlock(&priv->mutex); return; @@ -7403,7 +7369,7 @@ static int iwl4965_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk mutex_lock(&priv->mutex); IWL_DEBUG_MAC80211("enter\n"); - if (!iwl4965_is_ready_rf(priv)) { + if (!iwl_is_ready_rf(priv)) { IWL_DEBUG_MAC80211("leave - RF not ready\n"); mutex_unlock(&priv->mutex); return -EIO; @@ -7483,7 +7449,7 @@ static ssize_t show_temperature(struct device *d, { struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; - if (!iwl4965_is_alive(priv)) + if (!iwl_is_alive(priv)) return -EAGAIN; return sprintf(buf, "%d\n", iwl4965_hw_get_temperature(priv)); @@ -7705,7 +7671,7 @@ static ssize_t store_power_level(struct device *d, mode = simple_strtoul(buf, NULL, 0); mutex_lock(&priv->mutex); - if (!iwl4965_is_ready(priv)) { + if (!iwl_is_ready(priv)) { rc = -EAGAIN; goto out; } @@ -7802,7 +7768,7 @@ static ssize_t show_statistics(struct device *d, u8 *data = (u8 *) & priv->statistics; int rc = 0; - if (!iwl4965_is_alive(priv)) + if (!iwl_is_alive(priv)) return -EAGAIN; mutex_lock(&priv->mutex); @@ -7836,7 +7802,7 @@ static ssize_t show_antenna(struct device *d, { struct iwl_priv *priv = dev_get_drvdata(d); - if (!iwl4965_is_alive(priv)) + if (!iwl_is_alive(priv)) return -EAGAIN; return sprintf(buf, "%d\n", priv->antenna); @@ -7873,7 +7839,7 @@ static ssize_t show_status(struct device *d, struct device_attribute *attr, char *buf) { struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; - if (!iwl4965_is_alive(priv)) + if (!iwl_is_alive(priv)) return -EAGAIN; return sprintf(buf, "0x%08x\n", (int)priv->status); } -- cgit v1.2.1 From dc92e49729142047bce8f14762accb322962b585 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Thu, 3 Apr 2008 16:05:22 -0700 Subject: iwlwifi: use ieee80211_frequency_to_channel This patch replaces ieee80211chan2mhz from radiotap with ieee80211_frequency_to_channel provided by mac80211 Signed-off-by: Tomas Winkler Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-4965.c | 13 ++++++------- 2 files changed, 8 insertions(+), 9 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 0d3cc3559039..598e4eef4f40 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -669,12 +669,12 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv, rx_status.antenna = 0; rx_status.flag = 0; rx_status.mactime = le64_to_cpu(rx_end->timestamp); - rx_status.freq = ieee80211chan2mhz(le16_to_cpu(rx_hdr->channel)); + rx_status.freq = + ieee80211_frequency_to_channel(le16_to_cpu(rx_hdr->channel)); rx_status.band = (rx_hdr->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; rx_status.rate_idx = iwl3945_hwrate_to_plcp_idx(rx_hdr->rate); - if (rx_status.band == IEEE80211_BAND_5GHZ) rx_status.rate_idx -= IWL_FIRST_OFDM_RATE; diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 69e92177ad60..472ca3d7e034 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -3814,12 +3814,12 @@ static void iwl4965_rx_reply_rx(struct iwl_priv *priv, u8 network_packet; rx_status.mactime = le64_to_cpu(rx_start->timestamp); - rx_status.freq = ieee80211chan2mhz(le16_to_cpu(rx_start->channel)); + rx_status.freq = + ieee80211_frequency_to_channel(le16_to_cpu(rx_start->channel)); rx_status.band = (rx_start->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; - rx_status.rate_idx = iwl4965_hwrate_to_plcp_idx( - le32_to_cpu(rx_start->rate_n_flags)); - + rx_status.rate_idx = + iwl4965_hwrate_to_plcp_idx(le32_to_cpu(rx_start->rate_n_flags)); if (rx_status.band == IEEE80211_BAND_5GHZ) rx_status.rate_idx -= IWL_FIRST_OFDM_RATE; @@ -3827,9 +3827,8 @@ static void iwl4965_rx_reply_rx(struct iwl_priv *priv, rx_status.flag = 0; if ((unlikely(rx_start->cfg_phy_cnt > 20))) { - IWL_DEBUG_DROP - ("dsp size out of range [0,20]: " - "%d/n", rx_start->cfg_phy_cnt); + IWL_DEBUG_DROP("dsp size out of range [0,20]: %d/n", + rx_start->cfg_phy_cnt); return; } -- cgit v1.2.1 From fe00b5a5b7e29180e427e58b3d0a185d1dd3f105 Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Thu, 3 Apr 2008 16:05:23 -0700 Subject: iwlwifi: ensure led registration complete as part of initialization After the workqueue is notified the LED code may be accessed. Ensure that LED registration completes completely as part of initialization before anything waiting on this is notified. Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl3945-base.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl4965-base.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 51480a4920e8..d4daa04465a3 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -5874,12 +5874,12 @@ static void iwl3945_alive_start(struct iwl3945_priv *priv) iwl3945_reg_txpower_periodic(priv); + iwl3945_led_register(priv); + IWL_DEBUG_INFO("ALIVE processing complete.\n"); set_bit(STATUS_READY, &priv->status); wake_up_interruptible(&priv->wait_command_queue); - iwl3945_led_register(priv); - if (priv->error_recovering) iwl3945_error_recovery(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 5dfc414792c1..4517e4ce3a25 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -5701,12 +5701,12 @@ static void iwl4965_alive_start(struct iwl_priv *priv) iwl4965_rf_kill_ct_config(priv); + iwl_leds_register(priv); + IWL_DEBUG_INFO("ALIVE processing complete.\n"); set_bit(STATUS_READY, &priv->status); wake_up_interruptible(&priv->wait_command_queue); - iwl_leds_register(priv); - if (priv->error_recovering) iwl4965_error_recovery(priv); -- cgit v1.2.1 From 03d29c684917860f90f897565b297c4aba713e0b Mon Sep 17 00:00:00 2001 From: Mohamed Abbas Date: Thu, 3 Apr 2008 16:05:24 -0700 Subject: iwlwifi: fix rfkill memory error Do not free reference to device twice. After rfkill registration succeeds we only need to call rfkill_unregister() and not rfkill_free(). Also add some debugging. Signed-off-by: Mohamed Abbas Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-core.c | 7 +++++-- drivers/net/wireless/iwlwifi/iwl-rfkill.c | 31 +++++++++++++++++-------------- drivers/net/wireless/iwlwifi/iwl-rfkill.h | 2 -- 3 files changed, 22 insertions(+), 18 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index f12230780555..d8a226e68ed1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -256,9 +256,13 @@ EXPORT_SYMBOL(iwl_setup); int iwlcore_low_level_notify(struct iwl_priv *priv, enum iwlcore_card_notify notify) { + int ret; switch (notify) { case IWLCORE_INIT_EVT: - iwl_rfkill_init(priv); + ret = iwl_rfkill_init(priv); + if (ret) + IWL_ERROR("Unable to initialize RFKILL system. " + "Ignoring error: %d\n", ret); break; case IWLCORE_START_EVT: break; @@ -266,7 +270,6 @@ int iwlcore_low_level_notify(struct iwl_priv *priv, break; case IWLCORE_REMOVE_EVT: iwl_rfkill_unregister(priv); - iwl_rfkill_free(priv); break; } diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.c b/drivers/net/wireless/iwlwifi/iwl-rfkill.c index 308d69b18404..8f38c24491cd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rfkill.c +++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.c @@ -75,8 +75,10 @@ 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) { + IWL_ERROR("Unable to allocate rfkill device.\n"); ret = -ENOMEM; goto error; } @@ -92,6 +94,7 @@ int iwl_rfkill_init(struct iwl_priv *priv) 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; } @@ -105,27 +108,35 @@ int iwl_rfkill_init(struct iwl_priv *priv) set_bit(KEY_WLAN, priv->rfkill_mngr.input_dev->keybit); ret = rfkill_register(priv->rfkill_mngr.rfkill); - if (ret) + 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) + if (ret) { + IWL_ERROR("Unable to register rfkill input device: %d\n", ret); goto unregister_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: - rfkill_free(priv->rfkill_mngr.rfkill); + if (priv->rfkill_mngr.rfkill != NULL) + rfkill_free(priv->rfkill_mngr.rfkill); priv->rfkill_mngr.rfkill = NULL; error: + IWL_DEBUG_RF_KILL("RFKILL initialization complete.\n"); return ret; } EXPORT_SYMBOL(iwl_rfkill_init); @@ -138,19 +149,11 @@ void iwl_rfkill_unregister(struct iwl_priv *priv) if (priv->rfkill_mngr.rfkill) rfkill_unregister(priv->rfkill_mngr.rfkill); -} -EXPORT_SYMBOL(iwl_rfkill_unregister); - -void iwl_rfkill_free(struct iwl_priv *priv) -{ - if (priv->rfkill_mngr.input_dev) - input_free_device(priv->rfkill_mngr.input_dev); - - if (priv->rfkill_mngr.rfkill) - rfkill_free(priv->rfkill_mngr.rfkill); + priv->rfkill_mngr.input_dev = NULL; + priv->rfkill_mngr.rfkill = NULL; } -EXPORT_SYMBOL(iwl_rfkill_free); +EXPORT_SYMBOL(iwl_rfkill_unregister); /* set rf-kill to the right state. */ void iwl_rfkill_set_hw_state(struct iwl_priv *priv) diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.h b/drivers/net/wireless/iwlwifi/iwl-rfkill.h index a5cbc5ab45d9..e7aa51a1db18 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rfkill.h +++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.h @@ -41,12 +41,10 @@ struct iwl_rfkill_mngr { }; void iwl_rfkill_set_hw_state(struct iwl_priv *priv); -void iwl_rfkill_free(struct iwl_priv *priv); void iwl_rfkill_unregister(struct iwl_priv *priv); int iwl_rfkill_init(struct iwl_priv *priv); #else static inline void iwl_rfkill_set_hw_state(struct iwl_priv *priv) {} -static inline void iwl_rfkill_free(struct iwl_priv *priv) {} static inline void iwl_rfkill_unregister(struct iwl_priv *priv) {} static inline int iwl_rfkill_init(struct iwl_priv *priv) { return 0; } #endif -- cgit v1.2.1 From 182e2e66ca56f750845f5314708434c286edd6e4 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 4 Apr 2008 10:41:56 +0200 Subject: iwlwifi: honour regulatory restrictions in scan code When doing firmware-assisted scanning, iwlwifi drivers do not honour the regulatory control code that might disable channels that are enabled in the EEPROM, for example when the user is visiting another country and adjusted the regulatory domain accordingly. This patch fixes that. Signed-off-by: Johannes Berg Acked-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl3945-base.c | 3 +++ drivers/net/wireless/iwlwifi/iwl4965-base.c | 3 +++ 2 files changed, 6 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index d4daa04465a3..5e51cfcda39f 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -4965,6 +4965,9 @@ static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv, passive_dwell = iwl3945_get_passive_dwell_time(priv, band); for (i = 0, added = 0; i < sband->n_channels; i++) { + if (channels[i].flags & IEEE80211_CHAN_DISABLED) + continue; + if (channels[i].hw_value == le16_to_cpu(priv->active_rxon.channel)) { if (iwl3945_is_associated(priv)) { diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 4517e4ce3a25..b043871d53f1 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -4794,6 +4794,9 @@ static int iwl4965_get_channels_for_scan(struct iwl_priv *priv, passive_dwell = iwl4965_get_passive_dwell_time(priv, band); for (i = 0, added = 0; i < sband->n_channels; i++) { + if (channels[i].flags & IEEE80211_CHAN_DISABLED) + continue; + if (ieee80211_frequency_to_channel(channels[i].center_freq) == le16_to_cpu(priv->active_rxon.channel)) { if (iwl_is_associated(priv)) { -- cgit v1.2.1 From a82d992261f79506a0d55b9a179a211f96caf878 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Fri, 4 Apr 2008 21:40:06 +0200 Subject: b43: Beaconing fixes These are some beaconing related fixes. Basically it prevents the card from triggering the beacon IRQ over and over again. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/b43.h | 1 + drivers/net/wireless/b43/main.c | 42 +++++++++++++++++++++++++++++++++++------ 2 files changed, 37 insertions(+), 6 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index e478799c09cb..bf6b276d47e2 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -733,6 +733,7 @@ struct b43_wl { struct sk_buff *current_beacon; bool beacon0_uploaded; bool beacon1_uploaded; + struct work_struct beacon_update_trigger; /* The current QOS parameters for the 4 queues. * This is protected by the irq_lock. */ diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 6ecaf84da2fc..c98337b2d687 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -1337,7 +1337,8 @@ static void b43_write_beacon_template(struct b43_wldev *dev, b43warn(dev->wl, "Did not find a valid TIM IE in " "the beacon template packet. AP or IBSS operation " "may be broken.\n"); - } + } else + b43dbg(dev->wl, "Updated beacon template\n"); } static void b43_write_probe_resp_plcp(struct b43_wldev *dev, @@ -1447,6 +1448,27 @@ static void b43_write_probe_resp_template(struct b43_wldev *dev, kfree(probe_resp_data); } +static void b43_beacon_update_trigger_work(struct work_struct *work) +{ + struct b43_wl *wl = container_of(work, struct b43_wl, + beacon_update_trigger); + struct b43_wldev *dev; + + mutex_lock(&wl->mutex); + dev = wl->current_dev; + if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED))) { + /* Force the microcode to trigger the + * beacon update bottom-half IRQ. */ + spin_lock_irq(&wl->irq_lock); + b43_write32(dev, B43_MMIO_MACCMD, + b43_read32(dev, B43_MMIO_MACCMD) + | B43_MACCMD_BEACON0_VALID + | B43_MACCMD_BEACON1_VALID); + spin_unlock_irq(&wl->irq_lock); + } + mutex_unlock(&wl->mutex); +} + /* Asynchronously update the packet templates in template RAM. * Locking: Requires wl->irq_lock to be locked. */ static void b43_update_templates(struct b43_wl *wl, struct sk_buff *beacon) @@ -1462,6 +1484,7 @@ static void b43_update_templates(struct b43_wl *wl, struct sk_buff *beacon) wl->current_beacon = beacon; wl->beacon0_uploaded = 0; wl->beacon1_uploaded = 0; + queue_work(wl->hw->workqueue, &wl->beacon_update_trigger); } static void b43_set_ssid(struct b43_wldev *dev, const u8 * ssid, u8 ssid_len) @@ -1487,18 +1510,20 @@ static void b43_set_beacon_int(struct b43_wldev *dev, u16 beacon_int) { b43_time_lock(dev); if (dev->dev->id.revision >= 3) { - b43_write32(dev, 0x188, (beacon_int << 16)); + b43_write32(dev, B43_MMIO_TSF_CFP_REP, (beacon_int << 16)); + b43_write32(dev, B43_MMIO_TSF_CFP_START, (beacon_int << 10)); } else { b43_write16(dev, 0x606, (beacon_int >> 6)); b43_write16(dev, 0x610, beacon_int); } b43_time_unlock(dev); + b43dbg(dev->wl, "Set beacon interval to %u\n", beacon_int); } static void handle_irq_beacon(struct b43_wldev *dev) { struct b43_wl *wl = dev->wl; - u32 cmd; + u32 cmd, beacon0_valid, beacon1_valid; if (!b43_is_mode(wl, IEEE80211_IF_TYPE_AP)) return; @@ -1506,7 +1531,11 @@ static void handle_irq_beacon(struct b43_wldev *dev) /* This is the bottom half of the asynchronous beacon update. */ cmd = b43_read32(dev, B43_MMIO_MACCMD); - if (!(cmd & B43_MACCMD_BEACON0_VALID)) { + beacon0_valid = (cmd & B43_MACCMD_BEACON0_VALID); + beacon1_valid = (cmd & B43_MACCMD_BEACON1_VALID); + cmd &= ~(B43_MACCMD_BEACON0_VALID | B43_MACCMD_BEACON1_VALID); + + if (!beacon0_valid) { if (!wl->beacon0_uploaded) { b43_write_beacon_template(dev, 0x68, 0x18, B43_CCK_RATE_1MB); @@ -1515,8 +1544,7 @@ static void handle_irq_beacon(struct b43_wldev *dev) wl->beacon0_uploaded = 1; } cmd |= B43_MACCMD_BEACON0_VALID; - } - if (!(cmd & B43_MACCMD_BEACON1_VALID)) { + } else if (!beacon1_valid) { if (!wl->beacon1_uploaded) { b43_write_beacon_template(dev, 0x468, 0x1A, B43_CCK_RATE_1MB); @@ -4012,6 +4040,7 @@ static void b43_op_stop(struct ieee80211_hw *hw) b43_rfkill_exit(dev); cancel_work_sync(&(wl->qos_update_work)); + cancel_work_sync(&(wl->beacon_update_trigger)); mutex_lock(&wl->mutex); if (b43_status(dev) >= B43_STAT_STARTED) @@ -4389,6 +4418,7 @@ static int b43_wireless_init(struct ssb_device *dev) mutex_init(&wl->mutex); INIT_LIST_HEAD(&wl->devlist); INIT_WORK(&wl->qos_update_work, b43_qos_update_work); + INIT_WORK(&wl->beacon_update_trigger, b43_beacon_update_trigger_work); ssb_set_devtypedata(dev, wl); b43info(wl, "Broadcom %04X WLAN found\n", dev->bus->chip_id); -- cgit v1.2.1 From 84363e6e07f17f8cc580065260907ee3f0520485 Mon Sep 17 00:00:00 2001 From: Mohamed Abbas Date: Fri, 4 Apr 2008 16:59:58 -0700 Subject: mac80211: notify mac from low level driver (iwlwifi) Add new API to MAC80211 to allow low level driver to notify MAC with driver status. Signed-off-by: Mohamed Abbas Signed-off-by: Reinette Chatre Acked-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl3945-base.c | 1 + drivers/net/wireless/iwlwifi/iwl4965-base.c | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 5e51cfcda39f..29a9ecdcbf35 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -5886,6 +5886,7 @@ static void iwl3945_alive_start(struct iwl3945_priv *priv) if (priv->error_recovering) iwl3945_error_recovery(priv); + ieee80211_notify_mac(priv->hw, IEEE80211_NOTIFY_RE_ASSOC); return; restart: diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index b043871d53f1..06e44dad5f02 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -5714,6 +5714,7 @@ static void iwl4965_alive_start(struct iwl_priv *priv) iwl4965_error_recovery(priv); iwlcore_low_level_notify(priv, IWLCORE_START_EVT); + ieee80211_notify_mac(priv->hw, IEEE80211_NOTIFY_RE_ASSOC); return; restart: -- cgit v1.2.1 From c97a4ccc1fad35d3d183900af29c171b6d56b7f9 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sat, 5 Apr 2008 15:02:09 +0200 Subject: b43: Fix beacon BH update This fixes beacon updating in the bottomhalf. In case the device is busy, we will defer to later in the IRQ handler. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/b43.h | 1 - drivers/net/wireless/b43/main.c | 95 +++++++++++++++++++++++------------------ 2 files changed, 54 insertions(+), 42 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index bf6b276d47e2..4ba4a73673bc 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -411,7 +411,6 @@ enum { #define B43_IRQ_ALL 0xFFFFFFFF #define B43_IRQ_MASKTEMPLATE (B43_IRQ_MAC_SUSPENDED | \ - B43_IRQ_BEACON | \ B43_IRQ_TBTT_INDI | \ B43_IRQ_ATIM_END | \ B43_IRQ_PMQ | \ diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index c98337b2d687..ec28a6ef42be 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -1448,6 +1448,53 @@ static void b43_write_probe_resp_template(struct b43_wldev *dev, kfree(probe_resp_data); } +static void handle_irq_beacon(struct b43_wldev *dev) +{ + struct b43_wl *wl = dev->wl; + u32 cmd, beacon0_valid, beacon1_valid; + + if (!b43_is_mode(wl, IEEE80211_IF_TYPE_AP)) + return; + + /* This is the bottom half of the asynchronous beacon update. */ + + /* Ignore interrupt in the future. */ + dev->irq_savedstate &= ~B43_IRQ_BEACON; + + cmd = b43_read32(dev, B43_MMIO_MACCMD); + beacon0_valid = (cmd & B43_MACCMD_BEACON0_VALID); + beacon1_valid = (cmd & B43_MACCMD_BEACON1_VALID); + + /* Schedule interrupt manually, if busy. */ + if (beacon0_valid && beacon1_valid) { + b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, B43_IRQ_BEACON); + dev->irq_savedstate |= B43_IRQ_BEACON; + return; + } + + if (!beacon0_valid) { + if (!wl->beacon0_uploaded) { + b43_write_beacon_template(dev, 0x68, 0x18, + B43_CCK_RATE_1MB); + b43_write_probe_resp_template(dev, 0x268, 0x4A, + &__b43_ratetable[3]); + wl->beacon0_uploaded = 1; + } + cmd = b43_read32(dev, B43_MMIO_MACCMD); + cmd |= B43_MACCMD_BEACON0_VALID; + b43_write32(dev, B43_MMIO_MACCMD, cmd); + } else if (!beacon1_valid) { + if (!wl->beacon1_uploaded) { + b43_write_beacon_template(dev, 0x468, 0x1A, + B43_CCK_RATE_1MB); + wl->beacon1_uploaded = 1; + } + cmd = b43_read32(dev, B43_MMIO_MACCMD); + cmd |= B43_MACCMD_BEACON1_VALID; + b43_write32(dev, B43_MMIO_MACCMD, cmd); + } +} + static void b43_beacon_update_trigger_work(struct work_struct *work) { struct b43_wl *wl = container_of(work, struct b43_wl, @@ -1457,13 +1504,14 @@ static void b43_beacon_update_trigger_work(struct work_struct *work) mutex_lock(&wl->mutex); dev = wl->current_dev; if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED))) { - /* Force the microcode to trigger the - * beacon update bottom-half IRQ. */ spin_lock_irq(&wl->irq_lock); - b43_write32(dev, B43_MMIO_MACCMD, - b43_read32(dev, B43_MMIO_MACCMD) - | B43_MACCMD_BEACON0_VALID - | B43_MACCMD_BEACON1_VALID); + /* update beacon right away or defer to irq */ + dev->irq_savedstate = b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); + handle_irq_beacon(dev); + /* The handler might have updated the IRQ mask. */ + b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, + dev->irq_savedstate); + mmiowb(); spin_unlock_irq(&wl->irq_lock); } mutex_unlock(&wl->mutex); @@ -1520,41 +1568,6 @@ static void b43_set_beacon_int(struct b43_wldev *dev, u16 beacon_int) b43dbg(dev->wl, "Set beacon interval to %u\n", beacon_int); } -static void handle_irq_beacon(struct b43_wldev *dev) -{ - struct b43_wl *wl = dev->wl; - u32 cmd, beacon0_valid, beacon1_valid; - - if (!b43_is_mode(wl, IEEE80211_IF_TYPE_AP)) - return; - - /* This is the bottom half of the asynchronous beacon update. */ - - cmd = b43_read32(dev, B43_MMIO_MACCMD); - beacon0_valid = (cmd & B43_MACCMD_BEACON0_VALID); - beacon1_valid = (cmd & B43_MACCMD_BEACON1_VALID); - cmd &= ~(B43_MACCMD_BEACON0_VALID | B43_MACCMD_BEACON1_VALID); - - if (!beacon0_valid) { - if (!wl->beacon0_uploaded) { - b43_write_beacon_template(dev, 0x68, 0x18, - B43_CCK_RATE_1MB); - b43_write_probe_resp_template(dev, 0x268, 0x4A, - &__b43_ratetable[3]); - wl->beacon0_uploaded = 1; - } - cmd |= B43_MACCMD_BEACON0_VALID; - } else if (!beacon1_valid) { - if (!wl->beacon1_uploaded) { - b43_write_beacon_template(dev, 0x468, 0x1A, - B43_CCK_RATE_1MB); - wl->beacon1_uploaded = 1; - } - cmd |= B43_MACCMD_BEACON1_VALID; - } - b43_write32(dev, B43_MMIO_MACCMD, cmd); -} - static void handle_irq_ucode_debug(struct b43_wldev *dev) { //TODO -- cgit v1.2.1 From 5042c5070daaa6a3c033e4510439e3ac02a1df60 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sat, 5 Apr 2008 15:05:00 +0200 Subject: b43: Fix PHY TX control words in SHM This fixes the initialization of the PHY TX control words in shared memory. These control words are used for management frames like beacons. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/b43.h | 1 + drivers/net/wireless/b43/main.c | 199 +++++++++++++++++++++++----------------- 2 files changed, 117 insertions(+), 83 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index 4ba4a73673bc..eff2a158a411 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -730,6 +730,7 @@ struct b43_wl { /* The beacon we are currently using (AP or IBSS mode). * This beacon stuff is protected by the irq_lock. */ struct sk_buff *current_beacon; + struct ieee80211_tx_control beacon_txctl; bool beacon0_uploaded; bool beacon1_uploaded; struct work_struct beacon_update_trigger; diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index ec28a6ef42be..1aa0f727174b 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -1281,22 +1281,107 @@ static void b43_write_template_common(struct b43_wldev *dev, size + sizeof(struct b43_plcp_hdr6)); } +/* Check if the use of the antenna that ieee80211 told us to + * use is possible. This will fall back to DEFAULT. + * "antenna_nr" is the antenna identifier we got from ieee80211. */ +u8 b43_ieee80211_antenna_sanitize(struct b43_wldev *dev, + u8 antenna_nr) +{ + u8 antenna_mask; + + if (antenna_nr == 0) { + /* Zero means "use default antenna". That's always OK. */ + return 0; + } + + /* Get the mask of available antennas. */ + if (dev->phy.gmode) + antenna_mask = dev->dev->bus->sprom.ant_available_bg; + else + antenna_mask = dev->dev->bus->sprom.ant_available_a; + + if (!(antenna_mask & (1 << (antenna_nr - 1)))) { + /* This antenna is not available. Fall back to default. */ + return 0; + } + + return antenna_nr; +} + +static int b43_antenna_from_ieee80211(struct b43_wldev *dev, u8 antenna) +{ + antenna = b43_ieee80211_antenna_sanitize(dev, antenna); + switch (antenna) { + case 0: /* default/diversity */ + return B43_ANTENNA_DEFAULT; + case 1: /* Antenna 0 */ + return B43_ANTENNA0; + case 2: /* Antenna 1 */ + return B43_ANTENNA1; + case 3: /* Antenna 2 */ + return B43_ANTENNA2; + case 4: /* Antenna 3 */ + return B43_ANTENNA3; + default: + return B43_ANTENNA_DEFAULT; + } +} + +/* Convert a b43 antenna number value to the PHY TX control value. */ +static u16 b43_antenna_to_phyctl(int antenna) +{ + switch (antenna) { + case B43_ANTENNA0: + return B43_TXH_PHY_ANT0; + case B43_ANTENNA1: + return B43_TXH_PHY_ANT1; + case B43_ANTENNA2: + return B43_TXH_PHY_ANT2; + case B43_ANTENNA3: + return B43_TXH_PHY_ANT3; + case B43_ANTENNA_AUTO: + return B43_TXH_PHY_ANT01AUTO; + } + B43_WARN_ON(1); + return 0; +} + static void b43_write_beacon_template(struct b43_wldev *dev, u16 ram_offset, - u16 shm_size_offset, u8 rate) + u16 shm_size_offset) { unsigned int i, len, variable_len; const struct ieee80211_mgmt *bcn; const u8 *ie; bool tim_found = 0; + unsigned int rate; + u16 ctl; + int antenna; bcn = (const struct ieee80211_mgmt *)(dev->wl->current_beacon->data); len = min((size_t) dev->wl->current_beacon->len, 0x200 - sizeof(struct b43_plcp_hdr6)); + rate = dev->wl->beacon_txctl.tx_rate->hw_value; b43_write_template_common(dev, (const u8 *)bcn, len, ram_offset, shm_size_offset, rate); + /* Write the PHY TX control parameters. */ + antenna = b43_antenna_from_ieee80211(dev, + dev->wl->beacon_txctl.antenna_sel_tx); + antenna = b43_antenna_to_phyctl(antenna); + ctl = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL); + /* We can't send beacons with short preamble. Would get PHY errors. */ + ctl &= ~B43_TXH_PHY_SHORTPRMBL; + ctl &= ~B43_TXH_PHY_ANT; + ctl &= ~B43_TXH_PHY_ENC; + ctl |= antenna; + if (b43_is_cck_rate(rate)) + ctl |= B43_TXH_PHY_ENC_CCK; + else + ctl |= B43_TXH_PHY_ENC_OFDM; + b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL, ctl); + /* Find the position of the TIM and the DTIM_period value * and write them to SHM. */ ie = bcn->u.beacon.variable; @@ -1474,8 +1559,7 @@ static void handle_irq_beacon(struct b43_wldev *dev) if (!beacon0_valid) { if (!wl->beacon0_uploaded) { - b43_write_beacon_template(dev, 0x68, 0x18, - B43_CCK_RATE_1MB); + b43_write_beacon_template(dev, 0x68, 0x18); b43_write_probe_resp_template(dev, 0x268, 0x4A, &__b43_ratetable[3]); wl->beacon0_uploaded = 1; @@ -1485,8 +1569,7 @@ static void handle_irq_beacon(struct b43_wldev *dev) b43_write32(dev, B43_MMIO_MACCMD, cmd); } else if (!beacon1_valid) { if (!wl->beacon1_uploaded) { - b43_write_beacon_template(dev, 0x468, 0x1A, - B43_CCK_RATE_1MB); + b43_write_beacon_template(dev, 0x468, 0x1A); wl->beacon1_uploaded = 1; } cmd = b43_read32(dev, B43_MMIO_MACCMD); @@ -1519,7 +1602,8 @@ static void b43_beacon_update_trigger_work(struct work_struct *work) /* Asynchronously update the packet templates in template RAM. * Locking: Requires wl->irq_lock to be locked. */ -static void b43_update_templates(struct b43_wl *wl, struct sk_buff *beacon) +static void b43_update_templates(struct b43_wl *wl, struct sk_buff *beacon, + const struct ieee80211_tx_control *txctl) { /* This is the top half of the ansynchronous beacon update. * The bottom half is the beacon IRQ. @@ -1530,6 +1614,7 @@ static void b43_update_templates(struct b43_wl *wl, struct sk_buff *beacon) if (wl->current_beacon) dev_kfree_skb_any(wl->current_beacon); wl->current_beacon = beacon; + memcpy(&wl->beacon_txctl, txctl, sizeof(wl->beacon_txctl)); wl->beacon0_uploaded = 0; wl->beacon1_uploaded = 0; queue_work(wl->hw->workqueue, &wl->beacon_update_trigger); @@ -2363,38 +2448,28 @@ static void b43_rate_memory_init(struct b43_wldev *dev) } } +/* Set the default values for the PHY TX Control Words. */ +static void b43_set_phytxctl_defaults(struct b43_wldev *dev) +{ + u16 ctl = 0; + + ctl |= B43_TXH_PHY_ENC_CCK; + ctl |= B43_TXH_PHY_ANT01AUTO; + ctl |= B43_TXH_PHY_TXPWR; + + b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL, ctl); + b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_ACKCTSPHYCTL, ctl); + b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_PRPHYCTL, ctl); +} + /* Set the TX-Antenna for management frames sent by firmware. */ static void b43_mgmtframe_txantenna(struct b43_wldev *dev, int antenna) { - u16 ant = 0; + u16 ant; u16 tmp; - switch (antenna) { - case B43_ANTENNA0: - ant |= B43_TXH_PHY_ANT0; - break; - case B43_ANTENNA1: - ant |= B43_TXH_PHY_ANT1; - break; - case B43_ANTENNA2: - ant |= B43_TXH_PHY_ANT2; - break; - case B43_ANTENNA3: - ant |= B43_TXH_PHY_ANT3; - break; - case B43_ANTENNA_AUTO: - ant |= B43_TXH_PHY_ANT01AUTO; - break; - default: - B43_WARN_ON(1); - } - - /* FIXME We also need to set the other flags of the PHY control field somewhere. */ + ant = b43_antenna_to_phyctl(antenna); - /* For Beacons */ - tmp = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL); - tmp = (tmp & ~B43_TXH_PHY_ANT) | ant; - b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL, tmp); /* For ACK/CTS */ tmp = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_ACKCTSPHYCTL); tmp = (tmp & ~B43_TXH_PHY_ANT) | ant; @@ -3112,52 +3187,6 @@ init_failure: return err; } -/* Check if the use of the antenna that ieee80211 told us to - * use is possible. This will fall back to DEFAULT. - * "antenna_nr" is the antenna identifier we got from ieee80211. */ -u8 b43_ieee80211_antenna_sanitize(struct b43_wldev *dev, - u8 antenna_nr) -{ - u8 antenna_mask; - - if (antenna_nr == 0) { - /* Zero means "use default antenna". That's always OK. */ - return 0; - } - - /* Get the mask of available antennas. */ - if (dev->phy.gmode) - antenna_mask = dev->dev->bus->sprom.ant_available_bg; - else - antenna_mask = dev->dev->bus->sprom.ant_available_a; - - if (!(antenna_mask & (1 << (antenna_nr - 1)))) { - /* This antenna is not available. Fall back to default. */ - return 0; - } - - return antenna_nr; -} - -static int b43_antenna_from_ieee80211(struct b43_wldev *dev, u8 antenna) -{ - antenna = b43_ieee80211_antenna_sanitize(dev, antenna); - switch (antenna) { - case 0: /* default/diversity */ - return B43_ANTENNA_DEFAULT; - case 1: /* Antenna 0 */ - return B43_ANTENNA0; - case 2: /* Antenna 1 */ - return B43_ANTENNA1; - case 3: /* Antenna 2 */ - return B43_ANTENNA2; - case 4: /* Antenna 3 */ - return B43_ANTENNA3; - default: - return B43_ANTENNA_DEFAULT; - } -} - static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf) { struct b43_wl *wl = hw_to_b43_wl(hw); @@ -3405,8 +3434,10 @@ static int b43_op_config_interface(struct ieee80211_hw *hw, if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP)) { B43_WARN_ON(conf->type != IEEE80211_IF_TYPE_AP); b43_set_ssid(dev, conf->ssid, conf->ssid_len); - if (conf->beacon) - b43_update_templates(wl, conf->beacon); + if (conf->beacon) { + b43_update_templates(wl, conf->beacon, + conf->beacon_control); + } } b43_write_mac_bssid_templates(dev); } @@ -3877,6 +3908,7 @@ static int b43_wireless_core_init(struct b43_wldev *dev) b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_PRMAXTIME, 1); b43_rate_memory_init(dev); + b43_set_phytxctl_defaults(dev); /* Minimum Contention Window */ if (phy->type == B43_PHYTYPE_B) { @@ -4087,16 +4119,17 @@ static int b43_op_beacon_set_tim(struct ieee80211_hw *hw, int aid, int set) struct b43_wl *wl = hw_to_b43_wl(hw); struct sk_buff *beacon; unsigned long flags; + struct ieee80211_tx_control txctl; /* We could modify the existing beacon and set the aid bit in * the TIM field, but that would probably require resizing and * moving of data within the beacon template. * Simply request a new beacon and let mac80211 do the hard work. */ - beacon = ieee80211_beacon_get(hw, wl->vif, NULL); + beacon = ieee80211_beacon_get(hw, wl->vif, &txctl); if (unlikely(!beacon)) return -ENOMEM; spin_lock_irqsave(&wl->irq_lock, flags); - b43_update_templates(wl, beacon); + b43_update_templates(wl, beacon, &txctl); spin_unlock_irqrestore(&wl->irq_lock, flags); return 0; @@ -4110,7 +4143,7 @@ static int b43_op_ibss_beacon_update(struct ieee80211_hw *hw, unsigned long flags; spin_lock_irqsave(&wl->irq_lock, flags); - b43_update_templates(wl, beacon); + b43_update_templates(wl, beacon, ctl); spin_unlock_irqrestore(&wl->irq_lock, flags); return 0; -- cgit v1.2.1 From 8cf6a31e8d30cae1fbec8c782842f00472a4495c Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Sat, 5 Apr 2008 15:19:36 +0200 Subject: b43: use b43_is_mode() call We must use the b43_is_mode() call to check the current interface operation mode. Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 1aa0f727174b..345c34bdae9a 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -3771,7 +3771,7 @@ static void b43_set_synth_pu_delay(struct b43_wldev *dev, bool idle) pu_delay = 3700; else pu_delay = 1050; - if ((dev->wl->if_type == IEEE80211_IF_TYPE_IBSS) || idle) + if (b43_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS) || idle) pu_delay = 500; if ((dev->phy.radio_ver == 0x2050) && (dev->phy.radio_rev == 8)) pu_delay = max(pu_delay, (u16)2400); @@ -3785,7 +3785,7 @@ static void b43_set_pretbtt(struct b43_wldev *dev) u16 pretbtt; /* The time value is in microseconds. */ - if (dev->wl->if_type == IEEE80211_IF_TYPE_IBSS) { + if (b43_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS)) { pretbtt = 2; } else { if (dev->phy.type == B43_PHYTYPE_A) -- cgit v1.2.1 From e764948b1abd8316f8a1364757d6629f5cda199d Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Mon, 7 Apr 2008 21:08:55 +0200 Subject: adm8211: remove commented-out code Remove some commented-out code from adm8211. Signed-off-by: Pavel Machek Signed-off-by: John W. Linville --- drivers/net/wireless/adm8211.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c index 2e257ee2783b..5c0d2b082750 100644 --- a/drivers/net/wireless/adm8211.c +++ b/drivers/net/wireless/adm8211.c @@ -488,9 +488,6 @@ do { \ if (stsr & ADM8211_STSR_TCI) adm8211_interrupt_tci(dev); - /*ADM8211_INT(LinkOn);*/ - /*ADM8211_INT(LinkOff);*/ - ADM8211_INT(PCF); ADM8211_INT(BCNTC); ADM8211_INT(GPINT); @@ -500,7 +497,6 @@ do { \ ADM8211_INT(SQL); ADM8211_INT(WEPTD); ADM8211_INT(ATIME); - /*ADM8211_INT(TBTT);*/ ADM8211_INT(TEIS); ADM8211_INT(FBE); ADM8211_INT(REIS); @@ -508,9 +504,6 @@ do { \ ADM8211_INT(RPS); ADM8211_INT(RDU); ADM8211_INT(TUF); - /*ADM8211_INT(TRT);*/ - /*ADM8211_INT(TLT);*/ - /*ADM8211_INT(TDU);*/ ADM8211_INT(TPS); return IRQ_HANDLED; -- cgit v1.2.1 From 2c8dccc77420fb7433da5674818959d3499d35be Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 8 Apr 2008 15:14:40 -0400 Subject: mac80211: rename files This patch renames all mac80211 files (except ieee80211_i.h) to get rid of the useless ieee80211_ prefix. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-rs.c | 2 +- drivers/net/wireless/iwlwifi/iwl-4965-rs.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c index 8559f252a55f..85c22641542d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c @@ -37,7 +37,7 @@ #include -#include "../net/mac80211/ieee80211_rate.h" +#include "../net/mac80211/rate.h" #include "iwl-3945.h" diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c index 32eb414899d6..315b0433801e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c @@ -36,7 +36,7 @@ #include -#include "../net/mac80211/ieee80211_rate.h" +#include "../net/mac80211/rate.h" #include "iwl-4965.h" #include "iwl-core.h" -- cgit v1.2.1 From fb26971058845868f7c45b720636180d14c058e4 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Tue, 8 Apr 2008 15:38:00 -0400 Subject: p54: move to separate directory Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/Kconfig | 65 +-- drivers/net/wireless/Makefile | 4 +- drivers/net/wireless/net2280.h | 452 --------------- drivers/net/wireless/p54.h | 77 --- drivers/net/wireless/p54/Kconfig | 63 ++ drivers/net/wireless/p54/Makefile | 3 + drivers/net/wireless/p54/net2280.h | 452 +++++++++++++++ drivers/net/wireless/p54/p54.h | 77 +++ drivers/net/wireless/p54/p54common.c | 1051 ++++++++++++++++++++++++++++++++++ drivers/net/wireless/p54/p54common.h | 254 ++++++++ drivers/net/wireless/p54/p54pci.c | 697 ++++++++++++++++++++++ drivers/net/wireless/p54/p54pci.h | 106 ++++ drivers/net/wireless/p54/p54usb.c | 910 +++++++++++++++++++++++++++++ drivers/net/wireless/p54/p54usb.h | 133 +++++ drivers/net/wireless/p54common.c | 1051 ---------------------------------- drivers/net/wireless/p54common.h | 254 -------- drivers/net/wireless/p54pci.c | 697 ---------------------- drivers/net/wireless/p54pci.h | 106 ---- drivers/net/wireless/p54usb.c | 910 ----------------------------- drivers/net/wireless/p54usb.h | 133 ----- 20 files changed, 3748 insertions(+), 3747 deletions(-) delete mode 100644 drivers/net/wireless/net2280.h delete mode 100644 drivers/net/wireless/p54.h create mode 100644 drivers/net/wireless/p54/Kconfig create mode 100644 drivers/net/wireless/p54/Makefile create mode 100644 drivers/net/wireless/p54/net2280.h create mode 100644 drivers/net/wireless/p54/p54.h create mode 100644 drivers/net/wireless/p54/p54common.c create mode 100644 drivers/net/wireless/p54/p54common.h create mode 100644 drivers/net/wireless/p54/p54pci.c create mode 100644 drivers/net/wireless/p54/p54pci.h create mode 100644 drivers/net/wireless/p54/p54usb.c create mode 100644 drivers/net/wireless/p54/p54usb.h delete mode 100644 drivers/net/wireless/p54common.c delete mode 100644 drivers/net/wireless/p54common.h delete mode 100644 drivers/net/wireless/p54pci.c delete mode 100644 drivers/net/wireless/p54pci.h delete mode 100644 drivers/net/wireless/p54usb.c delete mode 100644 drivers/net/wireless/p54usb.h (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 3c8cf682e9bd..fdf5aa8b8429 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -673,70 +673,7 @@ config ADM8211 Thanks to Infineon-ADMtek for their support of this driver. -config P54_COMMON - tristate "Softmac Prism54 support" - depends on MAC80211 && WLAN_80211 && FW_LOADER && EXPERIMENTAL - ---help--- - This is common code for isl38xx based cards. - This module does nothing by itself - the USB/PCI frontends - also need to be enabled in order to support any devices. - - These devices require softmac firmware which can be found at - http://prism54.org/ - - If you choose to build a module, it'll be called p54common. - -config P54_USB - tristate "Prism54 USB support" - depends on P54_COMMON && USB - select CRC32 - ---help--- - This driver is for USB isl38xx based wireless cards. - These are USB based adapters found in devices such as: - - 3COM 3CRWE254G72 - SMC 2862W-G - Accton 802.11g WN4501 USB - Siemens Gigaset USB - Netgear WG121 - Netgear WG111 - Medion 40900, Roper Europe - Shuttle PN15, Airvast WM168g, IOGear GWU513 - Linksys WUSB54G - Linksys WUSB54G Portable - DLink DWL-G120 Spinnaker - DLink DWL-G122 - Belkin F5D7050 ver 1000 - Cohiba Proto board - SMC 2862W-G version 2 - U.S. Robotics U5 802.11g Adapter - FUJITSU E-5400 USB D1700 - Sagem XG703A - DLink DWL-G120 Cohiba - Spinnaker Proto board - Linksys WUSB54AG - Inventel UR054G - Spinnaker DUT - - These devices require softmac firmware which can be found at - http://prism54.org/ - - If you choose to build a module, it'll be called p54usb. - -config P54_PCI - tristate "Prism54 PCI support" - depends on P54_COMMON && PCI - ---help--- - This driver is for PCI isl38xx based wireless cards. - This driver supports most devices that are supported by the - fullmac prism54 driver plus many devices which are not - supported by the fullmac driver/firmware. - - This driver requires softmac firmware which can be found at - http://prism54.org/ - - If you choose to build a module, it'll be called p54pci. - +source "drivers/net/wireless/p54/Kconfig" source "drivers/net/wireless/ath5k/Kconfig" source "drivers/net/wireless/iwlwifi/Kconfig" source "drivers/net/wireless/hostap/Kconfig" diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile index dd3899747b5c..70092191fc53 100644 --- a/drivers/net/wireless/Makefile +++ b/drivers/net/wireless/Makefile @@ -60,8 +60,6 @@ obj-$(CONFIG_IWL3945) += iwlwifi/ obj-$(CONFIG_IWL4965) += iwlwifi/ obj-$(CONFIG_RT2X00) += rt2x00/ -obj-$(CONFIG_P54_COMMON) += p54common.o -obj-$(CONFIG_P54_USB) += p54usb.o -obj-$(CONFIG_P54_PCI) += p54pci.o +obj-$(CONFIG_P54_COMMON) += p54/ obj-$(CONFIG_ATH5K) += ath5k/ diff --git a/drivers/net/wireless/net2280.h b/drivers/net/wireless/net2280.h deleted file mode 100644 index 120eb831b287..000000000000 --- a/drivers/net/wireless/net2280.h +++ /dev/null @@ -1,452 +0,0 @@ -#ifndef NET2280_H -#define NET2280_H -/* - * NetChip 2280 high/full speed USB device controller. - * Unlike many such controllers, this one talks PCI. - */ - -/* - * Copyright (C) 2002 NetChip Technology, Inc. (http://www.netchip.com) - * Copyright (C) 2003 David Brownell - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/*-------------------------------------------------------------------------*/ - -/* NET2280 MEMORY MAPPED REGISTERS - * - * The register layout came from the chip documentation, and the bit - * number definitions were extracted from chip specification. - * - * Use the shift operator ('<<') to build bit masks, with readl/writel - * to access the registers through PCI. - */ - -/* main registers, BAR0 + 0x0000 */ -struct net2280_regs { - // offset 0x0000 - __le32 devinit; -#define LOCAL_CLOCK_FREQUENCY 8 -#define FORCE_PCI_RESET 7 -#define PCI_ID 6 -#define PCI_ENABLE 5 -#define FIFO_SOFT_RESET 4 -#define CFG_SOFT_RESET 3 -#define PCI_SOFT_RESET 2 -#define USB_SOFT_RESET 1 -#define M8051_RESET 0 - __le32 eectl; -#define EEPROM_ADDRESS_WIDTH 23 -#define EEPROM_CHIP_SELECT_ACTIVE 22 -#define EEPROM_PRESENT 21 -#define EEPROM_VALID 20 -#define EEPROM_BUSY 19 -#define EEPROM_CHIP_SELECT_ENABLE 18 -#define EEPROM_BYTE_READ_START 17 -#define EEPROM_BYTE_WRITE_START 16 -#define EEPROM_READ_DATA 8 -#define EEPROM_WRITE_DATA 0 - __le32 eeclkfreq; - u32 _unused0; - // offset 0x0010 - - __le32 pciirqenb0; /* interrupt PCI master ... */ -#define SETUP_PACKET_INTERRUPT_ENABLE 7 -#define ENDPOINT_F_INTERRUPT_ENABLE 6 -#define ENDPOINT_E_INTERRUPT_ENABLE 5 -#define ENDPOINT_D_INTERRUPT_ENABLE 4 -#define ENDPOINT_C_INTERRUPT_ENABLE 3 -#define ENDPOINT_B_INTERRUPT_ENABLE 2 -#define ENDPOINT_A_INTERRUPT_ENABLE 1 -#define ENDPOINT_0_INTERRUPT_ENABLE 0 - __le32 pciirqenb1; -#define PCI_INTERRUPT_ENABLE 31 -#define POWER_STATE_CHANGE_INTERRUPT_ENABLE 27 -#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE 26 -#define PCI_PARITY_ERROR_INTERRUPT_ENABLE 25 -#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE 20 -#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE 19 -#define PCI_TARGET_ABORT_ASSERTED_INTERRUPT_ENABLE 18 -#define PCI_RETRY_ABORT_INTERRUPT_ENABLE 17 -#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE 16 -#define GPIO_INTERRUPT_ENABLE 13 -#define DMA_D_INTERRUPT_ENABLE 12 -#define DMA_C_INTERRUPT_ENABLE 11 -#define DMA_B_INTERRUPT_ENABLE 10 -#define DMA_A_INTERRUPT_ENABLE 9 -#define EEPROM_DONE_INTERRUPT_ENABLE 8 -#define VBUS_INTERRUPT_ENABLE 7 -#define CONTROL_STATUS_INTERRUPT_ENABLE 6 -#define ROOT_PORT_RESET_INTERRUPT_ENABLE 4 -#define SUSPEND_REQUEST_INTERRUPT_ENABLE 3 -#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE 2 -#define RESUME_INTERRUPT_ENABLE 1 -#define SOF_INTERRUPT_ENABLE 0 - __le32 cpu_irqenb0; /* ... or onboard 8051 */ -#define SETUP_PACKET_INTERRUPT_ENABLE 7 -#define ENDPOINT_F_INTERRUPT_ENABLE 6 -#define ENDPOINT_E_INTERRUPT_ENABLE 5 -#define ENDPOINT_D_INTERRUPT_ENABLE 4 -#define ENDPOINT_C_INTERRUPT_ENABLE 3 -#define ENDPOINT_B_INTERRUPT_ENABLE 2 -#define ENDPOINT_A_INTERRUPT_ENABLE 1 -#define ENDPOINT_0_INTERRUPT_ENABLE 0 - __le32 cpu_irqenb1; -#define CPU_INTERRUPT_ENABLE 31 -#define POWER_STATE_CHANGE_INTERRUPT_ENABLE 27 -#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE 26 -#define PCI_PARITY_ERROR_INTERRUPT_ENABLE 25 -#define PCI_INTA_INTERRUPT_ENABLE 24 -#define PCI_PME_INTERRUPT_ENABLE 23 -#define PCI_SERR_INTERRUPT_ENABLE 22 -#define PCI_PERR_INTERRUPT_ENABLE 21 -#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE 20 -#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE 19 -#define PCI_RETRY_ABORT_INTERRUPT_ENABLE 17 -#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE 16 -#define GPIO_INTERRUPT_ENABLE 13 -#define DMA_D_INTERRUPT_ENABLE 12 -#define DMA_C_INTERRUPT_ENABLE 11 -#define DMA_B_INTERRUPT_ENABLE 10 -#define DMA_A_INTERRUPT_ENABLE 9 -#define EEPROM_DONE_INTERRUPT_ENABLE 8 -#define VBUS_INTERRUPT_ENABLE 7 -#define CONTROL_STATUS_INTERRUPT_ENABLE 6 -#define ROOT_PORT_RESET_INTERRUPT_ENABLE 4 -#define SUSPEND_REQUEST_INTERRUPT_ENABLE 3 -#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE 2 -#define RESUME_INTERRUPT_ENABLE 1 -#define SOF_INTERRUPT_ENABLE 0 - - // offset 0x0020 - u32 _unused1; - __le32 usbirqenb1; -#define USB_INTERRUPT_ENABLE 31 -#define POWER_STATE_CHANGE_INTERRUPT_ENABLE 27 -#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE 26 -#define PCI_PARITY_ERROR_INTERRUPT_ENABLE 25 -#define PCI_INTA_INTERRUPT_ENABLE 24 -#define PCI_PME_INTERRUPT_ENABLE 23 -#define PCI_SERR_INTERRUPT_ENABLE 22 -#define PCI_PERR_INTERRUPT_ENABLE 21 -#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE 20 -#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE 19 -#define PCI_RETRY_ABORT_INTERRUPT_ENABLE 17 -#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE 16 -#define GPIO_INTERRUPT_ENABLE 13 -#define DMA_D_INTERRUPT_ENABLE 12 -#define DMA_C_INTERRUPT_ENABLE 11 -#define DMA_B_INTERRUPT_ENABLE 10 -#define DMA_A_INTERRUPT_ENABLE 9 -#define EEPROM_DONE_INTERRUPT_ENABLE 8 -#define VBUS_INTERRUPT_ENABLE 7 -#define CONTROL_STATUS_INTERRUPT_ENABLE 6 -#define ROOT_PORT_RESET_INTERRUPT_ENABLE 4 -#define SUSPEND_REQUEST_INTERRUPT_ENABLE 3 -#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE 2 -#define RESUME_INTERRUPT_ENABLE 1 -#define SOF_INTERRUPT_ENABLE 0 - __le32 irqstat0; -#define INTA_ASSERTED 12 -#define SETUP_PACKET_INTERRUPT 7 -#define ENDPOINT_F_INTERRUPT 6 -#define ENDPOINT_E_INTERRUPT 5 -#define ENDPOINT_D_INTERRUPT 4 -#define ENDPOINT_C_INTERRUPT 3 -#define ENDPOINT_B_INTERRUPT 2 -#define ENDPOINT_A_INTERRUPT 1 -#define ENDPOINT_0_INTERRUPT 0 - __le32 irqstat1; -#define POWER_STATE_CHANGE_INTERRUPT 27 -#define PCI_ARBITER_TIMEOUT_INTERRUPT 26 -#define PCI_PARITY_ERROR_INTERRUPT 25 -#define PCI_INTA_INTERRUPT 24 -#define PCI_PME_INTERRUPT 23 -#define PCI_SERR_INTERRUPT 22 -#define PCI_PERR_INTERRUPT 21 -#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT 20 -#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT 19 -#define PCI_RETRY_ABORT_INTERRUPT 17 -#define PCI_MASTER_CYCLE_DONE_INTERRUPT 16 -#define GPIO_INTERRUPT 13 -#define DMA_D_INTERRUPT 12 -#define DMA_C_INTERRUPT 11 -#define DMA_B_INTERRUPT 10 -#define DMA_A_INTERRUPT 9 -#define EEPROM_DONE_INTERRUPT 8 -#define VBUS_INTERRUPT 7 -#define CONTROL_STATUS_INTERRUPT 6 -#define ROOT_PORT_RESET_INTERRUPT 4 -#define SUSPEND_REQUEST_INTERRUPT 3 -#define SUSPEND_REQUEST_CHANGE_INTERRUPT 2 -#define RESUME_INTERRUPT 1 -#define SOF_INTERRUPT 0 - // offset 0x0030 - __le32 idxaddr; - __le32 idxdata; - __le32 fifoctl; -#define PCI_BASE2_RANGE 16 -#define IGNORE_FIFO_AVAILABILITY 3 -#define PCI_BASE2_SELECT 2 -#define FIFO_CONFIGURATION_SELECT 0 - u32 _unused2; - // offset 0x0040 - __le32 memaddr; -#define START 28 -#define DIRECTION 27 -#define FIFO_DIAGNOSTIC_SELECT 24 -#define MEMORY_ADDRESS 0 - __le32 memdata0; - __le32 memdata1; - u32 _unused3; - // offset 0x0050 - __le32 gpioctl; -#define GPIO3_LED_SELECT 12 -#define GPIO3_INTERRUPT_ENABLE 11 -#define GPIO2_INTERRUPT_ENABLE 10 -#define GPIO1_INTERRUPT_ENABLE 9 -#define GPIO0_INTERRUPT_ENABLE 8 -#define GPIO3_OUTPUT_ENABLE 7 -#define GPIO2_OUTPUT_ENABLE 6 -#define GPIO1_OUTPUT_ENABLE 5 -#define GPIO0_OUTPUT_ENABLE 4 -#define GPIO3_DATA 3 -#define GPIO2_DATA 2 -#define GPIO1_DATA 1 -#define GPIO0_DATA 0 - __le32 gpiostat; -#define GPIO3_INTERRUPT 3 -#define GPIO2_INTERRUPT 2 -#define GPIO1_INTERRUPT 1 -#define GPIO0_INTERRUPT 0 -} __attribute__ ((packed)); - -/* usb control, BAR0 + 0x0080 */ -struct net2280_usb_regs { - // offset 0x0080 - __le32 stdrsp; -#define STALL_UNSUPPORTED_REQUESTS 31 -#define SET_TEST_MODE 16 -#define GET_OTHER_SPEED_CONFIGURATION 15 -#define GET_DEVICE_QUALIFIER 14 -#define SET_ADDRESS 13 -#define ENDPOINT_SET_CLEAR_HALT 12 -#define DEVICE_SET_CLEAR_DEVICE_REMOTE_WAKEUP 11 -#define GET_STRING_DESCRIPTOR_2 10 -#define GET_STRING_DESCRIPTOR_1 9 -#define GET_STRING_DESCRIPTOR_0 8 -#define GET_SET_INTERFACE 6 -#define GET_SET_CONFIGURATION 5 -#define GET_CONFIGURATION_DESCRIPTOR 4 -#define GET_DEVICE_DESCRIPTOR 3 -#define GET_ENDPOINT_STATUS 2 -#define GET_INTERFACE_STATUS 1 -#define GET_DEVICE_STATUS 0 - __le32 prodvendid; -#define PRODUCT_ID 16 -#define VENDOR_ID 0 - __le32 relnum; - __le32 usbctl; -#define SERIAL_NUMBER_INDEX 16 -#define PRODUCT_ID_STRING_ENABLE 13 -#define VENDOR_ID_STRING_ENABLE 12 -#define USB_ROOT_PORT_WAKEUP_ENABLE 11 -#define VBUS_PIN 10 -#define TIMED_DISCONNECT 9 -#define SUSPEND_IMMEDIATELY 7 -#define SELF_POWERED_USB_DEVICE 6 -#define REMOTE_WAKEUP_SUPPORT 5 -#define PME_POLARITY 4 -#define USB_DETECT_ENABLE 3 -#define PME_WAKEUP_ENABLE 2 -#define DEVICE_REMOTE_WAKEUP_ENABLE 1 -#define SELF_POWERED_STATUS 0 - // offset 0x0090 - __le32 usbstat; -#define HIGH_SPEED 7 -#define FULL_SPEED 6 -#define GENERATE_RESUME 5 -#define GENERATE_DEVICE_REMOTE_WAKEUP 4 - __le32 xcvrdiag; -#define FORCE_HIGH_SPEED_MODE 31 -#define FORCE_FULL_SPEED_MODE 30 -#define USB_TEST_MODE 24 -#define LINE_STATE 16 -#define TRANSCEIVER_OPERATION_MODE 2 -#define TRANSCEIVER_SELECT 1 -#define TERMINATION_SELECT 0 - __le32 setup0123; - __le32 setup4567; - // offset 0x0090 - u32 _unused0; - __le32 ouraddr; -#define FORCE_IMMEDIATE 7 -#define OUR_USB_ADDRESS 0 - __le32 ourconfig; -} __attribute__ ((packed)); - -/* pci control, BAR0 + 0x0100 */ -struct net2280_pci_regs { - // offset 0x0100 - __le32 pcimstctl; -#define PCI_ARBITER_PARK_SELECT 13 -#define PCI_MULTI LEVEL_ARBITER 12 -#define PCI_RETRY_ABORT_ENABLE 11 -#define DMA_MEMORY_WRITE_AND_INVALIDATE_ENABLE 10 -#define DMA_READ_MULTIPLE_ENABLE 9 -#define DMA_READ_LINE_ENABLE 8 -#define PCI_MASTER_COMMAND_SELECT 6 -#define MEM_READ_OR_WRITE 0 -#define IO_READ_OR_WRITE 1 -#define CFG_READ_OR_WRITE 2 -#define PCI_MASTER_START 5 -#define PCI_MASTER_READ_WRITE 4 -#define PCI_MASTER_WRITE 0 -#define PCI_MASTER_READ 1 -#define PCI_MASTER_BYTE_WRITE_ENABLES 0 - __le32 pcimstaddr; - __le32 pcimstdata; - __le32 pcimststat; -#define PCI_ARBITER_CLEAR 2 -#define PCI_EXTERNAL_ARBITER 1 -#define PCI_HOST_MODE 0 -} __attribute__ ((packed)); - -/* dma control, BAR0 + 0x0180 ... array of four structs like this, - * for channels 0..3. see also struct net2280_dma: descriptor - * that can be loaded into some of these registers. - */ -struct net2280_dma_regs { /* [11.7] */ - // offset 0x0180, 0x01a0, 0x01c0, 0x01e0, - __le32 dmactl; -#define DMA_SCATTER_GATHER_DONE_INTERRUPT_ENABLE 25 -#define DMA_CLEAR_COUNT_ENABLE 21 -#define DESCRIPTOR_POLLING_RATE 19 -#define POLL_CONTINUOUS 0 -#define POLL_1_USEC 1 -#define POLL_100_USEC 2 -#define POLL_1_MSEC 3 -#define DMA_VALID_BIT_POLLING_ENABLE 18 -#define DMA_VALID_BIT_ENABLE 17 -#define DMA_SCATTER_GATHER_ENABLE 16 -#define DMA_OUT_AUTO_START_ENABLE 4 -#define DMA_PREEMPT_ENABLE 3 -#define DMA_FIFO_VALIDATE 2 -#define DMA_ENABLE 1 -#define DMA_ADDRESS_HOLD 0 - __le32 dmastat; -#define DMA_SCATTER_GATHER_DONE_INTERRUPT 25 -#define DMA_TRANSACTION_DONE_INTERRUPT 24 -#define DMA_ABORT 1 -#define DMA_START 0 - u32 _unused0[2]; - // offset 0x0190, 0x01b0, 0x01d0, 0x01f0, - __le32 dmacount; -#define VALID_BIT 31 -#define DMA_DIRECTION 30 -#define DMA_DONE_INTERRUPT_ENABLE 29 -#define END_OF_CHAIN 28 -#define DMA_BYTE_COUNT_MASK ((1<<24)-1) -#define DMA_BYTE_COUNT 0 - __le32 dmaaddr; - __le32 dmadesc; - u32 _unused1; -} __attribute__ ((packed)); - -/* dedicated endpoint registers, BAR0 + 0x0200 */ - -struct net2280_dep_regs { /* [11.8] */ - // offset 0x0200, 0x0210, 0x220, 0x230, 0x240 - __le32 dep_cfg; - // offset 0x0204, 0x0214, 0x224, 0x234, 0x244 - __le32 dep_rsp; - u32 _unused[2]; -} __attribute__ ((packed)); - -/* configurable endpoint registers, BAR0 + 0x0300 ... array of seven structs - * like this, for ep0 then the configurable endpoints A..F - * ep0 reserved for control; E and F have only 64 bytes of fifo - */ -struct net2280_ep_regs { /* [11.9] */ - // offset 0x0300, 0x0320, 0x0340, 0x0360, 0x0380, 0x03a0, 0x03c0 - __le32 ep_cfg; -#define ENDPOINT_BYTE_COUNT 16 -#define ENDPOINT_ENABLE 10 -#define ENDPOINT_TYPE 8 -#define ENDPOINT_DIRECTION 7 -#define ENDPOINT_NUMBER 0 - __le32 ep_rsp; -#define SET_NAK_OUT_PACKETS 15 -#define SET_EP_HIDE_STATUS_PHASE 14 -#define SET_EP_FORCE_CRC_ERROR 13 -#define SET_INTERRUPT_MODE 12 -#define SET_CONTROL_STATUS_PHASE_HANDSHAKE 11 -#define SET_NAK_OUT_PACKETS_MODE 10 -#define SET_ENDPOINT_TOGGLE 9 -#define SET_ENDPOINT_HALT 8 -#define CLEAR_NAK_OUT_PACKETS 7 -#define CLEAR_EP_HIDE_STATUS_PHASE 6 -#define CLEAR_EP_FORCE_CRC_ERROR 5 -#define CLEAR_INTERRUPT_MODE 4 -#define CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE 3 -#define CLEAR_NAK_OUT_PACKETS_MODE 2 -#define CLEAR_ENDPOINT_TOGGLE 1 -#define CLEAR_ENDPOINT_HALT 0 - __le32 ep_irqenb; -#define SHORT_PACKET_OUT_DONE_INTERRUPT_ENABLE 6 -#define SHORT_PACKET_TRANSFERRED_INTERRUPT_ENABLE 5 -#define DATA_PACKET_RECEIVED_INTERRUPT_ENABLE 3 -#define DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE 2 -#define DATA_OUT_PING_TOKEN_INTERRUPT_ENABLE 1 -#define DATA_IN_TOKEN_INTERRUPT_ENABLE 0 - __le32 ep_stat; -#define FIFO_VALID_COUNT 24 -#define HIGH_BANDWIDTH_OUT_TRANSACTION_PID 22 -#define TIMEOUT 21 -#define USB_STALL_SENT 20 -#define USB_IN_NAK_SENT 19 -#define USB_IN_ACK_RCVD 18 -#define USB_OUT_PING_NAK_SENT 17 -#define USB_OUT_ACK_SENT 16 -#define FIFO_OVERFLOW 13 -#define FIFO_UNDERFLOW 12 -#define FIFO_FULL 11 -#define FIFO_EMPTY 10 -#define FIFO_FLUSH 9 -#define SHORT_PACKET_OUT_DONE_INTERRUPT 6 -#define SHORT_PACKET_TRANSFERRED_INTERRUPT 5 -#define NAK_OUT_PACKETS 4 -#define DATA_PACKET_RECEIVED_INTERRUPT 3 -#define DATA_PACKET_TRANSMITTED_INTERRUPT 2 -#define DATA_OUT_PING_TOKEN_INTERRUPT 1 -#define DATA_IN_TOKEN_INTERRUPT 0 - // offset 0x0310, 0x0330, 0x0350, 0x0370, 0x0390, 0x03b0, 0x03d0 - __le32 ep_avail; - __le32 ep_data; - u32 _unused0[2]; -} __attribute__ ((packed)); - -struct net2280_reg_write { - __le16 port; - __le32 addr; - __le32 val; -} __attribute__ ((packed)); - -struct net2280_reg_read { - __le16 port; - __le32 addr; -} __attribute__ ((packed)); -#endif /* NET2280_H */ diff --git a/drivers/net/wireless/p54.h b/drivers/net/wireless/p54.h deleted file mode 100644 index 06d2c67f4c81..000000000000 --- a/drivers/net/wireless/p54.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef PRISM54_H -#define PRISM54_H - -/* - * Shared defines for all mac80211 Prism54 code - * - * Copyright (c) 2006, Michael Wu - * - * Based on the islsm (softmac prism54) driver, which is: - * Copyright 2004-2006 Jean-Baptiste Note , et al. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -enum control_frame_types { - P54_CONTROL_TYPE_FILTER_SET = 0, - P54_CONTROL_TYPE_CHANNEL_CHANGE, - P54_CONTROL_TYPE_FREQDONE, - P54_CONTROL_TYPE_DCFINIT, - P54_CONTROL_TYPE_FREEQUEUE = 7, - P54_CONTROL_TYPE_TXDONE, - P54_CONTROL_TYPE_PING, - P54_CONTROL_TYPE_STAT_READBACK, - P54_CONTROL_TYPE_BBP, - P54_CONTROL_TYPE_EEPROM_READBACK, - P54_CONTROL_TYPE_LED -}; - -struct p54_control_hdr { - __le16 magic1; - __le16 len; - __le32 req_id; - __le16 type; /* enum control_frame_types */ - u8 retry1; - u8 retry2; - u8 data[0]; -} __attribute__ ((packed)); - -#define EEPROM_READBACK_LEN (sizeof(struct p54_control_hdr) + 4 /* p54_eeprom_lm86 */) -#define MAX_RX_SIZE (IEEE80211_MAX_RTS_THRESHOLD + sizeof(struct p54_control_hdr) + 20 /* length of struct p54_rx_hdr */ + 16 ) - -#define ISL38XX_DEV_FIRMWARE_ADDR 0x20000 - -struct p54_common { - u32 rx_start; - u32 rx_end; - struct sk_buff_head tx_queue; - void (*tx)(struct ieee80211_hw *dev, struct p54_control_hdr *data, - size_t len, int free_on_tx); - int (*open)(struct ieee80211_hw *dev); - void (*stop)(struct ieee80211_hw *dev); - int mode; - u8 mac_addr[ETH_ALEN]; - u8 bssid[ETH_ALEN]; - struct pda_iq_autocal_entry *iq_autocal; - unsigned int iq_autocal_len; - struct pda_channel_output_limit *output_limit; - unsigned int output_limit_len; - struct pda_pa_curve_data *curve_data; - __le16 rxhw; - u8 version; - unsigned int tx_hdr_len; - void *cached_vdcf; - unsigned int fw_var; - struct ieee80211_tx_queue_stats tx_stats; -}; - -int p54_rx(struct ieee80211_hw *dev, struct sk_buff *skb); -void p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw); -int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len); -void p54_fill_eeprom_readback(struct p54_control_hdr *hdr); -struct ieee80211_hw *p54_init_common(size_t priv_data_len); -void p54_free_common(struct ieee80211_hw *dev); - -#endif /* PRISM54_H */ diff --git a/drivers/net/wireless/p54/Kconfig b/drivers/net/wireless/p54/Kconfig new file mode 100644 index 000000000000..d3469d08f966 --- /dev/null +++ b/drivers/net/wireless/p54/Kconfig @@ -0,0 +1,63 @@ +config P54_COMMON + tristate "Softmac Prism54 support" + depends on MAC80211 && WLAN_80211 && FW_LOADER && EXPERIMENTAL + ---help--- + This is common code for isl38xx based cards. + This module does nothing by itself - the USB/PCI frontends + also need to be enabled in order to support any devices. + + These devices require softmac firmware which can be found at + http://prism54.org/ + + If you choose to build a module, it'll be called p54common. + +config P54_USB + tristate "Prism54 USB support" + depends on P54_COMMON && USB + select CRC32 + ---help--- + This driver is for USB isl38xx based wireless cards. + These are USB based adapters found in devices such as: + + 3COM 3CRWE254G72 + SMC 2862W-G + Accton 802.11g WN4501 USB + Siemens Gigaset USB + Netgear WG121 + Netgear WG111 + Medion 40900, Roper Europe + Shuttle PN15, Airvast WM168g, IOGear GWU513 + Linksys WUSB54G + Linksys WUSB54G Portable + DLink DWL-G120 Spinnaker + DLink DWL-G122 + Belkin F5D7050 ver 1000 + Cohiba Proto board + SMC 2862W-G version 2 + U.S. Robotics U5 802.11g Adapter + FUJITSU E-5400 USB D1700 + Sagem XG703A + DLink DWL-G120 Cohiba + Spinnaker Proto board + Linksys WUSB54AG + Inventel UR054G + Spinnaker DUT + + These devices require softmac firmware which can be found at + http://prism54.org/ + + If you choose to build a module, it'll be called p54usb. + +config P54_PCI + tristate "Prism54 PCI support" + depends on P54_COMMON && PCI + ---help--- + This driver is for PCI isl38xx based wireless cards. + This driver supports most devices that are supported by the + fullmac prism54 driver plus many devices which are not + supported by the fullmac driver/firmware. + + This driver requires softmac firmware which can be found at + http://prism54.org/ + + If you choose to build a module, it'll be called p54pci. diff --git a/drivers/net/wireless/p54/Makefile b/drivers/net/wireless/p54/Makefile new file mode 100644 index 000000000000..4fa9ce717360 --- /dev/null +++ b/drivers/net/wireless/p54/Makefile @@ -0,0 +1,3 @@ +obj-$(CONFIG_P54_COMMON) += p54common.o +obj-$(CONFIG_P54_USB) += p54usb.o +obj-$(CONFIG_P54_PCI) += p54pci.o diff --git a/drivers/net/wireless/p54/net2280.h b/drivers/net/wireless/p54/net2280.h new file mode 100644 index 000000000000..120eb831b287 --- /dev/null +++ b/drivers/net/wireless/p54/net2280.h @@ -0,0 +1,452 @@ +#ifndef NET2280_H +#define NET2280_H +/* + * NetChip 2280 high/full speed USB device controller. + * Unlike many such controllers, this one talks PCI. + */ + +/* + * Copyright (C) 2002 NetChip Technology, Inc. (http://www.netchip.com) + * Copyright (C) 2003 David Brownell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/*-------------------------------------------------------------------------*/ + +/* NET2280 MEMORY MAPPED REGISTERS + * + * The register layout came from the chip documentation, and the bit + * number definitions were extracted from chip specification. + * + * Use the shift operator ('<<') to build bit masks, with readl/writel + * to access the registers through PCI. + */ + +/* main registers, BAR0 + 0x0000 */ +struct net2280_regs { + // offset 0x0000 + __le32 devinit; +#define LOCAL_CLOCK_FREQUENCY 8 +#define FORCE_PCI_RESET 7 +#define PCI_ID 6 +#define PCI_ENABLE 5 +#define FIFO_SOFT_RESET 4 +#define CFG_SOFT_RESET 3 +#define PCI_SOFT_RESET 2 +#define USB_SOFT_RESET 1 +#define M8051_RESET 0 + __le32 eectl; +#define EEPROM_ADDRESS_WIDTH 23 +#define EEPROM_CHIP_SELECT_ACTIVE 22 +#define EEPROM_PRESENT 21 +#define EEPROM_VALID 20 +#define EEPROM_BUSY 19 +#define EEPROM_CHIP_SELECT_ENABLE 18 +#define EEPROM_BYTE_READ_START 17 +#define EEPROM_BYTE_WRITE_START 16 +#define EEPROM_READ_DATA 8 +#define EEPROM_WRITE_DATA 0 + __le32 eeclkfreq; + u32 _unused0; + // offset 0x0010 + + __le32 pciirqenb0; /* interrupt PCI master ... */ +#define SETUP_PACKET_INTERRUPT_ENABLE 7 +#define ENDPOINT_F_INTERRUPT_ENABLE 6 +#define ENDPOINT_E_INTERRUPT_ENABLE 5 +#define ENDPOINT_D_INTERRUPT_ENABLE 4 +#define ENDPOINT_C_INTERRUPT_ENABLE 3 +#define ENDPOINT_B_INTERRUPT_ENABLE 2 +#define ENDPOINT_A_INTERRUPT_ENABLE 1 +#define ENDPOINT_0_INTERRUPT_ENABLE 0 + __le32 pciirqenb1; +#define PCI_INTERRUPT_ENABLE 31 +#define POWER_STATE_CHANGE_INTERRUPT_ENABLE 27 +#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE 26 +#define PCI_PARITY_ERROR_INTERRUPT_ENABLE 25 +#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE 20 +#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE 19 +#define PCI_TARGET_ABORT_ASSERTED_INTERRUPT_ENABLE 18 +#define PCI_RETRY_ABORT_INTERRUPT_ENABLE 17 +#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE 16 +#define GPIO_INTERRUPT_ENABLE 13 +#define DMA_D_INTERRUPT_ENABLE 12 +#define DMA_C_INTERRUPT_ENABLE 11 +#define DMA_B_INTERRUPT_ENABLE 10 +#define DMA_A_INTERRUPT_ENABLE 9 +#define EEPROM_DONE_INTERRUPT_ENABLE 8 +#define VBUS_INTERRUPT_ENABLE 7 +#define CONTROL_STATUS_INTERRUPT_ENABLE 6 +#define ROOT_PORT_RESET_INTERRUPT_ENABLE 4 +#define SUSPEND_REQUEST_INTERRUPT_ENABLE 3 +#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE 2 +#define RESUME_INTERRUPT_ENABLE 1 +#define SOF_INTERRUPT_ENABLE 0 + __le32 cpu_irqenb0; /* ... or onboard 8051 */ +#define SETUP_PACKET_INTERRUPT_ENABLE 7 +#define ENDPOINT_F_INTERRUPT_ENABLE 6 +#define ENDPOINT_E_INTERRUPT_ENABLE 5 +#define ENDPOINT_D_INTERRUPT_ENABLE 4 +#define ENDPOINT_C_INTERRUPT_ENABLE 3 +#define ENDPOINT_B_INTERRUPT_ENABLE 2 +#define ENDPOINT_A_INTERRUPT_ENABLE 1 +#define ENDPOINT_0_INTERRUPT_ENABLE 0 + __le32 cpu_irqenb1; +#define CPU_INTERRUPT_ENABLE 31 +#define POWER_STATE_CHANGE_INTERRUPT_ENABLE 27 +#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE 26 +#define PCI_PARITY_ERROR_INTERRUPT_ENABLE 25 +#define PCI_INTA_INTERRUPT_ENABLE 24 +#define PCI_PME_INTERRUPT_ENABLE 23 +#define PCI_SERR_INTERRUPT_ENABLE 22 +#define PCI_PERR_INTERRUPT_ENABLE 21 +#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE 20 +#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE 19 +#define PCI_RETRY_ABORT_INTERRUPT_ENABLE 17 +#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE 16 +#define GPIO_INTERRUPT_ENABLE 13 +#define DMA_D_INTERRUPT_ENABLE 12 +#define DMA_C_INTERRUPT_ENABLE 11 +#define DMA_B_INTERRUPT_ENABLE 10 +#define DMA_A_INTERRUPT_ENABLE 9 +#define EEPROM_DONE_INTERRUPT_ENABLE 8 +#define VBUS_INTERRUPT_ENABLE 7 +#define CONTROL_STATUS_INTERRUPT_ENABLE 6 +#define ROOT_PORT_RESET_INTERRUPT_ENABLE 4 +#define SUSPEND_REQUEST_INTERRUPT_ENABLE 3 +#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE 2 +#define RESUME_INTERRUPT_ENABLE 1 +#define SOF_INTERRUPT_ENABLE 0 + + // offset 0x0020 + u32 _unused1; + __le32 usbirqenb1; +#define USB_INTERRUPT_ENABLE 31 +#define POWER_STATE_CHANGE_INTERRUPT_ENABLE 27 +#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE 26 +#define PCI_PARITY_ERROR_INTERRUPT_ENABLE 25 +#define PCI_INTA_INTERRUPT_ENABLE 24 +#define PCI_PME_INTERRUPT_ENABLE 23 +#define PCI_SERR_INTERRUPT_ENABLE 22 +#define PCI_PERR_INTERRUPT_ENABLE 21 +#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE 20 +#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE 19 +#define PCI_RETRY_ABORT_INTERRUPT_ENABLE 17 +#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE 16 +#define GPIO_INTERRUPT_ENABLE 13 +#define DMA_D_INTERRUPT_ENABLE 12 +#define DMA_C_INTERRUPT_ENABLE 11 +#define DMA_B_INTERRUPT_ENABLE 10 +#define DMA_A_INTERRUPT_ENABLE 9 +#define EEPROM_DONE_INTERRUPT_ENABLE 8 +#define VBUS_INTERRUPT_ENABLE 7 +#define CONTROL_STATUS_INTERRUPT_ENABLE 6 +#define ROOT_PORT_RESET_INTERRUPT_ENABLE 4 +#define SUSPEND_REQUEST_INTERRUPT_ENABLE 3 +#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE 2 +#define RESUME_INTERRUPT_ENABLE 1 +#define SOF_INTERRUPT_ENABLE 0 + __le32 irqstat0; +#define INTA_ASSERTED 12 +#define SETUP_PACKET_INTERRUPT 7 +#define ENDPOINT_F_INTERRUPT 6 +#define ENDPOINT_E_INTERRUPT 5 +#define ENDPOINT_D_INTERRUPT 4 +#define ENDPOINT_C_INTERRUPT 3 +#define ENDPOINT_B_INTERRUPT 2 +#define ENDPOINT_A_INTERRUPT 1 +#define ENDPOINT_0_INTERRUPT 0 + __le32 irqstat1; +#define POWER_STATE_CHANGE_INTERRUPT 27 +#define PCI_ARBITER_TIMEOUT_INTERRUPT 26 +#define PCI_PARITY_ERROR_INTERRUPT 25 +#define PCI_INTA_INTERRUPT 24 +#define PCI_PME_INTERRUPT 23 +#define PCI_SERR_INTERRUPT 22 +#define PCI_PERR_INTERRUPT 21 +#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT 20 +#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT 19 +#define PCI_RETRY_ABORT_INTERRUPT 17 +#define PCI_MASTER_CYCLE_DONE_INTERRUPT 16 +#define GPIO_INTERRUPT 13 +#define DMA_D_INTERRUPT 12 +#define DMA_C_INTERRUPT 11 +#define DMA_B_INTERRUPT 10 +#define DMA_A_INTERRUPT 9 +#define EEPROM_DONE_INTERRUPT 8 +#define VBUS_INTERRUPT 7 +#define CONTROL_STATUS_INTERRUPT 6 +#define ROOT_PORT_RESET_INTERRUPT 4 +#define SUSPEND_REQUEST_INTERRUPT 3 +#define SUSPEND_REQUEST_CHANGE_INTERRUPT 2 +#define RESUME_INTERRUPT 1 +#define SOF_INTERRUPT 0 + // offset 0x0030 + __le32 idxaddr; + __le32 idxdata; + __le32 fifoctl; +#define PCI_BASE2_RANGE 16 +#define IGNORE_FIFO_AVAILABILITY 3 +#define PCI_BASE2_SELECT 2 +#define FIFO_CONFIGURATION_SELECT 0 + u32 _unused2; + // offset 0x0040 + __le32 memaddr; +#define START 28 +#define DIRECTION 27 +#define FIFO_DIAGNOSTIC_SELECT 24 +#define MEMORY_ADDRESS 0 + __le32 memdata0; + __le32 memdata1; + u32 _unused3; + // offset 0x0050 + __le32 gpioctl; +#define GPIO3_LED_SELECT 12 +#define GPIO3_INTERRUPT_ENABLE 11 +#define GPIO2_INTERRUPT_ENABLE 10 +#define GPIO1_INTERRUPT_ENABLE 9 +#define GPIO0_INTERRUPT_ENABLE 8 +#define GPIO3_OUTPUT_ENABLE 7 +#define GPIO2_OUTPUT_ENABLE 6 +#define GPIO1_OUTPUT_ENABLE 5 +#define GPIO0_OUTPUT_ENABLE 4 +#define GPIO3_DATA 3 +#define GPIO2_DATA 2 +#define GPIO1_DATA 1 +#define GPIO0_DATA 0 + __le32 gpiostat; +#define GPIO3_INTERRUPT 3 +#define GPIO2_INTERRUPT 2 +#define GPIO1_INTERRUPT 1 +#define GPIO0_INTERRUPT 0 +} __attribute__ ((packed)); + +/* usb control, BAR0 + 0x0080 */ +struct net2280_usb_regs { + // offset 0x0080 + __le32 stdrsp; +#define STALL_UNSUPPORTED_REQUESTS 31 +#define SET_TEST_MODE 16 +#define GET_OTHER_SPEED_CONFIGURATION 15 +#define GET_DEVICE_QUALIFIER 14 +#define SET_ADDRESS 13 +#define ENDPOINT_SET_CLEAR_HALT 12 +#define DEVICE_SET_CLEAR_DEVICE_REMOTE_WAKEUP 11 +#define GET_STRING_DESCRIPTOR_2 10 +#define GET_STRING_DESCRIPTOR_1 9 +#define GET_STRING_DESCRIPTOR_0 8 +#define GET_SET_INTERFACE 6 +#define GET_SET_CONFIGURATION 5 +#define GET_CONFIGURATION_DESCRIPTOR 4 +#define GET_DEVICE_DESCRIPTOR 3 +#define GET_ENDPOINT_STATUS 2 +#define GET_INTERFACE_STATUS 1 +#define GET_DEVICE_STATUS 0 + __le32 prodvendid; +#define PRODUCT_ID 16 +#define VENDOR_ID 0 + __le32 relnum; + __le32 usbctl; +#define SERIAL_NUMBER_INDEX 16 +#define PRODUCT_ID_STRING_ENABLE 13 +#define VENDOR_ID_STRING_ENABLE 12 +#define USB_ROOT_PORT_WAKEUP_ENABLE 11 +#define VBUS_PIN 10 +#define TIMED_DISCONNECT 9 +#define SUSPEND_IMMEDIATELY 7 +#define SELF_POWERED_USB_DEVICE 6 +#define REMOTE_WAKEUP_SUPPORT 5 +#define PME_POLARITY 4 +#define USB_DETECT_ENABLE 3 +#define PME_WAKEUP_ENABLE 2 +#define DEVICE_REMOTE_WAKEUP_ENABLE 1 +#define SELF_POWERED_STATUS 0 + // offset 0x0090 + __le32 usbstat; +#define HIGH_SPEED 7 +#define FULL_SPEED 6 +#define GENERATE_RESUME 5 +#define GENERATE_DEVICE_REMOTE_WAKEUP 4 + __le32 xcvrdiag; +#define FORCE_HIGH_SPEED_MODE 31 +#define FORCE_FULL_SPEED_MODE 30 +#define USB_TEST_MODE 24 +#define LINE_STATE 16 +#define TRANSCEIVER_OPERATION_MODE 2 +#define TRANSCEIVER_SELECT 1 +#define TERMINATION_SELECT 0 + __le32 setup0123; + __le32 setup4567; + // offset 0x0090 + u32 _unused0; + __le32 ouraddr; +#define FORCE_IMMEDIATE 7 +#define OUR_USB_ADDRESS 0 + __le32 ourconfig; +} __attribute__ ((packed)); + +/* pci control, BAR0 + 0x0100 */ +struct net2280_pci_regs { + // offset 0x0100 + __le32 pcimstctl; +#define PCI_ARBITER_PARK_SELECT 13 +#define PCI_MULTI LEVEL_ARBITER 12 +#define PCI_RETRY_ABORT_ENABLE 11 +#define DMA_MEMORY_WRITE_AND_INVALIDATE_ENABLE 10 +#define DMA_READ_MULTIPLE_ENABLE 9 +#define DMA_READ_LINE_ENABLE 8 +#define PCI_MASTER_COMMAND_SELECT 6 +#define MEM_READ_OR_WRITE 0 +#define IO_READ_OR_WRITE 1 +#define CFG_READ_OR_WRITE 2 +#define PCI_MASTER_START 5 +#define PCI_MASTER_READ_WRITE 4 +#define PCI_MASTER_WRITE 0 +#define PCI_MASTER_READ 1 +#define PCI_MASTER_BYTE_WRITE_ENABLES 0 + __le32 pcimstaddr; + __le32 pcimstdata; + __le32 pcimststat; +#define PCI_ARBITER_CLEAR 2 +#define PCI_EXTERNAL_ARBITER 1 +#define PCI_HOST_MODE 0 +} __attribute__ ((packed)); + +/* dma control, BAR0 + 0x0180 ... array of four structs like this, + * for channels 0..3. see also struct net2280_dma: descriptor + * that can be loaded into some of these registers. + */ +struct net2280_dma_regs { /* [11.7] */ + // offset 0x0180, 0x01a0, 0x01c0, 0x01e0, + __le32 dmactl; +#define DMA_SCATTER_GATHER_DONE_INTERRUPT_ENABLE 25 +#define DMA_CLEAR_COUNT_ENABLE 21 +#define DESCRIPTOR_POLLING_RATE 19 +#define POLL_CONTINUOUS 0 +#define POLL_1_USEC 1 +#define POLL_100_USEC 2 +#define POLL_1_MSEC 3 +#define DMA_VALID_BIT_POLLING_ENABLE 18 +#define DMA_VALID_BIT_ENABLE 17 +#define DMA_SCATTER_GATHER_ENABLE 16 +#define DMA_OUT_AUTO_START_ENABLE 4 +#define DMA_PREEMPT_ENABLE 3 +#define DMA_FIFO_VALIDATE 2 +#define DMA_ENABLE 1 +#define DMA_ADDRESS_HOLD 0 + __le32 dmastat; +#define DMA_SCATTER_GATHER_DONE_INTERRUPT 25 +#define DMA_TRANSACTION_DONE_INTERRUPT 24 +#define DMA_ABORT 1 +#define DMA_START 0 + u32 _unused0[2]; + // offset 0x0190, 0x01b0, 0x01d0, 0x01f0, + __le32 dmacount; +#define VALID_BIT 31 +#define DMA_DIRECTION 30 +#define DMA_DONE_INTERRUPT_ENABLE 29 +#define END_OF_CHAIN 28 +#define DMA_BYTE_COUNT_MASK ((1<<24)-1) +#define DMA_BYTE_COUNT 0 + __le32 dmaaddr; + __le32 dmadesc; + u32 _unused1; +} __attribute__ ((packed)); + +/* dedicated endpoint registers, BAR0 + 0x0200 */ + +struct net2280_dep_regs { /* [11.8] */ + // offset 0x0200, 0x0210, 0x220, 0x230, 0x240 + __le32 dep_cfg; + // offset 0x0204, 0x0214, 0x224, 0x234, 0x244 + __le32 dep_rsp; + u32 _unused[2]; +} __attribute__ ((packed)); + +/* configurable endpoint registers, BAR0 + 0x0300 ... array of seven structs + * like this, for ep0 then the configurable endpoints A..F + * ep0 reserved for control; E and F have only 64 bytes of fifo + */ +struct net2280_ep_regs { /* [11.9] */ + // offset 0x0300, 0x0320, 0x0340, 0x0360, 0x0380, 0x03a0, 0x03c0 + __le32 ep_cfg; +#define ENDPOINT_BYTE_COUNT 16 +#define ENDPOINT_ENABLE 10 +#define ENDPOINT_TYPE 8 +#define ENDPOINT_DIRECTION 7 +#define ENDPOINT_NUMBER 0 + __le32 ep_rsp; +#define SET_NAK_OUT_PACKETS 15 +#define SET_EP_HIDE_STATUS_PHASE 14 +#define SET_EP_FORCE_CRC_ERROR 13 +#define SET_INTERRUPT_MODE 12 +#define SET_CONTROL_STATUS_PHASE_HANDSHAKE 11 +#define SET_NAK_OUT_PACKETS_MODE 10 +#define SET_ENDPOINT_TOGGLE 9 +#define SET_ENDPOINT_HALT 8 +#define CLEAR_NAK_OUT_PACKETS 7 +#define CLEAR_EP_HIDE_STATUS_PHASE 6 +#define CLEAR_EP_FORCE_CRC_ERROR 5 +#define CLEAR_INTERRUPT_MODE 4 +#define CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE 3 +#define CLEAR_NAK_OUT_PACKETS_MODE 2 +#define CLEAR_ENDPOINT_TOGGLE 1 +#define CLEAR_ENDPOINT_HALT 0 + __le32 ep_irqenb; +#define SHORT_PACKET_OUT_DONE_INTERRUPT_ENABLE 6 +#define SHORT_PACKET_TRANSFERRED_INTERRUPT_ENABLE 5 +#define DATA_PACKET_RECEIVED_INTERRUPT_ENABLE 3 +#define DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE 2 +#define DATA_OUT_PING_TOKEN_INTERRUPT_ENABLE 1 +#define DATA_IN_TOKEN_INTERRUPT_ENABLE 0 + __le32 ep_stat; +#define FIFO_VALID_COUNT 24 +#define HIGH_BANDWIDTH_OUT_TRANSACTION_PID 22 +#define TIMEOUT 21 +#define USB_STALL_SENT 20 +#define USB_IN_NAK_SENT 19 +#define USB_IN_ACK_RCVD 18 +#define USB_OUT_PING_NAK_SENT 17 +#define USB_OUT_ACK_SENT 16 +#define FIFO_OVERFLOW 13 +#define FIFO_UNDERFLOW 12 +#define FIFO_FULL 11 +#define FIFO_EMPTY 10 +#define FIFO_FLUSH 9 +#define SHORT_PACKET_OUT_DONE_INTERRUPT 6 +#define SHORT_PACKET_TRANSFERRED_INTERRUPT 5 +#define NAK_OUT_PACKETS 4 +#define DATA_PACKET_RECEIVED_INTERRUPT 3 +#define DATA_PACKET_TRANSMITTED_INTERRUPT 2 +#define DATA_OUT_PING_TOKEN_INTERRUPT 1 +#define DATA_IN_TOKEN_INTERRUPT 0 + // offset 0x0310, 0x0330, 0x0350, 0x0370, 0x0390, 0x03b0, 0x03d0 + __le32 ep_avail; + __le32 ep_data; + u32 _unused0[2]; +} __attribute__ ((packed)); + +struct net2280_reg_write { + __le16 port; + __le32 addr; + __le32 val; +} __attribute__ ((packed)); + +struct net2280_reg_read { + __le16 port; + __le32 addr; +} __attribute__ ((packed)); +#endif /* NET2280_H */ diff --git a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h new file mode 100644 index 000000000000..06d2c67f4c81 --- /dev/null +++ b/drivers/net/wireless/p54/p54.h @@ -0,0 +1,77 @@ +#ifndef PRISM54_H +#define PRISM54_H + +/* + * Shared defines for all mac80211 Prism54 code + * + * Copyright (c) 2006, Michael Wu + * + * Based on the islsm (softmac prism54) driver, which is: + * Copyright 2004-2006 Jean-Baptiste Note , et al. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +enum control_frame_types { + P54_CONTROL_TYPE_FILTER_SET = 0, + P54_CONTROL_TYPE_CHANNEL_CHANGE, + P54_CONTROL_TYPE_FREQDONE, + P54_CONTROL_TYPE_DCFINIT, + P54_CONTROL_TYPE_FREEQUEUE = 7, + P54_CONTROL_TYPE_TXDONE, + P54_CONTROL_TYPE_PING, + P54_CONTROL_TYPE_STAT_READBACK, + P54_CONTROL_TYPE_BBP, + P54_CONTROL_TYPE_EEPROM_READBACK, + P54_CONTROL_TYPE_LED +}; + +struct p54_control_hdr { + __le16 magic1; + __le16 len; + __le32 req_id; + __le16 type; /* enum control_frame_types */ + u8 retry1; + u8 retry2; + u8 data[0]; +} __attribute__ ((packed)); + +#define EEPROM_READBACK_LEN (sizeof(struct p54_control_hdr) + 4 /* p54_eeprom_lm86 */) +#define MAX_RX_SIZE (IEEE80211_MAX_RTS_THRESHOLD + sizeof(struct p54_control_hdr) + 20 /* length of struct p54_rx_hdr */ + 16 ) + +#define ISL38XX_DEV_FIRMWARE_ADDR 0x20000 + +struct p54_common { + u32 rx_start; + u32 rx_end; + struct sk_buff_head tx_queue; + void (*tx)(struct ieee80211_hw *dev, struct p54_control_hdr *data, + size_t len, int free_on_tx); + int (*open)(struct ieee80211_hw *dev); + void (*stop)(struct ieee80211_hw *dev); + int mode; + u8 mac_addr[ETH_ALEN]; + u8 bssid[ETH_ALEN]; + struct pda_iq_autocal_entry *iq_autocal; + unsigned int iq_autocal_len; + struct pda_channel_output_limit *output_limit; + unsigned int output_limit_len; + struct pda_pa_curve_data *curve_data; + __le16 rxhw; + u8 version; + unsigned int tx_hdr_len; + void *cached_vdcf; + unsigned int fw_var; + struct ieee80211_tx_queue_stats tx_stats; +}; + +int p54_rx(struct ieee80211_hw *dev, struct sk_buff *skb); +void p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw); +int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len); +void p54_fill_eeprom_readback(struct p54_control_hdr *hdr); +struct ieee80211_hw *p54_init_common(size_t priv_data_len); +void p54_free_common(struct ieee80211_hw *dev); + +#endif /* PRISM54_H */ diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c new file mode 100644 index 000000000000..63f9badf3f52 --- /dev/null +++ b/drivers/net/wireless/p54/p54common.c @@ -0,0 +1,1051 @@ + +/* + * Common code for mac80211 Prism54 drivers + * + * Copyright (c) 2006, Michael Wu + * Copyright (c) 2007, Christian Lamparter + * + * Based on the islsm (softmac prism54) driver, which is: + * Copyright 2004-2006 Jean-Baptiste Note , et al. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include + +#include + +#include "p54.h" +#include "p54common.h" + +MODULE_AUTHOR("Michael Wu "); +MODULE_DESCRIPTION("Softmac Prism54 common code"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("prism54common"); + +static struct ieee80211_rate p54_rates[] = { + { .bitrate = 10, .hw_value = 0, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, + { .bitrate = 20, .hw_value = 1, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, + { .bitrate = 55, .hw_value = 2, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, + { .bitrate = 110, .hw_value = 3, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, + { .bitrate = 60, .hw_value = 4, }, + { .bitrate = 90, .hw_value = 5, }, + { .bitrate = 120, .hw_value = 6, }, + { .bitrate = 180, .hw_value = 7, }, + { .bitrate = 240, .hw_value = 8, }, + { .bitrate = 360, .hw_value = 9, }, + { .bitrate = 480, .hw_value = 10, }, + { .bitrate = 540, .hw_value = 11, }, +}; + +static struct ieee80211_channel p54_channels[] = { + { .center_freq = 2412, .hw_value = 1, }, + { .center_freq = 2417, .hw_value = 2, }, + { .center_freq = 2422, .hw_value = 3, }, + { .center_freq = 2427, .hw_value = 4, }, + { .center_freq = 2432, .hw_value = 5, }, + { .center_freq = 2437, .hw_value = 6, }, + { .center_freq = 2442, .hw_value = 7, }, + { .center_freq = 2447, .hw_value = 8, }, + { .center_freq = 2452, .hw_value = 9, }, + { .center_freq = 2457, .hw_value = 10, }, + { .center_freq = 2462, .hw_value = 11, }, + { .center_freq = 2467, .hw_value = 12, }, + { .center_freq = 2472, .hw_value = 13, }, + { .center_freq = 2484, .hw_value = 14, }, +}; + +static struct ieee80211_supported_band band_2GHz = { + .channels = p54_channels, + .n_channels = ARRAY_SIZE(p54_channels), + .bitrates = p54_rates, + .n_bitrates = ARRAY_SIZE(p54_rates), +}; + + +void p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw) +{ + struct p54_common *priv = dev->priv; + struct bootrec_exp_if *exp_if; + struct bootrec *bootrec; + u32 *data = (u32 *)fw->data; + u32 *end_data = (u32 *)fw->data + (fw->size >> 2); + u8 *fw_version = NULL; + size_t len; + int i; + + if (priv->rx_start) + return; + + while (data < end_data && *data) + data++; + + while (data < end_data && !*data) + data++; + + bootrec = (struct bootrec *) data; + + while (bootrec->data <= end_data && + (bootrec->data + (len = le32_to_cpu(bootrec->len))) <= end_data) { + u32 code = le32_to_cpu(bootrec->code); + switch (code) { + case BR_CODE_COMPONENT_ID: + switch (be32_to_cpu(*(__be32 *)bootrec->data)) { + case FW_FMAC: + printk(KERN_INFO "p54: FreeMAC firmware\n"); + break; + case FW_LM20: + printk(KERN_INFO "p54: LM20 firmware\n"); + break; + case FW_LM86: + printk(KERN_INFO "p54: LM86 firmware\n"); + break; + case FW_LM87: + printk(KERN_INFO "p54: LM87 firmware - not supported yet!\n"); + break; + default: + printk(KERN_INFO "p54: unknown firmware\n"); + break; + } + break; + case BR_CODE_COMPONENT_VERSION: + /* 24 bytes should be enough for all firmwares */ + if (strnlen((unsigned char*)bootrec->data, 24) < 24) + fw_version = (unsigned char*)bootrec->data; + break; + case BR_CODE_DESCR: + priv->rx_start = le32_to_cpu(((__le32 *)bootrec->data)[1]); + /* FIXME add sanity checking */ + priv->rx_end = le32_to_cpu(((__le32 *)bootrec->data)[2]) - 0x3500; + break; + case BR_CODE_EXPOSED_IF: + exp_if = (struct bootrec_exp_if *) bootrec->data; + for (i = 0; i < (len * sizeof(*exp_if) / 4); i++) + if (exp_if[i].if_id == cpu_to_le16(0x1a)) + priv->fw_var = le16_to_cpu(exp_if[i].variant); + break; + case BR_CODE_DEPENDENT_IF: + break; + case BR_CODE_END_OF_BRA: + case LEGACY_BR_CODE_END_OF_BRA: + end_data = NULL; + break; + default: + break; + } + bootrec = (struct bootrec *)&bootrec->data[len]; + } + + if (fw_version) + printk(KERN_INFO "p54: FW rev %s - Softmac protocol %x.%x\n", + fw_version, priv->fw_var >> 8, priv->fw_var & 0xff); + + if (priv->fw_var >= 0x300) { + /* Firmware supports QoS, use it! */ + priv->tx_stats.data[0].limit = 3; + priv->tx_stats.data[1].limit = 4; + priv->tx_stats.data[2].limit = 3; + priv->tx_stats.data[3].limit = 1; + dev->queues = 4; + } +} +EXPORT_SYMBOL_GPL(p54_parse_firmware); + +static int p54_convert_rev0_to_rev1(struct ieee80211_hw *dev, + struct pda_pa_curve_data *curve_data) +{ + struct p54_common *priv = dev->priv; + struct pda_pa_curve_data_sample_rev1 *rev1; + struct pda_pa_curve_data_sample_rev0 *rev0; + size_t cd_len = sizeof(*curve_data) + + (curve_data->points_per_channel*sizeof(*rev1) + 2) * + curve_data->channels; + unsigned int i, j; + void *source, *target; + + priv->curve_data = kmalloc(cd_len, GFP_KERNEL); + if (!priv->curve_data) + return -ENOMEM; + + memcpy(priv->curve_data, curve_data, sizeof(*curve_data)); + source = curve_data->data; + target = priv->curve_data->data; + for (i = 0; i < curve_data->channels; i++) { + __le16 *freq = source; + source += sizeof(__le16); + *((__le16 *)target) = *freq; + target += sizeof(__le16); + for (j = 0; j < curve_data->points_per_channel; j++) { + rev1 = target; + rev0 = source; + + rev1->rf_power = rev0->rf_power; + rev1->pa_detector = rev0->pa_detector; + rev1->data_64qam = rev0->pcv; + /* "invent" the points for the other modulations */ +#define SUB(x,y) (u8)((x) - (y)) > (x) ? 0 : (x) - (y) + rev1->data_16qam = SUB(rev0->pcv, 12); + rev1->data_qpsk = SUB(rev1->data_16qam, 12); + rev1->data_bpsk = SUB(rev1->data_qpsk, 12); + rev1->data_barker= SUB(rev1->data_bpsk, 14); +#undef SUB + target += sizeof(*rev1); + source += sizeof(*rev0); + } + } + + return 0; +} + +int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) +{ + struct p54_common *priv = dev->priv; + struct eeprom_pda_wrap *wrap = NULL; + struct pda_entry *entry; + unsigned int data_len, entry_len; + void *tmp; + int err; + u8 *end = (u8 *)eeprom + len; + + wrap = (struct eeprom_pda_wrap *) eeprom; + entry = (void *)wrap->data + le16_to_cpu(wrap->len); + + /* verify that at least the entry length/code fits */ + while ((u8 *)entry <= end - sizeof(*entry)) { + entry_len = le16_to_cpu(entry->len); + data_len = ((entry_len - 1) << 1); + + /* abort if entry exceeds whole structure */ + if ((u8 *)entry + sizeof(*entry) + data_len > end) + break; + + switch (le16_to_cpu(entry->code)) { + case PDR_MAC_ADDRESS: + SET_IEEE80211_PERM_ADDR(dev, entry->data); + break; + case PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS: + if (data_len < 2) { + err = -EINVAL; + goto err; + } + + if (2 + entry->data[1]*sizeof(*priv->output_limit) > data_len) { + err = -EINVAL; + goto err; + } + + priv->output_limit = kmalloc(entry->data[1] * + sizeof(*priv->output_limit), GFP_KERNEL); + + if (!priv->output_limit) { + err = -ENOMEM; + goto err; + } + + memcpy(priv->output_limit, &entry->data[2], + entry->data[1]*sizeof(*priv->output_limit)); + priv->output_limit_len = entry->data[1]; + break; + case PDR_PRISM_PA_CAL_CURVE_DATA: + if (data_len < sizeof(struct pda_pa_curve_data)) { + err = -EINVAL; + goto err; + } + + if (((struct pda_pa_curve_data *)entry->data)->cal_method_rev) { + priv->curve_data = kmalloc(data_len, GFP_KERNEL); + if (!priv->curve_data) { + err = -ENOMEM; + goto err; + } + + memcpy(priv->curve_data, entry->data, data_len); + } else { + err = p54_convert_rev0_to_rev1(dev, (struct pda_pa_curve_data *)entry->data); + if (err) + goto err; + } + + break; + case PDR_PRISM_ZIF_TX_IQ_CALIBRATION: + priv->iq_autocal = kmalloc(data_len, GFP_KERNEL); + if (!priv->iq_autocal) { + err = -ENOMEM; + goto err; + } + + memcpy(priv->iq_autocal, entry->data, data_len); + priv->iq_autocal_len = data_len / sizeof(struct pda_iq_autocal_entry); + break; + case PDR_INTERFACE_LIST: + tmp = entry->data; + while ((u8 *)tmp < entry->data + data_len) { + struct bootrec_exp_if *exp_if = tmp; + if (le16_to_cpu(exp_if->if_id) == 0xF) + priv->rxhw = exp_if->variant & cpu_to_le16(0x07); + tmp += sizeof(struct bootrec_exp_if); + } + break; + case PDR_HARDWARE_PLATFORM_COMPONENT_ID: + priv->version = *(u8 *)(entry->data + 1); + break; + case PDR_END: + /* make it overrun */ + entry_len = len; + break; + default: + printk(KERN_INFO "p54: unknown eeprom code : 0x%x\n", + le16_to_cpu(entry->code)); + break; + } + + entry = (void *)entry + (entry_len + 1)*2; + } + + if (!priv->iq_autocal || !priv->output_limit || !priv->curve_data) { + printk(KERN_ERR "p54: not all required entries found in eeprom!\n"); + err = -EINVAL; + goto err; + } + + return 0; + + err: + if (priv->iq_autocal) { + kfree(priv->iq_autocal); + priv->iq_autocal = NULL; + } + + if (priv->output_limit) { + kfree(priv->output_limit); + priv->output_limit = NULL; + } + + if (priv->curve_data) { + kfree(priv->curve_data); + priv->curve_data = NULL; + } + + printk(KERN_ERR "p54: eeprom parse failed!\n"); + return err; +} +EXPORT_SYMBOL_GPL(p54_parse_eeprom); + +void p54_fill_eeprom_readback(struct p54_control_hdr *hdr) +{ + struct p54_eeprom_lm86 *eeprom_hdr; + + hdr->magic1 = cpu_to_le16(0x8000); + hdr->len = cpu_to_le16(sizeof(*eeprom_hdr) + 0x2000); + hdr->type = cpu_to_le16(P54_CONTROL_TYPE_EEPROM_READBACK); + hdr->retry1 = hdr->retry2 = 0; + eeprom_hdr = (struct p54_eeprom_lm86 *) hdr->data; + eeprom_hdr->offset = 0x0; + eeprom_hdr->len = cpu_to_le16(0x2000); +} +EXPORT_SYMBOL_GPL(p54_fill_eeprom_readback); + +static void p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb) +{ + struct p54_rx_hdr *hdr = (struct p54_rx_hdr *) skb->data; + struct ieee80211_rx_status rx_status = {0}; + u16 freq = le16_to_cpu(hdr->freq); + + rx_status.ssi = hdr->rssi; + /* XX correct? */ + rx_status.rate_idx = hdr->rate & 0xf; + rx_status.freq = freq; + rx_status.band = IEEE80211_BAND_2GHZ; + rx_status.antenna = hdr->antenna; + rx_status.mactime = le64_to_cpu(hdr->timestamp); + rx_status.flag |= RX_FLAG_TSFT; + + skb_pull(skb, sizeof(*hdr)); + skb_trim(skb, le16_to_cpu(hdr->len)); + + ieee80211_rx_irqsafe(dev, skb, &rx_status); +} + +static void inline p54_wake_free_queues(struct ieee80211_hw *dev) +{ + struct p54_common *priv = dev->priv; + int i; + + /* ieee80211_start_queues is great if all queues are really empty. + * But, what if some are full? */ + + for (i = 0; i < dev->queues; i++) + if (priv->tx_stats.data[i].len < priv->tx_stats.data[i].limit) + ieee80211_wake_queue(dev, i); +} + +static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) +{ + struct p54_common *priv = dev->priv; + struct p54_control_hdr *hdr = (struct p54_control_hdr *) skb->data; + struct p54_frame_sent_hdr *payload = (struct p54_frame_sent_hdr *) hdr->data; + struct sk_buff *entry = (struct sk_buff *) priv->tx_queue.next; + u32 addr = le32_to_cpu(hdr->req_id) - 0x70; + struct memrecord *range = NULL; + u32 freed = 0; + u32 last_addr = priv->rx_start; + + while (entry != (struct sk_buff *)&priv->tx_queue) { + range = (struct memrecord *)&entry->cb; + if (range->start_addr == addr) { + struct ieee80211_tx_status status; + struct p54_control_hdr *entry_hdr; + struct p54_tx_control_allocdata *entry_data; + int pad = 0; + + if (entry->next != (struct sk_buff *)&priv->tx_queue) + freed = ((struct memrecord *)&entry->next->cb)->start_addr - last_addr; + else + freed = priv->rx_end - last_addr; + + last_addr = range->end_addr; + __skb_unlink(entry, &priv->tx_queue); + if (!range->control) { + kfree_skb(entry); + break; + } + memset(&status, 0, sizeof(status)); + memcpy(&status.control, range->control, + sizeof(status.control)); + kfree(range->control); + priv->tx_stats.data[status.control.queue].len--; + + entry_hdr = (struct p54_control_hdr *) entry->data; + entry_data = (struct p54_tx_control_allocdata *) entry_hdr->data; + if ((entry_hdr->magic1 & cpu_to_le16(0x4000)) != 0) + pad = entry_data->align[0]; + + if (!(status.control.flags & IEEE80211_TXCTL_NO_ACK)) { + if (!(payload->status & 0x01)) + status.flags |= IEEE80211_TX_STATUS_ACK; + else + status.excessive_retries = 1; + } + status.retry_count = payload->retries - 1; + status.ack_signal = le16_to_cpu(payload->ack_rssi); + skb_pull(entry, sizeof(*hdr) + pad + sizeof(*entry_data)); + ieee80211_tx_status_irqsafe(dev, entry, &status); + break; + } else + last_addr = range->end_addr; + entry = entry->next; + } + + if (freed >= IEEE80211_MAX_RTS_THRESHOLD + 0x170 + + sizeof(struct p54_control_hdr)) + p54_wake_free_queues(dev); +} + +static void p54_rx_control(struct ieee80211_hw *dev, struct sk_buff *skb) +{ + struct p54_control_hdr *hdr = (struct p54_control_hdr *) skb->data; + + switch (le16_to_cpu(hdr->type)) { + case P54_CONTROL_TYPE_TXDONE: + p54_rx_frame_sent(dev, skb); + break; + case P54_CONTROL_TYPE_BBP: + break; + default: + printk(KERN_DEBUG "%s: not handling 0x%02x type control frame\n", + wiphy_name(dev->wiphy), le16_to_cpu(hdr->type)); + break; + } +} + +/* returns zero if skb can be reused */ +int p54_rx(struct ieee80211_hw *dev, struct sk_buff *skb) +{ + u8 type = le16_to_cpu(*((__le16 *)skb->data)) >> 8; + switch (type) { + case 0x00: + case 0x01: + p54_rx_data(dev, skb); + return -1; + case 0x4d: + /* TODO: do something better... but then again, I've never seen this happen */ + printk(KERN_ERR "%s: Received fault. Probably need to restart hardware now..\n", + wiphy_name(dev->wiphy)); + break; + case 0x80: + p54_rx_control(dev, skb); + break; + default: + printk(KERN_ERR "%s: unknown frame RXed (0x%02x)\n", + wiphy_name(dev->wiphy), type); + break; + } + return 0; +} +EXPORT_SYMBOL_GPL(p54_rx); + +/* + * So, the firmware is somewhat stupid and doesn't know what places in its + * memory incoming data should go to. By poking around in the firmware, we + * can find some unused memory to upload our packets to. However, data that we + * want the card to TX needs to stay intact until the card has told us that + * it is done with it. This function finds empty places we can upload to and + * marks allocated areas as reserved if necessary. p54_rx_frame_sent frees + * allocated areas. + */ +static void p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb, + struct p54_control_hdr *data, u32 len, + struct ieee80211_tx_control *control) +{ + struct p54_common *priv = dev->priv; + struct sk_buff *entry = priv->tx_queue.next; + struct sk_buff *target_skb = NULL; + struct memrecord *range; + u32 last_addr = priv->rx_start; + u32 largest_hole = 0; + u32 target_addr = priv->rx_start; + unsigned long flags; + unsigned int left; + len = (len + 0x170 + 3) & ~0x3; /* 0x70 headroom, 0x100 tailroom */ + + spin_lock_irqsave(&priv->tx_queue.lock, flags); + left = skb_queue_len(&priv->tx_queue); + while (left--) { + u32 hole_size; + range = (struct memrecord *)&entry->cb; + hole_size = range->start_addr - last_addr; + if (!target_skb && hole_size >= len) { + target_skb = entry->prev; + hole_size -= len; + target_addr = last_addr; + } + largest_hole = max(largest_hole, hole_size); + last_addr = range->end_addr; + entry = entry->next; + } + if (!target_skb && priv->rx_end - last_addr >= len) { + target_skb = priv->tx_queue.prev; + largest_hole = max(largest_hole, priv->rx_end - last_addr - len); + if (!skb_queue_empty(&priv->tx_queue)) { + range = (struct memrecord *)&target_skb->cb; + target_addr = range->end_addr; + } + } else + largest_hole = max(largest_hole, priv->rx_end - last_addr); + + if (skb) { + range = (struct memrecord *)&skb->cb; + range->start_addr = target_addr; + range->end_addr = target_addr + len; + range->control = control; + __skb_queue_after(&priv->tx_queue, target_skb, skb); + if (largest_hole < IEEE80211_MAX_RTS_THRESHOLD + 0x170 + + sizeof(struct p54_control_hdr)) + ieee80211_stop_queues(dev); + } + spin_unlock_irqrestore(&priv->tx_queue.lock, flags); + + data->req_id = cpu_to_le32(target_addr + 0x70); +} + +static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb, + struct ieee80211_tx_control *control) +{ + struct ieee80211_tx_queue_stats_data *current_queue; + struct p54_common *priv = dev->priv; + struct p54_control_hdr *hdr; + struct p54_tx_control_allocdata *txhdr; + struct ieee80211_tx_control *control_copy; + size_t padding, len; + u8 rate; + + current_queue = &priv->tx_stats.data[control->queue]; + if (unlikely(current_queue->len > current_queue->limit)) + return NETDEV_TX_BUSY; + current_queue->len++; + current_queue->count++; + if (current_queue->len == current_queue->limit) + ieee80211_stop_queue(dev, control->queue); + + padding = (unsigned long)(skb->data - (sizeof(*hdr) + sizeof(*txhdr))) & 3; + len = skb->len; + + control_copy = kmalloc(sizeof(*control), GFP_ATOMIC); + if (control_copy) + memcpy(control_copy, control, sizeof(*control)); + + txhdr = (struct p54_tx_control_allocdata *) + skb_push(skb, sizeof(*txhdr) + padding); + hdr = (struct p54_control_hdr *) skb_push(skb, sizeof(*hdr)); + + if (padding) + hdr->magic1 = cpu_to_le16(0x4010); + else + hdr->magic1 = cpu_to_le16(0x0010); + hdr->len = cpu_to_le16(len); + hdr->type = (control->flags & IEEE80211_TXCTL_NO_ACK) ? 0 : cpu_to_le16(1); + hdr->retry1 = hdr->retry2 = control->retry_limit; + p54_assign_address(dev, skb, hdr, skb->len, control_copy); + + memset(txhdr->wep_key, 0x0, 16); + txhdr->padding = 0; + txhdr->padding2 = 0; + + /* TODO: add support for alternate retry TX rates */ + rate = control->tx_rate->hw_value; + if (control->flags & IEEE80211_TXCTL_SHORT_PREAMBLE) + rate |= 0x10; + if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS) + rate |= 0x40; + else if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) + rate |= 0x20; + memset(txhdr->rateset, rate, 8); + txhdr->wep_key_present = 0; + txhdr->wep_key_len = 0; + txhdr->frame_type = cpu_to_le32(control->queue + 4); + txhdr->magic4 = 0; + txhdr->antenna = (control->antenna_sel_tx == 0) ? + 2 : control->antenna_sel_tx - 1; + txhdr->output_power = 0x7f; // HW Maximum + txhdr->magic5 = (control->flags & IEEE80211_TXCTL_NO_ACK) ? + 0 : ((rate > 0x3) ? cpu_to_le32(0x33) : cpu_to_le32(0x23)); + if (padding) + txhdr->align[0] = padding; + + priv->tx(dev, hdr, skb->len, 0); + return 0; +} + +static int p54_set_filter(struct ieee80211_hw *dev, u16 filter_type, + const u8 *dst, const u8 *src, u8 antenna, + u32 magic3, u32 magic8, u32 magic9) +{ + struct p54_common *priv = dev->priv; + struct p54_control_hdr *hdr; + struct p54_tx_control_filter *filter; + + hdr = kzalloc(sizeof(*hdr) + sizeof(*filter) + + priv->tx_hdr_len, GFP_ATOMIC); + if (!hdr) + return -ENOMEM; + + hdr = (void *)hdr + priv->tx_hdr_len; + + filter = (struct p54_tx_control_filter *) hdr->data; + hdr->magic1 = cpu_to_le16(0x8001); + hdr->len = cpu_to_le16(sizeof(*filter)); + p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*filter), NULL); + hdr->type = cpu_to_le16(P54_CONTROL_TYPE_FILTER_SET); + + filter->filter_type = cpu_to_le16(filter_type); + memcpy(filter->dst, dst, ETH_ALEN); + if (!src) + memset(filter->src, ~0, ETH_ALEN); + else + memcpy(filter->src, src, ETH_ALEN); + filter->antenna = antenna; + filter->magic3 = cpu_to_le32(magic3); + filter->rx_addr = cpu_to_le32(priv->rx_end); + filter->max_rx = cpu_to_le16(0x0620); /* FIXME: for usb ver 1.. maybe */ + filter->rxhw = priv->rxhw; + filter->magic8 = cpu_to_le16(magic8); + filter->magic9 = cpu_to_le16(magic9); + + priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*filter), 1); + return 0; +} + +static int p54_set_freq(struct ieee80211_hw *dev, __le16 freq) +{ + struct p54_common *priv = dev->priv; + struct p54_control_hdr *hdr; + struct p54_tx_control_channel *chan; + unsigned int i; + size_t payload_len = sizeof(*chan) + sizeof(u32)*2 + + sizeof(*chan->curve_data) * + priv->curve_data->points_per_channel; + void *entry; + + hdr = kzalloc(sizeof(*hdr) + payload_len + + priv->tx_hdr_len, GFP_KERNEL); + if (!hdr) + return -ENOMEM; + + hdr = (void *)hdr + priv->tx_hdr_len; + + chan = (struct p54_tx_control_channel *) hdr->data; + + hdr->magic1 = cpu_to_le16(0x8001); + hdr->len = cpu_to_le16(sizeof(*chan)); + hdr->type = cpu_to_le16(P54_CONTROL_TYPE_CHANNEL_CHANGE); + p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + payload_len, NULL); + + chan->magic1 = cpu_to_le16(0x1); + chan->magic2 = cpu_to_le16(0x0); + + for (i = 0; i < priv->iq_autocal_len; i++) { + if (priv->iq_autocal[i].freq != freq) + continue; + + memcpy(&chan->iq_autocal, &priv->iq_autocal[i], + sizeof(*priv->iq_autocal)); + break; + } + if (i == priv->iq_autocal_len) + goto err; + + for (i = 0; i < priv->output_limit_len; i++) { + if (priv->output_limit[i].freq != freq) + continue; + + chan->val_barker = 0x38; + chan->val_bpsk = priv->output_limit[i].val_bpsk; + chan->val_qpsk = priv->output_limit[i].val_qpsk; + chan->val_16qam = priv->output_limit[i].val_16qam; + chan->val_64qam = priv->output_limit[i].val_64qam; + break; + } + if (i == priv->output_limit_len) + goto err; + + chan->pa_points_per_curve = priv->curve_data->points_per_channel; + + entry = priv->curve_data->data; + for (i = 0; i < priv->curve_data->channels; i++) { + if (*((__le16 *)entry) != freq) { + entry += sizeof(__le16); + entry += sizeof(struct pda_pa_curve_data_sample_rev1) * + chan->pa_points_per_curve; + continue; + } + + entry += sizeof(__le16); + memcpy(chan->curve_data, entry, sizeof(*chan->curve_data) * + chan->pa_points_per_curve); + break; + } + + memcpy(hdr->data + payload_len - 4, &chan->val_bpsk, 4); + + priv->tx(dev, hdr, sizeof(*hdr) + payload_len, 1); + return 0; + + err: + printk(KERN_ERR "%s: frequency change failed\n", wiphy_name(dev->wiphy)); + kfree(hdr); + return -EINVAL; +} + +static int p54_set_leds(struct ieee80211_hw *dev, int mode, int link, int act) +{ + struct p54_common *priv = dev->priv; + struct p54_control_hdr *hdr; + struct p54_tx_control_led *led; + + hdr = kzalloc(sizeof(*hdr) + sizeof(*led) + + priv->tx_hdr_len, GFP_KERNEL); + if (!hdr) + return -ENOMEM; + + hdr = (void *)hdr + priv->tx_hdr_len; + hdr->magic1 = cpu_to_le16(0x8001); + hdr->len = cpu_to_le16(sizeof(*led)); + hdr->type = cpu_to_le16(P54_CONTROL_TYPE_LED); + p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*led), NULL); + + led = (struct p54_tx_control_led *) hdr->data; + led->mode = cpu_to_le16(mode); + led->led_permanent = cpu_to_le16(link); + led->led_temporary = cpu_to_le16(act); + led->duration = cpu_to_le16(1000); + + priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*led), 1); + + return 0; +} + +#define P54_SET_QUEUE(queue, ai_fs, cw_min, cw_max, _txop) \ +do { \ + queue.aifs = cpu_to_le16(ai_fs); \ + queue.cwmin = cpu_to_le16(cw_min); \ + queue.cwmax = cpu_to_le16(cw_max); \ + queue.txop = cpu_to_le16(_txop); \ +} while(0) + +static void p54_init_vdcf(struct ieee80211_hw *dev) +{ + struct p54_common *priv = dev->priv; + struct p54_control_hdr *hdr; + struct p54_tx_control_vdcf *vdcf; + + /* all USB V1 adapters need a extra headroom */ + hdr = (void *)priv->cached_vdcf + priv->tx_hdr_len; + hdr->magic1 = cpu_to_le16(0x8001); + hdr->len = cpu_to_le16(sizeof(*vdcf)); + hdr->type = cpu_to_le16(P54_CONTROL_TYPE_DCFINIT); + hdr->req_id = cpu_to_le32(priv->rx_start); + + vdcf = (struct p54_tx_control_vdcf *) hdr->data; + + P54_SET_QUEUE(vdcf->queue[0], 0x0002, 0x0003, 0x0007, 47); + P54_SET_QUEUE(vdcf->queue[1], 0x0002, 0x0007, 0x000f, 94); + P54_SET_QUEUE(vdcf->queue[2], 0x0003, 0x000f, 0x03ff, 0); + P54_SET_QUEUE(vdcf->queue[3], 0x0007, 0x000f, 0x03ff, 0); +} + +static void p54_set_vdcf(struct ieee80211_hw *dev) +{ + struct p54_common *priv = dev->priv; + struct p54_control_hdr *hdr; + struct p54_tx_control_vdcf *vdcf; + + hdr = (void *)priv->cached_vdcf + priv->tx_hdr_len; + + p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*vdcf), NULL); + + vdcf = (struct p54_tx_control_vdcf *) hdr->data; + + if (dev->conf.flags & IEEE80211_CONF_SHORT_SLOT_TIME) { + vdcf->slottime = 9; + vdcf->magic1 = 0x00; + vdcf->magic2 = 0x10; + } else { + vdcf->slottime = 20; + vdcf->magic1 = 0x0a; + vdcf->magic2 = 0x06; + } + + /* (see prism54/isl_oid.h for further details) */ + vdcf->frameburst = cpu_to_le16(0); + + priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*vdcf), 0); +} + +static int p54_start(struct ieee80211_hw *dev) +{ + struct p54_common *priv = dev->priv; + int err; + + err = priv->open(dev); + if (!err) + priv->mode = IEEE80211_IF_TYPE_MNTR; + + return err; +} + +static void p54_stop(struct ieee80211_hw *dev) +{ + struct p54_common *priv = dev->priv; + struct sk_buff *skb; + while ((skb = skb_dequeue(&priv->tx_queue))) { + struct memrecord *range = (struct memrecord *)&skb->cb; + if (range->control) + kfree(range->control); + kfree_skb(skb); + } + priv->stop(dev); + priv->mode = IEEE80211_IF_TYPE_INVALID; +} + +static int p54_add_interface(struct ieee80211_hw *dev, + struct ieee80211_if_init_conf *conf) +{ + struct p54_common *priv = dev->priv; + + if (priv->mode != IEEE80211_IF_TYPE_MNTR) + return -EOPNOTSUPP; + + switch (conf->type) { + case IEEE80211_IF_TYPE_STA: + priv->mode = conf->type; + break; + default: + return -EOPNOTSUPP; + } + + memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN); + + p54_set_filter(dev, 0, priv->mac_addr, NULL, 0, 1, 0, 0xF642); + p54_set_filter(dev, 0, priv->mac_addr, NULL, 1, 0, 0, 0xF642); + + switch (conf->type) { + case IEEE80211_IF_TYPE_STA: + p54_set_filter(dev, 1, priv->mac_addr, NULL, 0, 0x15F, 0x1F4, 0); + break; + default: + BUG(); /* impossible */ + break; + } + + p54_set_leds(dev, 1, 0, 0); + + return 0; +} + +static void p54_remove_interface(struct ieee80211_hw *dev, + struct ieee80211_if_init_conf *conf) +{ + struct p54_common *priv = dev->priv; + priv->mode = IEEE80211_IF_TYPE_MNTR; + memset(priv->mac_addr, 0, ETH_ALEN); + p54_set_filter(dev, 0, priv->mac_addr, NULL, 2, 0, 0, 0); +} + +static int p54_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf) +{ + int ret; + + ret = p54_set_freq(dev, cpu_to_le16(conf->channel->center_freq)); + p54_set_vdcf(dev); + return ret; +} + +static int p54_config_interface(struct ieee80211_hw *dev, + struct ieee80211_vif *vif, + struct ieee80211_if_conf *conf) +{ + struct p54_common *priv = dev->priv; + + p54_set_filter(dev, 0, priv->mac_addr, conf->bssid, 0, 1, 0, 0xF642); + p54_set_filter(dev, 0, priv->mac_addr, conf->bssid, 2, 0, 0, 0); + p54_set_leds(dev, 1, !is_multicast_ether_addr(conf->bssid), 0); + memcpy(priv->bssid, conf->bssid, ETH_ALEN); + return 0; +} + +static void p54_configure_filter(struct ieee80211_hw *dev, + unsigned int changed_flags, + unsigned int *total_flags, + int mc_count, struct dev_mc_list *mclist) +{ + struct p54_common *priv = dev->priv; + + *total_flags &= FIF_BCN_PRBRESP_PROMISC; + + if (changed_flags & FIF_BCN_PRBRESP_PROMISC) { + if (*total_flags & FIF_BCN_PRBRESP_PROMISC) + p54_set_filter(dev, 0, priv->mac_addr, + NULL, 2, 0, 0, 0); + else + p54_set_filter(dev, 0, priv->mac_addr, + priv->bssid, 2, 0, 0, 0); + } +} + +static int p54_conf_tx(struct ieee80211_hw *dev, int queue, + const struct ieee80211_tx_queue_params *params) +{ + struct p54_common *priv = dev->priv; + struct p54_tx_control_vdcf *vdcf; + + vdcf = (struct p54_tx_control_vdcf *)(((struct p54_control_hdr *) + ((void *)priv->cached_vdcf + priv->tx_hdr_len))->data); + + if ((params) && !((queue < 0) || (queue > 4))) { + P54_SET_QUEUE(vdcf->queue[queue], params->aifs, + params->cw_min, params->cw_max, params->txop); + } else + return -EINVAL; + + p54_set_vdcf(dev); + + return 0; +} + +static int p54_get_stats(struct ieee80211_hw *dev, + struct ieee80211_low_level_stats *stats) +{ + /* TODO */ + return 0; +} + +static int p54_get_tx_stats(struct ieee80211_hw *dev, + struct ieee80211_tx_queue_stats *stats) +{ + struct p54_common *priv = dev->priv; + unsigned int i; + + for (i = 0; i < dev->queues; i++) + memcpy(&stats->data[i], &priv->tx_stats.data[i], + sizeof(stats->data[i])); + + return 0; +} + +static const struct ieee80211_ops p54_ops = { + .tx = p54_tx, + .start = p54_start, + .stop = p54_stop, + .add_interface = p54_add_interface, + .remove_interface = p54_remove_interface, + .config = p54_config, + .config_interface = p54_config_interface, + .configure_filter = p54_configure_filter, + .conf_tx = p54_conf_tx, + .get_stats = p54_get_stats, + .get_tx_stats = p54_get_tx_stats +}; + +struct ieee80211_hw *p54_init_common(size_t priv_data_len) +{ + struct ieee80211_hw *dev; + struct p54_common *priv; + + dev = ieee80211_alloc_hw(priv_data_len, &p54_ops); + if (!dev) + return NULL; + + priv = dev->priv; + priv->mode = IEEE80211_IF_TYPE_INVALID; + skb_queue_head_init(&priv->tx_queue); + dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &band_2GHz; + dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | /* not sure */ + IEEE80211_HW_RX_INCLUDES_FCS; + dev->channel_change_time = 1000; /* TODO: find actual value */ + dev->max_rssi = 127; + + priv->tx_stats.data[0].limit = 5; + dev->queues = 1; + + dev->extra_tx_headroom = sizeof(struct p54_control_hdr) + 4 + + sizeof(struct p54_tx_control_allocdata); + + priv->cached_vdcf = kzalloc(sizeof(struct p54_tx_control_vdcf) + + priv->tx_hdr_len + sizeof(struct p54_control_hdr), GFP_KERNEL); + + if (!priv->cached_vdcf) { + ieee80211_free_hw(dev); + return NULL; + } + + p54_init_vdcf(dev); + + return dev; +} +EXPORT_SYMBOL_GPL(p54_init_common); + +void p54_free_common(struct ieee80211_hw *dev) +{ + struct p54_common *priv = dev->priv; + kfree(priv->iq_autocal); + kfree(priv->output_limit); + kfree(priv->curve_data); + kfree(priv->cached_vdcf); +} +EXPORT_SYMBOL_GPL(p54_free_common); + +static int __init p54_init(void) +{ + return 0; +} + +static void __exit p54_exit(void) +{ +} + +module_init(p54_init); +module_exit(p54_exit); diff --git a/drivers/net/wireless/p54/p54common.h b/drivers/net/wireless/p54/p54common.h new file mode 100644 index 000000000000..c15b56e1d75e --- /dev/null +++ b/drivers/net/wireless/p54/p54common.h @@ -0,0 +1,254 @@ +#ifndef PRISM54COMMON_H +#define PRISM54COMMON_H + +/* + * Common code specific definitions for mac80211 Prism54 drivers + * + * Copyright (c) 2006, Michael Wu + * Copyright (c) 2007, Christian Lamparter + * + * Based on the islsm (softmac prism54) driver, which is: + * Copyright 2004-2006 Jean-Baptiste Note , et al. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +struct bootrec { + __le32 code; + __le32 len; + u32 data[0]; +} __attribute__((packed)); + +struct bootrec_exp_if { + __le16 role; + __le16 if_id; + __le16 variant; + __le16 btm_compat; + __le16 top_compat; +} __attribute__((packed)); + +#define BR_CODE_MIN 0x80000000 +#define BR_CODE_COMPONENT_ID 0x80000001 +#define BR_CODE_COMPONENT_VERSION 0x80000002 +#define BR_CODE_DEPENDENT_IF 0x80000003 +#define BR_CODE_EXPOSED_IF 0x80000004 +#define BR_CODE_DESCR 0x80000101 +#define BR_CODE_MAX 0x8FFFFFFF +#define BR_CODE_END_OF_BRA 0xFF0000FF +#define LEGACY_BR_CODE_END_OF_BRA 0xFFFFFFFF + +#define FW_FMAC 0x464d4143 +#define FW_LM86 0x4c4d3836 +#define FW_LM87 0x4c4d3837 +#define FW_LM20 0x4c4d3230 + +/* PDA defines are Copyright (C) 2005 Nokia Corporation (taken from islsm_pda.h) */ + +struct pda_entry { + __le16 len; /* includes both code and data */ + __le16 code; + u8 data[0]; +} __attribute__ ((packed)); + +struct eeprom_pda_wrap { + __le32 magic; + __le16 pad; + __le16 len; + __le32 arm_opcode; + u8 data[0]; +} __attribute__ ((packed)); + +struct pda_iq_autocal_entry { + __le16 freq; + __le16 iq_param[4]; +} __attribute__ ((packed)); + +struct pda_channel_output_limit { + __le16 freq; + u8 val_bpsk; + u8 val_qpsk; + u8 val_16qam; + u8 val_64qam; + u8 rate_set_mask; + u8 rate_set_size; +} __attribute__ ((packed)); + +struct pda_pa_curve_data_sample_rev0 { + u8 rf_power; + u8 pa_detector; + u8 pcv; +} __attribute__ ((packed)); + +struct pda_pa_curve_data_sample_rev1 { + u8 rf_power; + u8 pa_detector; + u8 data_barker; + u8 data_bpsk; + u8 data_qpsk; + u8 data_16qam; + u8 data_64qam; + u8 padding; +} __attribute__ ((packed)); + +struct pda_pa_curve_data { + u8 cal_method_rev; + u8 channels; + u8 points_per_channel; + u8 padding; + u8 data[0]; +} __attribute__ ((packed)); + +/* + * this defines the PDR codes used to build PDAs as defined in document + * number 553155. The current implementation mirrors version 1.1 of the + * document and lists only PDRs supported by the ARM platform. + */ + +/* common and choice range (0x0000 - 0x0fff) */ +#define PDR_END 0x0000 +#define PDR_MANUFACTURING_PART_NUMBER 0x0001 +#define PDR_PDA_VERSION 0x0002 +#define PDR_NIC_SERIAL_NUMBER 0x0003 + +#define PDR_MAC_ADDRESS 0x0101 +#define PDR_REGULATORY_DOMAIN_LIST 0x0103 +#define PDR_TEMPERATURE_TYPE 0x0107 + +#define PDR_PRISM_PCI_IDENTIFIER 0x0402 + +/* ARM range (0x1000 - 0x1fff) */ +#define PDR_COUNTRY_INFORMATION 0x1000 +#define PDR_INTERFACE_LIST 0x1001 +#define PDR_HARDWARE_PLATFORM_COMPONENT_ID 0x1002 +#define PDR_OEM_NAME 0x1003 +#define PDR_PRODUCT_NAME 0x1004 +#define PDR_UTF8_OEM_NAME 0x1005 +#define PDR_UTF8_PRODUCT_NAME 0x1006 +#define PDR_COUNTRY_LIST 0x1007 +#define PDR_DEFAULT_COUNTRY 0x1008 + +#define PDR_ANTENNA_GAIN 0x1100 + +#define PDR_PRISM_INDIGO_PA_CALIBRATION_DATA 0x1901 +#define PDR_RSSI_LINEAR_APPROXIMATION 0x1902 +#define PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS 0x1903 +#define PDR_PRISM_PA_CAL_CURVE_DATA 0x1904 +#define PDR_RSSI_LINEAR_APPROXIMATION_DUAL_BAND 0x1905 +#define PDR_PRISM_ZIF_TX_IQ_CALIBRATION 0x1906 +#define PDR_REGULATORY_POWER_LIMITS 0x1907 +#define PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED 0x1908 +#define PDR_RADIATED_TRANSMISSION_CORRECTION 0x1909 +#define PDR_PRISM_TX_IQ_CALIBRATION 0x190a + +/* reserved range (0x2000 - 0x7fff) */ + +/* customer range (0x8000 - 0xffff) */ +#define PDR_BASEBAND_REGISTERS 0x8000 +#define PDR_PER_CHANNEL_BASEBAND_REGISTERS 0x8001 + +/* stored in skb->cb */ +struct memrecord { + u32 start_addr; + u32 end_addr; + struct ieee80211_tx_control *control; +}; + +struct p54_eeprom_lm86 { + __le16 offset; + __le16 len; + u8 data[0]; +} __attribute__ ((packed)); + +struct p54_rx_hdr { + __le16 magic; + __le16 len; + __le16 freq; + u8 antenna; + u8 rate; + u8 rssi; + u8 quality; + u16 unknown2; + __le64 timestamp; + u8 data[0]; +} __attribute__ ((packed)); + +struct p54_frame_sent_hdr { + u8 status; + u8 retries; + __le16 ack_rssi; + __le16 seq; + u16 rate; +} __attribute__ ((packed)); + +struct p54_tx_control_allocdata { + u8 rateset[8]; + u16 padding; + u8 wep_key_present; + u8 wep_key_len; + u8 wep_key[16]; + __le32 frame_type; + u32 padding2; + __le16 magic4; + u8 antenna; + u8 output_power; + __le32 magic5; + u8 align[0]; +} __attribute__ ((packed)); + +struct p54_tx_control_filter { + __le16 filter_type; + u8 dst[ETH_ALEN]; + u8 src[ETH_ALEN]; + u8 antenna; + u8 debug; + __le32 magic3; + u8 rates[8]; // FIXME: what's this for? + __le32 rx_addr; + __le16 max_rx; + __le16 rxhw; + __le16 magic8; + __le16 magic9; +} __attribute__ ((packed)); + +struct p54_tx_control_channel { + __le16 magic1; + __le16 magic2; + u8 padding1[20]; + struct pda_iq_autocal_entry iq_autocal; + u8 pa_points_per_curve; + u8 val_barker; + u8 val_bpsk; + u8 val_qpsk; + u8 val_16qam; + u8 val_64qam; + struct pda_pa_curve_data_sample_rev1 curve_data[0]; + /* additional padding/data after curve_data */ +} __attribute__ ((packed)); + +struct p54_tx_control_led { + __le16 mode; + __le16 led_temporary; + __le16 led_permanent; + __le16 duration; +} __attribute__ ((packed)); + +struct p54_tx_vdcf_queues { + __le16 aifs; + __le16 cwmin; + __le16 cwmax; + __le16 txop; +} __attribute__ ((packed)); + +struct p54_tx_control_vdcf { + u8 padding; + u8 slottime; + u8 magic1; + u8 magic2; + struct p54_tx_vdcf_queues queue[8]; + u8 pad2[4]; + __le16 frameburst; +} __attribute__ ((packed)); + +#endif /* PRISM54COMMON_H */ diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c new file mode 100644 index 000000000000..fa527723fbe0 --- /dev/null +++ b/drivers/net/wireless/p54/p54pci.c @@ -0,0 +1,697 @@ + +/* + * Linux device driver for PCI based Prism54 + * + * Copyright (c) 2006, Michael Wu + * + * Based on the islsm (softmac prism54) driver, which is: + * Copyright 2004-2006 Jean-Baptiste Note , et al. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "p54.h" +#include "p54pci.h" + +MODULE_AUTHOR("Michael Wu "); +MODULE_DESCRIPTION("Prism54 PCI wireless driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("prism54pci"); + +static struct pci_device_id p54p_table[] __devinitdata = { + /* Intersil PRISM Duette/Prism GT Wireless LAN adapter */ + { PCI_DEVICE(0x1260, 0x3890) }, + /* 3COM 3CRWE154G72 Wireless LAN adapter */ + { PCI_DEVICE(0x10b7, 0x6001) }, + /* Intersil PRISM Indigo Wireless LAN adapter */ + { PCI_DEVICE(0x1260, 0x3877) }, + /* Intersil PRISM Javelin/Xbow Wireless LAN adapter */ + { PCI_DEVICE(0x1260, 0x3886) }, + { }, +}; + +MODULE_DEVICE_TABLE(pci, p54p_table); + +static int p54p_upload_firmware(struct ieee80211_hw *dev) +{ + struct p54p_priv *priv = dev->priv; + const struct firmware *fw_entry = NULL; + __le32 reg; + int err; + __le32 *data; + u32 remains, left, device_addr; + + P54P_WRITE(int_enable, cpu_to_le32(0)); + P54P_READ(int_enable); + udelay(10); + + reg = P54P_READ(ctrl_stat); + reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET); + reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RAMBOOT); + P54P_WRITE(ctrl_stat, reg); + P54P_READ(ctrl_stat); + udelay(10); + + reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RESET); + P54P_WRITE(ctrl_stat, reg); + wmb(); + udelay(10); + + reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET); + P54P_WRITE(ctrl_stat, reg); + wmb(); + + mdelay(50); + + err = request_firmware(&fw_entry, "isl3886", &priv->pdev->dev); + if (err) { + printk(KERN_ERR "%s (prism54pci): cannot find firmware " + "(isl3886)\n", pci_name(priv->pdev)); + return err; + } + + p54_parse_firmware(dev, fw_entry); + + data = (__le32 *) fw_entry->data; + remains = fw_entry->size; + device_addr = ISL38XX_DEV_FIRMWARE_ADDR; + while (remains) { + u32 i = 0; + left = min((u32)0x1000, remains); + P54P_WRITE(direct_mem_base, cpu_to_le32(device_addr)); + P54P_READ(int_enable); + + device_addr += 0x1000; + while (i < left) { + P54P_WRITE(direct_mem_win[i], *data++); + i += sizeof(u32); + } + + remains -= left; + P54P_READ(int_enable); + } + + release_firmware(fw_entry); + + reg = P54P_READ(ctrl_stat); + reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_CLKRUN); + reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET); + reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RAMBOOT); + P54P_WRITE(ctrl_stat, reg); + P54P_READ(ctrl_stat); + udelay(10); + + reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RESET); + P54P_WRITE(ctrl_stat, reg); + wmb(); + udelay(10); + + reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET); + P54P_WRITE(ctrl_stat, reg); + wmb(); + udelay(10); + + return 0; +} + +static irqreturn_t p54p_simple_interrupt(int irq, void *dev_id) +{ + struct p54p_priv *priv = (struct p54p_priv *) dev_id; + __le32 reg; + + reg = P54P_READ(int_ident); + P54P_WRITE(int_ack, reg); + + if (reg & P54P_READ(int_enable)) + complete(&priv->boot_comp); + + return IRQ_HANDLED; +} + +static int p54p_read_eeprom(struct ieee80211_hw *dev) +{ + struct p54p_priv *priv = dev->priv; + struct p54p_ring_control *ring_control = priv->ring_control; + int err; + struct p54_control_hdr *hdr; + void *eeprom; + dma_addr_t rx_mapping, tx_mapping; + u16 alen; + + init_completion(&priv->boot_comp); + err = request_irq(priv->pdev->irq, &p54p_simple_interrupt, + IRQF_SHARED, "prism54pci", priv); + if (err) { + printk(KERN_ERR "%s (prism54pci): failed to register IRQ handler\n", + pci_name(priv->pdev)); + return err; + } + + eeprom = kmalloc(0x2010 + EEPROM_READBACK_LEN, GFP_KERNEL); + if (!eeprom) { + printk(KERN_ERR "%s (prism54pci): no memory for eeprom!\n", + pci_name(priv->pdev)); + err = -ENOMEM; + goto out; + } + + memset(ring_control, 0, sizeof(*ring_control)); + P54P_WRITE(ring_control_base, cpu_to_le32(priv->ring_control_dma)); + P54P_READ(ring_control_base); + udelay(10); + + P54P_WRITE(int_enable, cpu_to_le32(ISL38XX_INT_IDENT_INIT)); + P54P_READ(int_enable); + udelay(10); + + P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET)); + + if (!wait_for_completion_interruptible_timeout(&priv->boot_comp, HZ)) { + printk(KERN_ERR "%s (prism54pci): Cannot boot firmware!\n", + pci_name(priv->pdev)); + err = -EINVAL; + goto out; + } + + P54P_WRITE(int_enable, cpu_to_le32(ISL38XX_INT_IDENT_UPDATE)); + P54P_READ(int_enable); + + hdr = eeprom + 0x2010; + p54_fill_eeprom_readback(hdr); + hdr->req_id = cpu_to_le32(priv->common.rx_start); + + rx_mapping = pci_map_single(priv->pdev, eeprom, + 0x2010, PCI_DMA_FROMDEVICE); + tx_mapping = pci_map_single(priv->pdev, (void *)hdr, + EEPROM_READBACK_LEN, PCI_DMA_TODEVICE); + + ring_control->rx_mgmt[0].host_addr = cpu_to_le32(rx_mapping); + ring_control->rx_mgmt[0].len = cpu_to_le16(0x2010); + ring_control->tx_data[0].host_addr = cpu_to_le32(tx_mapping); + ring_control->tx_data[0].device_addr = hdr->req_id; + ring_control->tx_data[0].len = cpu_to_le16(EEPROM_READBACK_LEN); + + ring_control->host_idx[2] = cpu_to_le32(1); + ring_control->host_idx[1] = cpu_to_le32(1); + + wmb(); + mdelay(100); + P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE)); + + wait_for_completion_interruptible_timeout(&priv->boot_comp, HZ); + wait_for_completion_interruptible_timeout(&priv->boot_comp, HZ); + + pci_unmap_single(priv->pdev, tx_mapping, + EEPROM_READBACK_LEN, PCI_DMA_TODEVICE); + pci_unmap_single(priv->pdev, rx_mapping, + 0x2010, PCI_DMA_FROMDEVICE); + + alen = le16_to_cpu(ring_control->rx_mgmt[0].len); + if (le32_to_cpu(ring_control->device_idx[2]) != 1 || + alen < 0x10) { + printk(KERN_ERR "%s (prism54pci): Cannot read eeprom!\n", + pci_name(priv->pdev)); + err = -EINVAL; + goto out; + } + + p54_parse_eeprom(dev, (u8 *)eeprom + 0x10, alen - 0x10); + + out: + kfree(eeprom); + P54P_WRITE(int_enable, cpu_to_le32(0)); + P54P_READ(int_enable); + udelay(10); + free_irq(priv->pdev->irq, priv); + P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET)); + return err; +} + +static void p54p_refill_rx_ring(struct ieee80211_hw *dev) +{ + struct p54p_priv *priv = dev->priv; + struct p54p_ring_control *ring_control = priv->ring_control; + u32 limit, host_idx, idx; + + host_idx = le32_to_cpu(ring_control->host_idx[0]); + limit = host_idx; + limit -= le32_to_cpu(ring_control->device_idx[0]); + limit = ARRAY_SIZE(ring_control->rx_data) - limit; + + idx = host_idx % ARRAY_SIZE(ring_control->rx_data); + while (limit-- > 1) { + struct p54p_desc *desc = &ring_control->rx_data[idx]; + + if (!desc->host_addr) { + struct sk_buff *skb; + dma_addr_t mapping; + skb = dev_alloc_skb(MAX_RX_SIZE); + if (!skb) + break; + + mapping = pci_map_single(priv->pdev, + skb_tail_pointer(skb), + MAX_RX_SIZE, + PCI_DMA_FROMDEVICE); + desc->host_addr = cpu_to_le32(mapping); + desc->device_addr = 0; // FIXME: necessary? + desc->len = cpu_to_le16(MAX_RX_SIZE); + desc->flags = 0; + priv->rx_buf[idx] = skb; + } + + idx++; + host_idx++; + idx %= ARRAY_SIZE(ring_control->rx_data); + } + + wmb(); + ring_control->host_idx[0] = cpu_to_le32(host_idx); +} + +static irqreturn_t p54p_interrupt(int irq, void *dev_id) +{ + struct ieee80211_hw *dev = dev_id; + struct p54p_priv *priv = dev->priv; + struct p54p_ring_control *ring_control = priv->ring_control; + __le32 reg; + + spin_lock(&priv->lock); + reg = P54P_READ(int_ident); + if (unlikely(reg == cpu_to_le32(0xFFFFFFFF))) { + spin_unlock(&priv->lock); + return IRQ_HANDLED; + } + + P54P_WRITE(int_ack, reg); + + reg &= P54P_READ(int_enable); + + if (reg & cpu_to_le32(ISL38XX_INT_IDENT_UPDATE)) { + struct p54p_desc *desc; + u32 idx, i; + i = priv->tx_idx; + i %= ARRAY_SIZE(ring_control->tx_data); + priv->tx_idx = idx = le32_to_cpu(ring_control->device_idx[1]); + idx %= ARRAY_SIZE(ring_control->tx_data); + + while (i != idx) { + desc = &ring_control->tx_data[i]; + if (priv->tx_buf[i]) { + kfree(priv->tx_buf[i]); + priv->tx_buf[i] = NULL; + } + + pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr), + le16_to_cpu(desc->len), PCI_DMA_TODEVICE); + + desc->host_addr = 0; + desc->device_addr = 0; + desc->len = 0; + desc->flags = 0; + + i++; + i %= ARRAY_SIZE(ring_control->tx_data); + } + + i = priv->rx_idx; + i %= ARRAY_SIZE(ring_control->rx_data); + priv->rx_idx = idx = le32_to_cpu(ring_control->device_idx[0]); + idx %= ARRAY_SIZE(ring_control->rx_data); + while (i != idx) { + u16 len; + struct sk_buff *skb; + desc = &ring_control->rx_data[i]; + len = le16_to_cpu(desc->len); + skb = priv->rx_buf[i]; + + skb_put(skb, len); + + if (p54_rx(dev, skb)) { + pci_unmap_single(priv->pdev, + le32_to_cpu(desc->host_addr), + MAX_RX_SIZE, PCI_DMA_FROMDEVICE); + + priv->rx_buf[i] = NULL; + desc->host_addr = 0; + } else { + skb_trim(skb, 0); + desc->len = cpu_to_le16(MAX_RX_SIZE); + } + + i++; + i %= ARRAY_SIZE(ring_control->rx_data); + } + + p54p_refill_rx_ring(dev); + + wmb(); + P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE)); + } else if (reg & cpu_to_le32(ISL38XX_INT_IDENT_INIT)) + complete(&priv->boot_comp); + + spin_unlock(&priv->lock); + + return reg ? IRQ_HANDLED : IRQ_NONE; +} + +static void p54p_tx(struct ieee80211_hw *dev, struct p54_control_hdr *data, + size_t len, int free_on_tx) +{ + struct p54p_priv *priv = dev->priv; + struct p54p_ring_control *ring_control = priv->ring_control; + unsigned long flags; + struct p54p_desc *desc; + dma_addr_t mapping; + u32 device_idx, idx, i; + + spin_lock_irqsave(&priv->lock, flags); + + device_idx = le32_to_cpu(ring_control->device_idx[1]); + idx = le32_to_cpu(ring_control->host_idx[1]); + i = idx % ARRAY_SIZE(ring_control->tx_data); + + mapping = pci_map_single(priv->pdev, data, len, PCI_DMA_TODEVICE); + desc = &ring_control->tx_data[i]; + desc->host_addr = cpu_to_le32(mapping); + desc->device_addr = data->req_id; + desc->len = cpu_to_le16(len); + desc->flags = 0; + + wmb(); + ring_control->host_idx[1] = cpu_to_le32(idx + 1); + + if (free_on_tx) + priv->tx_buf[i] = data; + + spin_unlock_irqrestore(&priv->lock, flags); + + P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE)); + P54P_READ(dev_int); + + /* FIXME: unlikely to happen because the device usually runs out of + memory before we fill the ring up, but we can make it impossible */ + if (idx - device_idx > ARRAY_SIZE(ring_control->tx_data) - 2) + printk(KERN_INFO "%s: tx overflow.\n", wiphy_name(dev->wiphy)); +} + +static int p54p_open(struct ieee80211_hw *dev) +{ + struct p54p_priv *priv = dev->priv; + int err; + + init_completion(&priv->boot_comp); + err = request_irq(priv->pdev->irq, &p54p_interrupt, + IRQF_SHARED, "prism54pci", dev); + if (err) { + printk(KERN_ERR "%s: failed to register IRQ handler\n", + wiphy_name(dev->wiphy)); + return err; + } + + memset(priv->ring_control, 0, sizeof(*priv->ring_control)); + priv->rx_idx = priv->tx_idx = 0; + p54p_refill_rx_ring(dev); + + p54p_upload_firmware(dev); + + P54P_WRITE(ring_control_base, cpu_to_le32(priv->ring_control_dma)); + P54P_READ(ring_control_base); + wmb(); + udelay(10); + + P54P_WRITE(int_enable, cpu_to_le32(ISL38XX_INT_IDENT_INIT)); + P54P_READ(int_enable); + wmb(); + udelay(10); + + P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET)); + P54P_READ(dev_int); + + if (!wait_for_completion_interruptible_timeout(&priv->boot_comp, HZ)) { + printk(KERN_ERR "%s: Cannot boot firmware!\n", + wiphy_name(dev->wiphy)); + free_irq(priv->pdev->irq, dev); + return -ETIMEDOUT; + } + + P54P_WRITE(int_enable, cpu_to_le32(ISL38XX_INT_IDENT_UPDATE)); + P54P_READ(int_enable); + wmb(); + udelay(10); + + P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE)); + P54P_READ(dev_int); + wmb(); + udelay(10); + + return 0; +} + +static void p54p_stop(struct ieee80211_hw *dev) +{ + struct p54p_priv *priv = dev->priv; + struct p54p_ring_control *ring_control = priv->ring_control; + unsigned int i; + struct p54p_desc *desc; + + P54P_WRITE(int_enable, cpu_to_le32(0)); + P54P_READ(int_enable); + udelay(10); + + free_irq(priv->pdev->irq, dev); + + P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET)); + + for (i = 0; i < ARRAY_SIZE(priv->rx_buf); i++) { + desc = &ring_control->rx_data[i]; + if (desc->host_addr) + pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr), + MAX_RX_SIZE, PCI_DMA_FROMDEVICE); + kfree_skb(priv->rx_buf[i]); + priv->rx_buf[i] = NULL; + } + + for (i = 0; i < ARRAY_SIZE(priv->tx_buf); i++) { + desc = &ring_control->tx_data[i]; + if (desc->host_addr) + pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr), + le16_to_cpu(desc->len), PCI_DMA_TODEVICE); + + kfree(priv->tx_buf[i]); + priv->tx_buf[i] = NULL; + } + + memset(ring_control, 0, sizeof(ring_control)); +} + +static int __devinit p54p_probe(struct pci_dev *pdev, + const struct pci_device_id *id) +{ + struct p54p_priv *priv; + struct ieee80211_hw *dev; + unsigned long mem_addr, mem_len; + int err; + DECLARE_MAC_BUF(mac); + + err = pci_enable_device(pdev); + if (err) { + printk(KERN_ERR "%s (prism54pci): Cannot enable new PCI device\n", + pci_name(pdev)); + return err; + } + + mem_addr = pci_resource_start(pdev, 0); + mem_len = pci_resource_len(pdev, 0); + if (mem_len < sizeof(struct p54p_csr)) { + printk(KERN_ERR "%s (prism54pci): Too short PCI resources\n", + pci_name(pdev)); + pci_disable_device(pdev); + return err; + } + + err = pci_request_regions(pdev, "prism54pci"); + if (err) { + printk(KERN_ERR "%s (prism54pci): Cannot obtain PCI resources\n", + pci_name(pdev)); + return err; + } + + if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) || + pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) { + printk(KERN_ERR "%s (prism54pci): No suitable DMA available\n", + pci_name(pdev)); + goto err_free_reg; + } + + pci_set_master(pdev); + pci_try_set_mwi(pdev); + + pci_write_config_byte(pdev, 0x40, 0); + pci_write_config_byte(pdev, 0x41, 0); + + dev = p54_init_common(sizeof(*priv)); + if (!dev) { + printk(KERN_ERR "%s (prism54pci): ieee80211 alloc failed\n", + pci_name(pdev)); + err = -ENOMEM; + goto err_free_reg; + } + + priv = dev->priv; + priv->pdev = pdev; + + SET_IEEE80211_DEV(dev, &pdev->dev); + pci_set_drvdata(pdev, dev); + + priv->map = ioremap(mem_addr, mem_len); + if (!priv->map) { + printk(KERN_ERR "%s (prism54pci): Cannot map device memory\n", + pci_name(pdev)); + err = -EINVAL; // TODO: use a better error code? + goto err_free_dev; + } + + priv->ring_control = pci_alloc_consistent(pdev, sizeof(*priv->ring_control), + &priv->ring_control_dma); + if (!priv->ring_control) { + printk(KERN_ERR "%s (prism54pci): Cannot allocate rings\n", + pci_name(pdev)); + err = -ENOMEM; + goto err_iounmap; + } + memset(priv->ring_control, 0, sizeof(*priv->ring_control)); + + err = p54p_upload_firmware(dev); + if (err) + goto err_free_desc; + + err = p54p_read_eeprom(dev); + if (err) + goto err_free_desc; + + priv->common.open = p54p_open; + priv->common.stop = p54p_stop; + priv->common.tx = p54p_tx; + + spin_lock_init(&priv->lock); + + err = ieee80211_register_hw(dev); + if (err) { + printk(KERN_ERR "%s (prism54pci): Cannot register netdevice\n", + pci_name(pdev)); + goto err_free_common; + } + + printk(KERN_INFO "%s: hwaddr %s, isl38%02x\n", + wiphy_name(dev->wiphy), + print_mac(mac, dev->wiphy->perm_addr), + priv->common.version); + + return 0; + + err_free_common: + p54_free_common(dev); + + err_free_desc: + pci_free_consistent(pdev, sizeof(*priv->ring_control), + priv->ring_control, priv->ring_control_dma); + + err_iounmap: + iounmap(priv->map); + + err_free_dev: + pci_set_drvdata(pdev, NULL); + ieee80211_free_hw(dev); + + err_free_reg: + pci_release_regions(pdev); + pci_disable_device(pdev); + return err; +} + +static void __devexit p54p_remove(struct pci_dev *pdev) +{ + struct ieee80211_hw *dev = pci_get_drvdata(pdev); + struct p54p_priv *priv; + + if (!dev) + return; + + ieee80211_unregister_hw(dev); + priv = dev->priv; + pci_free_consistent(pdev, sizeof(*priv->ring_control), + priv->ring_control, priv->ring_control_dma); + p54_free_common(dev); + iounmap(priv->map); + pci_release_regions(pdev); + pci_disable_device(pdev); + ieee80211_free_hw(dev); +} + +#ifdef CONFIG_PM +static int p54p_suspend(struct pci_dev *pdev, pm_message_t state) +{ + struct ieee80211_hw *dev = pci_get_drvdata(pdev); + struct p54p_priv *priv = dev->priv; + + if (priv->common.mode != IEEE80211_IF_TYPE_INVALID) { + ieee80211_stop_queues(dev); + p54p_stop(dev); + } + + pci_save_state(pdev); + pci_set_power_state(pdev, pci_choose_state(pdev, state)); + return 0; +} + +static int p54p_resume(struct pci_dev *pdev) +{ + struct ieee80211_hw *dev = pci_get_drvdata(pdev); + struct p54p_priv *priv = dev->priv; + + pci_set_power_state(pdev, PCI_D0); + pci_restore_state(pdev); + + if (priv->common.mode != IEEE80211_IF_TYPE_INVALID) { + p54p_open(dev); + ieee80211_start_queues(dev); + } + + return 0; +} +#endif /* CONFIG_PM */ + +static struct pci_driver p54p_driver = { + .name = "prism54pci", + .id_table = p54p_table, + .probe = p54p_probe, + .remove = __devexit_p(p54p_remove), +#ifdef CONFIG_PM + .suspend = p54p_suspend, + .resume = p54p_resume, +#endif /* CONFIG_PM */ +}; + +static int __init p54p_init(void) +{ + return pci_register_driver(&p54p_driver); +} + +static void __exit p54p_exit(void) +{ + pci_unregister_driver(&p54p_driver); +} + +module_init(p54p_init); +module_exit(p54p_exit); diff --git a/drivers/net/wireless/p54/p54pci.h b/drivers/net/wireless/p54/p54pci.h new file mode 100644 index 000000000000..5bedd7af385d --- /dev/null +++ b/drivers/net/wireless/p54/p54pci.h @@ -0,0 +1,106 @@ +#ifndef PRISM54PCI_H +#define PRISM54PCI_H + +/* + * Defines for PCI based mac80211 Prism54 driver + * + * Copyright (c) 2006, Michael Wu + * + * Based on the islsm (softmac prism54) driver, which is: + * Copyright 2004-2006 Jean-Baptiste Note , et al. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/* Device Interrupt register bits */ +#define ISL38XX_DEV_INT_RESET 0x0001 +#define ISL38XX_DEV_INT_UPDATE 0x0002 +#define ISL38XX_DEV_INT_WAKEUP 0x0008 +#define ISL38XX_DEV_INT_SLEEP 0x0010 +#define ISL38XX_DEV_INT_ABORT 0x0020 +/* these two only used in USB */ +#define ISL38XX_DEV_INT_DATA 0x0040 +#define ISL38XX_DEV_INT_MGMT 0x0080 + +#define ISL38XX_DEV_INT_PCIUART_CTS 0x4000 +#define ISL38XX_DEV_INT_PCIUART_DR 0x8000 + +/* Interrupt Identification/Acknowledge/Enable register bits */ +#define ISL38XX_INT_IDENT_UPDATE 0x0002 +#define ISL38XX_INT_IDENT_INIT 0x0004 +#define ISL38XX_INT_IDENT_WAKEUP 0x0008 +#define ISL38XX_INT_IDENT_SLEEP 0x0010 +#define ISL38XX_INT_IDENT_PCIUART_CTS 0x4000 +#define ISL38XX_INT_IDENT_PCIUART_DR 0x8000 + +/* Control/Status register bits */ +#define ISL38XX_CTRL_STAT_SLEEPMODE 0x00000200 +#define ISL38XX_CTRL_STAT_CLKRUN 0x00800000 +#define ISL38XX_CTRL_STAT_RESET 0x10000000 +#define ISL38XX_CTRL_STAT_RAMBOOT 0x20000000 +#define ISL38XX_CTRL_STAT_STARTHALTED 0x40000000 +#define ISL38XX_CTRL_STAT_HOST_OVERRIDE 0x80000000 + +struct p54p_csr { + __le32 dev_int; + u8 unused_1[12]; + __le32 int_ident; + __le32 int_ack; + __le32 int_enable; + u8 unused_2[4]; + union { + __le32 ring_control_base; + __le32 gen_purp_com[2]; + }; + u8 unused_3[8]; + __le32 direct_mem_base; + u8 unused_4[44]; + __le32 dma_addr; + __le32 dma_len; + __le32 dma_ctrl; + u8 unused_5[12]; + __le32 ctrl_stat; + u8 unused_6[1924]; + u8 cardbus_cis[0x800]; + u8 direct_mem_win[0x1000]; +} __attribute__ ((packed)); + +/* usb backend only needs the register defines above */ +#ifndef PRISM54USB_H +struct p54p_desc { + __le32 host_addr; + __le32 device_addr; + __le16 len; + __le16 flags; +} __attribute__ ((packed)); + +struct p54p_ring_control { + __le32 host_idx[4]; + __le32 device_idx[4]; + struct p54p_desc rx_data[8]; + struct p54p_desc tx_data[32]; + struct p54p_desc rx_mgmt[4]; + struct p54p_desc tx_mgmt[4]; +} __attribute__ ((packed)); + +#define P54P_READ(r) (__force __le32)__raw_readl(&priv->map->r) +#define P54P_WRITE(r, val) __raw_writel((__force u32)(__le32)(val), &priv->map->r) + +struct p54p_priv { + struct p54_common common; + struct pci_dev *pdev; + struct p54p_csr __iomem *map; + + spinlock_t lock; + struct p54p_ring_control *ring_control; + dma_addr_t ring_control_dma; + u32 rx_idx, tx_idx; + struct sk_buff *rx_buf[8]; + void *tx_buf[32]; + struct completion boot_comp; +}; + +#endif /* PRISM54USB_H */ +#endif /* PRISM54PCI_H */ diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c new file mode 100644 index 000000000000..98ddbb3b3273 --- /dev/null +++ b/drivers/net/wireless/p54/p54usb.c @@ -0,0 +1,910 @@ + +/* + * Linux device driver for USB based Prism54 + * + * Copyright (c) 2006, Michael Wu + * + * Based on the islsm (softmac prism54) driver, which is: + * Copyright 2004-2006 Jean-Baptiste Note , et al. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "p54.h" +#include "p54usb.h" + +MODULE_AUTHOR("Michael Wu "); +MODULE_DESCRIPTION("Prism54 USB wireless driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("prism54usb"); + +static struct usb_device_id p54u_table[] __devinitdata = { + /* Version 1 devices (pci chip + net2280) */ + {USB_DEVICE(0x0506, 0x0a11)}, /* 3COM 3CRWE254G72 */ + {USB_DEVICE(0x0707, 0xee06)}, /* SMC 2862W-G */ + {USB_DEVICE(0x083a, 0x4501)}, /* Accton 802.11g WN4501 USB */ + {USB_DEVICE(0x083a, 0x4502)}, /* Siemens Gigaset USB Adapter */ + {USB_DEVICE(0x083a, 0x5501)}, /* Phillips CPWUA054 */ + {USB_DEVICE(0x0846, 0x4200)}, /* Netgear WG121 */ + {USB_DEVICE(0x0846, 0x4210)}, /* Netgear WG121 the second ? */ + {USB_DEVICE(0x0846, 0x4220)}, /* Netgear WG111 */ + {USB_DEVICE(0x0cde, 0x0006)}, /* Medion 40900, Roper Europe */ + {USB_DEVICE(0x124a, 0x4023)}, /* Shuttle PN15, Airvast WM168g, IOGear GWU513 */ + {USB_DEVICE(0x1915, 0x2234)}, /* Linksys WUSB54G OEM */ + {USB_DEVICE(0x1915, 0x2235)}, /* Linksys WUSB54G Portable OEM */ + {USB_DEVICE(0x2001, 0x3701)}, /* DLink DWL-G120 Spinnaker */ + {USB_DEVICE(0x2001, 0x3703)}, /* DLink DWL-G122 */ + {USB_DEVICE(0x5041, 0x2234)}, /* Linksys WUSB54G */ + {USB_DEVICE(0x5041, 0x2235)}, /* Linksys WUSB54G Portable */ + + /* Version 2 devices (3887) */ + {USB_DEVICE(0x050d, 0x7050)}, /* Belkin F5D7050 ver 1000 */ + {USB_DEVICE(0x0572, 0x2000)}, /* Cohiba Proto board */ + {USB_DEVICE(0x0572, 0x2002)}, /* Cohiba Proto board */ + {USB_DEVICE(0x0707, 0xee13)}, /* SMC 2862W-G version 2 */ + {USB_DEVICE(0x083a, 0x4521)}, /* Siemens Gigaset USB Adapter 54 version 2 */ + {USB_DEVICE(0x0846, 0x4240)}, /* Netgear WG111 (v2) */ + {USB_DEVICE(0x0915, 0x2000)}, /* Cohiba Proto board */ + {USB_DEVICE(0x0915, 0x2002)}, /* Cohiba Proto board */ + {USB_DEVICE(0x0baf, 0x0118)}, /* U.S. Robotics U5 802.11g Adapter*/ + {USB_DEVICE(0x0bf8, 0x1009)}, /* FUJITSU E-5400 USB D1700*/ + {USB_DEVICE(0x0cde, 0x0006)}, /* Medion MD40900 */ + {USB_DEVICE(0x0cde, 0x0008)}, /* Sagem XG703A */ + {USB_DEVICE(0x0d8e, 0x3762)}, /* DLink DWL-G120 Cohiba */ + {USB_DEVICE(0x09aa, 0x1000)}, /* Spinnaker Proto board */ + {USB_DEVICE(0x124a, 0x4025)}, /* IOGear GWU513 (GW3887IK chip) */ + {USB_DEVICE(0x13b1, 0x000a)}, /* Linksys WUSB54G ver 2 */ + {USB_DEVICE(0x13B1, 0x000C)}, /* Linksys WUSB54AG */ + {USB_DEVICE(0x1435, 0x0427)}, /* Inventel UR054G */ + {USB_DEVICE(0x2001, 0x3704)}, /* DLink DWL-G122 rev A2 */ + {USB_DEVICE(0x413c, 0x8102)}, /* Spinnaker DUT */ + {USB_DEVICE(0x413c, 0x8104)}, /* Cohiba Proto board */ + {} +}; + +MODULE_DEVICE_TABLE(usb, p54u_table); + +static void p54u_rx_cb(struct urb *urb) +{ + struct sk_buff *skb = (struct sk_buff *) urb->context; + struct p54u_rx_info *info = (struct p54u_rx_info *)skb->cb; + struct ieee80211_hw *dev = info->dev; + struct p54u_priv *priv = dev->priv; + + if (unlikely(urb->status)) { + info->urb = NULL; + usb_free_urb(urb); + return; + } + + skb_unlink(skb, &priv->rx_queue); + skb_put(skb, urb->actual_length); + if (!priv->hw_type) + skb_pull(skb, sizeof(struct net2280_tx_hdr)); + + if (p54_rx(dev, skb)) { + skb = dev_alloc_skb(MAX_RX_SIZE); + if (unlikely(!skb)) { + usb_free_urb(urb); + /* TODO check rx queue length and refill *somewhere* */ + return; + } + + info = (struct p54u_rx_info *) skb->cb; + info->urb = urb; + info->dev = dev; + urb->transfer_buffer = skb_tail_pointer(skb); + urb->context = skb; + skb_queue_tail(&priv->rx_queue, skb); + } else { + skb_trim(skb, 0); + skb_queue_tail(&priv->rx_queue, skb); + } + + usb_submit_urb(urb, GFP_ATOMIC); +} + +static void p54u_tx_cb(struct urb *urb) +{ + usb_free_urb(urb); +} + +static void p54u_tx_free_cb(struct urb *urb) +{ + kfree(urb->transfer_buffer); + usb_free_urb(urb); +} + +static int p54u_init_urbs(struct ieee80211_hw *dev) +{ + struct p54u_priv *priv = dev->priv; + struct urb *entry; + struct sk_buff *skb; + struct p54u_rx_info *info; + + while (skb_queue_len(&priv->rx_queue) < 32) { + skb = __dev_alloc_skb(MAX_RX_SIZE, GFP_KERNEL); + if (!skb) + break; + entry = usb_alloc_urb(0, GFP_KERNEL); + if (!entry) { + kfree_skb(skb); + break; + } + usb_fill_bulk_urb(entry, priv->udev, usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA), skb_tail_pointer(skb), MAX_RX_SIZE, p54u_rx_cb, skb); + info = (struct p54u_rx_info *) skb->cb; + info->urb = entry; + info->dev = dev; + skb_queue_tail(&priv->rx_queue, skb); + usb_submit_urb(entry, GFP_KERNEL); + } + + return 0; +} + +static void p54u_free_urbs(struct ieee80211_hw *dev) +{ + struct p54u_priv *priv = dev->priv; + struct p54u_rx_info *info; + struct sk_buff *skb; + + while ((skb = skb_dequeue(&priv->rx_queue))) { + info = (struct p54u_rx_info *) skb->cb; + if (!info->urb) + continue; + + usb_kill_urb(info->urb); + kfree_skb(skb); + } +} + +static void p54u_tx_3887(struct ieee80211_hw *dev, struct p54_control_hdr *data, + size_t len, int free_on_tx) +{ + struct p54u_priv *priv = dev->priv; + struct urb *addr_urb, *data_urb; + + addr_urb = usb_alloc_urb(0, GFP_ATOMIC); + if (!addr_urb) + return; + + data_urb = usb_alloc_urb(0, GFP_ATOMIC); + if (!data_urb) { + usb_free_urb(addr_urb); + return; + } + + usb_fill_bulk_urb(addr_urb, priv->udev, + usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), &data->req_id, + sizeof(data->req_id), p54u_tx_cb, dev); + usb_fill_bulk_urb(data_urb, priv->udev, + usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), data, len, + free_on_tx ? p54u_tx_free_cb : p54u_tx_cb, dev); + + usb_submit_urb(addr_urb, GFP_ATOMIC); + usb_submit_urb(data_urb, GFP_ATOMIC); +} + +static void p54u_tx_net2280(struct ieee80211_hw *dev, struct p54_control_hdr *data, + size_t len, int free_on_tx) +{ + struct p54u_priv *priv = dev->priv; + struct urb *int_urb, *data_urb; + struct net2280_tx_hdr *hdr; + struct net2280_reg_write *reg; + + reg = kmalloc(sizeof(*reg), GFP_ATOMIC); + if (!reg) + return; + + int_urb = usb_alloc_urb(0, GFP_ATOMIC); + if (!int_urb) { + kfree(reg); + return; + } + + data_urb = usb_alloc_urb(0, GFP_ATOMIC); + if (!data_urb) { + kfree(reg); + usb_free_urb(int_urb); + return; + } + + reg->port = cpu_to_le16(NET2280_DEV_U32); + reg->addr = cpu_to_le32(P54U_DEV_BASE); + reg->val = cpu_to_le32(ISL38XX_DEV_INT_DATA); + + len += sizeof(*data); + hdr = (void *)data - sizeof(*hdr); + memset(hdr, 0, sizeof(*hdr)); + hdr->device_addr = data->req_id; + hdr->len = cpu_to_le16(len); + + usb_fill_bulk_urb(int_urb, priv->udev, + usb_sndbulkpipe(priv->udev, P54U_PIPE_DEV), reg, sizeof(*reg), + p54u_tx_free_cb, dev); + usb_submit_urb(int_urb, GFP_ATOMIC); + + usb_fill_bulk_urb(data_urb, priv->udev, + usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), hdr, len + sizeof(*hdr), + free_on_tx ? p54u_tx_free_cb : p54u_tx_cb, dev); + usb_submit_urb(data_urb, GFP_ATOMIC); +} + +static int p54u_write(struct p54u_priv *priv, + struct net2280_reg_write *buf, + enum net2280_op_type type, + __le32 addr, __le32 val) +{ + unsigned int ep; + int alen; + + if (type & 0x0800) + ep = usb_sndbulkpipe(priv->udev, P54U_PIPE_DEV); + else + ep = usb_sndbulkpipe(priv->udev, P54U_PIPE_BRG); + + buf->port = cpu_to_le16(type); + buf->addr = addr; + buf->val = val; + + return usb_bulk_msg(priv->udev, ep, buf, sizeof(*buf), &alen, 1000); +} + +static int p54u_read(struct p54u_priv *priv, void *buf, + enum net2280_op_type type, + __le32 addr, __le32 *val) +{ + struct net2280_reg_read *read = buf; + __le32 *reg = buf; + unsigned int ep; + int alen, err; + + if (type & 0x0800) + ep = P54U_PIPE_DEV; + else + ep = P54U_PIPE_BRG; + + read->port = cpu_to_le16(type); + read->addr = addr; + + err = usb_bulk_msg(priv->udev, usb_sndbulkpipe(priv->udev, ep), + read, sizeof(*read), &alen, 1000); + if (err) + return err; + + err = usb_bulk_msg(priv->udev, usb_rcvbulkpipe(priv->udev, ep), + reg, sizeof(*reg), &alen, 1000); + if (err) + return err; + + *val = *reg; + return 0; +} + +static int p54u_bulk_msg(struct p54u_priv *priv, unsigned int ep, + void *data, size_t len) +{ + int alen; + return usb_bulk_msg(priv->udev, usb_sndbulkpipe(priv->udev, ep), + data, len, &alen, 2000); +} + +static int p54u_read_eeprom(struct ieee80211_hw *dev) +{ + struct p54u_priv *priv = dev->priv; + void *buf; + struct p54_control_hdr *hdr; + int err, alen; + size_t offset = priv->hw_type ? 0x10 : 0x20; + + buf = kmalloc(0x2020, GFP_KERNEL); + if (!buf) { + printk(KERN_ERR "prism54usb: cannot allocate memory for " + "eeprom readback!\n"); + return -ENOMEM; + } + + if (priv->hw_type) { + *((u32 *) buf) = priv->common.rx_start; + err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, sizeof(u32)); + if (err) { + printk(KERN_ERR "prism54usb: addr send failed\n"); + goto fail; + } + } else { + struct net2280_reg_write *reg = buf; + reg->port = cpu_to_le16(NET2280_DEV_U32); + reg->addr = cpu_to_le32(P54U_DEV_BASE); + reg->val = cpu_to_le32(ISL38XX_DEV_INT_DATA); + err = p54u_bulk_msg(priv, P54U_PIPE_DEV, buf, sizeof(*reg)); + if (err) { + printk(KERN_ERR "prism54usb: dev_int send failed\n"); + goto fail; + } + } + + hdr = buf + priv->common.tx_hdr_len; + p54_fill_eeprom_readback(hdr); + hdr->req_id = cpu_to_le32(priv->common.rx_start); + if (priv->common.tx_hdr_len) { + struct net2280_tx_hdr *tx_hdr = buf; + tx_hdr->device_addr = hdr->req_id; + tx_hdr->len = cpu_to_le16(EEPROM_READBACK_LEN); + } + + /* we can just pretend to send 0x2000 bytes of nothing in the headers */ + err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, + EEPROM_READBACK_LEN + priv->common.tx_hdr_len); + if (err) { + printk(KERN_ERR "prism54usb: eeprom req send failed\n"); + goto fail; + } + + err = usb_bulk_msg(priv->udev, + usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA), + buf, 0x2020, &alen, 1000); + if (!err && alen > offset) { + p54_parse_eeprom(dev, (u8 *)buf + offset, alen - offset); + } else { + printk(KERN_ERR "prism54usb: eeprom read failed!\n"); + err = -EINVAL; + goto fail; + } + + fail: + kfree(buf); + return err; +} + +static int p54u_upload_firmware_3887(struct ieee80211_hw *dev) +{ + static char start_string[] = "~~~~<\r"; + struct p54u_priv *priv = dev->priv; + const struct firmware *fw_entry = NULL; + int err, alen; + u8 carry = 0; + u8 *buf, *tmp, *data; + unsigned int left, remains, block_size; + struct x2_header *hdr; + unsigned long timeout; + + tmp = buf = kmalloc(P54U_FW_BLOCK, GFP_KERNEL); + if (!buf) { + printk(KERN_ERR "p54usb: cannot allocate firmware upload buffer!\n"); + err = -ENOMEM; + goto err_bufalloc; + } + + memcpy(buf, start_string, 4); + err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, 4); + if (err) { + printk(KERN_ERR "p54usb: reset failed! (%d)\n", err); + goto err_reset; + } + + err = request_firmware(&fw_entry, "isl3887usb_bare", &priv->udev->dev); + if (err) { + printk(KERN_ERR "p54usb: cannot find firmware (isl3887usb_bare)!\n"); + goto err_req_fw_failed; + } + + p54_parse_firmware(dev, fw_entry); + + left = block_size = min((size_t)P54U_FW_BLOCK, fw_entry->size); + strcpy(buf, start_string); + left -= strlen(start_string); + tmp += strlen(start_string); + + data = fw_entry->data; + remains = fw_entry->size; + + hdr = (struct x2_header *)(buf + strlen(start_string)); + memcpy(hdr->signature, X2_SIGNATURE, X2_SIGNATURE_SIZE); + hdr->fw_load_addr = cpu_to_le32(ISL38XX_DEV_FIRMWARE_ADDR); + hdr->fw_length = cpu_to_le32(fw_entry->size); + hdr->crc = cpu_to_le32(~crc32_le(~0, (void *)&hdr->fw_load_addr, + sizeof(u32)*2)); + left -= sizeof(*hdr); + tmp += sizeof(*hdr); + + while (remains) { + while (left--) { + if (carry) { + *tmp++ = carry; + carry = 0; + remains--; + continue; + } + switch (*data) { + case '~': + *tmp++ = '}'; + carry = '^'; + break; + case '}': + *tmp++ = '}'; + carry = ']'; + break; + default: + *tmp++ = *data; + remains--; + break; + } + data++; + } + + err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, block_size); + if (err) { + printk(KERN_ERR "prism54usb: firmware upload failed!\n"); + goto err_upload_failed; + } + + tmp = buf; + left = block_size = min((unsigned int)P54U_FW_BLOCK, remains); + } + + *((__le32 *)buf) = cpu_to_le32(~crc32_le(~0, fw_entry->data, fw_entry->size)); + err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, sizeof(u32)); + if (err) { + printk(KERN_ERR "prism54usb: firmware upload failed!\n"); + goto err_upload_failed; + } + + timeout = jiffies + msecs_to_jiffies(1000); + while (!(err = usb_bulk_msg(priv->udev, + usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA), buf, 128, &alen, 1000))) { + if (alen > 2 && !memcmp(buf, "OK", 2)) + break; + + if (alen > 5 && !memcmp(buf, "ERROR", 5)) { + printk(KERN_INFO "prism54usb: firmware upload failed!\n"); + err = -EINVAL; + break; + } + + if (time_after(jiffies, timeout)) { + printk(KERN_ERR "prism54usb: firmware boot timed out!\n"); + err = -ETIMEDOUT; + break; + } + } + if (err) + goto err_upload_failed; + + buf[0] = 'g'; + buf[1] = '\r'; + err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, 2); + if (err) { + printk(KERN_ERR "prism54usb: firmware boot failed!\n"); + goto err_upload_failed; + } + + timeout = jiffies + msecs_to_jiffies(1000); + while (!(err = usb_bulk_msg(priv->udev, + usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA), buf, 128, &alen, 1000))) { + if (alen > 0 && buf[0] == 'g') + break; + + if (time_after(jiffies, timeout)) { + err = -ETIMEDOUT; + break; + } + } + if (err) + goto err_upload_failed; + + err_upload_failed: + release_firmware(fw_entry); + err_req_fw_failed: + err_reset: + kfree(buf); + err_bufalloc: + return err; +} + +static int p54u_upload_firmware_net2280(struct ieee80211_hw *dev) +{ + struct p54u_priv *priv = dev->priv; + const struct firmware *fw_entry = NULL; + const struct p54p_csr *devreg = (const struct p54p_csr *) P54U_DEV_BASE; + int err, alen; + void *buf; + __le32 reg; + unsigned int remains, offset; + u8 *data; + + buf = kmalloc(512, GFP_KERNEL); + if (!buf) { + printk(KERN_ERR "p54usb: firmware buffer alloc failed!\n"); + return -ENOMEM; + } + + err = request_firmware(&fw_entry, "isl3890usb", &priv->udev->dev); + if (err) { + printk(KERN_ERR "p54usb: cannot find firmware (isl3890usb)!\n"); + kfree(buf); + return err; + } + + p54_parse_firmware(dev, fw_entry); + +#define P54U_WRITE(type, addr, data) \ + do {\ + err = p54u_write(priv, buf, type,\ + cpu_to_le32((u32)(unsigned long)addr), data);\ + if (err) \ + goto fail;\ + } while (0) + +#define P54U_READ(type, addr) \ + do {\ + err = p54u_read(priv, buf, type,\ + cpu_to_le32((u32)(unsigned long)addr), ®);\ + if (err)\ + goto fail;\ + } while (0) + + /* power down net2280 bridge */ + P54U_READ(NET2280_BRG_U32, NET2280_GPIOCTL); + reg |= cpu_to_le32(P54U_BRG_POWER_DOWN); + reg &= cpu_to_le32(~P54U_BRG_POWER_UP); + P54U_WRITE(NET2280_BRG_U32, NET2280_GPIOCTL, reg); + + mdelay(100); + + /* power up bridge */ + reg |= cpu_to_le32(P54U_BRG_POWER_UP); + reg &= cpu_to_le32(~P54U_BRG_POWER_DOWN); + P54U_WRITE(NET2280_BRG_U32, NET2280_GPIOCTL, reg); + + mdelay(100); + + P54U_WRITE(NET2280_BRG_U32, NET2280_DEVINIT, + cpu_to_le32(NET2280_CLK_30Mhz | + NET2280_PCI_ENABLE | + NET2280_PCI_SOFT_RESET)); + + mdelay(20); + + P54U_WRITE(NET2280_BRG_CFG_U16, PCI_COMMAND, + cpu_to_le32(PCI_COMMAND_MEMORY | + PCI_COMMAND_MASTER)); + + P54U_WRITE(NET2280_BRG_CFG_U32, PCI_BASE_ADDRESS_0, + cpu_to_le32(NET2280_BASE)); + + P54U_READ(NET2280_BRG_CFG_U16, PCI_STATUS); + reg |= cpu_to_le32(PCI_STATUS_REC_MASTER_ABORT); + P54U_WRITE(NET2280_BRG_CFG_U16, PCI_STATUS, reg); + + // TODO: we really need this? + P54U_READ(NET2280_BRG_U32, NET2280_RELNUM); + + P54U_WRITE(NET2280_BRG_U32, NET2280_EPA_RSP, + cpu_to_le32(NET2280_CLEAR_NAK_OUT_PACKETS_MODE)); + P54U_WRITE(NET2280_BRG_U32, NET2280_EPC_RSP, + cpu_to_le32(NET2280_CLEAR_NAK_OUT_PACKETS_MODE)); + + P54U_WRITE(NET2280_BRG_CFG_U32, PCI_BASE_ADDRESS_2, + cpu_to_le32(NET2280_BASE2)); + + /* finally done setting up the bridge */ + + P54U_WRITE(NET2280_DEV_CFG_U16, 0x10000 | PCI_COMMAND, + cpu_to_le32(PCI_COMMAND_MEMORY | + PCI_COMMAND_MASTER)); + + P54U_WRITE(NET2280_DEV_CFG_U16, 0x10000 | 0x40 /* TRDY timeout */, 0); + P54U_WRITE(NET2280_DEV_CFG_U32, 0x10000 | PCI_BASE_ADDRESS_0, + cpu_to_le32(P54U_DEV_BASE)); + + P54U_WRITE(NET2280_BRG_U32, NET2280_USBIRQENB1, 0); + P54U_WRITE(NET2280_BRG_U32, NET2280_IRQSTAT1, + cpu_to_le32(NET2280_PCI_INTA_INTERRUPT)); + + /* do romboot */ + P54U_WRITE(NET2280_DEV_U32, &devreg->int_enable, 0); + + P54U_READ(NET2280_DEV_U32, &devreg->ctrl_stat); + reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET); + reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RAMBOOT); + reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_CLKRUN); + P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg); + + mdelay(20); + + reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RESET); + P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg); + + mdelay(20); + + reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET); + P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg); + + mdelay(100); + + P54U_READ(NET2280_DEV_U32, &devreg->int_ident); + P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg); + + /* finally, we can upload firmware now! */ + remains = fw_entry->size; + data = fw_entry->data; + offset = ISL38XX_DEV_FIRMWARE_ADDR; + + while (remains) { + unsigned int block_len = min(remains, (unsigned int)512); + memcpy(buf, data, block_len); + + err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, block_len); + if (err) { + printk(KERN_ERR "prism54usb: firmware block upload " + "failed\n"); + goto fail; + } + + P54U_WRITE(NET2280_DEV_U32, &devreg->direct_mem_base, + cpu_to_le32(0xc0000f00)); + + P54U_WRITE(NET2280_DEV_U32, + 0x0020 | (unsigned long)&devreg->direct_mem_win, 0); + P54U_WRITE(NET2280_DEV_U32, + 0x0020 | (unsigned long)&devreg->direct_mem_win, + cpu_to_le32(1)); + + P54U_WRITE(NET2280_DEV_U32, + 0x0024 | (unsigned long)&devreg->direct_mem_win, + cpu_to_le32(block_len)); + P54U_WRITE(NET2280_DEV_U32, + 0x0028 | (unsigned long)&devreg->direct_mem_win, + cpu_to_le32(offset)); + + P54U_WRITE(NET2280_DEV_U32, &devreg->dma_addr, + cpu_to_le32(NET2280_EPA_FIFO_PCI_ADDR)); + P54U_WRITE(NET2280_DEV_U32, &devreg->dma_len, + cpu_to_le32(block_len >> 2)); + P54U_WRITE(NET2280_DEV_U32, &devreg->dma_ctrl, + cpu_to_le32(ISL38XX_DMA_MASTER_CONTROL_TRIGGER)); + + mdelay(10); + + P54U_READ(NET2280_DEV_U32, + 0x002C | (unsigned long)&devreg->direct_mem_win); + if (!(reg & cpu_to_le32(ISL38XX_DMA_STATUS_DONE)) || + !(reg & cpu_to_le32(ISL38XX_DMA_STATUS_READY))) { + printk(KERN_ERR "prism54usb: firmware DMA transfer " + "failed\n"); + goto fail; + } + + P54U_WRITE(NET2280_BRG_U32, NET2280_EPA_STAT, + cpu_to_le32(NET2280_FIFO_FLUSH)); + + remains -= block_len; + data += block_len; + offset += block_len; + } + + /* do ramboot */ + P54U_READ(NET2280_DEV_U32, &devreg->ctrl_stat); + reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET); + reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_CLKRUN); + reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RAMBOOT); + P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg); + + mdelay(20); + + reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RESET); + P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg); + + reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET); + P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg); + + mdelay(100); + + P54U_READ(NET2280_DEV_U32, &devreg->int_ident); + P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg); + + /* start up the firmware */ + P54U_WRITE(NET2280_DEV_U32, &devreg->int_enable, + cpu_to_le32(ISL38XX_INT_IDENT_INIT)); + + P54U_WRITE(NET2280_BRG_U32, NET2280_IRQSTAT1, + cpu_to_le32(NET2280_PCI_INTA_INTERRUPT)); + + P54U_WRITE(NET2280_BRG_U32, NET2280_USBIRQENB1, + cpu_to_le32(NET2280_PCI_INTA_INTERRUPT_ENABLE | + NET2280_USB_INTERRUPT_ENABLE)); + + P54U_WRITE(NET2280_DEV_U32, &devreg->dev_int, + cpu_to_le32(ISL38XX_DEV_INT_RESET)); + + err = usb_interrupt_msg(priv->udev, + usb_rcvbulkpipe(priv->udev, P54U_PIPE_INT), + buf, sizeof(__le32), &alen, 1000); + if (err || alen != sizeof(__le32)) + goto fail; + + P54U_READ(NET2280_DEV_U32, &devreg->int_ident); + P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg); + + if (!(reg & cpu_to_le32(ISL38XX_INT_IDENT_INIT))) + err = -EINVAL; + + P54U_WRITE(NET2280_BRG_U32, NET2280_USBIRQENB1, 0); + P54U_WRITE(NET2280_BRG_U32, NET2280_IRQSTAT1, + cpu_to_le32(NET2280_PCI_INTA_INTERRUPT)); + +#undef P54U_WRITE +#undef P54U_READ + + fail: + release_firmware(fw_entry); + kfree(buf); + return err; +} + +static int p54u_open(struct ieee80211_hw *dev) +{ + struct p54u_priv *priv = dev->priv; + int err; + + err = p54u_init_urbs(dev); + if (err) { + return err; + } + + priv->common.open = p54u_init_urbs; + + return 0; +} + +static void p54u_stop(struct ieee80211_hw *dev) +{ + /* TODO: figure out how to reliably stop the 3887 and net2280 so + the hardware is still usable next time we want to start it. + until then, we just stop listening to the hardware.. */ + p54u_free_urbs(dev); + return; +} + +static int __devinit p54u_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct usb_device *udev = interface_to_usbdev(intf); + struct ieee80211_hw *dev; + struct p54u_priv *priv; + int err; + unsigned int i, recognized_pipes; + DECLARE_MAC_BUF(mac); + + dev = p54_init_common(sizeof(*priv)); + if (!dev) { + printk(KERN_ERR "prism54usb: ieee80211 alloc failed\n"); + return -ENOMEM; + } + + priv = dev->priv; + + SET_IEEE80211_DEV(dev, &intf->dev); + usb_set_intfdata(intf, dev); + priv->udev = udev; + + usb_get_dev(udev); + + /* really lazy and simple way of figuring out if we're a 3887 */ + /* TODO: should just stick the identification in the device table */ + i = intf->altsetting->desc.bNumEndpoints; + recognized_pipes = 0; + while (i--) { + switch (intf->altsetting->endpoint[i].desc.bEndpointAddress) { + case P54U_PIPE_DATA: + case P54U_PIPE_MGMT: + case P54U_PIPE_BRG: + case P54U_PIPE_DEV: + case P54U_PIPE_DATA | USB_DIR_IN: + case P54U_PIPE_MGMT | USB_DIR_IN: + case P54U_PIPE_BRG | USB_DIR_IN: + case P54U_PIPE_DEV | USB_DIR_IN: + case P54U_PIPE_INT | USB_DIR_IN: + recognized_pipes++; + } + } + priv->common.open = p54u_open; + + if (recognized_pipes < P54U_PIPE_NUMBER) { + priv->hw_type = P54U_3887; + priv->common.tx = p54u_tx_3887; + } else { + dev->extra_tx_headroom += sizeof(struct net2280_tx_hdr); + priv->common.tx_hdr_len = sizeof(struct net2280_tx_hdr); + priv->common.tx = p54u_tx_net2280; + } + priv->common.stop = p54u_stop; + + if (priv->hw_type) + err = p54u_upload_firmware_3887(dev); + else + err = p54u_upload_firmware_net2280(dev); + if (err) + goto err_free_dev; + + err = p54u_read_eeprom(dev); + if (err) + goto err_free_dev; + + if (!is_valid_ether_addr(dev->wiphy->perm_addr)) { + u8 perm_addr[ETH_ALEN]; + + printk(KERN_WARNING "prism54usb: Invalid hwaddr! Using randomly generated MAC addr\n"); + random_ether_addr(perm_addr); + SET_IEEE80211_PERM_ADDR(dev, perm_addr); + } + + skb_queue_head_init(&priv->rx_queue); + + err = ieee80211_register_hw(dev); + if (err) { + printk(KERN_ERR "prism54usb: Cannot register netdevice\n"); + goto err_free_dev; + } + + printk(KERN_INFO "%s: hwaddr %s, isl38%02x\n", + wiphy_name(dev->wiphy), + print_mac(mac, dev->wiphy->perm_addr), + priv->common.version); + + return 0; + + err_free_dev: + ieee80211_free_hw(dev); + usb_set_intfdata(intf, NULL); + usb_put_dev(udev); + return err; +} + +static void __devexit p54u_disconnect(struct usb_interface *intf) +{ + struct ieee80211_hw *dev = usb_get_intfdata(intf); + struct p54u_priv *priv; + + if (!dev) + return; + + ieee80211_unregister_hw(dev); + + priv = dev->priv; + usb_put_dev(interface_to_usbdev(intf)); + p54_free_common(dev); + ieee80211_free_hw(dev); +} + +static struct usb_driver p54u_driver = { + .name = "prism54usb", + .id_table = p54u_table, + .probe = p54u_probe, + .disconnect = p54u_disconnect, +}; + +static int __init p54u_init(void) +{ + return usb_register(&p54u_driver); +} + +static void __exit p54u_exit(void) +{ + usb_deregister(&p54u_driver); +} + +module_init(p54u_init); +module_exit(p54u_exit); diff --git a/drivers/net/wireless/p54/p54usb.h b/drivers/net/wireless/p54/p54usb.h new file mode 100644 index 000000000000..d1896b396c1c --- /dev/null +++ b/drivers/net/wireless/p54/p54usb.h @@ -0,0 +1,133 @@ +#ifndef PRISM54USB_H +#define PRISM54USB_H + +/* + * Defines for USB based mac80211 Prism54 driver + * + * Copyright (c) 2006, Michael Wu + * + * Based on the islsm (softmac prism54) driver, which is: + * Copyright 2004-2006 Jean-Baptiste Note , et al. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/* for isl3886 register definitions used on ver 1 devices */ +#include "p54pci.h" +#include "net2280.h" + +/* pci */ +#define NET2280_BASE 0x10000000 +#define NET2280_BASE2 0x20000000 + +/* gpio */ +#define P54U_BRG_POWER_UP (1 << GPIO0_DATA) +#define P54U_BRG_POWER_DOWN (1 << GPIO1_DATA) + +/* devinit */ +#define NET2280_CLK_4Mhz (15 << LOCAL_CLOCK_FREQUENCY) +#define NET2280_CLK_30Mhz (2 << LOCAL_CLOCK_FREQUENCY) +#define NET2280_CLK_60Mhz (1 << LOCAL_CLOCK_FREQUENCY) +#define NET2280_CLK_STOP (0 << LOCAL_CLOCK_FREQUENCY) +#define NET2280_PCI_ENABLE (1 << PCI_ENABLE) +#define NET2280_PCI_SOFT_RESET (1 << PCI_SOFT_RESET) + +/* endpoints */ +#define NET2280_CLEAR_NAK_OUT_PACKETS_MODE (1 << CLEAR_NAK_OUT_PACKETS_MODE) +#define NET2280_FIFO_FLUSH (1 << FIFO_FLUSH) + +/* irq */ +#define NET2280_USB_INTERRUPT_ENABLE (1 << USB_INTERRUPT_ENABLE) +#define NET2280_PCI_INTA_INTERRUPT (1 << PCI_INTA_INTERRUPT) +#define NET2280_PCI_INTA_INTERRUPT_ENABLE (1 << PCI_INTA_INTERRUPT_ENABLE) + +/* registers */ +#define NET2280_DEVINIT 0x00 +#define NET2280_USBIRQENB1 0x24 +#define NET2280_IRQSTAT1 0x2c +#define NET2280_FIFOCTL 0x38 +#define NET2280_GPIOCTL 0x50 +#define NET2280_RELNUM 0x88 +#define NET2280_EPA_RSP 0x324 +#define NET2280_EPA_STAT 0x32c +#define NET2280_EPB_STAT 0x34c +#define NET2280_EPC_RSP 0x364 +#define NET2280_EPC_STAT 0x36c +#define NET2280_EPD_STAT 0x38c + +#define NET2280_EPA_CFG 0x320 +#define NET2280_EPB_CFG 0x340 +#define NET2280_EPC_CFG 0x360 +#define NET2280_EPD_CFG 0x380 +#define NET2280_EPE_CFG 0x3A0 +#define NET2280_EPF_CFG 0x3C0 +#define P54U_DEV_BASE 0x40000000 + +struct net2280_tx_hdr { + __le32 device_addr; + __le16 len; + __le16 follower; /* ? */ + u8 padding[8]; +} __attribute__((packed)); + +/* Some flags for the isl hardware registers controlling DMA inside the + * chip */ +#define ISL38XX_DMA_STATUS_DONE 0x00000001 +#define ISL38XX_DMA_STATUS_READY 0x00000002 +#define NET2280_EPA_FIFO_PCI_ADDR 0x20000000 +#define ISL38XX_DMA_MASTER_CONTROL_TRIGGER 0x00000004 + +enum net2280_op_type { + NET2280_BRG_U32 = 0x001F, + NET2280_BRG_CFG_U32 = 0x000F, + NET2280_BRG_CFG_U16 = 0x0003, + NET2280_DEV_U32 = 0x080F, + NET2280_DEV_CFG_U32 = 0x088F, + NET2280_DEV_CFG_U16 = 0x0883 +}; + +#define P54U_FW_BLOCK 2048 + +#define X2_SIGNATURE "x2 " +#define X2_SIGNATURE_SIZE 4 + +struct x2_header { + u8 signature[X2_SIGNATURE_SIZE]; + __le32 fw_load_addr; + __le32 fw_length; + __le32 crc; +} __attribute__((packed)); + +/* pipes 3 and 4 are not used by the driver */ +#define P54U_PIPE_NUMBER 9 + +enum p54u_pipe_addr { + P54U_PIPE_DATA = 0x01, + P54U_PIPE_MGMT = 0x02, + P54U_PIPE_3 = 0x03, + P54U_PIPE_4 = 0x04, + P54U_PIPE_BRG = 0x0d, + P54U_PIPE_DEV = 0x0e, + P54U_PIPE_INT = 0x0f +}; + +struct p54u_rx_info { + struct urb *urb; + struct ieee80211_hw *dev; +}; + +struct p54u_priv { + struct p54_common common; + struct usb_device *udev; + enum { + P54U_NET2280 = 0, + P54U_3887 + } hw_type; + + spinlock_t lock; + struct sk_buff_head rx_queue; +}; + +#endif /* PRISM54USB_H */ diff --git a/drivers/net/wireless/p54common.c b/drivers/net/wireless/p54common.c deleted file mode 100644 index 63f9badf3f52..000000000000 --- a/drivers/net/wireless/p54common.c +++ /dev/null @@ -1,1051 +0,0 @@ - -/* - * Common code for mac80211 Prism54 drivers - * - * Copyright (c) 2006, Michael Wu - * Copyright (c) 2007, Christian Lamparter - * - * Based on the islsm (softmac prism54) driver, which is: - * Copyright 2004-2006 Jean-Baptiste Note , et al. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include - -#include - -#include "p54.h" -#include "p54common.h" - -MODULE_AUTHOR("Michael Wu "); -MODULE_DESCRIPTION("Softmac Prism54 common code"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("prism54common"); - -static struct ieee80211_rate p54_rates[] = { - { .bitrate = 10, .hw_value = 0, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, - { .bitrate = 20, .hw_value = 1, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, - { .bitrate = 55, .hw_value = 2, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, - { .bitrate = 110, .hw_value = 3, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, - { .bitrate = 60, .hw_value = 4, }, - { .bitrate = 90, .hw_value = 5, }, - { .bitrate = 120, .hw_value = 6, }, - { .bitrate = 180, .hw_value = 7, }, - { .bitrate = 240, .hw_value = 8, }, - { .bitrate = 360, .hw_value = 9, }, - { .bitrate = 480, .hw_value = 10, }, - { .bitrate = 540, .hw_value = 11, }, -}; - -static struct ieee80211_channel p54_channels[] = { - { .center_freq = 2412, .hw_value = 1, }, - { .center_freq = 2417, .hw_value = 2, }, - { .center_freq = 2422, .hw_value = 3, }, - { .center_freq = 2427, .hw_value = 4, }, - { .center_freq = 2432, .hw_value = 5, }, - { .center_freq = 2437, .hw_value = 6, }, - { .center_freq = 2442, .hw_value = 7, }, - { .center_freq = 2447, .hw_value = 8, }, - { .center_freq = 2452, .hw_value = 9, }, - { .center_freq = 2457, .hw_value = 10, }, - { .center_freq = 2462, .hw_value = 11, }, - { .center_freq = 2467, .hw_value = 12, }, - { .center_freq = 2472, .hw_value = 13, }, - { .center_freq = 2484, .hw_value = 14, }, -}; - -static struct ieee80211_supported_band band_2GHz = { - .channels = p54_channels, - .n_channels = ARRAY_SIZE(p54_channels), - .bitrates = p54_rates, - .n_bitrates = ARRAY_SIZE(p54_rates), -}; - - -void p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw) -{ - struct p54_common *priv = dev->priv; - struct bootrec_exp_if *exp_if; - struct bootrec *bootrec; - u32 *data = (u32 *)fw->data; - u32 *end_data = (u32 *)fw->data + (fw->size >> 2); - u8 *fw_version = NULL; - size_t len; - int i; - - if (priv->rx_start) - return; - - while (data < end_data && *data) - data++; - - while (data < end_data && !*data) - data++; - - bootrec = (struct bootrec *) data; - - while (bootrec->data <= end_data && - (bootrec->data + (len = le32_to_cpu(bootrec->len))) <= end_data) { - u32 code = le32_to_cpu(bootrec->code); - switch (code) { - case BR_CODE_COMPONENT_ID: - switch (be32_to_cpu(*(__be32 *)bootrec->data)) { - case FW_FMAC: - printk(KERN_INFO "p54: FreeMAC firmware\n"); - break; - case FW_LM20: - printk(KERN_INFO "p54: LM20 firmware\n"); - break; - case FW_LM86: - printk(KERN_INFO "p54: LM86 firmware\n"); - break; - case FW_LM87: - printk(KERN_INFO "p54: LM87 firmware - not supported yet!\n"); - break; - default: - printk(KERN_INFO "p54: unknown firmware\n"); - break; - } - break; - case BR_CODE_COMPONENT_VERSION: - /* 24 bytes should be enough for all firmwares */ - if (strnlen((unsigned char*)bootrec->data, 24) < 24) - fw_version = (unsigned char*)bootrec->data; - break; - case BR_CODE_DESCR: - priv->rx_start = le32_to_cpu(((__le32 *)bootrec->data)[1]); - /* FIXME add sanity checking */ - priv->rx_end = le32_to_cpu(((__le32 *)bootrec->data)[2]) - 0x3500; - break; - case BR_CODE_EXPOSED_IF: - exp_if = (struct bootrec_exp_if *) bootrec->data; - for (i = 0; i < (len * sizeof(*exp_if) / 4); i++) - if (exp_if[i].if_id == cpu_to_le16(0x1a)) - priv->fw_var = le16_to_cpu(exp_if[i].variant); - break; - case BR_CODE_DEPENDENT_IF: - break; - case BR_CODE_END_OF_BRA: - case LEGACY_BR_CODE_END_OF_BRA: - end_data = NULL; - break; - default: - break; - } - bootrec = (struct bootrec *)&bootrec->data[len]; - } - - if (fw_version) - printk(KERN_INFO "p54: FW rev %s - Softmac protocol %x.%x\n", - fw_version, priv->fw_var >> 8, priv->fw_var & 0xff); - - if (priv->fw_var >= 0x300) { - /* Firmware supports QoS, use it! */ - priv->tx_stats.data[0].limit = 3; - priv->tx_stats.data[1].limit = 4; - priv->tx_stats.data[2].limit = 3; - priv->tx_stats.data[3].limit = 1; - dev->queues = 4; - } -} -EXPORT_SYMBOL_GPL(p54_parse_firmware); - -static int p54_convert_rev0_to_rev1(struct ieee80211_hw *dev, - struct pda_pa_curve_data *curve_data) -{ - struct p54_common *priv = dev->priv; - struct pda_pa_curve_data_sample_rev1 *rev1; - struct pda_pa_curve_data_sample_rev0 *rev0; - size_t cd_len = sizeof(*curve_data) + - (curve_data->points_per_channel*sizeof(*rev1) + 2) * - curve_data->channels; - unsigned int i, j; - void *source, *target; - - priv->curve_data = kmalloc(cd_len, GFP_KERNEL); - if (!priv->curve_data) - return -ENOMEM; - - memcpy(priv->curve_data, curve_data, sizeof(*curve_data)); - source = curve_data->data; - target = priv->curve_data->data; - for (i = 0; i < curve_data->channels; i++) { - __le16 *freq = source; - source += sizeof(__le16); - *((__le16 *)target) = *freq; - target += sizeof(__le16); - for (j = 0; j < curve_data->points_per_channel; j++) { - rev1 = target; - rev0 = source; - - rev1->rf_power = rev0->rf_power; - rev1->pa_detector = rev0->pa_detector; - rev1->data_64qam = rev0->pcv; - /* "invent" the points for the other modulations */ -#define SUB(x,y) (u8)((x) - (y)) > (x) ? 0 : (x) - (y) - rev1->data_16qam = SUB(rev0->pcv, 12); - rev1->data_qpsk = SUB(rev1->data_16qam, 12); - rev1->data_bpsk = SUB(rev1->data_qpsk, 12); - rev1->data_barker= SUB(rev1->data_bpsk, 14); -#undef SUB - target += sizeof(*rev1); - source += sizeof(*rev0); - } - } - - return 0; -} - -int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) -{ - struct p54_common *priv = dev->priv; - struct eeprom_pda_wrap *wrap = NULL; - struct pda_entry *entry; - unsigned int data_len, entry_len; - void *tmp; - int err; - u8 *end = (u8 *)eeprom + len; - - wrap = (struct eeprom_pda_wrap *) eeprom; - entry = (void *)wrap->data + le16_to_cpu(wrap->len); - - /* verify that at least the entry length/code fits */ - while ((u8 *)entry <= end - sizeof(*entry)) { - entry_len = le16_to_cpu(entry->len); - data_len = ((entry_len - 1) << 1); - - /* abort if entry exceeds whole structure */ - if ((u8 *)entry + sizeof(*entry) + data_len > end) - break; - - switch (le16_to_cpu(entry->code)) { - case PDR_MAC_ADDRESS: - SET_IEEE80211_PERM_ADDR(dev, entry->data); - break; - case PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS: - if (data_len < 2) { - err = -EINVAL; - goto err; - } - - if (2 + entry->data[1]*sizeof(*priv->output_limit) > data_len) { - err = -EINVAL; - goto err; - } - - priv->output_limit = kmalloc(entry->data[1] * - sizeof(*priv->output_limit), GFP_KERNEL); - - if (!priv->output_limit) { - err = -ENOMEM; - goto err; - } - - memcpy(priv->output_limit, &entry->data[2], - entry->data[1]*sizeof(*priv->output_limit)); - priv->output_limit_len = entry->data[1]; - break; - case PDR_PRISM_PA_CAL_CURVE_DATA: - if (data_len < sizeof(struct pda_pa_curve_data)) { - err = -EINVAL; - goto err; - } - - if (((struct pda_pa_curve_data *)entry->data)->cal_method_rev) { - priv->curve_data = kmalloc(data_len, GFP_KERNEL); - if (!priv->curve_data) { - err = -ENOMEM; - goto err; - } - - memcpy(priv->curve_data, entry->data, data_len); - } else { - err = p54_convert_rev0_to_rev1(dev, (struct pda_pa_curve_data *)entry->data); - if (err) - goto err; - } - - break; - case PDR_PRISM_ZIF_TX_IQ_CALIBRATION: - priv->iq_autocal = kmalloc(data_len, GFP_KERNEL); - if (!priv->iq_autocal) { - err = -ENOMEM; - goto err; - } - - memcpy(priv->iq_autocal, entry->data, data_len); - priv->iq_autocal_len = data_len / sizeof(struct pda_iq_autocal_entry); - break; - case PDR_INTERFACE_LIST: - tmp = entry->data; - while ((u8 *)tmp < entry->data + data_len) { - struct bootrec_exp_if *exp_if = tmp; - if (le16_to_cpu(exp_if->if_id) == 0xF) - priv->rxhw = exp_if->variant & cpu_to_le16(0x07); - tmp += sizeof(struct bootrec_exp_if); - } - break; - case PDR_HARDWARE_PLATFORM_COMPONENT_ID: - priv->version = *(u8 *)(entry->data + 1); - break; - case PDR_END: - /* make it overrun */ - entry_len = len; - break; - default: - printk(KERN_INFO "p54: unknown eeprom code : 0x%x\n", - le16_to_cpu(entry->code)); - break; - } - - entry = (void *)entry + (entry_len + 1)*2; - } - - if (!priv->iq_autocal || !priv->output_limit || !priv->curve_data) { - printk(KERN_ERR "p54: not all required entries found in eeprom!\n"); - err = -EINVAL; - goto err; - } - - return 0; - - err: - if (priv->iq_autocal) { - kfree(priv->iq_autocal); - priv->iq_autocal = NULL; - } - - if (priv->output_limit) { - kfree(priv->output_limit); - priv->output_limit = NULL; - } - - if (priv->curve_data) { - kfree(priv->curve_data); - priv->curve_data = NULL; - } - - printk(KERN_ERR "p54: eeprom parse failed!\n"); - return err; -} -EXPORT_SYMBOL_GPL(p54_parse_eeprom); - -void p54_fill_eeprom_readback(struct p54_control_hdr *hdr) -{ - struct p54_eeprom_lm86 *eeprom_hdr; - - hdr->magic1 = cpu_to_le16(0x8000); - hdr->len = cpu_to_le16(sizeof(*eeprom_hdr) + 0x2000); - hdr->type = cpu_to_le16(P54_CONTROL_TYPE_EEPROM_READBACK); - hdr->retry1 = hdr->retry2 = 0; - eeprom_hdr = (struct p54_eeprom_lm86 *) hdr->data; - eeprom_hdr->offset = 0x0; - eeprom_hdr->len = cpu_to_le16(0x2000); -} -EXPORT_SYMBOL_GPL(p54_fill_eeprom_readback); - -static void p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb) -{ - struct p54_rx_hdr *hdr = (struct p54_rx_hdr *) skb->data; - struct ieee80211_rx_status rx_status = {0}; - u16 freq = le16_to_cpu(hdr->freq); - - rx_status.ssi = hdr->rssi; - /* XX correct? */ - rx_status.rate_idx = hdr->rate & 0xf; - rx_status.freq = freq; - rx_status.band = IEEE80211_BAND_2GHZ; - rx_status.antenna = hdr->antenna; - rx_status.mactime = le64_to_cpu(hdr->timestamp); - rx_status.flag |= RX_FLAG_TSFT; - - skb_pull(skb, sizeof(*hdr)); - skb_trim(skb, le16_to_cpu(hdr->len)); - - ieee80211_rx_irqsafe(dev, skb, &rx_status); -} - -static void inline p54_wake_free_queues(struct ieee80211_hw *dev) -{ - struct p54_common *priv = dev->priv; - int i; - - /* ieee80211_start_queues is great if all queues are really empty. - * But, what if some are full? */ - - for (i = 0; i < dev->queues; i++) - if (priv->tx_stats.data[i].len < priv->tx_stats.data[i].limit) - ieee80211_wake_queue(dev, i); -} - -static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) -{ - struct p54_common *priv = dev->priv; - struct p54_control_hdr *hdr = (struct p54_control_hdr *) skb->data; - struct p54_frame_sent_hdr *payload = (struct p54_frame_sent_hdr *) hdr->data; - struct sk_buff *entry = (struct sk_buff *) priv->tx_queue.next; - u32 addr = le32_to_cpu(hdr->req_id) - 0x70; - struct memrecord *range = NULL; - u32 freed = 0; - u32 last_addr = priv->rx_start; - - while (entry != (struct sk_buff *)&priv->tx_queue) { - range = (struct memrecord *)&entry->cb; - if (range->start_addr == addr) { - struct ieee80211_tx_status status; - struct p54_control_hdr *entry_hdr; - struct p54_tx_control_allocdata *entry_data; - int pad = 0; - - if (entry->next != (struct sk_buff *)&priv->tx_queue) - freed = ((struct memrecord *)&entry->next->cb)->start_addr - last_addr; - else - freed = priv->rx_end - last_addr; - - last_addr = range->end_addr; - __skb_unlink(entry, &priv->tx_queue); - if (!range->control) { - kfree_skb(entry); - break; - } - memset(&status, 0, sizeof(status)); - memcpy(&status.control, range->control, - sizeof(status.control)); - kfree(range->control); - priv->tx_stats.data[status.control.queue].len--; - - entry_hdr = (struct p54_control_hdr *) entry->data; - entry_data = (struct p54_tx_control_allocdata *) entry_hdr->data; - if ((entry_hdr->magic1 & cpu_to_le16(0x4000)) != 0) - pad = entry_data->align[0]; - - if (!(status.control.flags & IEEE80211_TXCTL_NO_ACK)) { - if (!(payload->status & 0x01)) - status.flags |= IEEE80211_TX_STATUS_ACK; - else - status.excessive_retries = 1; - } - status.retry_count = payload->retries - 1; - status.ack_signal = le16_to_cpu(payload->ack_rssi); - skb_pull(entry, sizeof(*hdr) + pad + sizeof(*entry_data)); - ieee80211_tx_status_irqsafe(dev, entry, &status); - break; - } else - last_addr = range->end_addr; - entry = entry->next; - } - - if (freed >= IEEE80211_MAX_RTS_THRESHOLD + 0x170 + - sizeof(struct p54_control_hdr)) - p54_wake_free_queues(dev); -} - -static void p54_rx_control(struct ieee80211_hw *dev, struct sk_buff *skb) -{ - struct p54_control_hdr *hdr = (struct p54_control_hdr *) skb->data; - - switch (le16_to_cpu(hdr->type)) { - case P54_CONTROL_TYPE_TXDONE: - p54_rx_frame_sent(dev, skb); - break; - case P54_CONTROL_TYPE_BBP: - break; - default: - printk(KERN_DEBUG "%s: not handling 0x%02x type control frame\n", - wiphy_name(dev->wiphy), le16_to_cpu(hdr->type)); - break; - } -} - -/* returns zero if skb can be reused */ -int p54_rx(struct ieee80211_hw *dev, struct sk_buff *skb) -{ - u8 type = le16_to_cpu(*((__le16 *)skb->data)) >> 8; - switch (type) { - case 0x00: - case 0x01: - p54_rx_data(dev, skb); - return -1; - case 0x4d: - /* TODO: do something better... but then again, I've never seen this happen */ - printk(KERN_ERR "%s: Received fault. Probably need to restart hardware now..\n", - wiphy_name(dev->wiphy)); - break; - case 0x80: - p54_rx_control(dev, skb); - break; - default: - printk(KERN_ERR "%s: unknown frame RXed (0x%02x)\n", - wiphy_name(dev->wiphy), type); - break; - } - return 0; -} -EXPORT_SYMBOL_GPL(p54_rx); - -/* - * So, the firmware is somewhat stupid and doesn't know what places in its - * memory incoming data should go to. By poking around in the firmware, we - * can find some unused memory to upload our packets to. However, data that we - * want the card to TX needs to stay intact until the card has told us that - * it is done with it. This function finds empty places we can upload to and - * marks allocated areas as reserved if necessary. p54_rx_frame_sent frees - * allocated areas. - */ -static void p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb, - struct p54_control_hdr *data, u32 len, - struct ieee80211_tx_control *control) -{ - struct p54_common *priv = dev->priv; - struct sk_buff *entry = priv->tx_queue.next; - struct sk_buff *target_skb = NULL; - struct memrecord *range; - u32 last_addr = priv->rx_start; - u32 largest_hole = 0; - u32 target_addr = priv->rx_start; - unsigned long flags; - unsigned int left; - len = (len + 0x170 + 3) & ~0x3; /* 0x70 headroom, 0x100 tailroom */ - - spin_lock_irqsave(&priv->tx_queue.lock, flags); - left = skb_queue_len(&priv->tx_queue); - while (left--) { - u32 hole_size; - range = (struct memrecord *)&entry->cb; - hole_size = range->start_addr - last_addr; - if (!target_skb && hole_size >= len) { - target_skb = entry->prev; - hole_size -= len; - target_addr = last_addr; - } - largest_hole = max(largest_hole, hole_size); - last_addr = range->end_addr; - entry = entry->next; - } - if (!target_skb && priv->rx_end - last_addr >= len) { - target_skb = priv->tx_queue.prev; - largest_hole = max(largest_hole, priv->rx_end - last_addr - len); - if (!skb_queue_empty(&priv->tx_queue)) { - range = (struct memrecord *)&target_skb->cb; - target_addr = range->end_addr; - } - } else - largest_hole = max(largest_hole, priv->rx_end - last_addr); - - if (skb) { - range = (struct memrecord *)&skb->cb; - range->start_addr = target_addr; - range->end_addr = target_addr + len; - range->control = control; - __skb_queue_after(&priv->tx_queue, target_skb, skb); - if (largest_hole < IEEE80211_MAX_RTS_THRESHOLD + 0x170 + - sizeof(struct p54_control_hdr)) - ieee80211_stop_queues(dev); - } - spin_unlock_irqrestore(&priv->tx_queue.lock, flags); - - data->req_id = cpu_to_le32(target_addr + 0x70); -} - -static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb, - struct ieee80211_tx_control *control) -{ - struct ieee80211_tx_queue_stats_data *current_queue; - struct p54_common *priv = dev->priv; - struct p54_control_hdr *hdr; - struct p54_tx_control_allocdata *txhdr; - struct ieee80211_tx_control *control_copy; - size_t padding, len; - u8 rate; - - current_queue = &priv->tx_stats.data[control->queue]; - if (unlikely(current_queue->len > current_queue->limit)) - return NETDEV_TX_BUSY; - current_queue->len++; - current_queue->count++; - if (current_queue->len == current_queue->limit) - ieee80211_stop_queue(dev, control->queue); - - padding = (unsigned long)(skb->data - (sizeof(*hdr) + sizeof(*txhdr))) & 3; - len = skb->len; - - control_copy = kmalloc(sizeof(*control), GFP_ATOMIC); - if (control_copy) - memcpy(control_copy, control, sizeof(*control)); - - txhdr = (struct p54_tx_control_allocdata *) - skb_push(skb, sizeof(*txhdr) + padding); - hdr = (struct p54_control_hdr *) skb_push(skb, sizeof(*hdr)); - - if (padding) - hdr->magic1 = cpu_to_le16(0x4010); - else - hdr->magic1 = cpu_to_le16(0x0010); - hdr->len = cpu_to_le16(len); - hdr->type = (control->flags & IEEE80211_TXCTL_NO_ACK) ? 0 : cpu_to_le16(1); - hdr->retry1 = hdr->retry2 = control->retry_limit; - p54_assign_address(dev, skb, hdr, skb->len, control_copy); - - memset(txhdr->wep_key, 0x0, 16); - txhdr->padding = 0; - txhdr->padding2 = 0; - - /* TODO: add support for alternate retry TX rates */ - rate = control->tx_rate->hw_value; - if (control->flags & IEEE80211_TXCTL_SHORT_PREAMBLE) - rate |= 0x10; - if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS) - rate |= 0x40; - else if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) - rate |= 0x20; - memset(txhdr->rateset, rate, 8); - txhdr->wep_key_present = 0; - txhdr->wep_key_len = 0; - txhdr->frame_type = cpu_to_le32(control->queue + 4); - txhdr->magic4 = 0; - txhdr->antenna = (control->antenna_sel_tx == 0) ? - 2 : control->antenna_sel_tx - 1; - txhdr->output_power = 0x7f; // HW Maximum - txhdr->magic5 = (control->flags & IEEE80211_TXCTL_NO_ACK) ? - 0 : ((rate > 0x3) ? cpu_to_le32(0x33) : cpu_to_le32(0x23)); - if (padding) - txhdr->align[0] = padding; - - priv->tx(dev, hdr, skb->len, 0); - return 0; -} - -static int p54_set_filter(struct ieee80211_hw *dev, u16 filter_type, - const u8 *dst, const u8 *src, u8 antenna, - u32 magic3, u32 magic8, u32 magic9) -{ - struct p54_common *priv = dev->priv; - struct p54_control_hdr *hdr; - struct p54_tx_control_filter *filter; - - hdr = kzalloc(sizeof(*hdr) + sizeof(*filter) + - priv->tx_hdr_len, GFP_ATOMIC); - if (!hdr) - return -ENOMEM; - - hdr = (void *)hdr + priv->tx_hdr_len; - - filter = (struct p54_tx_control_filter *) hdr->data; - hdr->magic1 = cpu_to_le16(0x8001); - hdr->len = cpu_to_le16(sizeof(*filter)); - p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*filter), NULL); - hdr->type = cpu_to_le16(P54_CONTROL_TYPE_FILTER_SET); - - filter->filter_type = cpu_to_le16(filter_type); - memcpy(filter->dst, dst, ETH_ALEN); - if (!src) - memset(filter->src, ~0, ETH_ALEN); - else - memcpy(filter->src, src, ETH_ALEN); - filter->antenna = antenna; - filter->magic3 = cpu_to_le32(magic3); - filter->rx_addr = cpu_to_le32(priv->rx_end); - filter->max_rx = cpu_to_le16(0x0620); /* FIXME: for usb ver 1.. maybe */ - filter->rxhw = priv->rxhw; - filter->magic8 = cpu_to_le16(magic8); - filter->magic9 = cpu_to_le16(magic9); - - priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*filter), 1); - return 0; -} - -static int p54_set_freq(struct ieee80211_hw *dev, __le16 freq) -{ - struct p54_common *priv = dev->priv; - struct p54_control_hdr *hdr; - struct p54_tx_control_channel *chan; - unsigned int i; - size_t payload_len = sizeof(*chan) + sizeof(u32)*2 + - sizeof(*chan->curve_data) * - priv->curve_data->points_per_channel; - void *entry; - - hdr = kzalloc(sizeof(*hdr) + payload_len + - priv->tx_hdr_len, GFP_KERNEL); - if (!hdr) - return -ENOMEM; - - hdr = (void *)hdr + priv->tx_hdr_len; - - chan = (struct p54_tx_control_channel *) hdr->data; - - hdr->magic1 = cpu_to_le16(0x8001); - hdr->len = cpu_to_le16(sizeof(*chan)); - hdr->type = cpu_to_le16(P54_CONTROL_TYPE_CHANNEL_CHANGE); - p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + payload_len, NULL); - - chan->magic1 = cpu_to_le16(0x1); - chan->magic2 = cpu_to_le16(0x0); - - for (i = 0; i < priv->iq_autocal_len; i++) { - if (priv->iq_autocal[i].freq != freq) - continue; - - memcpy(&chan->iq_autocal, &priv->iq_autocal[i], - sizeof(*priv->iq_autocal)); - break; - } - if (i == priv->iq_autocal_len) - goto err; - - for (i = 0; i < priv->output_limit_len; i++) { - if (priv->output_limit[i].freq != freq) - continue; - - chan->val_barker = 0x38; - chan->val_bpsk = priv->output_limit[i].val_bpsk; - chan->val_qpsk = priv->output_limit[i].val_qpsk; - chan->val_16qam = priv->output_limit[i].val_16qam; - chan->val_64qam = priv->output_limit[i].val_64qam; - break; - } - if (i == priv->output_limit_len) - goto err; - - chan->pa_points_per_curve = priv->curve_data->points_per_channel; - - entry = priv->curve_data->data; - for (i = 0; i < priv->curve_data->channels; i++) { - if (*((__le16 *)entry) != freq) { - entry += sizeof(__le16); - entry += sizeof(struct pda_pa_curve_data_sample_rev1) * - chan->pa_points_per_curve; - continue; - } - - entry += sizeof(__le16); - memcpy(chan->curve_data, entry, sizeof(*chan->curve_data) * - chan->pa_points_per_curve); - break; - } - - memcpy(hdr->data + payload_len - 4, &chan->val_bpsk, 4); - - priv->tx(dev, hdr, sizeof(*hdr) + payload_len, 1); - return 0; - - err: - printk(KERN_ERR "%s: frequency change failed\n", wiphy_name(dev->wiphy)); - kfree(hdr); - return -EINVAL; -} - -static int p54_set_leds(struct ieee80211_hw *dev, int mode, int link, int act) -{ - struct p54_common *priv = dev->priv; - struct p54_control_hdr *hdr; - struct p54_tx_control_led *led; - - hdr = kzalloc(sizeof(*hdr) + sizeof(*led) + - priv->tx_hdr_len, GFP_KERNEL); - if (!hdr) - return -ENOMEM; - - hdr = (void *)hdr + priv->tx_hdr_len; - hdr->magic1 = cpu_to_le16(0x8001); - hdr->len = cpu_to_le16(sizeof(*led)); - hdr->type = cpu_to_le16(P54_CONTROL_TYPE_LED); - p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*led), NULL); - - led = (struct p54_tx_control_led *) hdr->data; - led->mode = cpu_to_le16(mode); - led->led_permanent = cpu_to_le16(link); - led->led_temporary = cpu_to_le16(act); - led->duration = cpu_to_le16(1000); - - priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*led), 1); - - return 0; -} - -#define P54_SET_QUEUE(queue, ai_fs, cw_min, cw_max, _txop) \ -do { \ - queue.aifs = cpu_to_le16(ai_fs); \ - queue.cwmin = cpu_to_le16(cw_min); \ - queue.cwmax = cpu_to_le16(cw_max); \ - queue.txop = cpu_to_le16(_txop); \ -} while(0) - -static void p54_init_vdcf(struct ieee80211_hw *dev) -{ - struct p54_common *priv = dev->priv; - struct p54_control_hdr *hdr; - struct p54_tx_control_vdcf *vdcf; - - /* all USB V1 adapters need a extra headroom */ - hdr = (void *)priv->cached_vdcf + priv->tx_hdr_len; - hdr->magic1 = cpu_to_le16(0x8001); - hdr->len = cpu_to_le16(sizeof(*vdcf)); - hdr->type = cpu_to_le16(P54_CONTROL_TYPE_DCFINIT); - hdr->req_id = cpu_to_le32(priv->rx_start); - - vdcf = (struct p54_tx_control_vdcf *) hdr->data; - - P54_SET_QUEUE(vdcf->queue[0], 0x0002, 0x0003, 0x0007, 47); - P54_SET_QUEUE(vdcf->queue[1], 0x0002, 0x0007, 0x000f, 94); - P54_SET_QUEUE(vdcf->queue[2], 0x0003, 0x000f, 0x03ff, 0); - P54_SET_QUEUE(vdcf->queue[3], 0x0007, 0x000f, 0x03ff, 0); -} - -static void p54_set_vdcf(struct ieee80211_hw *dev) -{ - struct p54_common *priv = dev->priv; - struct p54_control_hdr *hdr; - struct p54_tx_control_vdcf *vdcf; - - hdr = (void *)priv->cached_vdcf + priv->tx_hdr_len; - - p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*vdcf), NULL); - - vdcf = (struct p54_tx_control_vdcf *) hdr->data; - - if (dev->conf.flags & IEEE80211_CONF_SHORT_SLOT_TIME) { - vdcf->slottime = 9; - vdcf->magic1 = 0x00; - vdcf->magic2 = 0x10; - } else { - vdcf->slottime = 20; - vdcf->magic1 = 0x0a; - vdcf->magic2 = 0x06; - } - - /* (see prism54/isl_oid.h for further details) */ - vdcf->frameburst = cpu_to_le16(0); - - priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*vdcf), 0); -} - -static int p54_start(struct ieee80211_hw *dev) -{ - struct p54_common *priv = dev->priv; - int err; - - err = priv->open(dev); - if (!err) - priv->mode = IEEE80211_IF_TYPE_MNTR; - - return err; -} - -static void p54_stop(struct ieee80211_hw *dev) -{ - struct p54_common *priv = dev->priv; - struct sk_buff *skb; - while ((skb = skb_dequeue(&priv->tx_queue))) { - struct memrecord *range = (struct memrecord *)&skb->cb; - if (range->control) - kfree(range->control); - kfree_skb(skb); - } - priv->stop(dev); - priv->mode = IEEE80211_IF_TYPE_INVALID; -} - -static int p54_add_interface(struct ieee80211_hw *dev, - struct ieee80211_if_init_conf *conf) -{ - struct p54_common *priv = dev->priv; - - if (priv->mode != IEEE80211_IF_TYPE_MNTR) - return -EOPNOTSUPP; - - switch (conf->type) { - case IEEE80211_IF_TYPE_STA: - priv->mode = conf->type; - break; - default: - return -EOPNOTSUPP; - } - - memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN); - - p54_set_filter(dev, 0, priv->mac_addr, NULL, 0, 1, 0, 0xF642); - p54_set_filter(dev, 0, priv->mac_addr, NULL, 1, 0, 0, 0xF642); - - switch (conf->type) { - case IEEE80211_IF_TYPE_STA: - p54_set_filter(dev, 1, priv->mac_addr, NULL, 0, 0x15F, 0x1F4, 0); - break; - default: - BUG(); /* impossible */ - break; - } - - p54_set_leds(dev, 1, 0, 0); - - return 0; -} - -static void p54_remove_interface(struct ieee80211_hw *dev, - struct ieee80211_if_init_conf *conf) -{ - struct p54_common *priv = dev->priv; - priv->mode = IEEE80211_IF_TYPE_MNTR; - memset(priv->mac_addr, 0, ETH_ALEN); - p54_set_filter(dev, 0, priv->mac_addr, NULL, 2, 0, 0, 0); -} - -static int p54_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf) -{ - int ret; - - ret = p54_set_freq(dev, cpu_to_le16(conf->channel->center_freq)); - p54_set_vdcf(dev); - return ret; -} - -static int p54_config_interface(struct ieee80211_hw *dev, - struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf) -{ - struct p54_common *priv = dev->priv; - - p54_set_filter(dev, 0, priv->mac_addr, conf->bssid, 0, 1, 0, 0xF642); - p54_set_filter(dev, 0, priv->mac_addr, conf->bssid, 2, 0, 0, 0); - p54_set_leds(dev, 1, !is_multicast_ether_addr(conf->bssid), 0); - memcpy(priv->bssid, conf->bssid, ETH_ALEN); - return 0; -} - -static void p54_configure_filter(struct ieee80211_hw *dev, - unsigned int changed_flags, - unsigned int *total_flags, - int mc_count, struct dev_mc_list *mclist) -{ - struct p54_common *priv = dev->priv; - - *total_flags &= FIF_BCN_PRBRESP_PROMISC; - - if (changed_flags & FIF_BCN_PRBRESP_PROMISC) { - if (*total_flags & FIF_BCN_PRBRESP_PROMISC) - p54_set_filter(dev, 0, priv->mac_addr, - NULL, 2, 0, 0, 0); - else - p54_set_filter(dev, 0, priv->mac_addr, - priv->bssid, 2, 0, 0, 0); - } -} - -static int p54_conf_tx(struct ieee80211_hw *dev, int queue, - const struct ieee80211_tx_queue_params *params) -{ - struct p54_common *priv = dev->priv; - struct p54_tx_control_vdcf *vdcf; - - vdcf = (struct p54_tx_control_vdcf *)(((struct p54_control_hdr *) - ((void *)priv->cached_vdcf + priv->tx_hdr_len))->data); - - if ((params) && !((queue < 0) || (queue > 4))) { - P54_SET_QUEUE(vdcf->queue[queue], params->aifs, - params->cw_min, params->cw_max, params->txop); - } else - return -EINVAL; - - p54_set_vdcf(dev); - - return 0; -} - -static int p54_get_stats(struct ieee80211_hw *dev, - struct ieee80211_low_level_stats *stats) -{ - /* TODO */ - return 0; -} - -static int p54_get_tx_stats(struct ieee80211_hw *dev, - struct ieee80211_tx_queue_stats *stats) -{ - struct p54_common *priv = dev->priv; - unsigned int i; - - for (i = 0; i < dev->queues; i++) - memcpy(&stats->data[i], &priv->tx_stats.data[i], - sizeof(stats->data[i])); - - return 0; -} - -static const struct ieee80211_ops p54_ops = { - .tx = p54_tx, - .start = p54_start, - .stop = p54_stop, - .add_interface = p54_add_interface, - .remove_interface = p54_remove_interface, - .config = p54_config, - .config_interface = p54_config_interface, - .configure_filter = p54_configure_filter, - .conf_tx = p54_conf_tx, - .get_stats = p54_get_stats, - .get_tx_stats = p54_get_tx_stats -}; - -struct ieee80211_hw *p54_init_common(size_t priv_data_len) -{ - struct ieee80211_hw *dev; - struct p54_common *priv; - - dev = ieee80211_alloc_hw(priv_data_len, &p54_ops); - if (!dev) - return NULL; - - priv = dev->priv; - priv->mode = IEEE80211_IF_TYPE_INVALID; - skb_queue_head_init(&priv->tx_queue); - dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &band_2GHz; - dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | /* not sure */ - IEEE80211_HW_RX_INCLUDES_FCS; - dev->channel_change_time = 1000; /* TODO: find actual value */ - dev->max_rssi = 127; - - priv->tx_stats.data[0].limit = 5; - dev->queues = 1; - - dev->extra_tx_headroom = sizeof(struct p54_control_hdr) + 4 + - sizeof(struct p54_tx_control_allocdata); - - priv->cached_vdcf = kzalloc(sizeof(struct p54_tx_control_vdcf) + - priv->tx_hdr_len + sizeof(struct p54_control_hdr), GFP_KERNEL); - - if (!priv->cached_vdcf) { - ieee80211_free_hw(dev); - return NULL; - } - - p54_init_vdcf(dev); - - return dev; -} -EXPORT_SYMBOL_GPL(p54_init_common); - -void p54_free_common(struct ieee80211_hw *dev) -{ - struct p54_common *priv = dev->priv; - kfree(priv->iq_autocal); - kfree(priv->output_limit); - kfree(priv->curve_data); - kfree(priv->cached_vdcf); -} -EXPORT_SYMBOL_GPL(p54_free_common); - -static int __init p54_init(void) -{ - return 0; -} - -static void __exit p54_exit(void) -{ -} - -module_init(p54_init); -module_exit(p54_exit); diff --git a/drivers/net/wireless/p54common.h b/drivers/net/wireless/p54common.h deleted file mode 100644 index c15b56e1d75e..000000000000 --- a/drivers/net/wireless/p54common.h +++ /dev/null @@ -1,254 +0,0 @@ -#ifndef PRISM54COMMON_H -#define PRISM54COMMON_H - -/* - * Common code specific definitions for mac80211 Prism54 drivers - * - * Copyright (c) 2006, Michael Wu - * Copyright (c) 2007, Christian Lamparter - * - * Based on the islsm (softmac prism54) driver, which is: - * Copyright 2004-2006 Jean-Baptiste Note , et al. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -struct bootrec { - __le32 code; - __le32 len; - u32 data[0]; -} __attribute__((packed)); - -struct bootrec_exp_if { - __le16 role; - __le16 if_id; - __le16 variant; - __le16 btm_compat; - __le16 top_compat; -} __attribute__((packed)); - -#define BR_CODE_MIN 0x80000000 -#define BR_CODE_COMPONENT_ID 0x80000001 -#define BR_CODE_COMPONENT_VERSION 0x80000002 -#define BR_CODE_DEPENDENT_IF 0x80000003 -#define BR_CODE_EXPOSED_IF 0x80000004 -#define BR_CODE_DESCR 0x80000101 -#define BR_CODE_MAX 0x8FFFFFFF -#define BR_CODE_END_OF_BRA 0xFF0000FF -#define LEGACY_BR_CODE_END_OF_BRA 0xFFFFFFFF - -#define FW_FMAC 0x464d4143 -#define FW_LM86 0x4c4d3836 -#define FW_LM87 0x4c4d3837 -#define FW_LM20 0x4c4d3230 - -/* PDA defines are Copyright (C) 2005 Nokia Corporation (taken from islsm_pda.h) */ - -struct pda_entry { - __le16 len; /* includes both code and data */ - __le16 code; - u8 data[0]; -} __attribute__ ((packed)); - -struct eeprom_pda_wrap { - __le32 magic; - __le16 pad; - __le16 len; - __le32 arm_opcode; - u8 data[0]; -} __attribute__ ((packed)); - -struct pda_iq_autocal_entry { - __le16 freq; - __le16 iq_param[4]; -} __attribute__ ((packed)); - -struct pda_channel_output_limit { - __le16 freq; - u8 val_bpsk; - u8 val_qpsk; - u8 val_16qam; - u8 val_64qam; - u8 rate_set_mask; - u8 rate_set_size; -} __attribute__ ((packed)); - -struct pda_pa_curve_data_sample_rev0 { - u8 rf_power; - u8 pa_detector; - u8 pcv; -} __attribute__ ((packed)); - -struct pda_pa_curve_data_sample_rev1 { - u8 rf_power; - u8 pa_detector; - u8 data_barker; - u8 data_bpsk; - u8 data_qpsk; - u8 data_16qam; - u8 data_64qam; - u8 padding; -} __attribute__ ((packed)); - -struct pda_pa_curve_data { - u8 cal_method_rev; - u8 channels; - u8 points_per_channel; - u8 padding; - u8 data[0]; -} __attribute__ ((packed)); - -/* - * this defines the PDR codes used to build PDAs as defined in document - * number 553155. The current implementation mirrors version 1.1 of the - * document and lists only PDRs supported by the ARM platform. - */ - -/* common and choice range (0x0000 - 0x0fff) */ -#define PDR_END 0x0000 -#define PDR_MANUFACTURING_PART_NUMBER 0x0001 -#define PDR_PDA_VERSION 0x0002 -#define PDR_NIC_SERIAL_NUMBER 0x0003 - -#define PDR_MAC_ADDRESS 0x0101 -#define PDR_REGULATORY_DOMAIN_LIST 0x0103 -#define PDR_TEMPERATURE_TYPE 0x0107 - -#define PDR_PRISM_PCI_IDENTIFIER 0x0402 - -/* ARM range (0x1000 - 0x1fff) */ -#define PDR_COUNTRY_INFORMATION 0x1000 -#define PDR_INTERFACE_LIST 0x1001 -#define PDR_HARDWARE_PLATFORM_COMPONENT_ID 0x1002 -#define PDR_OEM_NAME 0x1003 -#define PDR_PRODUCT_NAME 0x1004 -#define PDR_UTF8_OEM_NAME 0x1005 -#define PDR_UTF8_PRODUCT_NAME 0x1006 -#define PDR_COUNTRY_LIST 0x1007 -#define PDR_DEFAULT_COUNTRY 0x1008 - -#define PDR_ANTENNA_GAIN 0x1100 - -#define PDR_PRISM_INDIGO_PA_CALIBRATION_DATA 0x1901 -#define PDR_RSSI_LINEAR_APPROXIMATION 0x1902 -#define PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS 0x1903 -#define PDR_PRISM_PA_CAL_CURVE_DATA 0x1904 -#define PDR_RSSI_LINEAR_APPROXIMATION_DUAL_BAND 0x1905 -#define PDR_PRISM_ZIF_TX_IQ_CALIBRATION 0x1906 -#define PDR_REGULATORY_POWER_LIMITS 0x1907 -#define PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED 0x1908 -#define PDR_RADIATED_TRANSMISSION_CORRECTION 0x1909 -#define PDR_PRISM_TX_IQ_CALIBRATION 0x190a - -/* reserved range (0x2000 - 0x7fff) */ - -/* customer range (0x8000 - 0xffff) */ -#define PDR_BASEBAND_REGISTERS 0x8000 -#define PDR_PER_CHANNEL_BASEBAND_REGISTERS 0x8001 - -/* stored in skb->cb */ -struct memrecord { - u32 start_addr; - u32 end_addr; - struct ieee80211_tx_control *control; -}; - -struct p54_eeprom_lm86 { - __le16 offset; - __le16 len; - u8 data[0]; -} __attribute__ ((packed)); - -struct p54_rx_hdr { - __le16 magic; - __le16 len; - __le16 freq; - u8 antenna; - u8 rate; - u8 rssi; - u8 quality; - u16 unknown2; - __le64 timestamp; - u8 data[0]; -} __attribute__ ((packed)); - -struct p54_frame_sent_hdr { - u8 status; - u8 retries; - __le16 ack_rssi; - __le16 seq; - u16 rate; -} __attribute__ ((packed)); - -struct p54_tx_control_allocdata { - u8 rateset[8]; - u16 padding; - u8 wep_key_present; - u8 wep_key_len; - u8 wep_key[16]; - __le32 frame_type; - u32 padding2; - __le16 magic4; - u8 antenna; - u8 output_power; - __le32 magic5; - u8 align[0]; -} __attribute__ ((packed)); - -struct p54_tx_control_filter { - __le16 filter_type; - u8 dst[ETH_ALEN]; - u8 src[ETH_ALEN]; - u8 antenna; - u8 debug; - __le32 magic3; - u8 rates[8]; // FIXME: what's this for? - __le32 rx_addr; - __le16 max_rx; - __le16 rxhw; - __le16 magic8; - __le16 magic9; -} __attribute__ ((packed)); - -struct p54_tx_control_channel { - __le16 magic1; - __le16 magic2; - u8 padding1[20]; - struct pda_iq_autocal_entry iq_autocal; - u8 pa_points_per_curve; - u8 val_barker; - u8 val_bpsk; - u8 val_qpsk; - u8 val_16qam; - u8 val_64qam; - struct pda_pa_curve_data_sample_rev1 curve_data[0]; - /* additional padding/data after curve_data */ -} __attribute__ ((packed)); - -struct p54_tx_control_led { - __le16 mode; - __le16 led_temporary; - __le16 led_permanent; - __le16 duration; -} __attribute__ ((packed)); - -struct p54_tx_vdcf_queues { - __le16 aifs; - __le16 cwmin; - __le16 cwmax; - __le16 txop; -} __attribute__ ((packed)); - -struct p54_tx_control_vdcf { - u8 padding; - u8 slottime; - u8 magic1; - u8 magic2; - struct p54_tx_vdcf_queues queue[8]; - u8 pad2[4]; - __le16 frameburst; -} __attribute__ ((packed)); - -#endif /* PRISM54COMMON_H */ diff --git a/drivers/net/wireless/p54pci.c b/drivers/net/wireless/p54pci.c deleted file mode 100644 index fa527723fbe0..000000000000 --- a/drivers/net/wireless/p54pci.c +++ /dev/null @@ -1,697 +0,0 @@ - -/* - * Linux device driver for PCI based Prism54 - * - * Copyright (c) 2006, Michael Wu - * - * Based on the islsm (softmac prism54) driver, which is: - * Copyright 2004-2006 Jean-Baptiste Note , et al. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "p54.h" -#include "p54pci.h" - -MODULE_AUTHOR("Michael Wu "); -MODULE_DESCRIPTION("Prism54 PCI wireless driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("prism54pci"); - -static struct pci_device_id p54p_table[] __devinitdata = { - /* Intersil PRISM Duette/Prism GT Wireless LAN adapter */ - { PCI_DEVICE(0x1260, 0x3890) }, - /* 3COM 3CRWE154G72 Wireless LAN adapter */ - { PCI_DEVICE(0x10b7, 0x6001) }, - /* Intersil PRISM Indigo Wireless LAN adapter */ - { PCI_DEVICE(0x1260, 0x3877) }, - /* Intersil PRISM Javelin/Xbow Wireless LAN adapter */ - { PCI_DEVICE(0x1260, 0x3886) }, - { }, -}; - -MODULE_DEVICE_TABLE(pci, p54p_table); - -static int p54p_upload_firmware(struct ieee80211_hw *dev) -{ - struct p54p_priv *priv = dev->priv; - const struct firmware *fw_entry = NULL; - __le32 reg; - int err; - __le32 *data; - u32 remains, left, device_addr; - - P54P_WRITE(int_enable, cpu_to_le32(0)); - P54P_READ(int_enable); - udelay(10); - - reg = P54P_READ(ctrl_stat); - reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET); - reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RAMBOOT); - P54P_WRITE(ctrl_stat, reg); - P54P_READ(ctrl_stat); - udelay(10); - - reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RESET); - P54P_WRITE(ctrl_stat, reg); - wmb(); - udelay(10); - - reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET); - P54P_WRITE(ctrl_stat, reg); - wmb(); - - mdelay(50); - - err = request_firmware(&fw_entry, "isl3886", &priv->pdev->dev); - if (err) { - printk(KERN_ERR "%s (prism54pci): cannot find firmware " - "(isl3886)\n", pci_name(priv->pdev)); - return err; - } - - p54_parse_firmware(dev, fw_entry); - - data = (__le32 *) fw_entry->data; - remains = fw_entry->size; - device_addr = ISL38XX_DEV_FIRMWARE_ADDR; - while (remains) { - u32 i = 0; - left = min((u32)0x1000, remains); - P54P_WRITE(direct_mem_base, cpu_to_le32(device_addr)); - P54P_READ(int_enable); - - device_addr += 0x1000; - while (i < left) { - P54P_WRITE(direct_mem_win[i], *data++); - i += sizeof(u32); - } - - remains -= left; - P54P_READ(int_enable); - } - - release_firmware(fw_entry); - - reg = P54P_READ(ctrl_stat); - reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_CLKRUN); - reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET); - reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RAMBOOT); - P54P_WRITE(ctrl_stat, reg); - P54P_READ(ctrl_stat); - udelay(10); - - reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RESET); - P54P_WRITE(ctrl_stat, reg); - wmb(); - udelay(10); - - reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET); - P54P_WRITE(ctrl_stat, reg); - wmb(); - udelay(10); - - return 0; -} - -static irqreturn_t p54p_simple_interrupt(int irq, void *dev_id) -{ - struct p54p_priv *priv = (struct p54p_priv *) dev_id; - __le32 reg; - - reg = P54P_READ(int_ident); - P54P_WRITE(int_ack, reg); - - if (reg & P54P_READ(int_enable)) - complete(&priv->boot_comp); - - return IRQ_HANDLED; -} - -static int p54p_read_eeprom(struct ieee80211_hw *dev) -{ - struct p54p_priv *priv = dev->priv; - struct p54p_ring_control *ring_control = priv->ring_control; - int err; - struct p54_control_hdr *hdr; - void *eeprom; - dma_addr_t rx_mapping, tx_mapping; - u16 alen; - - init_completion(&priv->boot_comp); - err = request_irq(priv->pdev->irq, &p54p_simple_interrupt, - IRQF_SHARED, "prism54pci", priv); - if (err) { - printk(KERN_ERR "%s (prism54pci): failed to register IRQ handler\n", - pci_name(priv->pdev)); - return err; - } - - eeprom = kmalloc(0x2010 + EEPROM_READBACK_LEN, GFP_KERNEL); - if (!eeprom) { - printk(KERN_ERR "%s (prism54pci): no memory for eeprom!\n", - pci_name(priv->pdev)); - err = -ENOMEM; - goto out; - } - - memset(ring_control, 0, sizeof(*ring_control)); - P54P_WRITE(ring_control_base, cpu_to_le32(priv->ring_control_dma)); - P54P_READ(ring_control_base); - udelay(10); - - P54P_WRITE(int_enable, cpu_to_le32(ISL38XX_INT_IDENT_INIT)); - P54P_READ(int_enable); - udelay(10); - - P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET)); - - if (!wait_for_completion_interruptible_timeout(&priv->boot_comp, HZ)) { - printk(KERN_ERR "%s (prism54pci): Cannot boot firmware!\n", - pci_name(priv->pdev)); - err = -EINVAL; - goto out; - } - - P54P_WRITE(int_enable, cpu_to_le32(ISL38XX_INT_IDENT_UPDATE)); - P54P_READ(int_enable); - - hdr = eeprom + 0x2010; - p54_fill_eeprom_readback(hdr); - hdr->req_id = cpu_to_le32(priv->common.rx_start); - - rx_mapping = pci_map_single(priv->pdev, eeprom, - 0x2010, PCI_DMA_FROMDEVICE); - tx_mapping = pci_map_single(priv->pdev, (void *)hdr, - EEPROM_READBACK_LEN, PCI_DMA_TODEVICE); - - ring_control->rx_mgmt[0].host_addr = cpu_to_le32(rx_mapping); - ring_control->rx_mgmt[0].len = cpu_to_le16(0x2010); - ring_control->tx_data[0].host_addr = cpu_to_le32(tx_mapping); - ring_control->tx_data[0].device_addr = hdr->req_id; - ring_control->tx_data[0].len = cpu_to_le16(EEPROM_READBACK_LEN); - - ring_control->host_idx[2] = cpu_to_le32(1); - ring_control->host_idx[1] = cpu_to_le32(1); - - wmb(); - mdelay(100); - P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE)); - - wait_for_completion_interruptible_timeout(&priv->boot_comp, HZ); - wait_for_completion_interruptible_timeout(&priv->boot_comp, HZ); - - pci_unmap_single(priv->pdev, tx_mapping, - EEPROM_READBACK_LEN, PCI_DMA_TODEVICE); - pci_unmap_single(priv->pdev, rx_mapping, - 0x2010, PCI_DMA_FROMDEVICE); - - alen = le16_to_cpu(ring_control->rx_mgmt[0].len); - if (le32_to_cpu(ring_control->device_idx[2]) != 1 || - alen < 0x10) { - printk(KERN_ERR "%s (prism54pci): Cannot read eeprom!\n", - pci_name(priv->pdev)); - err = -EINVAL; - goto out; - } - - p54_parse_eeprom(dev, (u8 *)eeprom + 0x10, alen - 0x10); - - out: - kfree(eeprom); - P54P_WRITE(int_enable, cpu_to_le32(0)); - P54P_READ(int_enable); - udelay(10); - free_irq(priv->pdev->irq, priv); - P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET)); - return err; -} - -static void p54p_refill_rx_ring(struct ieee80211_hw *dev) -{ - struct p54p_priv *priv = dev->priv; - struct p54p_ring_control *ring_control = priv->ring_control; - u32 limit, host_idx, idx; - - host_idx = le32_to_cpu(ring_control->host_idx[0]); - limit = host_idx; - limit -= le32_to_cpu(ring_control->device_idx[0]); - limit = ARRAY_SIZE(ring_control->rx_data) - limit; - - idx = host_idx % ARRAY_SIZE(ring_control->rx_data); - while (limit-- > 1) { - struct p54p_desc *desc = &ring_control->rx_data[idx]; - - if (!desc->host_addr) { - struct sk_buff *skb; - dma_addr_t mapping; - skb = dev_alloc_skb(MAX_RX_SIZE); - if (!skb) - break; - - mapping = pci_map_single(priv->pdev, - skb_tail_pointer(skb), - MAX_RX_SIZE, - PCI_DMA_FROMDEVICE); - desc->host_addr = cpu_to_le32(mapping); - desc->device_addr = 0; // FIXME: necessary? - desc->len = cpu_to_le16(MAX_RX_SIZE); - desc->flags = 0; - priv->rx_buf[idx] = skb; - } - - idx++; - host_idx++; - idx %= ARRAY_SIZE(ring_control->rx_data); - } - - wmb(); - ring_control->host_idx[0] = cpu_to_le32(host_idx); -} - -static irqreturn_t p54p_interrupt(int irq, void *dev_id) -{ - struct ieee80211_hw *dev = dev_id; - struct p54p_priv *priv = dev->priv; - struct p54p_ring_control *ring_control = priv->ring_control; - __le32 reg; - - spin_lock(&priv->lock); - reg = P54P_READ(int_ident); - if (unlikely(reg == cpu_to_le32(0xFFFFFFFF))) { - spin_unlock(&priv->lock); - return IRQ_HANDLED; - } - - P54P_WRITE(int_ack, reg); - - reg &= P54P_READ(int_enable); - - if (reg & cpu_to_le32(ISL38XX_INT_IDENT_UPDATE)) { - struct p54p_desc *desc; - u32 idx, i; - i = priv->tx_idx; - i %= ARRAY_SIZE(ring_control->tx_data); - priv->tx_idx = idx = le32_to_cpu(ring_control->device_idx[1]); - idx %= ARRAY_SIZE(ring_control->tx_data); - - while (i != idx) { - desc = &ring_control->tx_data[i]; - if (priv->tx_buf[i]) { - kfree(priv->tx_buf[i]); - priv->tx_buf[i] = NULL; - } - - pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr), - le16_to_cpu(desc->len), PCI_DMA_TODEVICE); - - desc->host_addr = 0; - desc->device_addr = 0; - desc->len = 0; - desc->flags = 0; - - i++; - i %= ARRAY_SIZE(ring_control->tx_data); - } - - i = priv->rx_idx; - i %= ARRAY_SIZE(ring_control->rx_data); - priv->rx_idx = idx = le32_to_cpu(ring_control->device_idx[0]); - idx %= ARRAY_SIZE(ring_control->rx_data); - while (i != idx) { - u16 len; - struct sk_buff *skb; - desc = &ring_control->rx_data[i]; - len = le16_to_cpu(desc->len); - skb = priv->rx_buf[i]; - - skb_put(skb, len); - - if (p54_rx(dev, skb)) { - pci_unmap_single(priv->pdev, - le32_to_cpu(desc->host_addr), - MAX_RX_SIZE, PCI_DMA_FROMDEVICE); - - priv->rx_buf[i] = NULL; - desc->host_addr = 0; - } else { - skb_trim(skb, 0); - desc->len = cpu_to_le16(MAX_RX_SIZE); - } - - i++; - i %= ARRAY_SIZE(ring_control->rx_data); - } - - p54p_refill_rx_ring(dev); - - wmb(); - P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE)); - } else if (reg & cpu_to_le32(ISL38XX_INT_IDENT_INIT)) - complete(&priv->boot_comp); - - spin_unlock(&priv->lock); - - return reg ? IRQ_HANDLED : IRQ_NONE; -} - -static void p54p_tx(struct ieee80211_hw *dev, struct p54_control_hdr *data, - size_t len, int free_on_tx) -{ - struct p54p_priv *priv = dev->priv; - struct p54p_ring_control *ring_control = priv->ring_control; - unsigned long flags; - struct p54p_desc *desc; - dma_addr_t mapping; - u32 device_idx, idx, i; - - spin_lock_irqsave(&priv->lock, flags); - - device_idx = le32_to_cpu(ring_control->device_idx[1]); - idx = le32_to_cpu(ring_control->host_idx[1]); - i = idx % ARRAY_SIZE(ring_control->tx_data); - - mapping = pci_map_single(priv->pdev, data, len, PCI_DMA_TODEVICE); - desc = &ring_control->tx_data[i]; - desc->host_addr = cpu_to_le32(mapping); - desc->device_addr = data->req_id; - desc->len = cpu_to_le16(len); - desc->flags = 0; - - wmb(); - ring_control->host_idx[1] = cpu_to_le32(idx + 1); - - if (free_on_tx) - priv->tx_buf[i] = data; - - spin_unlock_irqrestore(&priv->lock, flags); - - P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE)); - P54P_READ(dev_int); - - /* FIXME: unlikely to happen because the device usually runs out of - memory before we fill the ring up, but we can make it impossible */ - if (idx - device_idx > ARRAY_SIZE(ring_control->tx_data) - 2) - printk(KERN_INFO "%s: tx overflow.\n", wiphy_name(dev->wiphy)); -} - -static int p54p_open(struct ieee80211_hw *dev) -{ - struct p54p_priv *priv = dev->priv; - int err; - - init_completion(&priv->boot_comp); - err = request_irq(priv->pdev->irq, &p54p_interrupt, - IRQF_SHARED, "prism54pci", dev); - if (err) { - printk(KERN_ERR "%s: failed to register IRQ handler\n", - wiphy_name(dev->wiphy)); - return err; - } - - memset(priv->ring_control, 0, sizeof(*priv->ring_control)); - priv->rx_idx = priv->tx_idx = 0; - p54p_refill_rx_ring(dev); - - p54p_upload_firmware(dev); - - P54P_WRITE(ring_control_base, cpu_to_le32(priv->ring_control_dma)); - P54P_READ(ring_control_base); - wmb(); - udelay(10); - - P54P_WRITE(int_enable, cpu_to_le32(ISL38XX_INT_IDENT_INIT)); - P54P_READ(int_enable); - wmb(); - udelay(10); - - P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET)); - P54P_READ(dev_int); - - if (!wait_for_completion_interruptible_timeout(&priv->boot_comp, HZ)) { - printk(KERN_ERR "%s: Cannot boot firmware!\n", - wiphy_name(dev->wiphy)); - free_irq(priv->pdev->irq, dev); - return -ETIMEDOUT; - } - - P54P_WRITE(int_enable, cpu_to_le32(ISL38XX_INT_IDENT_UPDATE)); - P54P_READ(int_enable); - wmb(); - udelay(10); - - P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE)); - P54P_READ(dev_int); - wmb(); - udelay(10); - - return 0; -} - -static void p54p_stop(struct ieee80211_hw *dev) -{ - struct p54p_priv *priv = dev->priv; - struct p54p_ring_control *ring_control = priv->ring_control; - unsigned int i; - struct p54p_desc *desc; - - P54P_WRITE(int_enable, cpu_to_le32(0)); - P54P_READ(int_enable); - udelay(10); - - free_irq(priv->pdev->irq, dev); - - P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET)); - - for (i = 0; i < ARRAY_SIZE(priv->rx_buf); i++) { - desc = &ring_control->rx_data[i]; - if (desc->host_addr) - pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr), - MAX_RX_SIZE, PCI_DMA_FROMDEVICE); - kfree_skb(priv->rx_buf[i]); - priv->rx_buf[i] = NULL; - } - - for (i = 0; i < ARRAY_SIZE(priv->tx_buf); i++) { - desc = &ring_control->tx_data[i]; - if (desc->host_addr) - pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr), - le16_to_cpu(desc->len), PCI_DMA_TODEVICE); - - kfree(priv->tx_buf[i]); - priv->tx_buf[i] = NULL; - } - - memset(ring_control, 0, sizeof(ring_control)); -} - -static int __devinit p54p_probe(struct pci_dev *pdev, - const struct pci_device_id *id) -{ - struct p54p_priv *priv; - struct ieee80211_hw *dev; - unsigned long mem_addr, mem_len; - int err; - DECLARE_MAC_BUF(mac); - - err = pci_enable_device(pdev); - if (err) { - printk(KERN_ERR "%s (prism54pci): Cannot enable new PCI device\n", - pci_name(pdev)); - return err; - } - - mem_addr = pci_resource_start(pdev, 0); - mem_len = pci_resource_len(pdev, 0); - if (mem_len < sizeof(struct p54p_csr)) { - printk(KERN_ERR "%s (prism54pci): Too short PCI resources\n", - pci_name(pdev)); - pci_disable_device(pdev); - return err; - } - - err = pci_request_regions(pdev, "prism54pci"); - if (err) { - printk(KERN_ERR "%s (prism54pci): Cannot obtain PCI resources\n", - pci_name(pdev)); - return err; - } - - if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) || - pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) { - printk(KERN_ERR "%s (prism54pci): No suitable DMA available\n", - pci_name(pdev)); - goto err_free_reg; - } - - pci_set_master(pdev); - pci_try_set_mwi(pdev); - - pci_write_config_byte(pdev, 0x40, 0); - pci_write_config_byte(pdev, 0x41, 0); - - dev = p54_init_common(sizeof(*priv)); - if (!dev) { - printk(KERN_ERR "%s (prism54pci): ieee80211 alloc failed\n", - pci_name(pdev)); - err = -ENOMEM; - goto err_free_reg; - } - - priv = dev->priv; - priv->pdev = pdev; - - SET_IEEE80211_DEV(dev, &pdev->dev); - pci_set_drvdata(pdev, dev); - - priv->map = ioremap(mem_addr, mem_len); - if (!priv->map) { - printk(KERN_ERR "%s (prism54pci): Cannot map device memory\n", - pci_name(pdev)); - err = -EINVAL; // TODO: use a better error code? - goto err_free_dev; - } - - priv->ring_control = pci_alloc_consistent(pdev, sizeof(*priv->ring_control), - &priv->ring_control_dma); - if (!priv->ring_control) { - printk(KERN_ERR "%s (prism54pci): Cannot allocate rings\n", - pci_name(pdev)); - err = -ENOMEM; - goto err_iounmap; - } - memset(priv->ring_control, 0, sizeof(*priv->ring_control)); - - err = p54p_upload_firmware(dev); - if (err) - goto err_free_desc; - - err = p54p_read_eeprom(dev); - if (err) - goto err_free_desc; - - priv->common.open = p54p_open; - priv->common.stop = p54p_stop; - priv->common.tx = p54p_tx; - - spin_lock_init(&priv->lock); - - err = ieee80211_register_hw(dev); - if (err) { - printk(KERN_ERR "%s (prism54pci): Cannot register netdevice\n", - pci_name(pdev)); - goto err_free_common; - } - - printk(KERN_INFO "%s: hwaddr %s, isl38%02x\n", - wiphy_name(dev->wiphy), - print_mac(mac, dev->wiphy->perm_addr), - priv->common.version); - - return 0; - - err_free_common: - p54_free_common(dev); - - err_free_desc: - pci_free_consistent(pdev, sizeof(*priv->ring_control), - priv->ring_control, priv->ring_control_dma); - - err_iounmap: - iounmap(priv->map); - - err_free_dev: - pci_set_drvdata(pdev, NULL); - ieee80211_free_hw(dev); - - err_free_reg: - pci_release_regions(pdev); - pci_disable_device(pdev); - return err; -} - -static void __devexit p54p_remove(struct pci_dev *pdev) -{ - struct ieee80211_hw *dev = pci_get_drvdata(pdev); - struct p54p_priv *priv; - - if (!dev) - return; - - ieee80211_unregister_hw(dev); - priv = dev->priv; - pci_free_consistent(pdev, sizeof(*priv->ring_control), - priv->ring_control, priv->ring_control_dma); - p54_free_common(dev); - iounmap(priv->map); - pci_release_regions(pdev); - pci_disable_device(pdev); - ieee80211_free_hw(dev); -} - -#ifdef CONFIG_PM -static int p54p_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct ieee80211_hw *dev = pci_get_drvdata(pdev); - struct p54p_priv *priv = dev->priv; - - if (priv->common.mode != IEEE80211_IF_TYPE_INVALID) { - ieee80211_stop_queues(dev); - p54p_stop(dev); - } - - pci_save_state(pdev); - pci_set_power_state(pdev, pci_choose_state(pdev, state)); - return 0; -} - -static int p54p_resume(struct pci_dev *pdev) -{ - struct ieee80211_hw *dev = pci_get_drvdata(pdev); - struct p54p_priv *priv = dev->priv; - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - - if (priv->common.mode != IEEE80211_IF_TYPE_INVALID) { - p54p_open(dev); - ieee80211_start_queues(dev); - } - - return 0; -} -#endif /* CONFIG_PM */ - -static struct pci_driver p54p_driver = { - .name = "prism54pci", - .id_table = p54p_table, - .probe = p54p_probe, - .remove = __devexit_p(p54p_remove), -#ifdef CONFIG_PM - .suspend = p54p_suspend, - .resume = p54p_resume, -#endif /* CONFIG_PM */ -}; - -static int __init p54p_init(void) -{ - return pci_register_driver(&p54p_driver); -} - -static void __exit p54p_exit(void) -{ - pci_unregister_driver(&p54p_driver); -} - -module_init(p54p_init); -module_exit(p54p_exit); diff --git a/drivers/net/wireless/p54pci.h b/drivers/net/wireless/p54pci.h deleted file mode 100644 index 5bedd7af385d..000000000000 --- a/drivers/net/wireless/p54pci.h +++ /dev/null @@ -1,106 +0,0 @@ -#ifndef PRISM54PCI_H -#define PRISM54PCI_H - -/* - * Defines for PCI based mac80211 Prism54 driver - * - * Copyright (c) 2006, Michael Wu - * - * Based on the islsm (softmac prism54) driver, which is: - * Copyright 2004-2006 Jean-Baptiste Note , et al. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -/* Device Interrupt register bits */ -#define ISL38XX_DEV_INT_RESET 0x0001 -#define ISL38XX_DEV_INT_UPDATE 0x0002 -#define ISL38XX_DEV_INT_WAKEUP 0x0008 -#define ISL38XX_DEV_INT_SLEEP 0x0010 -#define ISL38XX_DEV_INT_ABORT 0x0020 -/* these two only used in USB */ -#define ISL38XX_DEV_INT_DATA 0x0040 -#define ISL38XX_DEV_INT_MGMT 0x0080 - -#define ISL38XX_DEV_INT_PCIUART_CTS 0x4000 -#define ISL38XX_DEV_INT_PCIUART_DR 0x8000 - -/* Interrupt Identification/Acknowledge/Enable register bits */ -#define ISL38XX_INT_IDENT_UPDATE 0x0002 -#define ISL38XX_INT_IDENT_INIT 0x0004 -#define ISL38XX_INT_IDENT_WAKEUP 0x0008 -#define ISL38XX_INT_IDENT_SLEEP 0x0010 -#define ISL38XX_INT_IDENT_PCIUART_CTS 0x4000 -#define ISL38XX_INT_IDENT_PCIUART_DR 0x8000 - -/* Control/Status register bits */ -#define ISL38XX_CTRL_STAT_SLEEPMODE 0x00000200 -#define ISL38XX_CTRL_STAT_CLKRUN 0x00800000 -#define ISL38XX_CTRL_STAT_RESET 0x10000000 -#define ISL38XX_CTRL_STAT_RAMBOOT 0x20000000 -#define ISL38XX_CTRL_STAT_STARTHALTED 0x40000000 -#define ISL38XX_CTRL_STAT_HOST_OVERRIDE 0x80000000 - -struct p54p_csr { - __le32 dev_int; - u8 unused_1[12]; - __le32 int_ident; - __le32 int_ack; - __le32 int_enable; - u8 unused_2[4]; - union { - __le32 ring_control_base; - __le32 gen_purp_com[2]; - }; - u8 unused_3[8]; - __le32 direct_mem_base; - u8 unused_4[44]; - __le32 dma_addr; - __le32 dma_len; - __le32 dma_ctrl; - u8 unused_5[12]; - __le32 ctrl_stat; - u8 unused_6[1924]; - u8 cardbus_cis[0x800]; - u8 direct_mem_win[0x1000]; -} __attribute__ ((packed)); - -/* usb backend only needs the register defines above */ -#ifndef PRISM54USB_H -struct p54p_desc { - __le32 host_addr; - __le32 device_addr; - __le16 len; - __le16 flags; -} __attribute__ ((packed)); - -struct p54p_ring_control { - __le32 host_idx[4]; - __le32 device_idx[4]; - struct p54p_desc rx_data[8]; - struct p54p_desc tx_data[32]; - struct p54p_desc rx_mgmt[4]; - struct p54p_desc tx_mgmt[4]; -} __attribute__ ((packed)); - -#define P54P_READ(r) (__force __le32)__raw_readl(&priv->map->r) -#define P54P_WRITE(r, val) __raw_writel((__force u32)(__le32)(val), &priv->map->r) - -struct p54p_priv { - struct p54_common common; - struct pci_dev *pdev; - struct p54p_csr __iomem *map; - - spinlock_t lock; - struct p54p_ring_control *ring_control; - dma_addr_t ring_control_dma; - u32 rx_idx, tx_idx; - struct sk_buff *rx_buf[8]; - void *tx_buf[32]; - struct completion boot_comp; -}; - -#endif /* PRISM54USB_H */ -#endif /* PRISM54PCI_H */ diff --git a/drivers/net/wireless/p54usb.c b/drivers/net/wireless/p54usb.c deleted file mode 100644 index 98ddbb3b3273..000000000000 --- a/drivers/net/wireless/p54usb.c +++ /dev/null @@ -1,910 +0,0 @@ - -/* - * Linux device driver for USB based Prism54 - * - * Copyright (c) 2006, Michael Wu - * - * Based on the islsm (softmac prism54) driver, which is: - * Copyright 2004-2006 Jean-Baptiste Note , et al. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "p54.h" -#include "p54usb.h" - -MODULE_AUTHOR("Michael Wu "); -MODULE_DESCRIPTION("Prism54 USB wireless driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("prism54usb"); - -static struct usb_device_id p54u_table[] __devinitdata = { - /* Version 1 devices (pci chip + net2280) */ - {USB_DEVICE(0x0506, 0x0a11)}, /* 3COM 3CRWE254G72 */ - {USB_DEVICE(0x0707, 0xee06)}, /* SMC 2862W-G */ - {USB_DEVICE(0x083a, 0x4501)}, /* Accton 802.11g WN4501 USB */ - {USB_DEVICE(0x083a, 0x4502)}, /* Siemens Gigaset USB Adapter */ - {USB_DEVICE(0x083a, 0x5501)}, /* Phillips CPWUA054 */ - {USB_DEVICE(0x0846, 0x4200)}, /* Netgear WG121 */ - {USB_DEVICE(0x0846, 0x4210)}, /* Netgear WG121 the second ? */ - {USB_DEVICE(0x0846, 0x4220)}, /* Netgear WG111 */ - {USB_DEVICE(0x0cde, 0x0006)}, /* Medion 40900, Roper Europe */ - {USB_DEVICE(0x124a, 0x4023)}, /* Shuttle PN15, Airvast WM168g, IOGear GWU513 */ - {USB_DEVICE(0x1915, 0x2234)}, /* Linksys WUSB54G OEM */ - {USB_DEVICE(0x1915, 0x2235)}, /* Linksys WUSB54G Portable OEM */ - {USB_DEVICE(0x2001, 0x3701)}, /* DLink DWL-G120 Spinnaker */ - {USB_DEVICE(0x2001, 0x3703)}, /* DLink DWL-G122 */ - {USB_DEVICE(0x5041, 0x2234)}, /* Linksys WUSB54G */ - {USB_DEVICE(0x5041, 0x2235)}, /* Linksys WUSB54G Portable */ - - /* Version 2 devices (3887) */ - {USB_DEVICE(0x050d, 0x7050)}, /* Belkin F5D7050 ver 1000 */ - {USB_DEVICE(0x0572, 0x2000)}, /* Cohiba Proto board */ - {USB_DEVICE(0x0572, 0x2002)}, /* Cohiba Proto board */ - {USB_DEVICE(0x0707, 0xee13)}, /* SMC 2862W-G version 2 */ - {USB_DEVICE(0x083a, 0x4521)}, /* Siemens Gigaset USB Adapter 54 version 2 */ - {USB_DEVICE(0x0846, 0x4240)}, /* Netgear WG111 (v2) */ - {USB_DEVICE(0x0915, 0x2000)}, /* Cohiba Proto board */ - {USB_DEVICE(0x0915, 0x2002)}, /* Cohiba Proto board */ - {USB_DEVICE(0x0baf, 0x0118)}, /* U.S. Robotics U5 802.11g Adapter*/ - {USB_DEVICE(0x0bf8, 0x1009)}, /* FUJITSU E-5400 USB D1700*/ - {USB_DEVICE(0x0cde, 0x0006)}, /* Medion MD40900 */ - {USB_DEVICE(0x0cde, 0x0008)}, /* Sagem XG703A */ - {USB_DEVICE(0x0d8e, 0x3762)}, /* DLink DWL-G120 Cohiba */ - {USB_DEVICE(0x09aa, 0x1000)}, /* Spinnaker Proto board */ - {USB_DEVICE(0x124a, 0x4025)}, /* IOGear GWU513 (GW3887IK chip) */ - {USB_DEVICE(0x13b1, 0x000a)}, /* Linksys WUSB54G ver 2 */ - {USB_DEVICE(0x13B1, 0x000C)}, /* Linksys WUSB54AG */ - {USB_DEVICE(0x1435, 0x0427)}, /* Inventel UR054G */ - {USB_DEVICE(0x2001, 0x3704)}, /* DLink DWL-G122 rev A2 */ - {USB_DEVICE(0x413c, 0x8102)}, /* Spinnaker DUT */ - {USB_DEVICE(0x413c, 0x8104)}, /* Cohiba Proto board */ - {} -}; - -MODULE_DEVICE_TABLE(usb, p54u_table); - -static void p54u_rx_cb(struct urb *urb) -{ - struct sk_buff *skb = (struct sk_buff *) urb->context; - struct p54u_rx_info *info = (struct p54u_rx_info *)skb->cb; - struct ieee80211_hw *dev = info->dev; - struct p54u_priv *priv = dev->priv; - - if (unlikely(urb->status)) { - info->urb = NULL; - usb_free_urb(urb); - return; - } - - skb_unlink(skb, &priv->rx_queue); - skb_put(skb, urb->actual_length); - if (!priv->hw_type) - skb_pull(skb, sizeof(struct net2280_tx_hdr)); - - if (p54_rx(dev, skb)) { - skb = dev_alloc_skb(MAX_RX_SIZE); - if (unlikely(!skb)) { - usb_free_urb(urb); - /* TODO check rx queue length and refill *somewhere* */ - return; - } - - info = (struct p54u_rx_info *) skb->cb; - info->urb = urb; - info->dev = dev; - urb->transfer_buffer = skb_tail_pointer(skb); - urb->context = skb; - skb_queue_tail(&priv->rx_queue, skb); - } else { - skb_trim(skb, 0); - skb_queue_tail(&priv->rx_queue, skb); - } - - usb_submit_urb(urb, GFP_ATOMIC); -} - -static void p54u_tx_cb(struct urb *urb) -{ - usb_free_urb(urb); -} - -static void p54u_tx_free_cb(struct urb *urb) -{ - kfree(urb->transfer_buffer); - usb_free_urb(urb); -} - -static int p54u_init_urbs(struct ieee80211_hw *dev) -{ - struct p54u_priv *priv = dev->priv; - struct urb *entry; - struct sk_buff *skb; - struct p54u_rx_info *info; - - while (skb_queue_len(&priv->rx_queue) < 32) { - skb = __dev_alloc_skb(MAX_RX_SIZE, GFP_KERNEL); - if (!skb) - break; - entry = usb_alloc_urb(0, GFP_KERNEL); - if (!entry) { - kfree_skb(skb); - break; - } - usb_fill_bulk_urb(entry, priv->udev, usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA), skb_tail_pointer(skb), MAX_RX_SIZE, p54u_rx_cb, skb); - info = (struct p54u_rx_info *) skb->cb; - info->urb = entry; - info->dev = dev; - skb_queue_tail(&priv->rx_queue, skb); - usb_submit_urb(entry, GFP_KERNEL); - } - - return 0; -} - -static void p54u_free_urbs(struct ieee80211_hw *dev) -{ - struct p54u_priv *priv = dev->priv; - struct p54u_rx_info *info; - struct sk_buff *skb; - - while ((skb = skb_dequeue(&priv->rx_queue))) { - info = (struct p54u_rx_info *) skb->cb; - if (!info->urb) - continue; - - usb_kill_urb(info->urb); - kfree_skb(skb); - } -} - -static void p54u_tx_3887(struct ieee80211_hw *dev, struct p54_control_hdr *data, - size_t len, int free_on_tx) -{ - struct p54u_priv *priv = dev->priv; - struct urb *addr_urb, *data_urb; - - addr_urb = usb_alloc_urb(0, GFP_ATOMIC); - if (!addr_urb) - return; - - data_urb = usb_alloc_urb(0, GFP_ATOMIC); - if (!data_urb) { - usb_free_urb(addr_urb); - return; - } - - usb_fill_bulk_urb(addr_urb, priv->udev, - usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), &data->req_id, - sizeof(data->req_id), p54u_tx_cb, dev); - usb_fill_bulk_urb(data_urb, priv->udev, - usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), data, len, - free_on_tx ? p54u_tx_free_cb : p54u_tx_cb, dev); - - usb_submit_urb(addr_urb, GFP_ATOMIC); - usb_submit_urb(data_urb, GFP_ATOMIC); -} - -static void p54u_tx_net2280(struct ieee80211_hw *dev, struct p54_control_hdr *data, - size_t len, int free_on_tx) -{ - struct p54u_priv *priv = dev->priv; - struct urb *int_urb, *data_urb; - struct net2280_tx_hdr *hdr; - struct net2280_reg_write *reg; - - reg = kmalloc(sizeof(*reg), GFP_ATOMIC); - if (!reg) - return; - - int_urb = usb_alloc_urb(0, GFP_ATOMIC); - if (!int_urb) { - kfree(reg); - return; - } - - data_urb = usb_alloc_urb(0, GFP_ATOMIC); - if (!data_urb) { - kfree(reg); - usb_free_urb(int_urb); - return; - } - - reg->port = cpu_to_le16(NET2280_DEV_U32); - reg->addr = cpu_to_le32(P54U_DEV_BASE); - reg->val = cpu_to_le32(ISL38XX_DEV_INT_DATA); - - len += sizeof(*data); - hdr = (void *)data - sizeof(*hdr); - memset(hdr, 0, sizeof(*hdr)); - hdr->device_addr = data->req_id; - hdr->len = cpu_to_le16(len); - - usb_fill_bulk_urb(int_urb, priv->udev, - usb_sndbulkpipe(priv->udev, P54U_PIPE_DEV), reg, sizeof(*reg), - p54u_tx_free_cb, dev); - usb_submit_urb(int_urb, GFP_ATOMIC); - - usb_fill_bulk_urb(data_urb, priv->udev, - usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), hdr, len + sizeof(*hdr), - free_on_tx ? p54u_tx_free_cb : p54u_tx_cb, dev); - usb_submit_urb(data_urb, GFP_ATOMIC); -} - -static int p54u_write(struct p54u_priv *priv, - struct net2280_reg_write *buf, - enum net2280_op_type type, - __le32 addr, __le32 val) -{ - unsigned int ep; - int alen; - - if (type & 0x0800) - ep = usb_sndbulkpipe(priv->udev, P54U_PIPE_DEV); - else - ep = usb_sndbulkpipe(priv->udev, P54U_PIPE_BRG); - - buf->port = cpu_to_le16(type); - buf->addr = addr; - buf->val = val; - - return usb_bulk_msg(priv->udev, ep, buf, sizeof(*buf), &alen, 1000); -} - -static int p54u_read(struct p54u_priv *priv, void *buf, - enum net2280_op_type type, - __le32 addr, __le32 *val) -{ - struct net2280_reg_read *read = buf; - __le32 *reg = buf; - unsigned int ep; - int alen, err; - - if (type & 0x0800) - ep = P54U_PIPE_DEV; - else - ep = P54U_PIPE_BRG; - - read->port = cpu_to_le16(type); - read->addr = addr; - - err = usb_bulk_msg(priv->udev, usb_sndbulkpipe(priv->udev, ep), - read, sizeof(*read), &alen, 1000); - if (err) - return err; - - err = usb_bulk_msg(priv->udev, usb_rcvbulkpipe(priv->udev, ep), - reg, sizeof(*reg), &alen, 1000); - if (err) - return err; - - *val = *reg; - return 0; -} - -static int p54u_bulk_msg(struct p54u_priv *priv, unsigned int ep, - void *data, size_t len) -{ - int alen; - return usb_bulk_msg(priv->udev, usb_sndbulkpipe(priv->udev, ep), - data, len, &alen, 2000); -} - -static int p54u_read_eeprom(struct ieee80211_hw *dev) -{ - struct p54u_priv *priv = dev->priv; - void *buf; - struct p54_control_hdr *hdr; - int err, alen; - size_t offset = priv->hw_type ? 0x10 : 0x20; - - buf = kmalloc(0x2020, GFP_KERNEL); - if (!buf) { - printk(KERN_ERR "prism54usb: cannot allocate memory for " - "eeprom readback!\n"); - return -ENOMEM; - } - - if (priv->hw_type) { - *((u32 *) buf) = priv->common.rx_start; - err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, sizeof(u32)); - if (err) { - printk(KERN_ERR "prism54usb: addr send failed\n"); - goto fail; - } - } else { - struct net2280_reg_write *reg = buf; - reg->port = cpu_to_le16(NET2280_DEV_U32); - reg->addr = cpu_to_le32(P54U_DEV_BASE); - reg->val = cpu_to_le32(ISL38XX_DEV_INT_DATA); - err = p54u_bulk_msg(priv, P54U_PIPE_DEV, buf, sizeof(*reg)); - if (err) { - printk(KERN_ERR "prism54usb: dev_int send failed\n"); - goto fail; - } - } - - hdr = buf + priv->common.tx_hdr_len; - p54_fill_eeprom_readback(hdr); - hdr->req_id = cpu_to_le32(priv->common.rx_start); - if (priv->common.tx_hdr_len) { - struct net2280_tx_hdr *tx_hdr = buf; - tx_hdr->device_addr = hdr->req_id; - tx_hdr->len = cpu_to_le16(EEPROM_READBACK_LEN); - } - - /* we can just pretend to send 0x2000 bytes of nothing in the headers */ - err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, - EEPROM_READBACK_LEN + priv->common.tx_hdr_len); - if (err) { - printk(KERN_ERR "prism54usb: eeprom req send failed\n"); - goto fail; - } - - err = usb_bulk_msg(priv->udev, - usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA), - buf, 0x2020, &alen, 1000); - if (!err && alen > offset) { - p54_parse_eeprom(dev, (u8 *)buf + offset, alen - offset); - } else { - printk(KERN_ERR "prism54usb: eeprom read failed!\n"); - err = -EINVAL; - goto fail; - } - - fail: - kfree(buf); - return err; -} - -static int p54u_upload_firmware_3887(struct ieee80211_hw *dev) -{ - static char start_string[] = "~~~~<\r"; - struct p54u_priv *priv = dev->priv; - const struct firmware *fw_entry = NULL; - int err, alen; - u8 carry = 0; - u8 *buf, *tmp, *data; - unsigned int left, remains, block_size; - struct x2_header *hdr; - unsigned long timeout; - - tmp = buf = kmalloc(P54U_FW_BLOCK, GFP_KERNEL); - if (!buf) { - printk(KERN_ERR "p54usb: cannot allocate firmware upload buffer!\n"); - err = -ENOMEM; - goto err_bufalloc; - } - - memcpy(buf, start_string, 4); - err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, 4); - if (err) { - printk(KERN_ERR "p54usb: reset failed! (%d)\n", err); - goto err_reset; - } - - err = request_firmware(&fw_entry, "isl3887usb_bare", &priv->udev->dev); - if (err) { - printk(KERN_ERR "p54usb: cannot find firmware (isl3887usb_bare)!\n"); - goto err_req_fw_failed; - } - - p54_parse_firmware(dev, fw_entry); - - left = block_size = min((size_t)P54U_FW_BLOCK, fw_entry->size); - strcpy(buf, start_string); - left -= strlen(start_string); - tmp += strlen(start_string); - - data = fw_entry->data; - remains = fw_entry->size; - - hdr = (struct x2_header *)(buf + strlen(start_string)); - memcpy(hdr->signature, X2_SIGNATURE, X2_SIGNATURE_SIZE); - hdr->fw_load_addr = cpu_to_le32(ISL38XX_DEV_FIRMWARE_ADDR); - hdr->fw_length = cpu_to_le32(fw_entry->size); - hdr->crc = cpu_to_le32(~crc32_le(~0, (void *)&hdr->fw_load_addr, - sizeof(u32)*2)); - left -= sizeof(*hdr); - tmp += sizeof(*hdr); - - while (remains) { - while (left--) { - if (carry) { - *tmp++ = carry; - carry = 0; - remains--; - continue; - } - switch (*data) { - case '~': - *tmp++ = '}'; - carry = '^'; - break; - case '}': - *tmp++ = '}'; - carry = ']'; - break; - default: - *tmp++ = *data; - remains--; - break; - } - data++; - } - - err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, block_size); - if (err) { - printk(KERN_ERR "prism54usb: firmware upload failed!\n"); - goto err_upload_failed; - } - - tmp = buf; - left = block_size = min((unsigned int)P54U_FW_BLOCK, remains); - } - - *((__le32 *)buf) = cpu_to_le32(~crc32_le(~0, fw_entry->data, fw_entry->size)); - err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, sizeof(u32)); - if (err) { - printk(KERN_ERR "prism54usb: firmware upload failed!\n"); - goto err_upload_failed; - } - - timeout = jiffies + msecs_to_jiffies(1000); - while (!(err = usb_bulk_msg(priv->udev, - usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA), buf, 128, &alen, 1000))) { - if (alen > 2 && !memcmp(buf, "OK", 2)) - break; - - if (alen > 5 && !memcmp(buf, "ERROR", 5)) { - printk(KERN_INFO "prism54usb: firmware upload failed!\n"); - err = -EINVAL; - break; - } - - if (time_after(jiffies, timeout)) { - printk(KERN_ERR "prism54usb: firmware boot timed out!\n"); - err = -ETIMEDOUT; - break; - } - } - if (err) - goto err_upload_failed; - - buf[0] = 'g'; - buf[1] = '\r'; - err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, 2); - if (err) { - printk(KERN_ERR "prism54usb: firmware boot failed!\n"); - goto err_upload_failed; - } - - timeout = jiffies + msecs_to_jiffies(1000); - while (!(err = usb_bulk_msg(priv->udev, - usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA), buf, 128, &alen, 1000))) { - if (alen > 0 && buf[0] == 'g') - break; - - if (time_after(jiffies, timeout)) { - err = -ETIMEDOUT; - break; - } - } - if (err) - goto err_upload_failed; - - err_upload_failed: - release_firmware(fw_entry); - err_req_fw_failed: - err_reset: - kfree(buf); - err_bufalloc: - return err; -} - -static int p54u_upload_firmware_net2280(struct ieee80211_hw *dev) -{ - struct p54u_priv *priv = dev->priv; - const struct firmware *fw_entry = NULL; - const struct p54p_csr *devreg = (const struct p54p_csr *) P54U_DEV_BASE; - int err, alen; - void *buf; - __le32 reg; - unsigned int remains, offset; - u8 *data; - - buf = kmalloc(512, GFP_KERNEL); - if (!buf) { - printk(KERN_ERR "p54usb: firmware buffer alloc failed!\n"); - return -ENOMEM; - } - - err = request_firmware(&fw_entry, "isl3890usb", &priv->udev->dev); - if (err) { - printk(KERN_ERR "p54usb: cannot find firmware (isl3890usb)!\n"); - kfree(buf); - return err; - } - - p54_parse_firmware(dev, fw_entry); - -#define P54U_WRITE(type, addr, data) \ - do {\ - err = p54u_write(priv, buf, type,\ - cpu_to_le32((u32)(unsigned long)addr), data);\ - if (err) \ - goto fail;\ - } while (0) - -#define P54U_READ(type, addr) \ - do {\ - err = p54u_read(priv, buf, type,\ - cpu_to_le32((u32)(unsigned long)addr), ®);\ - if (err)\ - goto fail;\ - } while (0) - - /* power down net2280 bridge */ - P54U_READ(NET2280_BRG_U32, NET2280_GPIOCTL); - reg |= cpu_to_le32(P54U_BRG_POWER_DOWN); - reg &= cpu_to_le32(~P54U_BRG_POWER_UP); - P54U_WRITE(NET2280_BRG_U32, NET2280_GPIOCTL, reg); - - mdelay(100); - - /* power up bridge */ - reg |= cpu_to_le32(P54U_BRG_POWER_UP); - reg &= cpu_to_le32(~P54U_BRG_POWER_DOWN); - P54U_WRITE(NET2280_BRG_U32, NET2280_GPIOCTL, reg); - - mdelay(100); - - P54U_WRITE(NET2280_BRG_U32, NET2280_DEVINIT, - cpu_to_le32(NET2280_CLK_30Mhz | - NET2280_PCI_ENABLE | - NET2280_PCI_SOFT_RESET)); - - mdelay(20); - - P54U_WRITE(NET2280_BRG_CFG_U16, PCI_COMMAND, - cpu_to_le32(PCI_COMMAND_MEMORY | - PCI_COMMAND_MASTER)); - - P54U_WRITE(NET2280_BRG_CFG_U32, PCI_BASE_ADDRESS_0, - cpu_to_le32(NET2280_BASE)); - - P54U_READ(NET2280_BRG_CFG_U16, PCI_STATUS); - reg |= cpu_to_le32(PCI_STATUS_REC_MASTER_ABORT); - P54U_WRITE(NET2280_BRG_CFG_U16, PCI_STATUS, reg); - - // TODO: we really need this? - P54U_READ(NET2280_BRG_U32, NET2280_RELNUM); - - P54U_WRITE(NET2280_BRG_U32, NET2280_EPA_RSP, - cpu_to_le32(NET2280_CLEAR_NAK_OUT_PACKETS_MODE)); - P54U_WRITE(NET2280_BRG_U32, NET2280_EPC_RSP, - cpu_to_le32(NET2280_CLEAR_NAK_OUT_PACKETS_MODE)); - - P54U_WRITE(NET2280_BRG_CFG_U32, PCI_BASE_ADDRESS_2, - cpu_to_le32(NET2280_BASE2)); - - /* finally done setting up the bridge */ - - P54U_WRITE(NET2280_DEV_CFG_U16, 0x10000 | PCI_COMMAND, - cpu_to_le32(PCI_COMMAND_MEMORY | - PCI_COMMAND_MASTER)); - - P54U_WRITE(NET2280_DEV_CFG_U16, 0x10000 | 0x40 /* TRDY timeout */, 0); - P54U_WRITE(NET2280_DEV_CFG_U32, 0x10000 | PCI_BASE_ADDRESS_0, - cpu_to_le32(P54U_DEV_BASE)); - - P54U_WRITE(NET2280_BRG_U32, NET2280_USBIRQENB1, 0); - P54U_WRITE(NET2280_BRG_U32, NET2280_IRQSTAT1, - cpu_to_le32(NET2280_PCI_INTA_INTERRUPT)); - - /* do romboot */ - P54U_WRITE(NET2280_DEV_U32, &devreg->int_enable, 0); - - P54U_READ(NET2280_DEV_U32, &devreg->ctrl_stat); - reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET); - reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RAMBOOT); - reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_CLKRUN); - P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg); - - mdelay(20); - - reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RESET); - P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg); - - mdelay(20); - - reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET); - P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg); - - mdelay(100); - - P54U_READ(NET2280_DEV_U32, &devreg->int_ident); - P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg); - - /* finally, we can upload firmware now! */ - remains = fw_entry->size; - data = fw_entry->data; - offset = ISL38XX_DEV_FIRMWARE_ADDR; - - while (remains) { - unsigned int block_len = min(remains, (unsigned int)512); - memcpy(buf, data, block_len); - - err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, block_len); - if (err) { - printk(KERN_ERR "prism54usb: firmware block upload " - "failed\n"); - goto fail; - } - - P54U_WRITE(NET2280_DEV_U32, &devreg->direct_mem_base, - cpu_to_le32(0xc0000f00)); - - P54U_WRITE(NET2280_DEV_U32, - 0x0020 | (unsigned long)&devreg->direct_mem_win, 0); - P54U_WRITE(NET2280_DEV_U32, - 0x0020 | (unsigned long)&devreg->direct_mem_win, - cpu_to_le32(1)); - - P54U_WRITE(NET2280_DEV_U32, - 0x0024 | (unsigned long)&devreg->direct_mem_win, - cpu_to_le32(block_len)); - P54U_WRITE(NET2280_DEV_U32, - 0x0028 | (unsigned long)&devreg->direct_mem_win, - cpu_to_le32(offset)); - - P54U_WRITE(NET2280_DEV_U32, &devreg->dma_addr, - cpu_to_le32(NET2280_EPA_FIFO_PCI_ADDR)); - P54U_WRITE(NET2280_DEV_U32, &devreg->dma_len, - cpu_to_le32(block_len >> 2)); - P54U_WRITE(NET2280_DEV_U32, &devreg->dma_ctrl, - cpu_to_le32(ISL38XX_DMA_MASTER_CONTROL_TRIGGER)); - - mdelay(10); - - P54U_READ(NET2280_DEV_U32, - 0x002C | (unsigned long)&devreg->direct_mem_win); - if (!(reg & cpu_to_le32(ISL38XX_DMA_STATUS_DONE)) || - !(reg & cpu_to_le32(ISL38XX_DMA_STATUS_READY))) { - printk(KERN_ERR "prism54usb: firmware DMA transfer " - "failed\n"); - goto fail; - } - - P54U_WRITE(NET2280_BRG_U32, NET2280_EPA_STAT, - cpu_to_le32(NET2280_FIFO_FLUSH)); - - remains -= block_len; - data += block_len; - offset += block_len; - } - - /* do ramboot */ - P54U_READ(NET2280_DEV_U32, &devreg->ctrl_stat); - reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET); - reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_CLKRUN); - reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RAMBOOT); - P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg); - - mdelay(20); - - reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RESET); - P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg); - - reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET); - P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg); - - mdelay(100); - - P54U_READ(NET2280_DEV_U32, &devreg->int_ident); - P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg); - - /* start up the firmware */ - P54U_WRITE(NET2280_DEV_U32, &devreg->int_enable, - cpu_to_le32(ISL38XX_INT_IDENT_INIT)); - - P54U_WRITE(NET2280_BRG_U32, NET2280_IRQSTAT1, - cpu_to_le32(NET2280_PCI_INTA_INTERRUPT)); - - P54U_WRITE(NET2280_BRG_U32, NET2280_USBIRQENB1, - cpu_to_le32(NET2280_PCI_INTA_INTERRUPT_ENABLE | - NET2280_USB_INTERRUPT_ENABLE)); - - P54U_WRITE(NET2280_DEV_U32, &devreg->dev_int, - cpu_to_le32(ISL38XX_DEV_INT_RESET)); - - err = usb_interrupt_msg(priv->udev, - usb_rcvbulkpipe(priv->udev, P54U_PIPE_INT), - buf, sizeof(__le32), &alen, 1000); - if (err || alen != sizeof(__le32)) - goto fail; - - P54U_READ(NET2280_DEV_U32, &devreg->int_ident); - P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg); - - if (!(reg & cpu_to_le32(ISL38XX_INT_IDENT_INIT))) - err = -EINVAL; - - P54U_WRITE(NET2280_BRG_U32, NET2280_USBIRQENB1, 0); - P54U_WRITE(NET2280_BRG_U32, NET2280_IRQSTAT1, - cpu_to_le32(NET2280_PCI_INTA_INTERRUPT)); - -#undef P54U_WRITE -#undef P54U_READ - - fail: - release_firmware(fw_entry); - kfree(buf); - return err; -} - -static int p54u_open(struct ieee80211_hw *dev) -{ - struct p54u_priv *priv = dev->priv; - int err; - - err = p54u_init_urbs(dev); - if (err) { - return err; - } - - priv->common.open = p54u_init_urbs; - - return 0; -} - -static void p54u_stop(struct ieee80211_hw *dev) -{ - /* TODO: figure out how to reliably stop the 3887 and net2280 so - the hardware is still usable next time we want to start it. - until then, we just stop listening to the hardware.. */ - p54u_free_urbs(dev); - return; -} - -static int __devinit p54u_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct usb_device *udev = interface_to_usbdev(intf); - struct ieee80211_hw *dev; - struct p54u_priv *priv; - int err; - unsigned int i, recognized_pipes; - DECLARE_MAC_BUF(mac); - - dev = p54_init_common(sizeof(*priv)); - if (!dev) { - printk(KERN_ERR "prism54usb: ieee80211 alloc failed\n"); - return -ENOMEM; - } - - priv = dev->priv; - - SET_IEEE80211_DEV(dev, &intf->dev); - usb_set_intfdata(intf, dev); - priv->udev = udev; - - usb_get_dev(udev); - - /* really lazy and simple way of figuring out if we're a 3887 */ - /* TODO: should just stick the identification in the device table */ - i = intf->altsetting->desc.bNumEndpoints; - recognized_pipes = 0; - while (i--) { - switch (intf->altsetting->endpoint[i].desc.bEndpointAddress) { - case P54U_PIPE_DATA: - case P54U_PIPE_MGMT: - case P54U_PIPE_BRG: - case P54U_PIPE_DEV: - case P54U_PIPE_DATA | USB_DIR_IN: - case P54U_PIPE_MGMT | USB_DIR_IN: - case P54U_PIPE_BRG | USB_DIR_IN: - case P54U_PIPE_DEV | USB_DIR_IN: - case P54U_PIPE_INT | USB_DIR_IN: - recognized_pipes++; - } - } - priv->common.open = p54u_open; - - if (recognized_pipes < P54U_PIPE_NUMBER) { - priv->hw_type = P54U_3887; - priv->common.tx = p54u_tx_3887; - } else { - dev->extra_tx_headroom += sizeof(struct net2280_tx_hdr); - priv->common.tx_hdr_len = sizeof(struct net2280_tx_hdr); - priv->common.tx = p54u_tx_net2280; - } - priv->common.stop = p54u_stop; - - if (priv->hw_type) - err = p54u_upload_firmware_3887(dev); - else - err = p54u_upload_firmware_net2280(dev); - if (err) - goto err_free_dev; - - err = p54u_read_eeprom(dev); - if (err) - goto err_free_dev; - - if (!is_valid_ether_addr(dev->wiphy->perm_addr)) { - u8 perm_addr[ETH_ALEN]; - - printk(KERN_WARNING "prism54usb: Invalid hwaddr! Using randomly generated MAC addr\n"); - random_ether_addr(perm_addr); - SET_IEEE80211_PERM_ADDR(dev, perm_addr); - } - - skb_queue_head_init(&priv->rx_queue); - - err = ieee80211_register_hw(dev); - if (err) { - printk(KERN_ERR "prism54usb: Cannot register netdevice\n"); - goto err_free_dev; - } - - printk(KERN_INFO "%s: hwaddr %s, isl38%02x\n", - wiphy_name(dev->wiphy), - print_mac(mac, dev->wiphy->perm_addr), - priv->common.version); - - return 0; - - err_free_dev: - ieee80211_free_hw(dev); - usb_set_intfdata(intf, NULL); - usb_put_dev(udev); - return err; -} - -static void __devexit p54u_disconnect(struct usb_interface *intf) -{ - struct ieee80211_hw *dev = usb_get_intfdata(intf); - struct p54u_priv *priv; - - if (!dev) - return; - - ieee80211_unregister_hw(dev); - - priv = dev->priv; - usb_put_dev(interface_to_usbdev(intf)); - p54_free_common(dev); - ieee80211_free_hw(dev); -} - -static struct usb_driver p54u_driver = { - .name = "prism54usb", - .id_table = p54u_table, - .probe = p54u_probe, - .disconnect = p54u_disconnect, -}; - -static int __init p54u_init(void) -{ - return usb_register(&p54u_driver); -} - -static void __exit p54u_exit(void) -{ - usb_deregister(&p54u_driver); -} - -module_init(p54u_init); -module_exit(p54u_exit); diff --git a/drivers/net/wireless/p54usb.h b/drivers/net/wireless/p54usb.h deleted file mode 100644 index d1896b396c1c..000000000000 --- a/drivers/net/wireless/p54usb.h +++ /dev/null @@ -1,133 +0,0 @@ -#ifndef PRISM54USB_H -#define PRISM54USB_H - -/* - * Defines for USB based mac80211 Prism54 driver - * - * Copyright (c) 2006, Michael Wu - * - * Based on the islsm (softmac prism54) driver, which is: - * Copyright 2004-2006 Jean-Baptiste Note , et al. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -/* for isl3886 register definitions used on ver 1 devices */ -#include "p54pci.h" -#include "net2280.h" - -/* pci */ -#define NET2280_BASE 0x10000000 -#define NET2280_BASE2 0x20000000 - -/* gpio */ -#define P54U_BRG_POWER_UP (1 << GPIO0_DATA) -#define P54U_BRG_POWER_DOWN (1 << GPIO1_DATA) - -/* devinit */ -#define NET2280_CLK_4Mhz (15 << LOCAL_CLOCK_FREQUENCY) -#define NET2280_CLK_30Mhz (2 << LOCAL_CLOCK_FREQUENCY) -#define NET2280_CLK_60Mhz (1 << LOCAL_CLOCK_FREQUENCY) -#define NET2280_CLK_STOP (0 << LOCAL_CLOCK_FREQUENCY) -#define NET2280_PCI_ENABLE (1 << PCI_ENABLE) -#define NET2280_PCI_SOFT_RESET (1 << PCI_SOFT_RESET) - -/* endpoints */ -#define NET2280_CLEAR_NAK_OUT_PACKETS_MODE (1 << CLEAR_NAK_OUT_PACKETS_MODE) -#define NET2280_FIFO_FLUSH (1 << FIFO_FLUSH) - -/* irq */ -#define NET2280_USB_INTERRUPT_ENABLE (1 << USB_INTERRUPT_ENABLE) -#define NET2280_PCI_INTA_INTERRUPT (1 << PCI_INTA_INTERRUPT) -#define NET2280_PCI_INTA_INTERRUPT_ENABLE (1 << PCI_INTA_INTERRUPT_ENABLE) - -/* registers */ -#define NET2280_DEVINIT 0x00 -#define NET2280_USBIRQENB1 0x24 -#define NET2280_IRQSTAT1 0x2c -#define NET2280_FIFOCTL 0x38 -#define NET2280_GPIOCTL 0x50 -#define NET2280_RELNUM 0x88 -#define NET2280_EPA_RSP 0x324 -#define NET2280_EPA_STAT 0x32c -#define NET2280_EPB_STAT 0x34c -#define NET2280_EPC_RSP 0x364 -#define NET2280_EPC_STAT 0x36c -#define NET2280_EPD_STAT 0x38c - -#define NET2280_EPA_CFG 0x320 -#define NET2280_EPB_CFG 0x340 -#define NET2280_EPC_CFG 0x360 -#define NET2280_EPD_CFG 0x380 -#define NET2280_EPE_CFG 0x3A0 -#define NET2280_EPF_CFG 0x3C0 -#define P54U_DEV_BASE 0x40000000 - -struct net2280_tx_hdr { - __le32 device_addr; - __le16 len; - __le16 follower; /* ? */ - u8 padding[8]; -} __attribute__((packed)); - -/* Some flags for the isl hardware registers controlling DMA inside the - * chip */ -#define ISL38XX_DMA_STATUS_DONE 0x00000001 -#define ISL38XX_DMA_STATUS_READY 0x00000002 -#define NET2280_EPA_FIFO_PCI_ADDR 0x20000000 -#define ISL38XX_DMA_MASTER_CONTROL_TRIGGER 0x00000004 - -enum net2280_op_type { - NET2280_BRG_U32 = 0x001F, - NET2280_BRG_CFG_U32 = 0x000F, - NET2280_BRG_CFG_U16 = 0x0003, - NET2280_DEV_U32 = 0x080F, - NET2280_DEV_CFG_U32 = 0x088F, - NET2280_DEV_CFG_U16 = 0x0883 -}; - -#define P54U_FW_BLOCK 2048 - -#define X2_SIGNATURE "x2 " -#define X2_SIGNATURE_SIZE 4 - -struct x2_header { - u8 signature[X2_SIGNATURE_SIZE]; - __le32 fw_load_addr; - __le32 fw_length; - __le32 crc; -} __attribute__((packed)); - -/* pipes 3 and 4 are not used by the driver */ -#define P54U_PIPE_NUMBER 9 - -enum p54u_pipe_addr { - P54U_PIPE_DATA = 0x01, - P54U_PIPE_MGMT = 0x02, - P54U_PIPE_3 = 0x03, - P54U_PIPE_4 = 0x04, - P54U_PIPE_BRG = 0x0d, - P54U_PIPE_DEV = 0x0e, - P54U_PIPE_INT = 0x0f -}; - -struct p54u_rx_info { - struct urb *urb; - struct ieee80211_hw *dev; -}; - -struct p54u_priv { - struct p54_common common; - struct usb_device *udev; - enum { - P54U_NET2280 = 0, - P54U_3887 - } hw_type; - - spinlock_t lock; - struct sk_buff_head rx_queue; -}; - -#endif /* PRISM54USB_H */ -- cgit v1.2.1 From cfcdf40e52bdaa7622a9d1de62e5451d3427a5c6 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Tue, 8 Apr 2008 15:40:53 -0400 Subject: drivers/net/wireless/p54/net2280.h: silence checkpatch.pl Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/net2280.h | 736 ++++++++++++++++++------------------- 1 file changed, 368 insertions(+), 368 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/p54/net2280.h b/drivers/net/wireless/p54/net2280.h index 120eb831b287..4915d9d54203 100644 --- a/drivers/net/wireless/p54/net2280.h +++ b/drivers/net/wireless/p54/net2280.h @@ -37,292 +37,292 @@ /* main registers, BAR0 + 0x0000 */ struct net2280_regs { - // offset 0x0000 - __le32 devinit; -#define LOCAL_CLOCK_FREQUENCY 8 -#define FORCE_PCI_RESET 7 -#define PCI_ID 6 -#define PCI_ENABLE 5 -#define FIFO_SOFT_RESET 4 -#define CFG_SOFT_RESET 3 -#define PCI_SOFT_RESET 2 -#define USB_SOFT_RESET 1 -#define M8051_RESET 0 - __le32 eectl; -#define EEPROM_ADDRESS_WIDTH 23 -#define EEPROM_CHIP_SELECT_ACTIVE 22 -#define EEPROM_PRESENT 21 -#define EEPROM_VALID 20 -#define EEPROM_BUSY 19 -#define EEPROM_CHIP_SELECT_ENABLE 18 -#define EEPROM_BYTE_READ_START 17 -#define EEPROM_BYTE_WRITE_START 16 -#define EEPROM_READ_DATA 8 -#define EEPROM_WRITE_DATA 0 - __le32 eeclkfreq; - u32 _unused0; - // offset 0x0010 + /* offset 0x0000 */ + __le32 devinit; +#define LOCAL_CLOCK_FREQUENCY 8 +#define FORCE_PCI_RESET 7 +#define PCI_ID 6 +#define PCI_ENABLE 5 +#define FIFO_SOFT_RESET 4 +#define CFG_SOFT_RESET 3 +#define PCI_SOFT_RESET 2 +#define USB_SOFT_RESET 1 +#define M8051_RESET 0 + __le32 eectl; +#define EEPROM_ADDRESS_WIDTH 23 +#define EEPROM_CHIP_SELECT_ACTIVE 22 +#define EEPROM_PRESENT 21 +#define EEPROM_VALID 20 +#define EEPROM_BUSY 19 +#define EEPROM_CHIP_SELECT_ENABLE 18 +#define EEPROM_BYTE_READ_START 17 +#define EEPROM_BYTE_WRITE_START 16 +#define EEPROM_READ_DATA 8 +#define EEPROM_WRITE_DATA 0 + __le32 eeclkfreq; + u32 _unused0; + /* offset 0x0010 */ - __le32 pciirqenb0; /* interrupt PCI master ... */ -#define SETUP_PACKET_INTERRUPT_ENABLE 7 -#define ENDPOINT_F_INTERRUPT_ENABLE 6 -#define ENDPOINT_E_INTERRUPT_ENABLE 5 -#define ENDPOINT_D_INTERRUPT_ENABLE 4 -#define ENDPOINT_C_INTERRUPT_ENABLE 3 -#define ENDPOINT_B_INTERRUPT_ENABLE 2 -#define ENDPOINT_A_INTERRUPT_ENABLE 1 -#define ENDPOINT_0_INTERRUPT_ENABLE 0 - __le32 pciirqenb1; -#define PCI_INTERRUPT_ENABLE 31 -#define POWER_STATE_CHANGE_INTERRUPT_ENABLE 27 -#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE 26 -#define PCI_PARITY_ERROR_INTERRUPT_ENABLE 25 -#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE 20 -#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE 19 -#define PCI_TARGET_ABORT_ASSERTED_INTERRUPT_ENABLE 18 -#define PCI_RETRY_ABORT_INTERRUPT_ENABLE 17 -#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE 16 -#define GPIO_INTERRUPT_ENABLE 13 -#define DMA_D_INTERRUPT_ENABLE 12 -#define DMA_C_INTERRUPT_ENABLE 11 -#define DMA_B_INTERRUPT_ENABLE 10 -#define DMA_A_INTERRUPT_ENABLE 9 -#define EEPROM_DONE_INTERRUPT_ENABLE 8 -#define VBUS_INTERRUPT_ENABLE 7 -#define CONTROL_STATUS_INTERRUPT_ENABLE 6 -#define ROOT_PORT_RESET_INTERRUPT_ENABLE 4 -#define SUSPEND_REQUEST_INTERRUPT_ENABLE 3 -#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE 2 -#define RESUME_INTERRUPT_ENABLE 1 -#define SOF_INTERRUPT_ENABLE 0 + __le32 pciirqenb0; /* interrupt PCI master ... */ +#define SETUP_PACKET_INTERRUPT_ENABLE 7 +#define ENDPOINT_F_INTERRUPT_ENABLE 6 +#define ENDPOINT_E_INTERRUPT_ENABLE 5 +#define ENDPOINT_D_INTERRUPT_ENABLE 4 +#define ENDPOINT_C_INTERRUPT_ENABLE 3 +#define ENDPOINT_B_INTERRUPT_ENABLE 2 +#define ENDPOINT_A_INTERRUPT_ENABLE 1 +#define ENDPOINT_0_INTERRUPT_ENABLE 0 + __le32 pciirqenb1; +#define PCI_INTERRUPT_ENABLE 31 +#define POWER_STATE_CHANGE_INTERRUPT_ENABLE 27 +#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE 26 +#define PCI_PARITY_ERROR_INTERRUPT_ENABLE 25 +#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE 20 +#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE 19 +#define PCI_TARGET_ABORT_ASSERTED_INTERRUPT_ENABLE 18 +#define PCI_RETRY_ABORT_INTERRUPT_ENABLE 17 +#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE 16 +#define GPIO_INTERRUPT_ENABLE 13 +#define DMA_D_INTERRUPT_ENABLE 12 +#define DMA_C_INTERRUPT_ENABLE 11 +#define DMA_B_INTERRUPT_ENABLE 10 +#define DMA_A_INTERRUPT_ENABLE 9 +#define EEPROM_DONE_INTERRUPT_ENABLE 8 +#define VBUS_INTERRUPT_ENABLE 7 +#define CONTROL_STATUS_INTERRUPT_ENABLE 6 +#define ROOT_PORT_RESET_INTERRUPT_ENABLE 4 +#define SUSPEND_REQUEST_INTERRUPT_ENABLE 3 +#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE 2 +#define RESUME_INTERRUPT_ENABLE 1 +#define SOF_INTERRUPT_ENABLE 0 __le32 cpu_irqenb0; /* ... or onboard 8051 */ -#define SETUP_PACKET_INTERRUPT_ENABLE 7 -#define ENDPOINT_F_INTERRUPT_ENABLE 6 -#define ENDPOINT_E_INTERRUPT_ENABLE 5 -#define ENDPOINT_D_INTERRUPT_ENABLE 4 -#define ENDPOINT_C_INTERRUPT_ENABLE 3 -#define ENDPOINT_B_INTERRUPT_ENABLE 2 -#define ENDPOINT_A_INTERRUPT_ENABLE 1 -#define ENDPOINT_0_INTERRUPT_ENABLE 0 +#define SETUP_PACKET_INTERRUPT_ENABLE 7 +#define ENDPOINT_F_INTERRUPT_ENABLE 6 +#define ENDPOINT_E_INTERRUPT_ENABLE 5 +#define ENDPOINT_D_INTERRUPT_ENABLE 4 +#define ENDPOINT_C_INTERRUPT_ENABLE 3 +#define ENDPOINT_B_INTERRUPT_ENABLE 2 +#define ENDPOINT_A_INTERRUPT_ENABLE 1 +#define ENDPOINT_0_INTERRUPT_ENABLE 0 __le32 cpu_irqenb1; -#define CPU_INTERRUPT_ENABLE 31 -#define POWER_STATE_CHANGE_INTERRUPT_ENABLE 27 -#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE 26 -#define PCI_PARITY_ERROR_INTERRUPT_ENABLE 25 -#define PCI_INTA_INTERRUPT_ENABLE 24 -#define PCI_PME_INTERRUPT_ENABLE 23 -#define PCI_SERR_INTERRUPT_ENABLE 22 -#define PCI_PERR_INTERRUPT_ENABLE 21 -#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE 20 -#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE 19 -#define PCI_RETRY_ABORT_INTERRUPT_ENABLE 17 -#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE 16 -#define GPIO_INTERRUPT_ENABLE 13 -#define DMA_D_INTERRUPT_ENABLE 12 -#define DMA_C_INTERRUPT_ENABLE 11 -#define DMA_B_INTERRUPT_ENABLE 10 -#define DMA_A_INTERRUPT_ENABLE 9 -#define EEPROM_DONE_INTERRUPT_ENABLE 8 -#define VBUS_INTERRUPT_ENABLE 7 -#define CONTROL_STATUS_INTERRUPT_ENABLE 6 -#define ROOT_PORT_RESET_INTERRUPT_ENABLE 4 -#define SUSPEND_REQUEST_INTERRUPT_ENABLE 3 -#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE 2 -#define RESUME_INTERRUPT_ENABLE 1 -#define SOF_INTERRUPT_ENABLE 0 +#define CPU_INTERRUPT_ENABLE 31 +#define POWER_STATE_CHANGE_INTERRUPT_ENABLE 27 +#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE 26 +#define PCI_PARITY_ERROR_INTERRUPT_ENABLE 25 +#define PCI_INTA_INTERRUPT_ENABLE 24 +#define PCI_PME_INTERRUPT_ENABLE 23 +#define PCI_SERR_INTERRUPT_ENABLE 22 +#define PCI_PERR_INTERRUPT_ENABLE 21 +#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE 20 +#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE 19 +#define PCI_RETRY_ABORT_INTERRUPT_ENABLE 17 +#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE 16 +#define GPIO_INTERRUPT_ENABLE 13 +#define DMA_D_INTERRUPT_ENABLE 12 +#define DMA_C_INTERRUPT_ENABLE 11 +#define DMA_B_INTERRUPT_ENABLE 10 +#define DMA_A_INTERRUPT_ENABLE 9 +#define EEPROM_DONE_INTERRUPT_ENABLE 8 +#define VBUS_INTERRUPT_ENABLE 7 +#define CONTROL_STATUS_INTERRUPT_ENABLE 6 +#define ROOT_PORT_RESET_INTERRUPT_ENABLE 4 +#define SUSPEND_REQUEST_INTERRUPT_ENABLE 3 +#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE 2 +#define RESUME_INTERRUPT_ENABLE 1 +#define SOF_INTERRUPT_ENABLE 0 - // offset 0x0020 - u32 _unused1; - __le32 usbirqenb1; -#define USB_INTERRUPT_ENABLE 31 -#define POWER_STATE_CHANGE_INTERRUPT_ENABLE 27 -#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE 26 -#define PCI_PARITY_ERROR_INTERRUPT_ENABLE 25 -#define PCI_INTA_INTERRUPT_ENABLE 24 -#define PCI_PME_INTERRUPT_ENABLE 23 -#define PCI_SERR_INTERRUPT_ENABLE 22 -#define PCI_PERR_INTERRUPT_ENABLE 21 -#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE 20 -#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE 19 -#define PCI_RETRY_ABORT_INTERRUPT_ENABLE 17 -#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE 16 -#define GPIO_INTERRUPT_ENABLE 13 -#define DMA_D_INTERRUPT_ENABLE 12 -#define DMA_C_INTERRUPT_ENABLE 11 -#define DMA_B_INTERRUPT_ENABLE 10 -#define DMA_A_INTERRUPT_ENABLE 9 -#define EEPROM_DONE_INTERRUPT_ENABLE 8 -#define VBUS_INTERRUPT_ENABLE 7 -#define CONTROL_STATUS_INTERRUPT_ENABLE 6 -#define ROOT_PORT_RESET_INTERRUPT_ENABLE 4 -#define SUSPEND_REQUEST_INTERRUPT_ENABLE 3 -#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE 2 -#define RESUME_INTERRUPT_ENABLE 1 -#define SOF_INTERRUPT_ENABLE 0 - __le32 irqstat0; -#define INTA_ASSERTED 12 -#define SETUP_PACKET_INTERRUPT 7 -#define ENDPOINT_F_INTERRUPT 6 -#define ENDPOINT_E_INTERRUPT 5 -#define ENDPOINT_D_INTERRUPT 4 -#define ENDPOINT_C_INTERRUPT 3 -#define ENDPOINT_B_INTERRUPT 2 -#define ENDPOINT_A_INTERRUPT 1 -#define ENDPOINT_0_INTERRUPT 0 - __le32 irqstat1; -#define POWER_STATE_CHANGE_INTERRUPT 27 -#define PCI_ARBITER_TIMEOUT_INTERRUPT 26 -#define PCI_PARITY_ERROR_INTERRUPT 25 -#define PCI_INTA_INTERRUPT 24 -#define PCI_PME_INTERRUPT 23 -#define PCI_SERR_INTERRUPT 22 -#define PCI_PERR_INTERRUPT 21 -#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT 20 -#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT 19 -#define PCI_RETRY_ABORT_INTERRUPT 17 -#define PCI_MASTER_CYCLE_DONE_INTERRUPT 16 -#define GPIO_INTERRUPT 13 -#define DMA_D_INTERRUPT 12 -#define DMA_C_INTERRUPT 11 -#define DMA_B_INTERRUPT 10 -#define DMA_A_INTERRUPT 9 -#define EEPROM_DONE_INTERRUPT 8 -#define VBUS_INTERRUPT 7 -#define CONTROL_STATUS_INTERRUPT 6 -#define ROOT_PORT_RESET_INTERRUPT 4 -#define SUSPEND_REQUEST_INTERRUPT 3 -#define SUSPEND_REQUEST_CHANGE_INTERRUPT 2 -#define RESUME_INTERRUPT 1 -#define SOF_INTERRUPT 0 - // offset 0x0030 - __le32 idxaddr; - __le32 idxdata; - __le32 fifoctl; -#define PCI_BASE2_RANGE 16 -#define IGNORE_FIFO_AVAILABILITY 3 -#define PCI_BASE2_SELECT 2 -#define FIFO_CONFIGURATION_SELECT 0 - u32 _unused2; - // offset 0x0040 - __le32 memaddr; -#define START 28 -#define DIRECTION 27 -#define FIFO_DIAGNOSTIC_SELECT 24 -#define MEMORY_ADDRESS 0 - __le32 memdata0; - __le32 memdata1; - u32 _unused3; - // offset 0x0050 - __le32 gpioctl; -#define GPIO3_LED_SELECT 12 -#define GPIO3_INTERRUPT_ENABLE 11 -#define GPIO2_INTERRUPT_ENABLE 10 -#define GPIO1_INTERRUPT_ENABLE 9 -#define GPIO0_INTERRUPT_ENABLE 8 -#define GPIO3_OUTPUT_ENABLE 7 -#define GPIO2_OUTPUT_ENABLE 6 -#define GPIO1_OUTPUT_ENABLE 5 -#define GPIO0_OUTPUT_ENABLE 4 -#define GPIO3_DATA 3 -#define GPIO2_DATA 2 -#define GPIO1_DATA 1 -#define GPIO0_DATA 0 - __le32 gpiostat; -#define GPIO3_INTERRUPT 3 -#define GPIO2_INTERRUPT 2 -#define GPIO1_INTERRUPT 1 -#define GPIO0_INTERRUPT 0 + /* offset 0x0020 */ + u32 _unused1; + __le32 usbirqenb1; +#define USB_INTERRUPT_ENABLE 31 +#define POWER_STATE_CHANGE_INTERRUPT_ENABLE 27 +#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE 26 +#define PCI_PARITY_ERROR_INTERRUPT_ENABLE 25 +#define PCI_INTA_INTERRUPT_ENABLE 24 +#define PCI_PME_INTERRUPT_ENABLE 23 +#define PCI_SERR_INTERRUPT_ENABLE 22 +#define PCI_PERR_INTERRUPT_ENABLE 21 +#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE 20 +#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE 19 +#define PCI_RETRY_ABORT_INTERRUPT_ENABLE 17 +#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE 16 +#define GPIO_INTERRUPT_ENABLE 13 +#define DMA_D_INTERRUPT_ENABLE 12 +#define DMA_C_INTERRUPT_ENABLE 11 +#define DMA_B_INTERRUPT_ENABLE 10 +#define DMA_A_INTERRUPT_ENABLE 9 +#define EEPROM_DONE_INTERRUPT_ENABLE 8 +#define VBUS_INTERRUPT_ENABLE 7 +#define CONTROL_STATUS_INTERRUPT_ENABLE 6 +#define ROOT_PORT_RESET_INTERRUPT_ENABLE 4 +#define SUSPEND_REQUEST_INTERRUPT_ENABLE 3 +#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE 2 +#define RESUME_INTERRUPT_ENABLE 1 +#define SOF_INTERRUPT_ENABLE 0 + __le32 irqstat0; +#define INTA_ASSERTED 12 +#define SETUP_PACKET_INTERRUPT 7 +#define ENDPOINT_F_INTERRUPT 6 +#define ENDPOINT_E_INTERRUPT 5 +#define ENDPOINT_D_INTERRUPT 4 +#define ENDPOINT_C_INTERRUPT 3 +#define ENDPOINT_B_INTERRUPT 2 +#define ENDPOINT_A_INTERRUPT 1 +#define ENDPOINT_0_INTERRUPT 0 + __le32 irqstat1; +#define POWER_STATE_CHANGE_INTERRUPT 27 +#define PCI_ARBITER_TIMEOUT_INTERRUPT 26 +#define PCI_PARITY_ERROR_INTERRUPT 25 +#define PCI_INTA_INTERRUPT 24 +#define PCI_PME_INTERRUPT 23 +#define PCI_SERR_INTERRUPT 22 +#define PCI_PERR_INTERRUPT 21 +#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT 20 +#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT 19 +#define PCI_RETRY_ABORT_INTERRUPT 17 +#define PCI_MASTER_CYCLE_DONE_INTERRUPT 16 +#define GPIO_INTERRUPT 13 +#define DMA_D_INTERRUPT 12 +#define DMA_C_INTERRUPT 11 +#define DMA_B_INTERRUPT 10 +#define DMA_A_INTERRUPT 9 +#define EEPROM_DONE_INTERRUPT 8 +#define VBUS_INTERRUPT 7 +#define CONTROL_STATUS_INTERRUPT 6 +#define ROOT_PORT_RESET_INTERRUPT 4 +#define SUSPEND_REQUEST_INTERRUPT 3 +#define SUSPEND_REQUEST_CHANGE_INTERRUPT 2 +#define RESUME_INTERRUPT 1 +#define SOF_INTERRUPT 0 + /* offset 0x0030 */ + __le32 idxaddr; + __le32 idxdata; + __le32 fifoctl; +#define PCI_BASE2_RANGE 16 +#define IGNORE_FIFO_AVAILABILITY 3 +#define PCI_BASE2_SELECT 2 +#define FIFO_CONFIGURATION_SELECT 0 + u32 _unused2; + /* offset 0x0040 */ + __le32 memaddr; +#define START 28 +#define DIRECTION 27 +#define FIFO_DIAGNOSTIC_SELECT 24 +#define MEMORY_ADDRESS 0 + __le32 memdata0; + __le32 memdata1; + u32 _unused3; + /* offset 0x0050 */ + __le32 gpioctl; +#define GPIO3_LED_SELECT 12 +#define GPIO3_INTERRUPT_ENABLE 11 +#define GPIO2_INTERRUPT_ENABLE 10 +#define GPIO1_INTERRUPT_ENABLE 9 +#define GPIO0_INTERRUPT_ENABLE 8 +#define GPIO3_OUTPUT_ENABLE 7 +#define GPIO2_OUTPUT_ENABLE 6 +#define GPIO1_OUTPUT_ENABLE 5 +#define GPIO0_OUTPUT_ENABLE 4 +#define GPIO3_DATA 3 +#define GPIO2_DATA 2 +#define GPIO1_DATA 1 +#define GPIO0_DATA 0 + __le32 gpiostat; +#define GPIO3_INTERRUPT 3 +#define GPIO2_INTERRUPT 2 +#define GPIO1_INTERRUPT 1 +#define GPIO0_INTERRUPT 0 } __attribute__ ((packed)); /* usb control, BAR0 + 0x0080 */ struct net2280_usb_regs { - // offset 0x0080 - __le32 stdrsp; -#define STALL_UNSUPPORTED_REQUESTS 31 -#define SET_TEST_MODE 16 -#define GET_OTHER_SPEED_CONFIGURATION 15 -#define GET_DEVICE_QUALIFIER 14 -#define SET_ADDRESS 13 -#define ENDPOINT_SET_CLEAR_HALT 12 -#define DEVICE_SET_CLEAR_DEVICE_REMOTE_WAKEUP 11 -#define GET_STRING_DESCRIPTOR_2 10 -#define GET_STRING_DESCRIPTOR_1 9 -#define GET_STRING_DESCRIPTOR_0 8 -#define GET_SET_INTERFACE 6 -#define GET_SET_CONFIGURATION 5 -#define GET_CONFIGURATION_DESCRIPTOR 4 -#define GET_DEVICE_DESCRIPTOR 3 -#define GET_ENDPOINT_STATUS 2 -#define GET_INTERFACE_STATUS 1 -#define GET_DEVICE_STATUS 0 - __le32 prodvendid; -#define PRODUCT_ID 16 -#define VENDOR_ID 0 - __le32 relnum; - __le32 usbctl; -#define SERIAL_NUMBER_INDEX 16 -#define PRODUCT_ID_STRING_ENABLE 13 -#define VENDOR_ID_STRING_ENABLE 12 -#define USB_ROOT_PORT_WAKEUP_ENABLE 11 -#define VBUS_PIN 10 -#define TIMED_DISCONNECT 9 -#define SUSPEND_IMMEDIATELY 7 -#define SELF_POWERED_USB_DEVICE 6 -#define REMOTE_WAKEUP_SUPPORT 5 -#define PME_POLARITY 4 -#define USB_DETECT_ENABLE 3 -#define PME_WAKEUP_ENABLE 2 -#define DEVICE_REMOTE_WAKEUP_ENABLE 1 -#define SELF_POWERED_STATUS 0 - // offset 0x0090 - __le32 usbstat; -#define HIGH_SPEED 7 -#define FULL_SPEED 6 -#define GENERATE_RESUME 5 -#define GENERATE_DEVICE_REMOTE_WAKEUP 4 - __le32 xcvrdiag; -#define FORCE_HIGH_SPEED_MODE 31 -#define FORCE_FULL_SPEED_MODE 30 -#define USB_TEST_MODE 24 -#define LINE_STATE 16 -#define TRANSCEIVER_OPERATION_MODE 2 -#define TRANSCEIVER_SELECT 1 -#define TERMINATION_SELECT 0 - __le32 setup0123; - __le32 setup4567; - // offset 0x0090 - u32 _unused0; - __le32 ouraddr; -#define FORCE_IMMEDIATE 7 -#define OUR_USB_ADDRESS 0 - __le32 ourconfig; + /* offset 0x0080 */ + __le32 stdrsp; +#define STALL_UNSUPPORTED_REQUESTS 31 +#define SET_TEST_MODE 16 +#define GET_OTHER_SPEED_CONFIGURATION 15 +#define GET_DEVICE_QUALIFIER 14 +#define SET_ADDRESS 13 +#define ENDPOINT_SET_CLEAR_HALT 12 +#define DEVICE_SET_CLEAR_DEVICE_REMOTE_WAKEUP 11 +#define GET_STRING_DESCRIPTOR_2 10 +#define GET_STRING_DESCRIPTOR_1 9 +#define GET_STRING_DESCRIPTOR_0 8 +#define GET_SET_INTERFACE 6 +#define GET_SET_CONFIGURATION 5 +#define GET_CONFIGURATION_DESCRIPTOR 4 +#define GET_DEVICE_DESCRIPTOR 3 +#define GET_ENDPOINT_STATUS 2 +#define GET_INTERFACE_STATUS 1 +#define GET_DEVICE_STATUS 0 + __le32 prodvendid; +#define PRODUCT_ID 16 +#define VENDOR_ID 0 + __le32 relnum; + __le32 usbctl; +#define SERIAL_NUMBER_INDEX 16 +#define PRODUCT_ID_STRING_ENABLE 13 +#define VENDOR_ID_STRING_ENABLE 12 +#define USB_ROOT_PORT_WAKEUP_ENABLE 11 +#define VBUS_PIN 10 +#define TIMED_DISCONNECT 9 +#define SUSPEND_IMMEDIATELY 7 +#define SELF_POWERED_USB_DEVICE 6 +#define REMOTE_WAKEUP_SUPPORT 5 +#define PME_POLARITY 4 +#define USB_DETECT_ENABLE 3 +#define PME_WAKEUP_ENABLE 2 +#define DEVICE_REMOTE_WAKEUP_ENABLE 1 +#define SELF_POWERED_STATUS 0 + /* offset 0x0090 */ + __le32 usbstat; +#define HIGH_SPEED 7 +#define FULL_SPEED 6 +#define GENERATE_RESUME 5 +#define GENERATE_DEVICE_REMOTE_WAKEUP 4 + __le32 xcvrdiag; +#define FORCE_HIGH_SPEED_MODE 31 +#define FORCE_FULL_SPEED_MODE 30 +#define USB_TEST_MODE 24 +#define LINE_STATE 16 +#define TRANSCEIVER_OPERATION_MODE 2 +#define TRANSCEIVER_SELECT 1 +#define TERMINATION_SELECT 0 + __le32 setup0123; + __le32 setup4567; + /* offset 0x0090 */ + u32 _unused0; + __le32 ouraddr; +#define FORCE_IMMEDIATE 7 +#define OUR_USB_ADDRESS 0 + __le32 ourconfig; } __attribute__ ((packed)); /* pci control, BAR0 + 0x0100 */ struct net2280_pci_regs { - // offset 0x0100 - __le32 pcimstctl; -#define PCI_ARBITER_PARK_SELECT 13 -#define PCI_MULTI LEVEL_ARBITER 12 -#define PCI_RETRY_ABORT_ENABLE 11 -#define DMA_MEMORY_WRITE_AND_INVALIDATE_ENABLE 10 -#define DMA_READ_MULTIPLE_ENABLE 9 -#define DMA_READ_LINE_ENABLE 8 -#define PCI_MASTER_COMMAND_SELECT 6 -#define MEM_READ_OR_WRITE 0 -#define IO_READ_OR_WRITE 1 -#define CFG_READ_OR_WRITE 2 -#define PCI_MASTER_START 5 -#define PCI_MASTER_READ_WRITE 4 -#define PCI_MASTER_WRITE 0 -#define PCI_MASTER_READ 1 -#define PCI_MASTER_BYTE_WRITE_ENABLES 0 - __le32 pcimstaddr; - __le32 pcimstdata; - __le32 pcimststat; -#define PCI_ARBITER_CLEAR 2 -#define PCI_EXTERNAL_ARBITER 1 -#define PCI_HOST_MODE 0 + /* offset 0x0100 */ + __le32 pcimstctl; +#define PCI_ARBITER_PARK_SELECT 13 +#define PCI_MULTI LEVEL_ARBITER 12 +#define PCI_RETRY_ABORT_ENABLE 11 +#define DMA_MEMORY_WRITE_AND_INVALIDATE_ENABLE 10 +#define DMA_READ_MULTIPLE_ENABLE 9 +#define DMA_READ_LINE_ENABLE 8 +#define PCI_MASTER_COMMAND_SELECT 6 +#define MEM_READ_OR_WRITE 0 +#define IO_READ_OR_WRITE 1 +#define CFG_READ_OR_WRITE 2 +#define PCI_MASTER_START 5 +#define PCI_MASTER_READ_WRITE 4 +#define PCI_MASTER_WRITE 0 +#define PCI_MASTER_READ 1 +#define PCI_MASTER_BYTE_WRITE_ENABLES 0 + __le32 pcimstaddr; + __le32 pcimstdata; + __le32 pcimststat; +#define PCI_ARBITER_CLEAR 2 +#define PCI_EXTERNAL_ARBITER 1 +#define PCI_HOST_MODE 0 } __attribute__ ((packed)); /* dma control, BAR0 + 0x0180 ... array of four structs like this, @@ -330,50 +330,50 @@ struct net2280_pci_regs { * that can be loaded into some of these registers. */ struct net2280_dma_regs { /* [11.7] */ - // offset 0x0180, 0x01a0, 0x01c0, 0x01e0, - __le32 dmactl; -#define DMA_SCATTER_GATHER_DONE_INTERRUPT_ENABLE 25 -#define DMA_CLEAR_COUNT_ENABLE 21 -#define DESCRIPTOR_POLLING_RATE 19 -#define POLL_CONTINUOUS 0 -#define POLL_1_USEC 1 -#define POLL_100_USEC 2 -#define POLL_1_MSEC 3 -#define DMA_VALID_BIT_POLLING_ENABLE 18 -#define DMA_VALID_BIT_ENABLE 17 -#define DMA_SCATTER_GATHER_ENABLE 16 -#define DMA_OUT_AUTO_START_ENABLE 4 -#define DMA_PREEMPT_ENABLE 3 -#define DMA_FIFO_VALIDATE 2 -#define DMA_ENABLE 1 -#define DMA_ADDRESS_HOLD 0 - __le32 dmastat; -#define DMA_SCATTER_GATHER_DONE_INTERRUPT 25 -#define DMA_TRANSACTION_DONE_INTERRUPT 24 -#define DMA_ABORT 1 -#define DMA_START 0 - u32 _unused0[2]; - // offset 0x0190, 0x01b0, 0x01d0, 0x01f0, + /* offset 0x0180, 0x01a0, 0x01c0, 0x01e0, */ + __le32 dmactl; +#define DMA_SCATTER_GATHER_DONE_INTERRUPT_ENABLE 25 +#define DMA_CLEAR_COUNT_ENABLE 21 +#define DESCRIPTOR_POLLING_RATE 19 +#define POLL_CONTINUOUS 0 +#define POLL_1_USEC 1 +#define POLL_100_USEC 2 +#define POLL_1_MSEC 3 +#define DMA_VALID_BIT_POLLING_ENABLE 18 +#define DMA_VALID_BIT_ENABLE 17 +#define DMA_SCATTER_GATHER_ENABLE 16 +#define DMA_OUT_AUTO_START_ENABLE 4 +#define DMA_PREEMPT_ENABLE 3 +#define DMA_FIFO_VALIDATE 2 +#define DMA_ENABLE 1 +#define DMA_ADDRESS_HOLD 0 + __le32 dmastat; +#define DMA_SCATTER_GATHER_DONE_INTERRUPT 25 +#define DMA_TRANSACTION_DONE_INTERRUPT 24 +#define DMA_ABORT 1 +#define DMA_START 0 + u32 _unused0[2]; + /* offset 0x0190, 0x01b0, 0x01d0, 0x01f0, */ __le32 dmacount; -#define VALID_BIT 31 -#define DMA_DIRECTION 30 -#define DMA_DONE_INTERRUPT_ENABLE 29 -#define END_OF_CHAIN 28 -#define DMA_BYTE_COUNT_MASK ((1<<24)-1) -#define DMA_BYTE_COUNT 0 - __le32 dmaaddr; - __le32 dmadesc; - u32 _unused1; +#define VALID_BIT 31 +#define DMA_DIRECTION 30 +#define DMA_DONE_INTERRUPT_ENABLE 29 +#define END_OF_CHAIN 28 +#define DMA_BYTE_COUNT_MASK ((1<<24)-1) +#define DMA_BYTE_COUNT 0 + __le32 dmaaddr; + __le32 dmadesc; + u32 _unused1; } __attribute__ ((packed)); /* dedicated endpoint registers, BAR0 + 0x0200 */ struct net2280_dep_regs { /* [11.8] */ - // offset 0x0200, 0x0210, 0x220, 0x230, 0x240 - __le32 dep_cfg; - // offset 0x0204, 0x0214, 0x224, 0x234, 0x244 - __le32 dep_rsp; - u32 _unused[2]; + /* offset 0x0200, 0x0210, 0x220, 0x230, 0x240 */ + __le32 dep_cfg; + /* offset 0x0204, 0x0214, 0x224, 0x234, 0x244 */ + __le32 dep_rsp; + u32 _unused[2]; } __attribute__ ((packed)); /* configurable endpoint registers, BAR0 + 0x0300 ... array of seven structs @@ -381,62 +381,62 @@ struct net2280_dep_regs { /* [11.8] */ * ep0 reserved for control; E and F have only 64 bytes of fifo */ struct net2280_ep_regs { /* [11.9] */ - // offset 0x0300, 0x0320, 0x0340, 0x0360, 0x0380, 0x03a0, 0x03c0 - __le32 ep_cfg; -#define ENDPOINT_BYTE_COUNT 16 -#define ENDPOINT_ENABLE 10 -#define ENDPOINT_TYPE 8 -#define ENDPOINT_DIRECTION 7 -#define ENDPOINT_NUMBER 0 - __le32 ep_rsp; -#define SET_NAK_OUT_PACKETS 15 -#define SET_EP_HIDE_STATUS_PHASE 14 -#define SET_EP_FORCE_CRC_ERROR 13 -#define SET_INTERRUPT_MODE 12 -#define SET_CONTROL_STATUS_PHASE_HANDSHAKE 11 -#define SET_NAK_OUT_PACKETS_MODE 10 -#define SET_ENDPOINT_TOGGLE 9 -#define SET_ENDPOINT_HALT 8 -#define CLEAR_NAK_OUT_PACKETS 7 -#define CLEAR_EP_HIDE_STATUS_PHASE 6 -#define CLEAR_EP_FORCE_CRC_ERROR 5 -#define CLEAR_INTERRUPT_MODE 4 -#define CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE 3 -#define CLEAR_NAK_OUT_PACKETS_MODE 2 -#define CLEAR_ENDPOINT_TOGGLE 1 -#define CLEAR_ENDPOINT_HALT 0 - __le32 ep_irqenb; -#define SHORT_PACKET_OUT_DONE_INTERRUPT_ENABLE 6 -#define SHORT_PACKET_TRANSFERRED_INTERRUPT_ENABLE 5 -#define DATA_PACKET_RECEIVED_INTERRUPT_ENABLE 3 -#define DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE 2 -#define DATA_OUT_PING_TOKEN_INTERRUPT_ENABLE 1 -#define DATA_IN_TOKEN_INTERRUPT_ENABLE 0 - __le32 ep_stat; -#define FIFO_VALID_COUNT 24 -#define HIGH_BANDWIDTH_OUT_TRANSACTION_PID 22 -#define TIMEOUT 21 -#define USB_STALL_SENT 20 -#define USB_IN_NAK_SENT 19 -#define USB_IN_ACK_RCVD 18 -#define USB_OUT_PING_NAK_SENT 17 -#define USB_OUT_ACK_SENT 16 -#define FIFO_OVERFLOW 13 -#define FIFO_UNDERFLOW 12 -#define FIFO_FULL 11 -#define FIFO_EMPTY 10 -#define FIFO_FLUSH 9 -#define SHORT_PACKET_OUT_DONE_INTERRUPT 6 -#define SHORT_PACKET_TRANSFERRED_INTERRUPT 5 -#define NAK_OUT_PACKETS 4 -#define DATA_PACKET_RECEIVED_INTERRUPT 3 -#define DATA_PACKET_TRANSMITTED_INTERRUPT 2 -#define DATA_OUT_PING_TOKEN_INTERRUPT 1 -#define DATA_IN_TOKEN_INTERRUPT 0 - // offset 0x0310, 0x0330, 0x0350, 0x0370, 0x0390, 0x03b0, 0x03d0 - __le32 ep_avail; - __le32 ep_data; - u32 _unused0[2]; + /* offset 0x0300, 0x0320, 0x0340, 0x0360, 0x0380, 0x03a0, 0x03c0 */ + __le32 ep_cfg; +#define ENDPOINT_BYTE_COUNT 16 +#define ENDPOINT_ENABLE 10 +#define ENDPOINT_TYPE 8 +#define ENDPOINT_DIRECTION 7 +#define ENDPOINT_NUMBER 0 + __le32 ep_rsp; +#define SET_NAK_OUT_PACKETS 15 +#define SET_EP_HIDE_STATUS_PHASE 14 +#define SET_EP_FORCE_CRC_ERROR 13 +#define SET_INTERRUPT_MODE 12 +#define SET_CONTROL_STATUS_PHASE_HANDSHAKE 11 +#define SET_NAK_OUT_PACKETS_MODE 10 +#define SET_ENDPOINT_TOGGLE 9 +#define SET_ENDPOINT_HALT 8 +#define CLEAR_NAK_OUT_PACKETS 7 +#define CLEAR_EP_HIDE_STATUS_PHASE 6 +#define CLEAR_EP_FORCE_CRC_ERROR 5 +#define CLEAR_INTERRUPT_MODE 4 +#define CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE 3 +#define CLEAR_NAK_OUT_PACKETS_MODE 2 +#define CLEAR_ENDPOINT_TOGGLE 1 +#define CLEAR_ENDPOINT_HALT 0 + __le32 ep_irqenb; +#define SHORT_PACKET_OUT_DONE_INTERRUPT_ENABLE 6 +#define SHORT_PACKET_TRANSFERRED_INTERRUPT_ENABLE 5 +#define DATA_PACKET_RECEIVED_INTERRUPT_ENABLE 3 +#define DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE 2 +#define DATA_OUT_PING_TOKEN_INTERRUPT_ENABLE 1 +#define DATA_IN_TOKEN_INTERRUPT_ENABLE 0 + __le32 ep_stat; +#define FIFO_VALID_COUNT 24 +#define HIGH_BANDWIDTH_OUT_TRANSACTION_PID 22 +#define TIMEOUT 21 +#define USB_STALL_SENT 20 +#define USB_IN_NAK_SENT 19 +#define USB_IN_ACK_RCVD 18 +#define USB_OUT_PING_NAK_SENT 17 +#define USB_OUT_ACK_SENT 16 +#define FIFO_OVERFLOW 13 +#define FIFO_UNDERFLOW 12 +#define FIFO_FULL 11 +#define FIFO_EMPTY 10 +#define FIFO_FLUSH 9 +#define SHORT_PACKET_OUT_DONE_INTERRUPT 6 +#define SHORT_PACKET_TRANSFERRED_INTERRUPT 5 +#define NAK_OUT_PACKETS 4 +#define DATA_PACKET_RECEIVED_INTERRUPT 3 +#define DATA_PACKET_TRANSMITTED_INTERRUPT 2 +#define DATA_OUT_PING_TOKEN_INTERRUPT 1 +#define DATA_IN_TOKEN_INTERRUPT 0 + /* offset 0x0310, 0x0330, 0x0350, 0x0370, 0x0390, 0x03b0, 0x03d0 */ + __le32 ep_avail; + __le32 ep_data; + u32 _unused0[2]; } __attribute__ ((packed)); struct net2280_reg_write { -- cgit v1.2.1 From 171afcd4ba093b50cd2fb33fe2371fbc1f7fd389 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Wed, 9 Apr 2008 20:46:27 +0200 Subject: rt2x00: Only free skb when beacon_update fails In rt2x00lib_intf_scheduled_iter() we use the hw->beacon_update() callback function. This means that it should behave similarly as mac80211 when that uses the function. This means that the skb should only be freed when beacon_update() has failed, otherwise the driver is the owner and is responsible for freeing the buffer. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00dev.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 0361524d193c..f8fe7a139a8a 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -433,11 +433,9 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac, if (delayed_flags & DELAYED_UPDATE_BEACON) { skb = ieee80211_beacon_get(rt2x00dev->hw, vif, &control); - if (skb) { - rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw, skb, - &control); + if (skb && rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw, + skb, &control)) dev_kfree_skb(skb); - } } if (delayed_flags & DELAYED_CONFIG_ERP) -- cgit v1.2.1 From 7919b89c8276d657976d4d4d6b7cb58ea1aa08c3 Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Tue, 1 Apr 2008 14:50:43 +0200 Subject: libertas: convert libertas driver to use an event/cmdresp queue This patch (co-developed by Dan Williams and Holger Schurig) uses a kfifo object for events and a swapping buffer scheme for the command response to preserve the zero-copy semantics of the CF driver and keep memory usage low. The main thread should only ever touch the buffer indexed by priv->resp_idx, while the interface code is free to write to the second buffer, then swap priv->resp_idx under the driver spinlock. The firmware specs only permit one in-flight command, so there will only ever be one command response to process at a time. Signed-off-by: Holger Schurig Signed-off-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/cmd.c | 25 ++-- drivers/net/wireless/libertas/cmdresp.c | 23 +-- drivers/net/wireless/libertas/debugfs.c | 1 - drivers/net/wireless/libertas/decl.h | 10 +- drivers/net/wireless/libertas/defs.h | 2 - drivers/net/wireless/libertas/dev.h | 27 ++-- drivers/net/wireless/libertas/if_cs.c | 244 ++++++++++++++------------------ drivers/net/wireless/libertas/if_sdio.c | 65 ++------- drivers/net/wireless/libertas/if_usb.c | 71 +++------- drivers/net/wireless/libertas/if_usb.h | 2 - drivers/net/wireless/libertas/main.c | 158 ++++++++++++--------- drivers/net/wireless/libertas/rx.c | 4 +- drivers/net/wireless/libertas/tx.c | 20 +-- 13 files changed, 269 insertions(+), 383 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index 4a82f5114ca0..49267ed7cea3 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -4,6 +4,7 @@ */ #include +#include #include "host.h" #include "hostcmd.h" #include "decl.h" @@ -1829,15 +1830,20 @@ static void lbs_send_confirmsleep(struct lbs_private *priv) ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) &confirm_sleep, sizeof(confirm_sleep)); - if (ret) { lbs_pr_alert("confirm_sleep failed\n"); - } else { - spin_lock_irqsave(&priv->driver_lock, flags); - if (!priv->intcounter) - priv->psstate = PS_STATE_SLEEP; - spin_unlock_irqrestore(&priv->driver_lock, flags); + goto out; } + + spin_lock_irqsave(&priv->driver_lock, flags); + + /* If nothing to do, go back to sleep (?) */ + if (!__kfifo_len(priv->event_fifo) && !priv->resp_len[priv->resp_idx]) + priv->psstate = PS_STATE_SLEEP; + + spin_unlock_irqrestore(&priv->driver_lock, flags); + +out: lbs_deb_leave(LBS_DEB_HOST); } @@ -1899,13 +1905,16 @@ void lbs_ps_confirm_sleep(struct lbs_private *priv) } spin_lock_irqsave(&priv->driver_lock, flags); + /* In-progress command? */ if (priv->cur_cmd) { allowed = 0; lbs_deb_host("cur_cmd was set\n"); } - if (priv->intcounter > 0) { + + /* Pending events or command responses? */ + if (__kfifo_len(priv->event_fifo) || priv->resp_len[priv->resp_idx]) { allowed = 0; - lbs_deb_host("intcounter %d\n", priv->intcounter); + lbs_deb_host("pending events or command responses\n"); } spin_unlock_irqrestore(&priv->driver_lock, flags); diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c index 245d3c3a9274..5abecb7673e6 100644 --- a/drivers/net/wireless/libertas/cmdresp.c +++ b/drivers/net/wireless/libertas/cmdresp.c @@ -384,7 +384,7 @@ static inline int handle_cmd_response(struct lbs_private *priv, return ret; } -int lbs_process_rx_command(struct lbs_private *priv) +int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len) { uint16_t respcmd, curcmd; struct cmd_header *resp; @@ -404,14 +404,14 @@ int lbs_process_rx_command(struct lbs_private *priv) goto done; } - resp = (void *)priv->upld_buf; + resp = (void *)data; curcmd = le16_to_cpu(priv->cur_cmd->cmdbuf->command); respcmd = le16_to_cpu(resp->command); result = le16_to_cpu(resp->result); lbs_deb_cmd("CMD_RESP: response 0x%04x, seq %d, size %d\n", - respcmd, le16_to_cpu(resp->seqnum), priv->upld_len); - lbs_deb_hex(LBS_DEB_CMD, "CMD_RESP", (void *) resp, priv->upld_len); + respcmd, le16_to_cpu(resp->seqnum), len); + lbs_deb_hex(LBS_DEB_CMD, "CMD_RESP", (void *) resp, len); if (resp->seqnum != priv->cur_cmd->cmdbuf->seqnum) { lbs_pr_info("Received CMD_RESP with invalid sequence %d (expected %d)\n", @@ -569,18 +569,13 @@ static int lbs_send_confirmwake(struct lbs_private *priv) return ret; } -int lbs_process_event(struct lbs_private *priv) +int lbs_process_event(struct lbs_private *priv, u32 event) { int ret = 0; - u32 eventcause; lbs_deb_enter(LBS_DEB_CMD); - spin_lock_irq(&priv->driver_lock); - eventcause = priv->eventcause >> SBI_EVENT_CAUSE_SHIFT; - spin_unlock_irq(&priv->driver_lock); - - switch (eventcause) { + switch (event) { case MACREG_INT_CODE_LINK_SENSED: lbs_deb_cmd("EVENT: link sensed\n"); break; @@ -696,14 +691,10 @@ int lbs_process_event(struct lbs_private *priv) break; default: - lbs_pr_alert("EVENT: unknown event id %d\n", eventcause); + lbs_pr_alert("EVENT: unknown event id %d\n", event); break; } - spin_lock_irq(&priv->driver_lock); - priv->eventcause = 0; - spin_unlock_irq(&priv->driver_lock); - lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); return ret; } diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c index 7072e26b42d9..ad2fabca9116 100644 --- a/drivers/net/wireless/libertas/debugfs.c +++ b/drivers/net/wireless/libertas/debugfs.c @@ -824,7 +824,6 @@ struct debug_data { /* To debug any member of struct lbs_private, simply add one line here. */ static struct debug_data items[] = { - {"intcounter", item_size(intcounter), item_addr(intcounter)}, {"psmode", item_size(psmode), item_addr(psmode)}, {"psstate", item_size(psstate), item_addr(psstate)}, }; diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h index 4aea421f07ce..b652fa301e19 100644 --- a/drivers/net/wireless/libertas/decl.h +++ b/drivers/net/wireless/libertas/decl.h @@ -19,7 +19,7 @@ struct cmd_ds_command; void lbs_set_mac_control(struct lbs_private *priv); -void lbs_send_tx_feedback(struct lbs_private *priv); +void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count); int lbs_free_cmd_buffer(struct lbs_private *priv); @@ -30,14 +30,16 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, int lbs_allocate_cmd_buffer(struct lbs_private *priv); int lbs_execute_next_command(struct lbs_private *priv); -int lbs_process_event(struct lbs_private *priv); -void lbs_interrupt(struct lbs_private *priv); +int lbs_process_event(struct lbs_private *priv, u32 event); +void lbs_queue_event(struct lbs_private *priv, u32 event); +void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx); + int lbs_set_radio_control(struct lbs_private *priv); u32 lbs_fw_index_to_data_rate(u8 index); u8 lbs_data_rate_to_fw_index(u32 rate); /** The proc fs interface */ -int lbs_process_rx_command(struct lbs_private *priv); +int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len); void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd, int result); int lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev); diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h index 84e8de5e21da..d39520111062 100644 --- a/drivers/net/wireless/libertas/defs.h +++ b/drivers/net/wireless/libertas/defs.h @@ -177,8 +177,6 @@ static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, in #define MRVDRV_CMD_UPLD_RDY 0x0008 #define MRVDRV_CARDEVENT 0x0010 -#define SBI_EVENT_CAUSE_SHIFT 3 - /** TxPD status */ /* Station firmware use TxPD status field to report final Tx transmit diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index 1e6bae80396b..0d9edb9b11f5 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h @@ -129,10 +129,6 @@ struct lbs_private { u32 bbp_offset; u32 rf_offset; - /** Upload length */ - u32 upld_len; - /* Upload buffer */ - u8 upld_buf[LBS_UPLD_SIZE]; /* Download sent: bit0 1/0=data_sent/data_tx_done, bit1 1/0=cmd_sent/cmd_tx_done, @@ -155,21 +151,16 @@ struct lbs_private { /** Hardware access */ int (*hw_host_to_card) (struct lbs_private *priv, u8 type, u8 *payload, u16 nb); - int (*hw_get_int_status) (struct lbs_private *priv, u8 *); - int (*hw_read_event_cause) (struct lbs_private *); /* Wake On LAN */ uint32_t wol_criteria; uint8_t wol_gpio; uint8_t wol_gap; - /* was struct lbs_adapter from here... */ - /** Wlan adapter data structure*/ /** STATUS variables */ u32 fwrelease; u32 fwcapinfo; - /* protected with big lock */ struct mutex lock; @@ -181,7 +172,6 @@ struct lbs_private { /** command-related variables */ u16 seqnum; - /* protected by big lock */ struct cmd_ctrl_node *cmd_array; /** Current command */ @@ -194,12 +184,17 @@ struct lbs_private { struct list_head cmdpendingq; wait_queue_head_t cmd_pending; - /* command related variables protected by priv->driver_lock */ - /** Async and Sync Event variables */ - u32 intcounter; - u32 eventcause; - u8 nodename[16]; /* nickname */ + /* Command responses sent from the hardware to the driver */ + u8 resp_idx; + u8 resp_buf[2][LBS_UPLD_SIZE]; + u32 resp_len[2]; + + /* Events sent from hardware to driver */ + struct kfifo *event_fifo; + + /* nickname */ + u8 nodename[16]; /** spin locks */ spinlock_t driver_lock; @@ -209,8 +204,6 @@ struct lbs_private { int nr_retries; int cmd_timed_out; - u8 hisregcpy; - /** current ssid/bssid related parameters*/ struct current_bss_params curbssparams; diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c index 53afebac7146..54280e292ea5 100644 --- a/drivers/net/wireless/libertas/if_cs.c +++ b/drivers/net/wireless/libertas/if_cs.c @@ -83,14 +83,14 @@ static inline unsigned int if_cs_read8(struct if_cs_card *card, uint reg) { unsigned int val = ioread8(card->iobase + reg); if (debug_output) - printk(KERN_INFO "##inb %08x<%02x\n", reg, val); + printk(KERN_INFO "inb %08x<%02x\n", reg, val); return val; } static inline unsigned int if_cs_read16(struct if_cs_card *card, uint reg) { unsigned int val = ioread16(card->iobase + reg); if (debug_output) - printk(KERN_INFO "##inw %08x<%04x\n", reg, val); + printk(KERN_INFO "inw %08x<%04x\n", reg, val); return val; } static inline void if_cs_read16_rep( @@ -100,7 +100,7 @@ static inline void if_cs_read16_rep( unsigned long count) { if (debug_output) - printk(KERN_INFO "##insw %08x<(0x%lx words)\n", + printk(KERN_INFO "insw %08x<(0x%lx words)\n", reg, count); ioread16_rep(card->iobase + reg, buf, count); } @@ -108,14 +108,14 @@ static inline void if_cs_read16_rep( static inline void if_cs_write8(struct if_cs_card *card, uint reg, u8 val) { if (debug_output) - printk(KERN_INFO "##outb %08x>%02x\n", reg, val); + printk(KERN_INFO "outb %08x>%02x\n", reg, val); iowrite8(val, card->iobase + reg); } static inline void if_cs_write16(struct if_cs_card *card, uint reg, u16 val) { if (debug_output) - printk(KERN_INFO "##outw %08x>%04x\n", reg, val); + printk(KERN_INFO "outw %08x>%04x\n", reg, val); iowrite16(val, card->iobase + reg); } @@ -126,7 +126,7 @@ static inline void if_cs_write16_rep( unsigned long count) { if (debug_output) - printk(KERN_INFO "##outsw %08x>(0x%lx words)\n", + printk(KERN_INFO "outsw %08x>(0x%lx words)\n", reg, count); iowrite16_rep(card->iobase + reg, buf, count); } @@ -199,17 +199,6 @@ static int if_cs_poll_while_fw_download(struct if_cs_card *card, uint addr, u8 r #define IF_CS_C_S_CARDEVENT 0x0010 #define IF_CS_C_S_MASK 0x001f #define IF_CS_C_S_STATUS_MASK 0x7f00 -/* The following definitions should be the same as the MRVDRV_ ones */ - -#if MRVDRV_CMD_DNLD_RDY != IF_CS_C_S_CMD_DNLD_RDY -#error MRVDRV_CMD_DNLD_RDY and IF_CS_C_S_CMD_DNLD_RDY not in sync -#endif -#if MRVDRV_CMD_UPLD_RDY != IF_CS_C_S_CMD_UPLD_RDY -#error MRVDRV_CMD_UPLD_RDY and IF_CS_C_S_CMD_UPLD_RDY not in sync -#endif -#if MRVDRV_CARDEVENT != IF_CS_C_S_CARDEVENT -#error MRVDRV_CARDEVENT and IF_CS_C_S_CARDEVENT not in sync -#endif #define IF_CS_C_INT_CAUSE 0x00000022 #define IF_CS_C_IC_MASK 0x001f @@ -225,55 +214,6 @@ static int if_cs_poll_while_fw_download(struct if_cs_card *card, uint addr, u8 r -/********************************************************************/ -/* Interrupts */ -/********************************************************************/ - -static inline void if_cs_enable_ints(struct if_cs_card *card) -{ - lbs_deb_enter(LBS_DEB_CS); - if_cs_write16(card, IF_CS_H_INT_MASK, 0); -} - -static inline void if_cs_disable_ints(struct if_cs_card *card) -{ - lbs_deb_enter(LBS_DEB_CS); - if_cs_write16(card, IF_CS_H_INT_MASK, IF_CS_H_IM_MASK); -} - -static irqreturn_t if_cs_interrupt(int irq, void *data) -{ - struct if_cs_card *card = data; - u16 int_cause; - - lbs_deb_enter(LBS_DEB_CS); - - int_cause = if_cs_read16(card, IF_CS_C_INT_CAUSE); - if (int_cause == 0x0) { - /* Not for us */ - return IRQ_NONE; - - } else if (int_cause == 0xffff) { - /* Read in junk, the card has probably been removed */ - card->priv->surpriseremoved = 1; - return IRQ_HANDLED; - } else { - if (int_cause & IF_CS_H_IC_TX_OVER) - lbs_host_to_card_done(card->priv); - - /* clear interrupt */ - if_cs_write16(card, IF_CS_C_INT_CAUSE, int_cause & IF_CS_C_IC_MASK); - } - spin_lock(&card->priv->driver_lock); - lbs_interrupt(card->priv); - spin_unlock(&card->priv->driver_lock); - - return IRQ_HANDLED; -} - - - - /********************************************************************/ /* I/O */ /********************************************************************/ @@ -351,6 +291,7 @@ static void if_cs_send_data(struct lbs_private *priv, u8 *buf, u16 nb) */ static int if_cs_receive_cmdres(struct lbs_private *priv, u8 *data, u32 *len) { + unsigned long flags; int ret = -1; u16 val; @@ -378,6 +319,12 @@ static int if_cs_receive_cmdres(struct lbs_private *priv, u8 *data, u32 *len) * bytes */ *len -= 8; ret = 0; + + /* Clear this flag again */ + spin_lock_irqsave(&priv->driver_lock, flags); + priv->dnld_sent = DNLD_RES_RECEIVED; + spin_unlock_irqrestore(&priv->driver_lock, flags); + out: lbs_deb_leave_args(LBS_DEB_CS, "ret %d, len %d", ret, *len); return ret; @@ -396,11 +343,9 @@ static struct sk_buff *if_cs_receive_data(struct lbs_private *priv) if (len == 0 || len > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) { lbs_pr_err("card data buffer has invalid # of bytes (%d)\n", len); priv->stats.rx_dropped++; - printk(KERN_INFO "##HS %s:%d TODO\n", __FUNCTION__, __LINE__); goto dat_err; } - //TODO: skb = dev_alloc_skb(len+ETH_FRAME_LEN+MRVDRV_SNAP_HEADER_LEN+EXTRA_LEN); skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE + 2); if (!skb) goto out; @@ -424,6 +369,96 @@ out: +/********************************************************************/ +/* Interrupts */ +/********************************************************************/ + +static inline void if_cs_enable_ints(struct if_cs_card *card) +{ + lbs_deb_enter(LBS_DEB_CS); + if_cs_write16(card, IF_CS_H_INT_MASK, 0); +} + +static inline void if_cs_disable_ints(struct if_cs_card *card) +{ + lbs_deb_enter(LBS_DEB_CS); + if_cs_write16(card, IF_CS_H_INT_MASK, IF_CS_H_IM_MASK); +} + + +static irqreturn_t if_cs_interrupt(int irq, void *data) +{ + struct if_cs_card *card = data; + struct lbs_private *priv = card->priv; + u16 cause; + + lbs_deb_enter(LBS_DEB_CS); + + cause = if_cs_read16(card, IF_CS_C_INT_CAUSE); + if_cs_write16(card, IF_CS_C_INT_CAUSE, cause & IF_CS_C_IC_MASK); + + lbs_deb_cs("cause 0x%04x\n", cause); + if (cause == 0) { + /* Not for us */ + return IRQ_NONE; + } + + if (cause == 0xffff) { + /* Read in junk, the card has probably been removed */ + card->priv->surpriseremoved = 1; + return IRQ_HANDLED; + } + + /* TODO: I'm not sure what the best ordering is */ + + cause = if_cs_read16(card, IF_CS_C_STATUS) & IF_CS_C_S_MASK; + + if (cause & IF_CS_C_S_RX_UPLD_RDY) { + struct sk_buff *skb; + lbs_deb_cs("rx packet\n"); + skb = if_cs_receive_data(priv); + if (skb) + lbs_process_rxed_packet(priv, skb); + } + + if (cause & IF_CS_H_IC_TX_OVER) { + lbs_deb_cs("tx over\n"); + lbs_host_to_card_done(priv); + } + + if (cause & IF_CS_C_S_CMD_UPLD_RDY) { + unsigned long flags; + u8 i; + + lbs_deb_cs("cmd upload ready\n"); + spin_lock_irqsave(&priv->driver_lock, flags); + i = (priv->resp_idx == 0) ? 1 : 0; + spin_unlock_irqrestore(&priv->driver_lock, flags); + + BUG_ON(priv->resp_len[i]); + if_cs_receive_cmdres(priv, priv->resp_buf[i], + &priv->resp_len[i]); + + spin_lock_irqsave(&priv->driver_lock, flags); + lbs_notify_command_response(priv, i); + spin_unlock_irqrestore(&priv->driver_lock, flags); + } + + if (cause & IF_CS_H_IC_HOST_EVENT) { + u16 event = if_cs_read16(priv->card, IF_CS_C_STATUS) + & IF_CS_C_S_STATUS_MASK; + if_cs_write16(priv->card, IF_CS_H_INT_CAUSE, + IF_CS_H_IC_HOST_EVENT); + lbs_deb_cs("eventcause 0x%04x\n", event); + lbs_queue_event(priv, event >> 8 & 0xff); + } + + return IRQ_HANDLED; +} + + + + /********************************************************************/ /* Firmware */ /********************************************************************/ @@ -476,8 +511,6 @@ static int if_cs_prog_helper(struct if_cs_card *card) if (remain < count) count = remain; - /* printk(KERN_INFO "//HS %d loading %d of %d bytes\n", - __LINE__, sent, fw->size); */ /* "write the number of bytes to be sent to the I/O Command * write length register" */ @@ -544,18 +577,12 @@ static int if_cs_prog_real(struct if_cs_card *card) ret = if_cs_poll_while_fw_download(card, IF_CS_C_SQ_READ_LOW, IF_CS_C_SQ_HELPER_OK); if (ret < 0) { - int i; lbs_pr_err("helper firmware doesn't answer\n"); - for (i = 0; i < 0x50; i += 2) - printk(KERN_INFO "## HS %02x: %04x\n", - i, if_cs_read16(card, i)); goto err_release; } for (sent = 0; sent < fw->size; sent += len) { len = if_cs_read16(card, IF_CS_C_SQ_READ_LOW); - /* printk(KERN_INFO "//HS %d loading %d of %d bytes\n", - __LINE__, sent, fw->size); */ if (len & 1) { retry++; lbs_pr_info("odd, need to retry this firmware block\n"); @@ -642,64 +669,6 @@ static int if_cs_host_to_card(struct lbs_private *priv, } -static int if_cs_get_int_status(struct lbs_private *priv, u8 *ireg) -{ - struct if_cs_card *card = (struct if_cs_card *)priv->card; - int ret = 0; - u16 int_cause; - *ireg = 0; - - lbs_deb_enter(LBS_DEB_CS); - - if (priv->surpriseremoved) - goto out; - - int_cause = if_cs_read16(card, IF_CS_C_INT_CAUSE) & IF_CS_C_IC_MASK; - if_cs_write16(card, IF_CS_C_INT_CAUSE, int_cause); - - *ireg = if_cs_read16(card, IF_CS_C_STATUS) & IF_CS_C_S_MASK; - - if (!*ireg) - goto sbi_get_int_status_exit; - -sbi_get_int_status_exit: - - /* is there a data packet for us? */ - if (*ireg & IF_CS_C_S_RX_UPLD_RDY) { - struct sk_buff *skb = if_cs_receive_data(priv); - lbs_process_rxed_packet(priv, skb); - *ireg &= ~IF_CS_C_S_RX_UPLD_RDY; - } - - if (*ireg & IF_CS_C_S_TX_DNLD_RDY) { - priv->dnld_sent = DNLD_RES_RECEIVED; - } - - /* Card has a command result for us */ - if (*ireg & IF_CS_C_S_CMD_UPLD_RDY) { - ret = if_cs_receive_cmdres(priv, priv->upld_buf, &priv->upld_len); - if (ret < 0) - lbs_pr_err("could not receive cmd from card\n"); - } - -out: - lbs_deb_leave_args(LBS_DEB_CS, "ret %d, ireg 0x%x, hisregcpy 0x%x", ret, *ireg, priv->hisregcpy); - return ret; -} - - -static int if_cs_read_event_cause(struct lbs_private *priv) -{ - lbs_deb_enter(LBS_DEB_CS); - - priv->eventcause = (if_cs_read16(priv->card, IF_CS_C_STATUS) & IF_CS_C_S_STATUS_MASK) >> 5; - if_cs_write16(priv->card, IF_CS_H_INT_CAUSE, IF_CS_H_IC_HOST_EVENT); - - return 0; -} - - - /********************************************************************/ /* Card Services */ /********************************************************************/ @@ -852,13 +821,10 @@ static int if_cs_probe(struct pcmcia_device *p_dev) goto out2; } - /* Store pointers to our call-back functions */ + /* Finish setting up fields in lbs_private */ card->priv = priv; priv->card = card; - priv->hw_host_to_card = if_cs_host_to_card; - priv->hw_get_int_status = if_cs_get_int_status; - priv->hw_read_event_cause = if_cs_read_event_cause; - + priv->hw_host_to_card = if_cs_host_to_card; priv->fw_ready = 1; /* Now actually get the IRQ */ diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index eed73204bcc9..51f664bbee9d 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c @@ -91,8 +91,6 @@ struct if_sdio_card { const char *firmware; u8 buffer[65536]; - u8 int_cause; - u32 event; spinlock_t lock; struct if_sdio_packet *packets; @@ -129,13 +127,13 @@ static u16 if_sdio_read_scratch(struct if_sdio_card *card, int *err) static int if_sdio_handle_cmd(struct if_sdio_card *card, u8 *buffer, unsigned size) { + struct lbs_private *priv = card->priv; int ret; unsigned long flags; + u8 i; lbs_deb_enter(LBS_DEB_SDIO); - spin_lock_irqsave(&card->priv->driver_lock, flags); - if (size > LBS_CMD_BUFFER_SIZE) { lbs_deb_sdio("response packet too large (%d bytes)\n", (int)size); @@ -143,20 +141,20 @@ static int if_sdio_handle_cmd(struct if_sdio_card *card, goto out; } - memcpy(card->priv->upld_buf, buffer, size); - card->priv->upld_len = size; + spin_lock_irqsave(&priv->driver_lock, flags); - card->int_cause |= MRVDRV_CMD_UPLD_RDY; + i = (priv->resp_idx == 0) ? 1 : 0; + BUG_ON(priv->resp_len[i]); + priv->resp_len[i] = size; + memcpy(priv->resp_buf[i], buffer, size); + lbs_notify_command_response(priv, i); - lbs_interrupt(card->priv); + spin_unlock_irqrestore(&card->priv->driver_lock, flags); ret = 0; out: - spin_unlock_irqrestore(&card->priv->driver_lock, flags); - lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); - return ret; } @@ -202,7 +200,6 @@ static int if_sdio_handle_event(struct if_sdio_card *card, u8 *buffer, unsigned size) { int ret; - unsigned long flags; u32 event; lbs_deb_enter(LBS_DEB_SDIO); @@ -222,18 +219,9 @@ static int if_sdio_handle_event(struct if_sdio_card *card, event |= buffer[2] << 16; event |= buffer[1] << 8; event |= buffer[0] << 0; - event <<= SBI_EVENT_CAUSE_SHIFT; } - spin_lock_irqsave(&card->priv->driver_lock, flags); - - card->event = event; - card->int_cause |= MRVDRV_CARDEVENT; - - lbs_interrupt(card->priv); - - spin_unlock_irqrestore(&card->priv->driver_lock, flags); - + lbs_queue_event(card->priv, event & 0xFF); ret = 0; out: @@ -770,37 +758,6 @@ out: return ret; } -static int if_sdio_get_int_status(struct lbs_private *priv, u8 *ireg) -{ - struct if_sdio_card *card; - - lbs_deb_enter(LBS_DEB_SDIO); - - card = priv->card; - - *ireg = card->int_cause; - card->int_cause = 0; - - lbs_deb_leave(LBS_DEB_SDIO); - - return 0; -} - -static int if_sdio_read_event_cause(struct lbs_private *priv) -{ - struct if_sdio_card *card; - - lbs_deb_enter(LBS_DEB_SDIO); - - card = priv->card; - - priv->eventcause = card->event; - - lbs_deb_leave(LBS_DEB_SDIO); - - return 0; -} - /*******************************************************************/ /* SDIO callbacks */ /*******************************************************************/ @@ -953,8 +910,6 @@ static int if_sdio_probe(struct sdio_func *func, priv->card = card; priv->hw_host_to_card = if_sdio_host_to_card; - priv->hw_get_int_status = if_sdio_get_int_status; - priv->hw_read_event_cause = if_sdio_read_event_cause; priv->fw_ready = 1; diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c index 75aed9d07367..8032df72aaab 100644 --- a/drivers/net/wireless/libertas/if_usb.c +++ b/drivers/net/wireless/libertas/if_usb.c @@ -38,8 +38,6 @@ static void if_usb_receive_fwload(struct urb *urb); static int if_usb_prog_firmware(struct if_usb_card *cardp); static int if_usb_host_to_card(struct lbs_private *priv, uint8_t type, uint8_t *payload, uint16_t nb); -static int if_usb_get_int_status(struct lbs_private *priv, uint8_t *); -static int if_usb_read_event_cause(struct lbs_private *); static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload, uint16_t nb); static void if_usb_free(struct if_usb_card *cardp); @@ -233,8 +231,6 @@ static int if_usb_probe(struct usb_interface *intf, cardp->priv->fw_ready = 1; priv->hw_host_to_card = if_usb_host_to_card; - priv->hw_get_int_status = if_usb_get_int_status; - priv->hw_read_event_cause = if_usb_read_event_cause; cardp->boot2_version = udev->descriptor.bcdDevice; if_usb_submit_rx_urb(cardp); @@ -582,7 +578,6 @@ static inline void process_cmdtypedata(int recvlength, struct sk_buff *skb, skb_pull(skb, MESSAGE_HEADER_LEN); lbs_process_rxed_packet(priv, skb); - priv->upld_len = (recvlength - MESSAGE_HEADER_LEN); } static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff, @@ -590,6 +585,8 @@ static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff, struct if_usb_card *cardp, struct lbs_private *priv) { + u8 i; + if (recvlength > LBS_CMD_BUFFER_SIZE) { lbs_deb_usbd(&cardp->udev->dev, "The receive buffer is too large\n"); @@ -601,12 +598,15 @@ static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff, BUG(); spin_lock(&priv->driver_lock); - cardp->usb_int_cause |= MRVDRV_CMD_UPLD_RDY; - priv->upld_len = (recvlength - MESSAGE_HEADER_LEN); - memcpy(priv->upld_buf, recvbuff + MESSAGE_HEADER_LEN, priv->upld_len); + i = (priv->resp_idx == 0) ? 1 : 0; + BUG_ON(priv->resp_len[i]); + priv->resp_len[i] = (recvlength - MESSAGE_HEADER_LEN); + memcpy(priv->resp_buf[i], recvbuff + MESSAGE_HEADER_LEN, + priv->resp_len[i]); kfree_skb(skb); - lbs_interrupt(priv); + lbs_notify_command_response(priv, i); + spin_unlock(&priv->driver_lock); lbs_deb_usbd(&cardp->udev->dev, @@ -629,6 +629,7 @@ static void if_usb_receive(struct urb *urb) uint8_t *recvbuff = NULL; uint32_t recvtype = 0; __le32 *pkt = (__le32 *)(skb->data + IPFIELD_ALIGN_OFFSET); + uint32_t event; lbs_deb_enter(LBS_DEB_USB); @@ -660,26 +661,20 @@ static void if_usb_receive(struct urb *urb) break; case CMD_TYPE_INDICATION: - /* Event cause handling */ - spin_lock(&priv->driver_lock); + /* Event handling */ + event = le32_to_cpu(pkt[1]); + lbs_deb_usbd(&cardp->udev->dev, "**EVENT** 0x%X\n", event); + kfree_skb(skb); - cardp->usb_event_cause = le32_to_cpu(pkt[1]); + /* Icky undocumented magic special case */ + if (event & 0xffff0000) { + u32 trycount = (event & 0xffff0000) >> 16; - lbs_deb_usbd(&cardp->udev->dev,"**EVENT** 0x%X\n", - cardp->usb_event_cause); + lbs_send_tx_feedback(priv, trycount); + } else + lbs_queue_event(priv, event & 0xFF); + break; - /* Icky undocumented magic special case */ - if (cardp->usb_event_cause & 0xffff0000) { - lbs_send_tx_feedback(priv); - spin_unlock(&priv->driver_lock); - break; - } - cardp->usb_event_cause <<= 3; - cardp->usb_int_cause |= MRVDRV_CARDEVENT; - kfree_skb(skb); - lbs_interrupt(priv); - spin_unlock(&priv->driver_lock); - goto rx_exit; default: lbs_deb_usbd(&cardp->udev->dev, "Unknown command type 0x%X\n", recvtype); @@ -722,30 +717,6 @@ static int if_usb_host_to_card(struct lbs_private *priv, uint8_t type, return usb_tx_block(cardp, cardp->ep_out_buf, nb + MESSAGE_HEADER_LEN); } -/* called with priv->driver_lock held */ -static int if_usb_get_int_status(struct lbs_private *priv, uint8_t *ireg) -{ - struct if_usb_card *cardp = priv->card; - - *ireg = cardp->usb_int_cause; - cardp->usb_int_cause = 0; - - lbs_deb_usbd(&cardp->udev->dev, "Int cause is 0x%X\n", *ireg); - - return 0; -} - -static int if_usb_read_event_cause(struct lbs_private *priv) -{ - struct if_usb_card *cardp = priv->card; - - priv->eventcause = cardp->usb_event_cause; - /* Re-submit rx urb here to avoid event lost issue */ - if_usb_submit_rx_urb(cardp); - - return 0; -} - /** * @brief This function issues Boot command to the Boot2 code * @param ivalue 1:Boot from FW by USB-Download diff --git a/drivers/net/wireless/libertas/if_usb.h b/drivers/net/wireless/libertas/if_usb.h index e4829a391eb9..5771a83a43f0 100644 --- a/drivers/net/wireless/libertas/if_usb.h +++ b/drivers/net/wireless/libertas/if_usb.h @@ -46,8 +46,6 @@ struct if_usb_card { struct lbs_private *priv; struct sk_buff *rx_skb; - uint32_t usb_event_cause; - uint8_t usb_int_cause; uint8_t ep_in; uint8_t ep_out; diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 8f1122610974..406f54d40956 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -480,10 +481,9 @@ static void lbs_tx_timeout(struct net_device *dev) dev->trans_start = jiffies; - if (priv->currenttxskb) { - priv->eventcause = 0x01000000; - lbs_send_tx_feedback(priv); - } + if (priv->currenttxskb) + lbs_send_tx_feedback(priv, 0); + /* XX: Shouldn't we also call into the hw-specific driver to kick it somehow? */ lbs_host_to_card_done(priv); @@ -659,7 +659,6 @@ static int lbs_thread(void *data) struct net_device *dev = data; struct lbs_private *priv = dev->priv; wait_queue_t wait; - u8 ireg = 0; lbs_deb_enter(LBS_DEB_THREAD); @@ -667,9 +666,10 @@ static int lbs_thread(void *data) for (;;) { int shouldsleep; + u8 resp_idx; - lbs_deb_thread( "main-thread 111: intcounter=%d currenttxskb=%p dnld_sent=%d\n", - priv->intcounter, priv->currenttxskb, priv->dnld_sent); + lbs_deb_thread("1: currenttxskb %p, dnld_sent %d\n", + priv->currenttxskb, priv->dnld_sent); add_wait_queue(&priv->waitq, &wait); set_current_state(TASK_INTERRUPTIBLE); @@ -681,8 +681,6 @@ static int lbs_thread(void *data) shouldsleep = 1; /* We need to wait until we're _told_ to die */ else if (priv->psstate == PS_STATE_SLEEP) shouldsleep = 1; /* Sleep mode. Nothing we can do till it wakes */ - else if (priv->intcounter) - shouldsleep = 0; /* Interrupt pending. Deal with it now */ else if (priv->cmd_timed_out) shouldsleep = 0; /* Command timed out. Recover */ else if (!priv->fw_ready) @@ -695,29 +693,34 @@ static int lbs_thread(void *data) shouldsleep = 1; /* Can't send a command; one already running */ else if (!list_empty(&priv->cmdpendingq)) shouldsleep = 0; /* We have a command to send */ + else if (__kfifo_len(priv->event_fifo)) + shouldsleep = 0; /* We have an event to process */ + else if (priv->resp_len[priv->resp_idx]) + shouldsleep = 0; /* We have a command response */ else shouldsleep = 1; /* No command */ if (shouldsleep) { - lbs_deb_thread("main-thread sleeping... Conn=%d IntC=%d PS_mode=%d PS_State=%d\n", - priv->connect_status, priv->intcounter, - priv->psmode, priv->psstate); + lbs_deb_thread("sleeping, connect_status %d, " + "ps_mode %d, ps_state %d\n", + priv->connect_status, + priv->psmode, priv->psstate); spin_unlock_irq(&priv->driver_lock); schedule(); } else spin_unlock_irq(&priv->driver_lock); - lbs_deb_thread("main-thread 222 (waking up): intcounter=%d currenttxskb=%p dnld_sent=%d\n", - priv->intcounter, priv->currenttxskb, priv->dnld_sent); + lbs_deb_thread("2: currenttxskb %p, dnld_send %d\n", + priv->currenttxskb, priv->dnld_sent); set_current_state(TASK_RUNNING); remove_wait_queue(&priv->waitq, &wait); - lbs_deb_thread("main-thread 333: intcounter=%d currenttxskb=%p dnld_sent=%d\n", - priv->intcounter, priv->currenttxskb, priv->dnld_sent); + lbs_deb_thread("3: currenttxskb %p, dnld_sent %d\n", + priv->currenttxskb, priv->dnld_sent); if (kthread_should_stop()) { - lbs_deb_thread("main-thread: break from main thread\n"); + lbs_deb_thread("break from main thread\n"); break; } @@ -726,35 +729,23 @@ static int lbs_thread(void *data) continue; } - spin_lock_irq(&priv->driver_lock); - - if (priv->intcounter) { - u8 int_status; + lbs_deb_thread("4: currenttxskb %p, dnld_sent %d\n", + priv->currenttxskb, priv->dnld_sent); - priv->intcounter = 0; - int_status = priv->hw_get_int_status(priv, &ireg); - - if (int_status) { - lbs_deb_thread("main-thread: reading HOST_INT_STATUS_REG failed\n"); - spin_unlock_irq(&priv->driver_lock); - continue; - } - priv->hisregcpy |= ireg; - } - - lbs_deb_thread("main-thread 444: intcounter=%d currenttxskb=%p dnld_sent=%d\n", - priv->intcounter, priv->currenttxskb, priv->dnld_sent); - - /* command response? */ - if (priv->hisregcpy & MRVDRV_CMD_UPLD_RDY) { - lbs_deb_thread("main-thread: cmd response ready\n"); - - priv->hisregcpy &= ~MRVDRV_CMD_UPLD_RDY; + spin_lock_irq(&priv->driver_lock); + /* Process any pending command response */ + resp_idx = priv->resp_idx; + if (priv->resp_len[resp_idx]) { spin_unlock_irq(&priv->driver_lock); - lbs_process_rx_command(priv); + lbs_process_command_response(priv, + priv->resp_buf[resp_idx], + priv->resp_len[resp_idx]); spin_lock_irq(&priv->driver_lock); + priv->resp_len[resp_idx] = 0; } + spin_unlock_irq(&priv->driver_lock); + /* command timeout stuff */ if (priv->cmd_timed_out && priv->cur_cmd) { struct cmd_ctrl_node *cmdnode = priv->cur_cmd; @@ -775,21 +766,18 @@ static int lbs_thread(void *data) } priv->cmd_timed_out = 0; - /* Any Card Event */ - if (priv->hisregcpy & MRVDRV_CARDEVENT) { - lbs_deb_thread("main-thread: Card Event Activity\n"); - - priv->hisregcpy &= ~MRVDRV_CARDEVENT; + /* Process hardware events, e.g. card removed, link lost */ + spin_lock_irq(&priv->driver_lock); + while (__kfifo_len(priv->event_fifo)) { + u32 event; - if (priv->hw_read_event_cause(priv)) { - lbs_pr_alert("main-thread: hw_read_event_cause failed\n"); - spin_unlock_irq(&priv->driver_lock); - continue; - } - spin_unlock_irq(&priv->driver_lock); - lbs_process_event(priv); - } else + __kfifo_get(priv->event_fifo, (unsigned char *) &event, + sizeof(event)); spin_unlock_irq(&priv->driver_lock); + lbs_process_event(priv, event); + spin_lock_irq(&priv->driver_lock); + } + spin_unlock_irq(&priv->driver_lock); if (!priv->fw_ready) continue; @@ -798,8 +786,10 @@ static int lbs_thread(void *data) if (priv->psstate == PS_STATE_PRE_SLEEP && !priv->dnld_sent && !priv->cur_cmd) { if (priv->connect_status == LBS_CONNECTED) { - lbs_deb_thread("main_thread: PRE_SLEEP--intcounter=%d currenttxskb=%p dnld_sent=%d cur_cmd=%p, confirm now\n", - priv->intcounter, priv->currenttxskb, priv->dnld_sent, priv->cur_cmd); + lbs_deb_thread("pre-sleep, currenttxskb %p, " + "dnld_sent %d, cur_cmd %p\n", + priv->currenttxskb, priv->dnld_sent, + priv->cur_cmd); lbs_ps_confirm_sleep(priv); } else { @@ -809,7 +799,8 @@ static int lbs_thread(void *data) * after firmware fixes it */ priv->psstate = PS_STATE_AWAKE; - lbs_pr_alert("main-thread: ignore PS_SleepConfirm in non-connected state\n"); + lbs_pr_alert("ignore PS_SleepConfirm in " + "non-connected state\n"); } } @@ -1046,7 +1037,18 @@ static int lbs_init_adapter(struct lbs_private *priv) /* Allocate the command buffers */ if (lbs_allocate_cmd_buffer(priv)) { lbs_pr_err("Out of memory allocating command buffers\n"); - ret = -1; + ret = -ENOMEM; + goto out; + } + priv->resp_idx = 0; + priv->resp_len[0] = priv->resp_len[1] = 0; + + /* Create the event FIFO */ + priv->event_fifo = kfifo_alloc(sizeof(u32) * 16, GFP_KERNEL, NULL); + if (IS_ERR(priv->event_fifo)) { + lbs_pr_err("Out of memory allocating event FIFO buffer\n"); + ret = -ENOMEM; + goto out; } out: @@ -1060,6 +1062,8 @@ static void lbs_free_adapter(struct lbs_private *priv) lbs_deb_enter(LBS_DEB_MAIN); lbs_free_cmd_buffer(priv); + if (priv->event_fifo) + kfifo_free(priv->event_fifo); del_timer(&priv->command_timer); kfree(priv->networks); priv->networks = NULL; @@ -1434,27 +1438,41 @@ out: return ret; } -/** - * @brief This function handles the interrupt. it will change PS - * state if applicable. it will wake up main_thread to handle - * the interrupt event as well. - * - * @param dev A pointer to net_device structure - * @return n/a - */ -void lbs_interrupt(struct lbs_private *priv) +void lbs_queue_event(struct lbs_private *priv, u32 event) +{ + unsigned long flags; + + lbs_deb_enter(LBS_DEB_THREAD); + spin_lock_irqsave(&priv->driver_lock, flags); + + if (priv->psstate == PS_STATE_SLEEP) + priv->psstate = PS_STATE_AWAKE; + + __kfifo_put(priv->event_fifo, (unsigned char *) &event, sizeof(u32)); + + wake_up_interruptible(&priv->waitq); + + spin_unlock_irqrestore(&priv->driver_lock, flags); + lbs_deb_leave(LBS_DEB_THREAD); +} +EXPORT_SYMBOL_GPL(lbs_queue_event); + +void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx) { lbs_deb_enter(LBS_DEB_THREAD); - lbs_deb_thread("lbs_interrupt: intcounter=%d\n", priv->intcounter); - priv->intcounter++; if (priv->psstate == PS_STATE_SLEEP) priv->psstate = PS_STATE_AWAKE; + + /* Swap buffers by flipping the response index */ + BUG_ON(resp_idx > 1); + priv->resp_idx = resp_idx; + wake_up_interruptible(&priv->waitq); lbs_deb_leave(LBS_DEB_THREAD); } -EXPORT_SYMBOL_GPL(lbs_interrupt); +EXPORT_SYMBOL_GPL(lbs_notify_command_response); static int __init lbs_init_module(void) { diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c index 09f023089ea4..05af7316f698 100644 --- a/drivers/net/wireless/libertas/rx.c +++ b/drivers/net/wireless/libertas/rx.c @@ -145,14 +145,14 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb) struct net_device *dev = priv->dev; struct rxpackethdr *p_rx_pkt; struct rxpd *p_rx_pd; - int hdrchop; struct ethhdr *p_ethhdr; - const u8 rfc1042_eth_hdr[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; lbs_deb_enter(LBS_DEB_RX); + BUG_ON(!skb); + skb->ip_summed = CHECKSUM_NONE; if (priv->monitormode) diff --git a/drivers/net/wireless/libertas/tx.c b/drivers/net/wireless/libertas/tx.c index 77f1f9525b81..a4972fed2941 100644 --- a/drivers/net/wireless/libertas/tx.c +++ b/drivers/net/wireless/libertas/tx.c @@ -179,31 +179,17 @@ int lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) * * @returns void */ -void lbs_send_tx_feedback(struct lbs_private *priv) +void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count) { struct tx_radiotap_hdr *radiotap_hdr; - u32 status = priv->eventcause; - int txfail; - int try_count; if (!priv->monitormode || priv->currenttxskb == NULL) return; radiotap_hdr = (struct tx_radiotap_hdr *)priv->currenttxskb->data; - txfail = (status >> 24); - -#if 0 - /* The version of roofnet that we've tested does not use this yet - * But it may be used in the future. - */ - if (txfail) - radiotap_hdr->flags &= IEEE80211_RADIOTAP_F_TX_FAIL; -#endif - try_count = (status >> 16) & 0xff; - radiotap_hdr->data_retries = (try_count) ? - (1 + priv->txretrycount - try_count) : 0; - + radiotap_hdr->data_retries = try_count ? + (1 + priv->txretrycount - try_count) : 0; priv->currenttxskb->protocol = eth_type_trans(priv->currenttxskb, priv->rtap_net_dev); -- cgit v1.2.1 From 8d0c7fad35538e02dff6fdb2d67943ae582819b3 Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Wed, 9 Apr 2008 10:23:31 +0200 Subject: libertas: un-garbage various command structs Some command structs contain reserved or unused fields, which the driver send uninitialized down to the card. Signed-off-by: Holger Schurig Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/cmd.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index 49267ed7cea3..6328b9593877 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -296,6 +296,7 @@ int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action, lbs_deb_enter(LBS_DEB_CMD); + memset(&cmd, 0, sizeof(cmd)); cmd.hdr.command = cpu_to_le16(CMD_802_11_SET_WEP); cmd.hdr.size = cpu_to_le16(sizeof(cmd)); @@ -359,7 +360,9 @@ int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action, cmd.hdr.size = cpu_to_le16(sizeof(cmd)); cmd.action = cpu_to_le16(cmd_action); - if (cmd_action == CMD_ACT_SET) { + if (cmd_action == CMD_ACT_GET) + cmd.enable = 0; + else { if (*enable) cmd.enable = cpu_to_le16(CMD_ENABLE_RSN); else @@ -811,6 +814,7 @@ int lbs_get_channel(struct lbs_private *priv) lbs_deb_enter(LBS_DEB_CMD); + memset(&cmd, 0, sizeof(cmd)); cmd.hdr.size = cpu_to_le16(sizeof(cmd)); cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_GET); @@ -858,6 +862,7 @@ int lbs_set_channel(struct lbs_private *priv, u8 channel) lbs_deb_enter(LBS_DEB_CMD); + memset(&cmd, 0, sizeof(cmd)); cmd.hdr.size = cpu_to_le16(sizeof(cmd)); cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_SET); cmd.channel = cpu_to_le16(channel); -- cgit v1.2.1 From 6b914c521687ae6cb8923c7235fd69b7bc027703 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Thu, 10 Apr 2008 14:34:35 -0700 Subject: proc: switch /proc/driver/ray_cs/ray_cs to seq_file interface Signed-off-by: Alexey Dobriyan Cc: Dominik Brodowski Cc: Jean Tourrilhes Cc: David S. Miller Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: John W. Linville --- drivers/net/wireless/ray_cs.c | 73 +++++++++++++++++++++++++------------------ 1 file changed, 42 insertions(+), 31 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c index f3858ee36f32..963960dc30f2 100644 --- a/drivers/net/wireless/ray_cs.c +++ b/drivers/net/wireless/ray_cs.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -2582,7 +2583,7 @@ static char *nettype[] = {"Adhoc", "Infra "}; static char *framing[] = {"Encapsulation", "Translation"} ; /*===========================================================================*/ -static int ray_cs_proc_read(char *buf, char **start, off_t offset, int len) +static int ray_cs_proc_show(struct seq_file *m, void *v) { /* Print current values which are not available via other means * eg ifconfig @@ -2606,83 +2607,93 @@ static int ray_cs_proc_read(char *buf, char **start, off_t offset, int len) if (!local) return 0; - len = 0; - - len += sprintf(buf + len, "Raylink Wireless LAN driver status\n"); - len += sprintf(buf + len, "%s\n", rcsid); + seq_puts(m, "Raylink Wireless LAN driver status\n"); + seq_printf(m, "%s\n", rcsid); /* build 4 does not report version, and field is 0x55 after memtest */ - len += sprintf(buf + len, "Firmware version = "); + seq_puts(m, "Firmware version = "); if (local->fw_ver == 0x55) - len += sprintf(buf + len, "4 - Use dump_cis for more details\n"); + seq_puts(m, "4 - Use dump_cis for more details\n"); else - len += sprintf(buf + len, "%2d.%02d.%02d\n", + seq_printf(m, "%2d.%02d.%02d\n", local->fw_ver, local->fw_bld, local->fw_var); for (i=0; i<32; i++) c[i] = local->sparm.b5.a_current_ess_id[i]; c[32] = 0; - len += sprintf(buf + len, "%s network ESSID = \"%s\"\n", + seq_printf(m, "%s network ESSID = \"%s\"\n", nettype[local->sparm.b5.a_network_type], c); p = local->bss_id; - len += sprintf(buf + len, "BSSID = %s\n", + seq_printf(m, "BSSID = %s\n", print_mac(mac, p)); - len += sprintf(buf + len, "Country code = %d\n", + seq_printf(m, "Country code = %d\n", local->sparm.b5.a_curr_country_code); i = local->card_status; if (i < 0) i = 10; if (i > 16) i = 10; - len += sprintf(buf + len, "Card status = %s\n", card_status[i]); + seq_printf(m, "Card status = %s\n", card_status[i]); - len += sprintf(buf + len, "Framing mode = %s\n",framing[translate]); + seq_printf(m, "Framing mode = %s\n",framing[translate]); - len += sprintf(buf + len, "Last pkt signal lvl = %d\n", local->last_rsl); + seq_printf(m, "Last pkt signal lvl = %d\n", local->last_rsl); if (local->beacon_rxed) { /* Pull some fields out of last beacon received */ - len += sprintf(buf + len, "Beacon Interval = %d Kus\n", + seq_printf(m, "Beacon Interval = %d Kus\n", local->last_bcn.beacon_intvl[0] + 256 * local->last_bcn.beacon_intvl[1]); p = local->last_bcn.elements; if (p[0] == C_ESSID_ELEMENT_ID) p += p[1] + 2; else { - len += sprintf(buf + len, "Parse beacon failed at essid element id = %d\n",p[0]); - return len; + seq_printf(m, "Parse beacon failed at essid element id = %d\n",p[0]); + return 0; } if (p[0] == C_SUPPORTED_RATES_ELEMENT_ID) { - len += sprintf(buf + len, "Supported rate codes = "); + seq_puts(m, "Supported rate codes = "); for (i=2; idwell_time[0] + 256 * pfh->dwell_time[1]); - len += sprintf(buf + len, "Hop set = %d \n", pfh->hop_set); - len += sprintf(buf + len, "Hop pattern = %d \n", pfh->hop_pattern); - len += sprintf(buf + len, "Hop index = %d \n", pfh->hop_index); + seq_printf(m, "Hop set = %d \n", pfh->hop_set); + seq_printf(m, "Hop pattern = %d \n", pfh->hop_pattern); + seq_printf(m, "Hop index = %d \n", pfh->hop_index); p += p[1] + 2; } else { - len += sprintf(buf + len, "Parse beacon failed at FH param element\n"); - return len; + seq_puts(m, "Parse beacon failed at FH param element\n"); + return 0; } } else { - len += sprintf(buf + len, "No beacons received\n"); + seq_puts(m, "No beacons received\n"); } - return len; + return 0; } +static int ray_cs_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, ray_cs_proc_show, NULL); +} + +static const struct file_operations ray_cs_proc_fops = { + .owner = THIS_MODULE, + .open = ray_cs_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; #endif /*===========================================================================*/ static int build_auth_frame(ray_dev_t *local, UCHAR *dest, int auth_type) @@ -2815,7 +2826,7 @@ static int __init init_ray_cs(void) #ifdef CONFIG_PROC_FS proc_mkdir("driver/ray_cs", NULL); - create_proc_info_entry("driver/ray_cs/ray_cs", 0, NULL, &ray_cs_proc_read); + proc_create("driver/ray_cs/ray_cs", 0, NULL, &ray_cs_proc_fops); raycs_write("driver/ray_cs/essid", write_essid, NULL); raycs_write("driver/ray_cs/net_type", write_int, &net_type); raycs_write("driver/ray_cs/translate", write_int, &translate); -- cgit v1.2.1 From 3e2c40ef09f397b0123fc0233d5d0531c217dc39 Mon Sep 17 00:00:00 2001 From: Stefano Brivio Date: Mon, 14 Apr 2008 00:57:03 +0200 Subject: b43legacy: fix TBTT and PU timings This fixes some timings for pre-TBTT and synthetic PU. The patch by Michael Buesch has been ported to b43legacy. Signed-off-by: Stefano Brivio Signed-off-by: John W. Linville --- drivers/net/wireless/b43legacy/b43legacy.h | 3 +++ drivers/net/wireless/b43legacy/main.c | 34 +++++++++++++++++++++++++++--- 2 files changed, 34 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/b43legacy/b43legacy.h b/drivers/net/wireless/b43legacy/b43legacy.h index 242b8ad4e33c..ded3cd31b3df 100644 --- a/drivers/net/wireless/b43legacy/b43legacy.h +++ b/drivers/net/wireless/b43legacy/b43legacy.h @@ -97,6 +97,7 @@ #define B43legacy_MMIO_RADIO_HWENABLED_LO 0x49A #define B43legacy_MMIO_GPIO_CONTROL 0x49C #define B43legacy_MMIO_GPIO_MASK 0x49E +#define B43legacy_MMIO_TSF_CFP_PRETBTT 0x612 #define B43legacy_MMIO_TSF_0 0x632 /* core rev < 3 only */ #define B43legacy_MMIO_TSF_1 0x634 /* core rev < 3 only */ #define B43legacy_MMIO_TSF_2 0x636 /* core rev < 3 only */ @@ -149,6 +150,8 @@ #define B43legacy_SHM_SH_UCODEPATCH 0x0002 /* Microcode patchlevel */ #define B43legacy_SHM_SH_UCODEDATE 0x0004 /* Microcode date */ #define B43legacy_SHM_SH_UCODETIME 0x0006 /* Microcode time */ +#define B43legacy_SHM_SH_SPUWKUP 0x0094 /* pre-wakeup for synth PU in us */ +#define B43legacy_SHM_SH_PRETBTT 0x0096 /* pre-TBTT in us */ #define B43legacy_UCODEFLAGS_OFFSET 0x005E diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index f518e796bdec..2422a5dab1d2 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -3005,6 +3005,34 @@ static void b43legacy_set_retry_limits(struct b43legacy_wldev *dev, b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS, 0x0007, long_retry); } +static void b43legacy_set_synth_pu_delay(struct b43legacy_wldev *dev, + bool idle) { + u16 pu_delay = 1050; + + if (b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS) || idle) + pu_delay = 500; + if ((dev->phy.radio_ver == 0x2050) && (dev->phy.radio_rev == 8)) + pu_delay = max(pu_delay, (u16)2400); + + b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, + B43legacy_SHM_SH_SPUWKUP, pu_delay); +} + +/* Set the TSF CFP pre-TargetBeaconTransmissionTime. */ +static void b43legacy_set_pretbtt(struct b43legacy_wldev *dev) +{ + u16 pretbtt; + + /* The time value is in microseconds. */ + if (b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS)) + pretbtt = 2; + else + pretbtt = 250; + b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, + B43legacy_SHM_SH_PRETBTT, pretbtt); + b43legacy_write16(dev, B43legacy_MMIO_TSF_CFP_PRETBTT, pretbtt); +} + /* Shutdown a wireless core */ /* Locking: wl->mutex */ static void b43legacy_wireless_core_exit(struct b43legacy_wldev *dev) @@ -3191,9 +3219,7 @@ static int b43legacy_wireless_core_init(struct b43legacy_wldev *dev) if (err) goto err_chip_exit; - b43legacy_write16(dev, 0x0612, 0x0050); - b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0416, 0x0050); - b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0414, 0x01F4); + b43legacy_set_synth_pu_delay(dev, 1); ssb_bus_powerup(bus, 1); /* Enable dynamic PCTL */ b43legacy_upload_card_macaddress(dev); @@ -3249,6 +3275,8 @@ static int b43legacy_op_add_interface(struct ieee80211_hw *hw, spin_lock_irqsave(&wl->irq_lock, flags); b43legacy_adjust_opmode(dev); + b43legacy_set_pretbtt(dev); + b43legacy_set_synth_pu_delay(dev, 0); b43legacy_upload_card_macaddress(dev); spin_unlock_irqrestore(&wl->irq_lock, flags); -- cgit v1.2.1 From 57aab75a39089744aba4bd126df2de526481b128 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Mon, 14 Apr 2008 21:16:03 -0700 Subject: iwlwifi: generalize iwlwifi init flow This patch creates handlers to support iwlwifi init flow for multiple HWs Signed-off-by: Tomas Winkler Signed-off-by: Ron Rindjunsky Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965.c | 149 +++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-core.h | 11 +- drivers/net/wireless/iwlwifi/iwl4965-base.c | 179 +++------------------------- 3 files changed, 174 insertions(+), 165 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 472ca3d7e034..822169e61e9b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -114,6 +114,151 @@ static const u16 default_tid_to_tx_fifo[] = { #endif /*CONFIG_IWL4965_HT */ +/* check contents of special bootstrap uCode SRAM */ +static int iwl4965_verify_bsm(struct iwl_priv *priv) +{ + __le32 *image = priv->ucode_boot.v_addr; + u32 len = priv->ucode_boot.len; + u32 reg; + u32 val; + + IWL_DEBUG_INFO("Begin verify bsm\n"); + + /* verify BSM SRAM contents */ + val = iwl_read_prph(priv, BSM_WR_DWCOUNT_REG); + for (reg = BSM_SRAM_LOWER_BOUND; + reg < BSM_SRAM_LOWER_BOUND + len; + reg += sizeof(u32), image++) { + val = iwl_read_prph(priv, reg); + if (val != le32_to_cpu(*image)) { + IWL_ERROR("BSM uCode verification failed at " + "addr 0x%08X+%u (of %u), is 0x%x, s/b 0x%x\n", + BSM_SRAM_LOWER_BOUND, + reg - BSM_SRAM_LOWER_BOUND, len, + val, le32_to_cpu(*image)); + return -EIO; + } + } + + IWL_DEBUG_INFO("BSM bootstrap uCode image OK\n"); + + return 0; +} + +/** + * iwl4965_load_bsm - Load bootstrap instructions + * + * BSM operation: + * + * The Bootstrap State Machine (BSM) stores a short bootstrap uCode program + * in special SRAM that does not power down during RFKILL. When powering back + * up after power-saving sleeps (or during initial uCode load), the BSM loads + * the bootstrap program into the on-board processor, and starts it. + * + * The bootstrap program loads (via DMA) instructions and data for a new + * program from host DRAM locations indicated by the host driver in the + * BSM_DRAM_* registers. Once the new program is loaded, it starts + * automatically. + * + * When initializing the NIC, the host driver points the BSM to the + * "initialize" uCode image. This uCode sets up some internal data, then + * notifies host via "initialize alive" that it is complete. + * + * The host then replaces the BSM_DRAM_* pointer values to point to the + * normal runtime uCode instructions and a backup uCode data cache buffer + * (filled initially with starting data values for the on-board processor), + * then triggers the "initialize" uCode to load and launch the runtime uCode, + * which begins normal operation. + * + * When doing a power-save shutdown, runtime uCode saves data SRAM into + * the backup data cache in DRAM before SRAM is powered down. + * + * When powering back up, the BSM loads the bootstrap program. This reloads + * the runtime uCode instructions and the backup data cache into SRAM, + * and re-launches the runtime uCode from where it left off. + */ +static int iwl4965_load_bsm(struct iwl_priv *priv) +{ + __le32 *image = priv->ucode_boot.v_addr; + u32 len = priv->ucode_boot.len; + dma_addr_t pinst; + dma_addr_t pdata; + u32 inst_len; + u32 data_len; + int i; + u32 done; + u32 reg_offset; + int ret; + + IWL_DEBUG_INFO("Begin load bsm\n"); + + /* make sure bootstrap program is no larger than BSM's SRAM size */ + if (len > IWL_MAX_BSM_SIZE) + return -EINVAL; + + /* Tell bootstrap uCode where to find the "Initialize" uCode + * in host DRAM ... host DRAM physical address bits 35:4 for 4965. + * NOTE: iwl4965_initialize_alive_start() will replace these values, + * after the "initialize" uCode has run, to point to + * runtime/protocol instructions and backup data cache. */ + pinst = priv->ucode_init.p_addr >> 4; + pdata = priv->ucode_init_data.p_addr >> 4; + inst_len = priv->ucode_init.len; + data_len = priv->ucode_init_data.len; + + ret = iwl_grab_nic_access(priv); + if (ret) + return ret; + + iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst); + iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata); + iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, inst_len); + iwl_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG, data_len); + + /* Fill BSM memory with bootstrap instructions */ + for (reg_offset = BSM_SRAM_LOWER_BOUND; + reg_offset < BSM_SRAM_LOWER_BOUND + len; + reg_offset += sizeof(u32), image++) + _iwl_write_prph(priv, reg_offset, le32_to_cpu(*image)); + + ret = iwl4965_verify_bsm(priv); + if (ret) { + iwl_release_nic_access(priv); + return ret; + } + + /* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */ + iwl_write_prph(priv, BSM_WR_MEM_SRC_REG, 0x0); + iwl_write_prph(priv, BSM_WR_MEM_DST_REG, RTC_INST_LOWER_BOUND); + iwl_write_prph(priv, BSM_WR_DWCOUNT_REG, len / sizeof(u32)); + + /* Load bootstrap code into instruction SRAM now, + * to prepare to load "initialize" uCode */ + iwl_write_prph(priv, BSM_WR_CTRL_REG, BSM_WR_CTRL_REG_BIT_START); + + /* Wait for load of bootstrap uCode to finish */ + for (i = 0; i < 100; i++) { + done = iwl_read_prph(priv, BSM_WR_CTRL_REG); + if (!(done & BSM_WR_CTRL_REG_BIT_START)) + break; + udelay(10); + } + if (i < 100) + IWL_DEBUG_INFO("BSM write complete, poll %d iterations\n", i); + else { + IWL_ERROR("BSM write did not complete!\n"); + return -EIO; + } + + /* Enable future boot loads whenever power management unit triggers it + * (e.g. when powering back up after power-save shutdown) */ + iwl_write_prph(priv, BSM_WR_CTRL_REG, BSM_WR_CTRL_REG_BIT_START_EN); + + iwl_release_nic_access(priv); + + return 0; +} + static int iwl4965_init_drv(struct iwl_priv *priv) { int ret; @@ -4789,6 +4934,10 @@ static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = { static struct iwl_lib_ops iwl4965_lib = { .init_drv = iwl4965_init_drv, + .hw_nic_init = iwl4965_hw_nic_init, + .is_valid_rtc_data_addr = iwl4965_hw_valid_rtc_data_addr, + .alive_notify = iwl4965_alive_notify, + .load_ucode = iwl4965_load_bsm, .eeprom_ops = { .verify_signature = iwlcore_eeprom_verify_signature, .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 6d82376f43f9..889fdbaeb735 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -89,9 +89,18 @@ struct iwl_hcmd_utils_ops { struct iwl_lib_ops { /* iwlwifi driver (priv) init */ int (*init_drv)(struct iwl_priv *priv); + /* nic init */ + int (*hw_nic_init)(struct iwl_priv *priv); + /* alive notification */ + int (*alive_notify)(struct iwl_priv *priv); + /* check validity of rtc data address */ + int (*is_valid_rtc_data_addr)(u32 addr); + /* 1st ucode load */ + int (*load_ucode)(struct iwl_priv *priv); + /* rfkill */ + void (*radio_kill_sw)(struct iwl_priv *priv, int disable_radio); /* eeprom operations (as defined in iwl-eeprom.h) */ struct iwl_eeprom_ops eeprom_ops; - void (*radio_kill_sw)(struct iwl_priv *priv, int disable_radio); }; struct iwl_ops { diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 06e44dad5f02..ecc9cba62bf9 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -4305,7 +4305,7 @@ static void iwl4965_dump_nic_error_log(struct iwl_priv *priv) base = le32_to_cpu(priv->card_alive.error_event_table_ptr); - if (!iwl4965_hw_valid_rtc_data_addr(base)) { + if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { IWL_ERROR("Not valid error log pointer 0x%08X\n", base); return; } @@ -4400,7 +4400,7 @@ static void iwl4965_dump_nic_event_log(struct iwl_priv *priv) u32 size; /* # entries that we'll print */ base = le32_to_cpu(priv->card_alive.log_event_table_ptr); - if (!iwl4965_hw_valid_rtc_data_addr(base)) { + if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { IWL_ERROR("Invalid event log pointer 0x%08X\n", base); return; } @@ -5175,156 +5175,6 @@ static int iwl4965_verify_ucode(struct iwl_priv *priv) return rc; } - -/* check contents of special bootstrap uCode SRAM */ -static int iwl4965_verify_bsm(struct iwl_priv *priv) -{ - __le32 *image = priv->ucode_boot.v_addr; - u32 len = priv->ucode_boot.len; - u32 reg; - u32 val; - - IWL_DEBUG_INFO("Begin verify bsm\n"); - - /* verify BSM SRAM contents */ - val = iwl_read_prph(priv, BSM_WR_DWCOUNT_REG); - for (reg = BSM_SRAM_LOWER_BOUND; - reg < BSM_SRAM_LOWER_BOUND + len; - reg += sizeof(u32), image ++) { - val = iwl_read_prph(priv, reg); - if (val != le32_to_cpu(*image)) { - IWL_ERROR("BSM uCode verification failed at " - "addr 0x%08X+%u (of %u), is 0x%x, s/b 0x%x\n", - BSM_SRAM_LOWER_BOUND, - reg - BSM_SRAM_LOWER_BOUND, len, - val, le32_to_cpu(*image)); - return -EIO; - } - } - - IWL_DEBUG_INFO("BSM bootstrap uCode image OK\n"); - - return 0; -} - -/** - * iwl4965_load_bsm - Load bootstrap instructions - * - * BSM operation: - * - * The Bootstrap State Machine (BSM) stores a short bootstrap uCode program - * in special SRAM that does not power down during RFKILL. When powering back - * up after power-saving sleeps (or during initial uCode load), the BSM loads - * the bootstrap program into the on-board processor, and starts it. - * - * The bootstrap program loads (via DMA) instructions and data for a new - * program from host DRAM locations indicated by the host driver in the - * BSM_DRAM_* registers. Once the new program is loaded, it starts - * automatically. - * - * When initializing the NIC, the host driver points the BSM to the - * "initialize" uCode image. This uCode sets up some internal data, then - * notifies host via "initialize alive" that it is complete. - * - * The host then replaces the BSM_DRAM_* pointer values to point to the - * normal runtime uCode instructions and a backup uCode data cache buffer - * (filled initially with starting data values for the on-board processor), - * then triggers the "initialize" uCode to load and launch the runtime uCode, - * which begins normal operation. - * - * When doing a power-save shutdown, runtime uCode saves data SRAM into - * the backup data cache in DRAM before SRAM is powered down. - * - * When powering back up, the BSM loads the bootstrap program. This reloads - * the runtime uCode instructions and the backup data cache into SRAM, - * and re-launches the runtime uCode from where it left off. - */ -static int iwl4965_load_bsm(struct iwl_priv *priv) -{ - __le32 *image = priv->ucode_boot.v_addr; - u32 len = priv->ucode_boot.len; - dma_addr_t pinst; - dma_addr_t pdata; - u32 inst_len; - u32 data_len; - int rc; - int i; - u32 done; - u32 reg_offset; - - IWL_DEBUG_INFO("Begin load bsm\n"); - - /* make sure bootstrap program is no larger than BSM's SRAM size */ - if (len > IWL_MAX_BSM_SIZE) - return -EINVAL; - - /* Tell bootstrap uCode where to find the "Initialize" uCode - * in host DRAM ... host DRAM physical address bits 35:4 for 4965. - * NOTE: iwl4965_initialize_alive_start() will replace these values, - * after the "initialize" uCode has run, to point to - * runtime/protocol instructions and backup data cache. */ - pinst = priv->ucode_init.p_addr >> 4; - pdata = priv->ucode_init_data.p_addr >> 4; - inst_len = priv->ucode_init.len; - data_len = priv->ucode_init_data.len; - - rc = iwl_grab_nic_access(priv); - if (rc) - return rc; - - iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst); - iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata); - iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, inst_len); - iwl_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG, data_len); - - /* Fill BSM memory with bootstrap instructions */ - for (reg_offset = BSM_SRAM_LOWER_BOUND; - reg_offset < BSM_SRAM_LOWER_BOUND + len; - reg_offset += sizeof(u32), image++) - _iwl_write_prph(priv, reg_offset, - le32_to_cpu(*image)); - - rc = iwl4965_verify_bsm(priv); - if (rc) { - iwl_release_nic_access(priv); - return rc; - } - - /* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */ - iwl_write_prph(priv, BSM_WR_MEM_SRC_REG, 0x0); - iwl_write_prph(priv, BSM_WR_MEM_DST_REG, - RTC_INST_LOWER_BOUND); - iwl_write_prph(priv, BSM_WR_DWCOUNT_REG, len / sizeof(u32)); - - /* Load bootstrap code into instruction SRAM now, - * to prepare to load "initialize" uCode */ - iwl_write_prph(priv, BSM_WR_CTRL_REG, - BSM_WR_CTRL_REG_BIT_START); - - /* Wait for load of bootstrap uCode to finish */ - for (i = 0; i < 100; i++) { - done = iwl_read_prph(priv, BSM_WR_CTRL_REG); - if (!(done & BSM_WR_CTRL_REG_BIT_START)) - break; - udelay(10); - } - if (i < 100) - IWL_DEBUG_INFO("BSM write complete, poll %d iterations\n", i); - else { - IWL_ERROR("BSM write did not complete!\n"); - return -EIO; - } - - /* Enable future boot loads whenever power management unit triggers it - * (e.g. when powering back up after power-save shutdown) */ - iwl_write_prph(priv, BSM_WR_CTRL_REG, - BSM_WR_CTRL_REG_BIT_START_EN); - - iwl_release_nic_access(priv); - - return 0; -} - static void iwl4965_nic_start(struct iwl_priv *priv) { /* Remove all resets to allow NIC to operate */ @@ -5634,7 +5484,7 @@ static void iwl4965_init_alive_start(struct iwl_priv *priv) */ static void iwl4965_alive_start(struct iwl_priv *priv) { - int rc = 0; + int ret = 0; IWL_DEBUG_INFO("Runtime Alive received.\n"); @@ -5657,10 +5507,10 @@ static void iwl4965_alive_start(struct iwl_priv *priv) iwlcore_clear_stations_table(priv); - rc = iwl4965_alive_notify(priv); - if (rc) { + ret = priv->cfg->ops->lib->alive_notify(priv); + if (ret) { IWL_WARNING("Could not complete ALIVE transition [ntf]: %d\n", - rc); + ret); goto restart; } @@ -5835,7 +5685,8 @@ static void iwl4965_down(struct iwl_priv *priv) static int __iwl4965_up(struct iwl_priv *priv) { - int rc, i; + int i; + int ret; if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { IWL_WARNING("Exit pending; will not bring the NIC up\n"); @@ -5870,10 +5721,10 @@ static int __iwl4965_up(struct iwl_priv *priv) iwl_rfkill_set_hw_state(priv); iwl_write32(priv, CSR_INT, 0xFFFFFFFF); - rc = iwl4965_hw_nic_init(priv); - if (rc) { - IWL_ERROR("Unable to int nic\n"); - return rc; + ret = priv->cfg->ops->lib->hw_nic_init(priv); + if (ret) { + IWL_ERROR("Unable to init nic\n"); + return ret; } /* make sure rfkill handshake bits are cleared */ @@ -5906,10 +5757,10 @@ static int __iwl4965_up(struct iwl_priv *priv) /* load bootstrap state machine, * load bootstrap program into processor's memory, * prepare to load the "initialize" uCode */ - rc = iwl4965_load_bsm(priv); + ret = priv->cfg->ops->lib->load_ucode(priv); - if (rc) { - IWL_ERROR("Unable to set up bootstrap uCode: %d\n", rc); + if (ret) { + IWL_ERROR("Unable to set up bootstrap uCode: %d\n", ret); continue; } -- cgit v1.2.1 From db0589f3b9443f2b57ea6daaec09c1ab0ac99cb0 Mon Sep 17 00:00:00 2001 From: Abhijeet Kolekar Date: Mon, 14 Apr 2008 21:16:04 -0700 Subject: iwlwifi: replace sprintf with scnprintf for debugfs output The buffersize allocated is not accurate. Writing to these buffers with scnprintf is safer. Signed-off-by: Abhijeet Kolekar Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 71 ++++++++++++++++++------------ 1 file changed, 43 insertions(+), 28 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 23632e54aab2..cbea477eb078 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -102,10 +102,14 @@ static ssize_t iwl_dbgfs_tx_statistics_read(struct file *file, struct iwl_priv *priv = (struct iwl_priv *)file->private_data; char buf[256]; int pos = 0; + const size_t bufsz = sizeof(buf); - pos += sprintf(buf+pos, "mgmt: %u\n", priv->tx_stats[0].cnt); - pos += sprintf(buf+pos, "ctrl: %u\n", priv->tx_stats[1].cnt); - pos += sprintf(buf+pos, "data: %u\n", priv->tx_stats[2].cnt); + pos += scnprintf(buf + pos, bufsz - pos, "mgmt: %u\n", + priv->tx_stats[0].cnt); + pos += scnprintf(buf + pos, bufsz - pos, "ctrl: %u\n", + priv->tx_stats[1].cnt); + pos += scnprintf(buf + pos, bufsz - pos, "data: %u\n", + priv->tx_stats[2].cnt); return simple_read_from_buffer(user_buf, count, ppos, buf, pos); } @@ -117,10 +121,14 @@ static ssize_t iwl_dbgfs_rx_statistics_read(struct file *file, struct iwl_priv *priv = (struct iwl_priv *)file->private_data; char buf[256]; int pos = 0; + const size_t bufsz = sizeof(buf); - pos += sprintf(buf+pos, "mgmt: %u\n", priv->rx_stats[0].cnt); - pos += sprintf(buf+pos, "ctrl: %u\n", priv->rx_stats[1].cnt); - pos += sprintf(buf+pos, "data: %u\n", priv->rx_stats[2].cnt); + pos += scnprintf(buf + pos, bufsz - pos, "mgmt: %u\n", + priv->rx_stats[0].cnt); + pos += scnprintf(buf + pos, bufsz - pos, "ctrl: %u\n", + priv->rx_stats[1].cnt); + pos += scnprintf(buf + pos, bufsz - pos, "data: %u\n", + priv->rx_stats[2].cnt); return simple_read_from_buffer(user_buf, count, ppos, buf, pos); } @@ -138,6 +146,7 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, int i; int pos = 0; struct iwl_priv *priv = (struct iwl_priv *)file->private_data; + const size_t bufsz = sizeof(buf); printk(KERN_DEBUG "offset is: 0x%x\tlen is: 0x%x\n", priv->dbgfs->sram_offset, priv->dbgfs->sram_len); @@ -159,9 +168,9 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, break; } } - pos += sprintf(buf+pos, "0x%08x ", val); + pos += scnprintf(buf + pos, bufsz - pos, "0x%08x ", val); } - pos += sprintf(buf+pos, "\n"); + pos += scnprintf(buf + pos, bufsz - pos, "\n"); iwl_release_nic_access(priv); ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); @@ -210,44 +219,50 @@ static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf, if(!buf) return -ENOMEM; - pos += sprintf(buf+pos, "num of stations: %d\n\n", + pos += scnprintf(buf + pos, bufsz - pos, "num of stations: %d\n\n", priv->num_stations); for (i = 0; i < max_sta; i++) { station = &priv->stations[i]; if (station->used) { - pos += sprintf(buf+pos, "station %d:\ngeneral data:\n", - i+1); + pos += scnprintf(buf + pos, bufsz - pos, + "station %d:\ngeneral data:\n", i+1); print_mac(mac, station->sta.sta.addr); - pos += sprintf(buf+pos, "id: %u\n", + pos += scnprintf(buf + pos, bufsz - pos, "id: %u\n", station->sta.sta.sta_id); - pos += sprintf(buf+pos, "mode: %u\n", + pos += scnprintf(buf + pos, bufsz - pos, "mode: %u\n", station->sta.mode); - pos += sprintf(buf+pos, "flags: 0x%x\n", + pos += scnprintf(buf + pos, bufsz - pos, + "flags: 0x%x\n", station->sta.station_flags_msk); - pos += sprintf(buf+pos, "ps_status: %u\n", - station->ps_status); - - pos += sprintf(buf+pos, "tid data:\n"); - - pos += sprintf(buf+pos, "seq_num\t\ttxq_id\t"); - pos += sprintf(buf+pos, "frame_count\twait_for_ba\t"); - pos += sprintf(buf+pos, "start_idx\tbitmap0\t"); - pos += sprintf(buf+pos, "bitmap1\trate_n_flags\n"); + pos += scnprintf(buf + pos, bufsz - pos, + "ps_status: %u\n", station->ps_status); + pos += scnprintf(buf + pos, bufsz - pos, "tid data:\n"); + pos += scnprintf(buf + pos, bufsz - pos, + "seq_num\t\ttxq_id\t"); + pos += scnprintf(buf + pos, bufsz - pos, + "frame_count\twait_for_ba\t"); + pos += scnprintf(buf + pos, bufsz - pos, + "start_idx\tbitmap0\t"); + pos += scnprintf(buf + pos, bufsz - pos, + "bitmap1\trate_n_flags\n"); for (j = 0; j < MAX_TID_COUNT; j++) { - pos += sprintf(buf+pos, "[%d]:\t\t%u\t", - j, station->tid[j].seq_number); - pos += sprintf(buf+pos, "%u\t\t%u\t\t%u\t\t", + pos += scnprintf(buf + pos, bufsz - pos, + "[%d]:\t\t%u\t", j, + station->tid[j].seq_number); + pos += scnprintf(buf + pos, bufsz - pos, + "%u\t\t%u\t\t%u\t\t", station->tid[j].agg.txq_id, station->tid[j].agg.frame_count, station->tid[j].agg.wait_for_ba); - pos += sprintf(buf+pos, "%u\t%llu\t%u\n", + pos += scnprintf(buf + pos, bufsz - pos, + "%u\t%llu\t%u\n", station->tid[j].agg.start_idx, (unsigned long long)station->tid[j].agg.bitmap, station->tid[j].agg.rate_n_flags); } - pos += sprintf(buf+pos, "\n"); + pos += scnprintf(buf + pos, bufsz - pos, "\n"); } } -- cgit v1.2.1 From 0a0bed1d10105a9f58cd14ebe216e8479dd31fda Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Mon, 14 Apr 2008 21:16:05 -0700 Subject: iwlwifi: add default WEP key host command This patch adds declaration for static WEP host command. This command will be used for default WEP group keys when no key mapping keys are used. Signed-off-by: Emmanuel Grumbach Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965-commands.h | 27 ++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-hcmd.c | 1 + 2 files changed, 28 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h index 7e36ecb27575..65cd8ae363b4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h @@ -84,6 +84,9 @@ enum { REPLY_REMOVE_STA = 0x19, /* not used */ REPLY_REMOVE_ALL_STA = 0x1a, /* not used */ + /* Security */ + REPLY_WEPKEY = 0x20, + /* RX, TX, LEDs */ REPLY_TX = 0x1c, REPLY_RATE_SCALE = 0x47, /* 3945 only */ @@ -850,6 +853,30 @@ struct iwl4965_add_sta_resp { u8 status; /* ADD_STA_* */ } __attribute__ ((packed)); +/* + * REPLY_WEP_KEY = 0x20 + */ +struct iwl_wep_key { + u8 key_index; + u8 key_offset; + u8 reserved1[2]; + u8 key_size; + u8 reserved2[3]; + u8 key[16]; +} __attribute__ ((packed)); + +struct iwl_wep_cmd { + u8 num_keys; + u8 global_key_type; + u8 flags; + u8 reserved; + struct iwl_wep_key key[0]; +} __attribute__ ((packed)); + +#define WEP_KEY_WEP_TYPE 1 +#define WEP_KEYS_MAX 4 +#define WEP_INVALID_OFFSET 0xff +#define WEP_KEY_LEN_128 13 /****************************************************************************** * (4) diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c index 1f8c2999805b..fdb27f1cdc08 100644 --- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c @@ -51,6 +51,7 @@ const char *get_cmd_string(u8 cmd) IWL_CMD(REPLY_ADD_STA); IWL_CMD(REPLY_REMOVE_STA); IWL_CMD(REPLY_REMOVE_ALL_STA); + IWL_CMD(REPLY_WEPKEY); IWL_CMD(REPLY_TX); IWL_CMD(REPLY_RATE_SCALE); IWL_CMD(REPLY_LEDS_CMD); -- cgit v1.2.1 From 6974e36356524fa856435cb1be40aaffbac9601a Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Mon, 14 Apr 2008 21:16:06 -0700 Subject: iwlwifi: default WEP HW encryption This patch adds HW encryption support in default WEP mode. When no key mapping key/pairwise key is used. The key is broadcast key is used as default/global/static key. This code assumes that group cast key is added after pairwise key. Signed-off-by: Emmanuel Grumbach Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/Makefile | 2 +- drivers/net/wireless/iwlwifi/iwl-4965.h | 3 + drivers/net/wireless/iwlwifi/iwl-sta.c | 119 ++++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-sta.h | 46 +++++++++++ drivers/net/wireless/iwlwifi/iwl4965-base.c | 90 ++++++++++++--------- 5 files changed, 220 insertions(+), 40 deletions(-) create mode 100644 drivers/net/wireless/iwlwifi/iwl-sta.c create mode 100644 drivers/net/wireless/iwlwifi/iwl-sta.h (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 2751e8aa97d7..741ea346a295 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile @@ -22,5 +22,5 @@ endif obj-$(CONFIG_IWL4965) += iwl4965.o -iwl4965-objs = iwl4965-base.o iwl-4965.o iwl-4965-rs.o +iwl4965-objs = iwl4965-base.o iwl-4965.o iwl-4965-rs.o iwl-sta.o diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index 65e536782706..93df29e4689a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -1112,6 +1112,9 @@ struct iwl_priv { spinlock_t sta_lock; int num_stations; struct iwl4965_station_entry stations[IWL_STATION_COUNT]; + struct iwl_wep_key wep_keys[WEP_KEYS_MAX]; + u8 default_wep_key; + u8 key_mapping_key; /* Indication if ieee80211_ops->open has been called */ u8 is_open; diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c new file mode 100644 index 000000000000..a48e228e2ffd --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -0,0 +1,119 @@ +/****************************************************************************** + * + * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. + * + * Portions of this file are derived from the ipw3945 project, as well + * as portions of the ieee80211 subsystem header files. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * James P. Ketrenos + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + *****************************************************************************/ + +#include + +#include "iwl-eeprom.h" +#include "iwl-4965.h" +#include "iwl-core.h" +#include "iwl-sta.h" +#include "iwl-io.h" +#include "iwl-helpers.h" + +int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty) +{ + int i, not_empty = 0; + u8 buff[sizeof(struct iwl_wep_cmd) + + sizeof(struct iwl_wep_key) * WEP_KEYS_MAX]; + struct iwl_wep_cmd *wep_cmd = (struct iwl_wep_cmd *)buff; + size_t cmd_size = sizeof(struct iwl_wep_cmd); + struct iwl_host_cmd cmd = { + .id = REPLY_WEPKEY, + .data = wep_cmd, + .meta.flags = CMD_ASYNC, + }; + + memset(wep_cmd, 0, cmd_size + + (sizeof(struct iwl_wep_key) * WEP_KEYS_MAX)); + + for (i = 0; i < WEP_KEYS_MAX ; i++) { + wep_cmd->key[i].key_index = i; + if (priv->wep_keys[i].key_size) { + wep_cmd->key[i].key_offset = i; + not_empty = 1; + } else { + wep_cmd->key[i].key_offset = WEP_INVALID_OFFSET; + } + + wep_cmd->key[i].key_size = priv->wep_keys[i].key_size; + memcpy(&wep_cmd->key[i].key[3], priv->wep_keys[i].key, + priv->wep_keys[i].key_size); + } + + wep_cmd->global_key_type = WEP_KEY_WEP_TYPE; + wep_cmd->num_keys = WEP_KEYS_MAX; + + cmd_size += sizeof(struct iwl_wep_key) * WEP_KEYS_MAX; + + cmd.len = cmd_size; + + if (not_empty || send_if_empty) + return iwl_send_cmd(priv, &cmd); + else + return 0; +} + +int iwl_remove_default_wep_key(struct iwl_priv *priv, + struct ieee80211_key_conf *key) +{ + int ret; + unsigned long flags; + + spin_lock_irqsave(&priv->sta_lock, flags); + priv->default_wep_key--; + memset(&priv->wep_keys[key->keyidx], 0, sizeof(priv->wep_keys[0])); + ret = iwl_send_static_wepkey_cmd(priv, 1); + spin_unlock_irqrestore(&priv->sta_lock, flags); + + return ret; +} + +int iwl_set_default_wep_key(struct iwl_priv *priv, + struct ieee80211_key_conf *keyconf) +{ + int ret; + unsigned long flags; + + keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV; + keyconf->hw_key_idx = keyconf->keyidx; + priv->stations[IWL_AP_ID].keyinfo.alg = ALG_WEP; + + spin_lock_irqsave(&priv->sta_lock, flags); + priv->default_wep_key++; + + priv->wep_keys[keyconf->keyidx].key_size = keyconf->keylen; + memcpy(&priv->wep_keys[keyconf->keyidx].key, &keyconf->key, + keyconf->keylen); + + ret = iwl_send_static_wepkey_cmd(priv, 0); + spin_unlock_irqrestore(&priv->sta_lock, flags); + + return ret; +} + diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h new file mode 100644 index 000000000000..50e9f1470d8d --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h @@ -0,0 +1,46 @@ +/****************************************************************************** + * + * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved. + * + * Portions of this file are derived from the ipw3945 project, as well + * as portions of the ieee80211 subsystem header files. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * The full GNU General Public License is included in this distribution in the + * file called LICENSE. + * + * Contact Information: + * James P. Ketrenos + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + *****************************************************************************/ +#ifndef __iwl_sta_h__ +#define __iwl_sta_h__ + +#include + +#include "iwl-eeprom.h" +#include "iwl-core.h" +#include "iwl-4965.h" +#include "iwl-io.h" +#include "iwl-helpers.h" + +int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty); +int iwl_remove_default_wep_key(struct iwl_priv *priv, + struct ieee80211_key_conf *key); +int iwl_set_default_wep_key(struct iwl_priv *priv, + struct ieee80211_key_conf *key); + +#endif /* __iwl_sta_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index ecc9cba62bf9..dfd2b75492e6 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -50,6 +50,7 @@ #include "iwl-core.h" #include "iwl-io.h" #include "iwl-helpers.h" +#include "iwl-sta.h" static int iwl4965_tx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl4965_tx_queue *txq); @@ -941,6 +942,9 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv) return -EIO; } priv->assoc_station_added = 1; + if (priv->default_wep_key && + iwl_send_static_wepkey_cmd(priv, 0)) + IWL_ERROR("Could not send WEP static key.\n"); } return 0; @@ -1180,6 +1184,8 @@ static int iwl4965_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id) { unsigned long flags; + priv->key_mapping_key = 0; + spin_lock_irqsave(&priv->sta_lock, flags); memset(&priv->stations[sta_id].keyinfo, 0, sizeof(struct iwl4965_hw_key)); memset(&priv->stations[sta_id].sta.key, 0, sizeof(struct iwl4965_keyinfo)); @@ -1198,6 +1204,8 @@ static int iwl4965_set_dynamic_key(struct iwl_priv *priv, { int ret; + priv->key_mapping_key = 1; + switch (key->alg) { case ALG_CCMP: ret = iwl4965_set_ccmp_dynamic_key_info(priv, key, sta_id); @@ -1216,23 +1224,6 @@ static int iwl4965_set_dynamic_key(struct iwl_priv *priv, return ret; } -static int iwl4965_remove_static_key(struct iwl_priv *priv) -{ - int ret = -EOPNOTSUPP; - - return ret; -} - -static int iwl4965_set_static_key(struct iwl_priv *priv, - struct ieee80211_key_conf *key) -{ - if (key->alg == ALG_WEP) - return -EOPNOTSUPP; - - IWL_ERROR("Static key invalid: alg %d\n", key->alg); - return -EINVAL; -} - static void iwl4965_clear_free_frames(struct iwl_priv *priv) { struct list_head *element; @@ -2115,6 +2106,10 @@ static void iwl4965_build_tx_cmd_hwcrypto(struct iwl_priv *priv, int sta_id) { struct iwl4965_hw_key *keyinfo = &priv->stations[sta_id].keyinfo; + struct iwl_wep_key *wepkey; + int keyidx = 0; + + BUG_ON(ctl->key_idx > 3); switch (keyinfo->alg) { case ALG_CCMP: @@ -2133,16 +2128,24 @@ static void iwl4965_build_tx_cmd_hwcrypto(struct iwl_priv *priv, break; case ALG_WEP: - cmd->cmd.tx.sec_ctl = TX_CMD_SEC_WEP | - (ctl->key_idx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT; - - if (keyinfo->keylen == 13) - cmd->cmd.tx.sec_ctl |= TX_CMD_SEC_KEY128; + wepkey = &priv->wep_keys[ctl->key_idx]; + cmd->cmd.tx.sec_ctl = 0; + if (priv->default_wep_key) { + /* the WEP key was sent as static */ + keyidx = ctl->key_idx; + memcpy(&cmd->cmd.tx.key[3], wepkey->key, + wepkey->key_size); + if (wepkey->key_size == WEP_KEY_LEN_128) + cmd->cmd.tx.sec_ctl |= TX_CMD_SEC_KEY128; + } else { + IWL_ERROR("No support for WEP key mappings key\n"); + } - memcpy(&cmd->cmd.tx.key[3], keyinfo->key, keyinfo->keylen); + cmd->cmd.tx.sec_ctl |= (TX_CMD_SEC_WEP | + (keyidx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT); IWL_DEBUG_TX("Configuring packet for WEP encryption " - "with key %d\n", ctl->key_idx); + "with key %d\n", keyidx); break; default: @@ -6989,7 +6992,7 @@ static int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, DECLARE_MAC_BUF(mac); int ret = 0; u8 sta_id = IWL_INVALID_STATION; - u8 static_key; + u8 is_default_wep_key = 0; IWL_DEBUG_MAC80211("enter\n"); @@ -7002,33 +7005,42 @@ static int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, /* only support pairwise keys */ return -EOPNOTSUPP; - /* FIXME: need to differenciate between static and dynamic key - * in the level of mac80211 */ - static_key = !iwl_is_associated(priv); + sta_id = iwl4965_hw_find_station(priv, addr); + if (sta_id == IWL_INVALID_STATION) { + IWL_DEBUG_MAC80211("leave - %s not in station map.\n", + print_mac(mac, addr)); + return -EINVAL; - if (!static_key) { - sta_id = iwl4965_hw_find_station(priv, addr); - if (sta_id == IWL_INVALID_STATION) { - IWL_DEBUG_MAC80211("leave - %s not in station map.\n", - print_mac(mac, addr)); - return -EINVAL; - } } + mutex_lock(&priv->mutex); iwl4965_scan_cancel_timeout(priv, 100); + mutex_unlock(&priv->mutex); + + /* If we are getting WEP group key and we didn't receive any key mapping + * so far, we are in legacy wep mode (group key only), otherwise we are + * in 1X mode. + * In legacy wep mode, we use another host command to the uCode */ + if (key->alg == ALG_WEP && sta_id == priv->hw_setting.bcast_sta_id && + priv->iw_mode != IEEE80211_IF_TYPE_AP) { + if (cmd == SET_KEY) + is_default_wep_key = !priv->key_mapping_key; + else + is_default_wep_key = priv->default_wep_key; + } switch (cmd) { case SET_KEY: - if (static_key) - ret = iwl4965_set_static_key(priv, key); + if (is_default_wep_key) + ret = iwl_set_default_wep_key(priv, key); else ret = iwl4965_set_dynamic_key(priv, key, sta_id); IWL_DEBUG_MAC80211("enable hwcrypto key\n"); break; case DISABLE_KEY: - if (static_key) - ret = iwl4965_remove_static_key(priv); + if (is_default_wep_key) + ret = iwl_remove_default_wep_key(priv, key); else ret = iwl4965_clear_sta_key_info(priv, sta_id); -- cgit v1.2.1 From 0211ddda9deb681a804572936cd49e466a1aa88b Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Mon, 14 Apr 2008 21:16:07 -0700 Subject: iwlwifi: add 1X HW WEP support This patch adds support for HW encryption/decryption in 1X WEP. Signed-off-by: Emmanuel Grumbach Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965.h | 1 + drivers/net/wireless/iwlwifi/iwl-sta.c | 47 +++++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-sta.h | 3 ++ drivers/net/wireless/iwlwifi/iwl4965-base.c | 9 ++++-- 4 files changed, 58 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index 93df29e4689a..23ab5236504b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -461,6 +461,7 @@ struct iwl4965_tid_data { struct iwl4965_hw_key { enum ieee80211_key_alg alg; int keylen; + u8 keyidx; struct ieee80211_key_conf *conf; u8 key[32]; }; diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index a48e228e2ffd..cb964196ad2a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -35,6 +35,7 @@ #include "iwl-sta.h" #include "iwl-io.h" #include "iwl-helpers.h" +#include "iwl-4965.h" int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty) { @@ -117,3 +118,49 @@ int iwl_set_default_wep_key(struct iwl_priv *priv, return ret; } +int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv, + struct ieee80211_key_conf *keyconf, + u8 sta_id) +{ + unsigned long flags; + __le16 key_flags = 0; + int ret; + + keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV; + keyconf->hw_key_idx = keyconf->keyidx; + + key_flags |= (STA_KEY_FLG_WEP | STA_KEY_FLG_MAP_KEY_MSK); + key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); + key_flags &= ~STA_KEY_FLG_INVALID; + + if (keyconf->keylen == WEP_KEY_LEN_128) + key_flags |= STA_KEY_FLG_KEY_SIZE_MSK; + + if (sta_id == priv->hw_setting.bcast_sta_id) + key_flags |= STA_KEY_MULTICAST_MSK; + + spin_lock_irqsave(&priv->sta_lock, flags); + + priv->stations[sta_id].keyinfo.alg = keyconf->alg; + priv->stations[sta_id].keyinfo.keylen = keyconf->keylen; + priv->stations[sta_id].keyinfo.keyidx = keyconf->keyidx; + + memcpy(priv->stations[sta_id].keyinfo.key, + keyconf->key, keyconf->keylen); + + memcpy(&priv->stations[sta_id].sta.key.key[3], + keyconf->key, keyconf->keylen); + + priv->stations[sta_id].sta.key.key_offset = sta_id % 8; /* FIXME */ + priv->stations[sta_id].sta.key.key_flags = key_flags; + + priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; + priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; + + ret = iwl4965_send_add_station(priv, + &priv->stations[sta_id].sta, CMD_ASYNC); + + spin_unlock_irqrestore(&priv->sta_lock, flags); + + return ret; +} diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index 50e9f1470d8d..78e0254c93b5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h @@ -42,5 +42,8 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv, struct ieee80211_key_conf *key); int iwl_set_default_wep_key(struct iwl_priv *priv, struct ieee80211_key_conf *key); +int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv, + struct ieee80211_key_conf *keyconf, + u8 sta_id); #endif /* __iwl_sta_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index dfd2b75492e6..37ab1c565ce1 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -1214,7 +1214,7 @@ static int iwl4965_set_dynamic_key(struct iwl_priv *priv, ret = iwl4965_set_tkip_dynamic_key_info(priv, key, sta_id); break; case ALG_WEP: - ret = -EOPNOTSUPP; + ret = iwl_set_wep_dynamic_key_info(priv, key, sta_id); break; default: IWL_ERROR("Unknown alg: %s alg = %d\n", __func__, key->alg); @@ -2138,7 +2138,12 @@ static void iwl4965_build_tx_cmd_hwcrypto(struct iwl_priv *priv, if (wepkey->key_size == WEP_KEY_LEN_128) cmd->cmd.tx.sec_ctl |= TX_CMD_SEC_KEY128; } else { - IWL_ERROR("No support for WEP key mappings key\n"); + /* the WEP key was sent as dynamic */ + keyidx = keyinfo->keyidx; + memcpy(&cmd->cmd.tx.key[3], keyinfo->key, + keyinfo->keylen); + if (keyinfo->keylen == WEP_KEY_LEN_128) + cmd->cmd.tx.sec_ctl |= TX_CMD_SEC_KEY128; } cmd->cmd.tx.sec_ctl |= (TX_CMD_SEC_WEP | -- cgit v1.2.1 From 80fb47a11eaf3d1d70c02f3dc7976eaac9b0eef2 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Mon, 14 Apr 2008 21:16:08 -0700 Subject: iwlwifi: maintain uCode key table state This patch fix book keeping of key table in the driver to be synchronized with uCode Signed-off-by: Emmanuel Grumbach Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965.h | 1 + drivers/net/wireless/iwlwifi/iwl-sta.c | 28 +++++++++++++++++++++++++--- drivers/net/wireless/iwlwifi/iwl-sta.h | 1 + drivers/net/wireless/iwlwifi/iwl4965-base.c | 10 +++++++--- 4 files changed, 34 insertions(+), 6 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index 23ab5236504b..daf157adf24e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -1116,6 +1116,7 @@ struct iwl_priv { struct iwl_wep_key wep_keys[WEP_KEYS_MAX]; u8 default_wep_key; u8 key_mapping_key; + unsigned long ucode_key_table; /* Indication if ieee80211_ops->open has been called */ u8 is_open; diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index cb964196ad2a..41238f208ed5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -36,6 +36,18 @@ #include "iwl-io.h" #include "iwl-helpers.h" #include "iwl-4965.h" +#include "iwl-sta.h" + +int iwl_get_free_ucode_key_index(struct iwl_priv *priv) +{ + int i; + + for (i = 0; i < STA_KEY_MAX_NUM; i++) + if (test_and_set_bit(i, &priv->ucode_key_table)) + return i; + + return -1; +} int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty) { @@ -81,14 +93,19 @@ int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty) } int iwl_remove_default_wep_key(struct iwl_priv *priv, - struct ieee80211_key_conf *key) + struct ieee80211_key_conf *keyconf) { int ret; unsigned long flags; spin_lock_irqsave(&priv->sta_lock, flags); + + if (!test_and_clear_bit(keyconf->keyidx, &priv->ucode_key_table)) + IWL_ERROR("index %d not used in uCode key table.\n", + keyconf->keyidx); + priv->default_wep_key--; - memset(&priv->wep_keys[key->keyidx], 0, sizeof(priv->wep_keys[0])); + memset(&priv->wep_keys[keyconf->keyidx], 0, sizeof(priv->wep_keys[0])); ret = iwl_send_static_wepkey_cmd(priv, 1); spin_unlock_irqrestore(&priv->sta_lock, flags); @@ -108,6 +125,10 @@ int iwl_set_default_wep_key(struct iwl_priv *priv, spin_lock_irqsave(&priv->sta_lock, flags); priv->default_wep_key++; + if (test_and_set_bit(keyconf->keyidx, &priv->ucode_key_table)) + IWL_ERROR("index %d already used in uCode key table.\n", + keyconf->keyidx); + priv->wep_keys[keyconf->keyidx].key_size = keyconf->keylen; memcpy(&priv->wep_keys[keyconf->keyidx].key, &keyconf->key, keyconf->keylen); @@ -151,7 +172,8 @@ int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv, memcpy(&priv->stations[sta_id].sta.key.key[3], keyconf->key, keyconf->keylen); - priv->stations[sta_id].sta.key.key_offset = sta_id % 8; /* FIXME */ + priv->stations[sta_id].sta.key.key_offset = + iwl_get_free_ucode_key_index(priv); priv->stations[sta_id].sta.key.key_flags = key_flags; priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index 78e0254c93b5..3f1b20534396 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h @@ -37,6 +37,7 @@ #include "iwl-io.h" #include "iwl-helpers.h" +int iwl_get_free_ucode_key_index(struct iwl_priv *priv); int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty); int iwl_remove_default_wep_key(struct iwl_priv *priv, struct ieee80211_key_conf *key); diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 37ab1c565ce1..da01896bd406 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -1140,8 +1140,8 @@ static int iwl4965_set_ccmp_dynamic_key_info(struct iwl_priv *priv, memcpy(priv->stations[sta_id].sta.key.key, keyconf->key, keyconf->keylen); - priv->stations[sta_id].sta.key.key_offset - = (sta_id % STA_KEY_MAX_NUM);/*FIXME*/ + priv->stations[sta_id].sta.key.key_offset = + iwl_get_free_ucode_key_index(priv); priv->stations[sta_id].sta.key.key_flags = key_flags; priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; @@ -1187,6 +1187,10 @@ static int iwl4965_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id) priv->key_mapping_key = 0; spin_lock_irqsave(&priv->sta_lock, flags); + if (!test_and_clear_bit(priv->stations[sta_id].sta.key.key_offset, + &priv->ucode_key_table)) + IWL_ERROR("index %d not used in uCode key table.\n", + priv->stations[sta_id].sta.key.key_offset); memset(&priv->stations[sta_id].keyinfo, 0, sizeof(struct iwl4965_hw_key)); memset(&priv->stations[sta_id].sta.key, 0, sizeof(struct iwl4965_keyinfo)); priv->stations[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC; @@ -6971,7 +6975,7 @@ static void iwl4965_mac_update_tkip_key(struct ieee80211_hw *hw, spin_lock_irqsave(&priv->sta_lock, flags); priv->stations[sta_id].sta.key.key_offset = - (sta_id % STA_KEY_MAX_NUM);/* FIXME */ + iwl_get_free_ucode_key_index(priv); priv->stations[sta_id].sta.key.key_flags = key_flags; priv->stations[sta_id].sta.key.tkip_rx_tsc_byte2 = (u8) iv32; -- cgit v1.2.1 From 7480513f5b436321f86f5a5210af5bf8edb19e9a Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Mon, 14 Apr 2008 21:16:09 -0700 Subject: iwlwifi: moves security functions to iwl-sta.c This patch moves security related functions to iwl-sta.c. Note that iwl4965_mac_update_tkip_key is still in iwl4965-base.c since it is a mac80211 handler. Signed-off-by: Emmanuel Grumbach Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-sta.c | 119 ++++++++++++++++++++++++++- drivers/net/wireless/iwlwifi/iwl-sta.h | 7 +- drivers/net/wireless/iwlwifi/iwl4965-base.c | 120 +--------------------------- 3 files changed, 123 insertions(+), 123 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 41238f208ed5..8765358c1a11 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -139,7 +139,7 @@ int iwl_set_default_wep_key(struct iwl_priv *priv, return ret; } -int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv, +static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv, struct ieee80211_key_conf *keyconf, u8 sta_id) { @@ -186,3 +186,120 @@ int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv, return ret; } + +static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv, + struct ieee80211_key_conf *keyconf, + u8 sta_id) +{ + unsigned long flags; + __le16 key_flags = 0; + + key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK); + key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); + key_flags &= ~STA_KEY_FLG_INVALID; + + if (sta_id == priv->hw_setting.bcast_sta_id) + key_flags |= STA_KEY_MULTICAST_MSK; + + keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; + keyconf->hw_key_idx = keyconf->keyidx; + + spin_lock_irqsave(&priv->sta_lock, flags); + priv->stations[sta_id].keyinfo.alg = keyconf->alg; + priv->stations[sta_id].keyinfo.keylen = keyconf->keylen; + + memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, + keyconf->keylen); + + memcpy(priv->stations[sta_id].sta.key.key, keyconf->key, + keyconf->keylen); + + priv->stations[sta_id].sta.key.key_offset = + iwl_get_free_ucode_key_index(priv); + priv->stations[sta_id].sta.key.key_flags = key_flags; + priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; + priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; + + spin_unlock_irqrestore(&priv->sta_lock, flags); + + IWL_DEBUG_INFO("hwcrypto: modify ucode station key info\n"); + return iwl4965_send_add_station(priv, + &priv->stations[sta_id].sta, CMD_ASYNC); +} + +static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv, + struct ieee80211_key_conf *keyconf, + u8 sta_id) +{ + unsigned long flags; + int ret = 0; + + keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; + keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; + keyconf->hw_key_idx = keyconf->keyidx; + + spin_lock_irqsave(&priv->sta_lock, flags); + + priv->stations[sta_id].keyinfo.alg = keyconf->alg; + priv->stations[sta_id].keyinfo.conf = keyconf; + priv->stations[sta_id].keyinfo.keylen = 16; + + /* This copy is acutally not needed: we get the key with each TX */ + memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, 16); + + memcpy(priv->stations[sta_id].sta.key.key, keyconf->key, 16); + + spin_unlock_irqrestore(&priv->sta_lock, flags); + + return ret; +} + +int iwl_remove_dynamic_key(struct iwl_priv *priv, u8 sta_id) +{ + unsigned long flags; + + priv->key_mapping_key = 0; + + spin_lock_irqsave(&priv->sta_lock, flags); + if (!test_and_clear_bit(priv->stations[sta_id].sta.key.key_offset, + &priv->ucode_key_table)) + IWL_ERROR("index %d not used in uCode key table.\n", + priv->stations[sta_id].sta.key.key_offset); + memset(&priv->stations[sta_id].keyinfo, 0, + sizeof(struct iwl4965_hw_key)); + memset(&priv->stations[sta_id].sta.key, 0, + sizeof(struct iwl4965_keyinfo)); + priv->stations[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC; + priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; + priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; + spin_unlock_irqrestore(&priv->sta_lock, flags); + + IWL_DEBUG_INFO("hwcrypto: clear ucode station key info\n"); + return iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, 0); +} + +int iwl_set_dynamic_key(struct iwl_priv *priv, + struct ieee80211_key_conf *key, u8 sta_id) +{ + int ret; + + priv->key_mapping_key = 1; + + switch (key->alg) { + case ALG_CCMP: + ret = iwl_set_ccmp_dynamic_key_info(priv, key, sta_id); + break; + case ALG_TKIP: + ret = iwl_set_tkip_dynamic_key_info(priv, key, sta_id); + break; + case ALG_WEP: + ret = iwl_set_wep_dynamic_key_info(priv, key, sta_id); + break; + default: + IWL_ERROR("Unknown alg: %s alg = %d\n", __func__, key->alg); + ret = -EINVAL; + } + + return ret; +} + diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index 3f1b20534396..44f272ecc827 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h @@ -43,8 +43,7 @@ int iwl_remove_default_wep_key(struct iwl_priv *priv, struct ieee80211_key_conf *key); int iwl_set_default_wep_key(struct iwl_priv *priv, struct ieee80211_key_conf *key); -int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv, - struct ieee80211_key_conf *keyconf, - u8 sta_id); - +int iwl_remove_dynamic_key(struct iwl_priv *priv, u8 sta_id); +int iwl_set_dynamic_key(struct iwl_priv *priv, + struct ieee80211_key_conf *key, u8 sta_id); #endif /* __iwl_sta_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index da01896bd406..bfefb05e18e9 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -1112,122 +1112,6 @@ int iwl4965_send_add_station(struct iwl_priv *priv, return rc; } -static int iwl4965_set_ccmp_dynamic_key_info(struct iwl_priv *priv, - struct ieee80211_key_conf *keyconf, - u8 sta_id) -{ - unsigned long flags; - __le16 key_flags = 0; - - key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK); - key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); - - if (sta_id == priv->hw_setting.bcast_sta_id) - key_flags |= STA_KEY_MULTICAST_MSK; - - keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; - keyconf->hw_key_idx = keyconf->keyidx; - - key_flags &= ~STA_KEY_FLG_INVALID; - - spin_lock_irqsave(&priv->sta_lock, flags); - priv->stations[sta_id].keyinfo.alg = keyconf->alg; - priv->stations[sta_id].keyinfo.keylen = keyconf->keylen; - - memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, - keyconf->keylen); - - memcpy(priv->stations[sta_id].sta.key.key, keyconf->key, - keyconf->keylen); - - priv->stations[sta_id].sta.key.key_offset = - iwl_get_free_ucode_key_index(priv); - priv->stations[sta_id].sta.key.key_flags = key_flags; - priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; - priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; - - spin_unlock_irqrestore(&priv->sta_lock, flags); - - IWL_DEBUG_INFO("hwcrypto: modify ucode station key info\n"); - return iwl4965_send_add_station(priv, - &priv->stations[sta_id].sta, CMD_ASYNC); -} - -static int iwl4965_set_tkip_dynamic_key_info(struct iwl_priv *priv, - struct ieee80211_key_conf *keyconf, - u8 sta_id) -{ - unsigned long flags; - int ret = 0; - - keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; - keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; - keyconf->hw_key_idx = keyconf->keyidx; - - spin_lock_irqsave(&priv->sta_lock, flags); - - priv->stations[sta_id].keyinfo.alg = keyconf->alg; - priv->stations[sta_id].keyinfo.conf = keyconf; - priv->stations[sta_id].keyinfo.keylen = 16; - - /* This copy is acutally not needed: we get the key with each TX */ - memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, 16); - - memcpy(priv->stations[sta_id].sta.key.key, keyconf->key, 16); - - spin_unlock_irqrestore(&priv->sta_lock, flags); - - return ret; -} - -static int iwl4965_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id) -{ - unsigned long flags; - - priv->key_mapping_key = 0; - - spin_lock_irqsave(&priv->sta_lock, flags); - if (!test_and_clear_bit(priv->stations[sta_id].sta.key.key_offset, - &priv->ucode_key_table)) - IWL_ERROR("index %d not used in uCode key table.\n", - priv->stations[sta_id].sta.key.key_offset); - memset(&priv->stations[sta_id].keyinfo, 0, sizeof(struct iwl4965_hw_key)); - memset(&priv->stations[sta_id].sta.key, 0, sizeof(struct iwl4965_keyinfo)); - priv->stations[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC; - priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; - priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; - spin_unlock_irqrestore(&priv->sta_lock, flags); - - IWL_DEBUG_INFO("hwcrypto: clear ucode station key info\n"); - iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, 0); - return 0; -} - -static int iwl4965_set_dynamic_key(struct iwl_priv *priv, - struct ieee80211_key_conf *key, u8 sta_id) -{ - int ret; - - priv->key_mapping_key = 1; - - switch (key->alg) { - case ALG_CCMP: - ret = iwl4965_set_ccmp_dynamic_key_info(priv, key, sta_id); - break; - case ALG_TKIP: - ret = iwl4965_set_tkip_dynamic_key_info(priv, key, sta_id); - break; - case ALG_WEP: - ret = iwl_set_wep_dynamic_key_info(priv, key, sta_id); - break; - default: - IWL_ERROR("Unknown alg: %s alg = %d\n", __func__, key->alg); - ret = -EINVAL; - } - - return ret; -} - static void iwl4965_clear_free_frames(struct iwl_priv *priv) { struct list_head *element; @@ -7043,7 +6927,7 @@ static int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, if (is_default_wep_key) ret = iwl_set_default_wep_key(priv, key); else - ret = iwl4965_set_dynamic_key(priv, key, sta_id); + ret = iwl_set_dynamic_key(priv, key, sta_id); IWL_DEBUG_MAC80211("enable hwcrypto key\n"); break; @@ -7051,7 +6935,7 @@ static int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, if (is_default_wep_key) ret = iwl_remove_default_wep_key(priv, key); else - ret = iwl4965_clear_sta_key_info(priv, sta_id); + ret = iwl_remove_dynamic_key(priv, sta_id); IWL_DEBUG_MAC80211("disable hwcrypto key\n"); break; -- cgit v1.2.1 From e2a722eba1b3aa504ae177353d100287398881c3 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Mon, 14 Apr 2008 21:16:10 -0700 Subject: iwlwifi: Fix byte count table for fragmented packets This patch fix byte count table update. Table must be updated for each fragment Signed-off-by: Tomas Winkler Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965.c | 13 +++++-------- drivers/net/wireless/iwlwifi/iwl-core.h | 4 ++++ drivers/net/wireless/iwlwifi/iwl4965-base.c | 6 +++--- 3 files changed, 12 insertions(+), 11 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 822169e61e9b..04fed5e0724a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -3141,18 +3141,16 @@ static void iwl4965_hw_card_show_info(struct iwl_priv *priv) #define IWL_TX_DELIMITER_SIZE 4 /** - * iwl4965_tx_queue_update_wr_ptr - Set up entry in Tx byte-count array + * iwl4965_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array */ -int iwl4965_tx_queue_update_wr_ptr(struct iwl_priv *priv, - struct iwl4965_tx_queue *txq, u16 byte_cnt) +static void iwl4965_txq_update_byte_cnt_tbl(struct iwl_priv *priv, + struct iwl4965_tx_queue *txq, + u16 byte_cnt) { int len; int txq_id = txq->q.id; struct iwl4965_shared *shared_data = priv->hw_setting.shared_virt; - if (txq->need_update == 0) - return 0; - len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE; /* Set up byte count within first 256 entries */ @@ -3164,8 +3162,6 @@ int iwl4965_tx_queue_update_wr_ptr(struct iwl_priv *priv, IWL_SET_BITS16(shared_data->queues_byte_cnt_tbls[txq_id]. tfd_offset[IWL4965_QUEUE_SIZE + txq->q.write_ptr], byte_cnt, len); - - return 0; } /** @@ -4934,6 +4930,7 @@ static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = { static struct iwl_lib_ops iwl4965_lib = { .init_drv = iwl4965_init_drv, + .txq_update_byte_cnt_tbl = iwl4965_txq_update_byte_cnt_tbl, .hw_nic_init = iwl4965_hw_nic_init, .is_valid_rtc_data_addr = iwl4965_hw_valid_rtc_data_addr, .alive_notify = iwl4965_alive_notify, diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 889fdbaeb735..23c21e38ca8a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -89,6 +89,10 @@ struct iwl_hcmd_utils_ops { struct iwl_lib_ops { /* iwlwifi driver (priv) init */ int (*init_drv)(struct iwl_priv *priv); + + void (*txq_update_byte_cnt_tbl)(struct iwl_priv *priv, + struct iwl4965_tx_queue *txq, + u16 byte_cnt); /* nic init */ int (*hw_nic_init)(struct iwl_priv *priv); /* alive notification */ diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index bfefb05e18e9..60c0b8375f24 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -575,11 +575,11 @@ int iwl4965_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) txq->need_update = 1; /* Set up entry in queue's byte count circular buffer */ - ret = iwl4965_tx_queue_update_wr_ptr(priv, txq, 0); + priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq, 0); /* Increment and update queue's write index */ q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); - iwl4965_tx_queue_update_write_ptr(priv, txq); + ret = iwl4965_tx_queue_update_write_ptr(priv, txq); spin_unlock_irqrestore(&priv->hcmd_lock, flags); return ret ? ret : idx; @@ -2392,7 +2392,7 @@ static int iwl4965_tx_skb(struct iwl_priv *priv, ieee80211_get_hdrlen(fc)); /* Set up entry for this TFD in Tx byte-count array */ - iwl4965_tx_queue_update_wr_ptr(priv, txq, len); + priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq, len); /* Tell device the write index *just past* this latest filled TFD */ q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); -- cgit v1.2.1 From 51dbfd1d59b0f55aef2105e06f770f3a97fc4e3a Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Mon, 14 Apr 2008 21:16:11 -0700 Subject: iwl4965: make iwl4965_send_rxon_assoc asynchronous Signed-off-by: Reinette Chatre Acked-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl4965-base.c | 27 ++++++--------------------- 1 file changed, 6 insertions(+), 21 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 60c0b8375f24..9fb985770fd2 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -758,15 +758,8 @@ static int iwl4965_full_rxon_required(struct iwl_priv *priv) static int iwl4965_send_rxon_assoc(struct iwl_priv *priv) { - int rc = 0; - struct iwl4965_rx_packet *res = NULL; + int ret = 0; struct iwl4965_rxon_assoc_cmd rxon_assoc; - struct iwl_host_cmd cmd = { - .id = REPLY_RXON_ASSOC, - .len = sizeof(rxon_assoc), - .meta.flags = CMD_WANT_SKB, - .data = &rxon_assoc, - }; const struct iwl4965_rxon_cmd *rxon1 = &priv->staging_rxon; const struct iwl4965_rxon_cmd *rxon2 = &priv->active_rxon; @@ -794,20 +787,12 @@ static int iwl4965_send_rxon_assoc(struct iwl_priv *priv) priv->staging_rxon.ofdm_ht_dual_stream_basic_rates; rxon_assoc.rx_chain_select_flags = priv->staging_rxon.rx_chain; - rc = iwl_send_cmd_sync(priv, &cmd); - if (rc) - return rc; - - res = (struct iwl4965_rx_packet *)cmd.meta.u.skb->data; - if (res->hdr.flags & IWL_CMD_FAILED_MSK) { - IWL_ERROR("Bad return from REPLY_RXON_ASSOC command\n"); - rc = -EIO; - } - - priv->alloc_rxb_skb--; - dev_kfree_skb_any(cmd.meta.u.skb); + ret = iwl_send_cmd_pdu_async(priv, REPLY_RXON_ASSOC, + sizeof(rxon_assoc), &rxon_assoc, NULL); + if (ret) + return ret; - return rc; + return ret; } /** -- cgit v1.2.1 From eadd3c4b9a90e31d5b6034a8813bfabecbe48681 Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Mon, 14 Apr 2008 21:16:12 -0700 Subject: iwlwifi: make Makefile more concise Also change CONFIG_IWLCORE_RFKILL to CONFIG_IWLWIFI_RFKILL to be more consistent with other config variables. Signed-off-by: Reinette Chatre Acked-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/Kconfig | 2 +- drivers/net/wireless/iwlwifi/Makefile | 29 ++++++++--------------------- drivers/net/wireless/iwlwifi/iwl-4965.h | 2 +- drivers/net/wireless/iwlwifi/iwl-rfkill.h | 2 +- 4 files changed, 11 insertions(+), 24 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index bcaa61b7c563..f844b738d34e 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig @@ -6,7 +6,7 @@ config IWLWIFI_LEDS bool default n -config IWLCORE_RFKILL +config IWLWIFI_RFKILL boolean "IWLWIFI RF kill support" depends on IWLCORE select RFKILL diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 741ea346a295..4f3e88b12e3a 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile @@ -1,26 +1,13 @@ -obj-$(CONFIG_IWLCORE) += iwlcore.o -iwlcore-objs = iwl-core.o iwl-eeprom.o iwl-hcmd.o - -ifeq ($(CONFIG_IWLWIFI_DEBUGFS),y) - iwlcore-objs += iwl-debugfs.o -endif - -ifeq ($(CONFIG_IWLWIFI_LEDS),y) - iwlcore-objs += iwl-led.o -endif - -ifeq ($(CONFIG_IWLCORE_RFKILL),y) - iwlcore-objs += iwl-rfkill.o -endif +obj-$(CONFIG_IWLCORE) := iwlcore.o +iwlcore-objs := iwl-core.o iwl-eeprom.o iwl-hcmd.o +iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o +iwlcore-$(CONFIG_IWLWIFI_LEDS) += iwl-led.o +iwlcore-$(CONFIG_IWLWIFI_RFKILL) += iwl-rfkill.o obj-$(CONFIG_IWL3945) += iwl3945.o -iwl3945-objs = iwl3945-base.o iwl-3945.o iwl-3945-rs.o - -ifeq ($(CONFIG_IWL3945_LEDS),y) - iwl3945-objs += iwl-3945-led.o -endif - +iwl3945-objs := iwl3945-base.o iwl-3945.o iwl-3945-rs.o +iwl3945-$(CONFIG_IWL3945_LEDS) += iwl-3945-led.o obj-$(CONFIG_IWL4965) += iwl4965.o -iwl4965-objs = iwl4965-base.o iwl-4965.o iwl-4965-rs.o iwl-sta.o +iwl4965-objs := iwl4965-base.o iwl-4965.o iwl-4965-rs.o iwl-sta.o diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index daf157adf24e..17c4bcfe113b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -1034,7 +1034,7 @@ struct iwl_priv { * 4965's initialize alive response contains some calibration data. */ struct iwl4965_init_alive_resp card_alive_init; struct iwl4965_alive_resp card_alive; -#ifdef CONFIG_IWLCORE_RFKILL +#ifdef CONFIG_IWLWIFI_RFKILL struct iwl_rfkill_mngr rfkill_mngr; #endif diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.h b/drivers/net/wireless/iwlwifi/iwl-rfkill.h index e7aa51a1db18..a7f04b855403 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rfkill.h +++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.h @@ -34,7 +34,7 @@ struct iwl_priv; #include -#ifdef CONFIG_IWLCORE_RFKILL +#ifdef CONFIG_IWLWIFI_RFKILL struct iwl_rfkill_mngr { struct rfkill *rfkill; struct input_dev *input_dev; -- cgit v1.2.1 From 508e32e177f54d1f6ebcfa181b9d6f2583c3b1c0 Mon Sep 17 00:00:00 2001 From: Reinette Chatre Date: Mon, 14 Apr 2008 21:16:13 -0700 Subject: iwlwifi: perform bss_info_changed post association work right away Do not use workqueue for bss_info_changed post association work. When driver is notified of association the upper layer will be notified right after that the association is complete. Doing the post association work in a workqueue introduces a race condition where the upper layer may want to make use of the association, but it is not yet complete. Signed-off-by: Reinette Chatre Acked-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl4965-base.c | 31 ++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 9fb985770fd2..1f343409c904 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -1840,7 +1840,7 @@ static void iwl4965_set_flags_for_phymode(struct iwl_priv *priv, | RXON_FLG_CCK_MSK); priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; } else { - /* Copied from iwl4965_bg_post_associate() */ + /* Copied from iwl4965_post_associate() */ if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; else @@ -6004,10 +6004,8 @@ static void iwl4965_bg_rx_replenish(struct work_struct *data) #define IWL_DELAY_NEXT_SCAN (HZ*2) -static void iwl4965_bg_post_associate(struct work_struct *data) +static void iwl4965_post_associate(struct iwl_priv *priv) { - struct iwl_priv *priv = container_of(data, struct iwl_priv, - post_associate.work); struct ieee80211_conf *conf = NULL; int ret = 0; DECLARE_MAC_BUF(mac); @@ -6025,12 +6023,10 @@ static void iwl4965_bg_post_associate(struct work_struct *data) if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; - mutex_lock(&priv->mutex); - if (!priv->vif || !priv->is_open) { - mutex_unlock(&priv->mutex); + if (!priv->vif || !priv->is_open) return; - } + iwl4965_scan_cancel_timeout(priv, 200); conf = ieee80211_get_hw_conf(priv->hw); @@ -6114,7 +6110,18 @@ static void iwl4965_bg_post_associate(struct work_struct *data) /* we have just associated, don't start scan too early */ priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN; +} + + +static void iwl4965_bg_post_associate(struct work_struct *data) +{ + struct iwl_priv *priv = container_of(data, struct iwl_priv, + post_associate.work); + + mutex_lock(&priv->mutex); + iwl4965_post_associate(priv); mutex_unlock(&priv->mutex); + } static void iwl4965_bg_abort_scan(struct work_struct *work) @@ -6736,6 +6743,10 @@ static void iwl4965_bss_info_changed(struct ieee80211_hw *hw, if (changes & BSS_CHANGED_ASSOC) { IWL_DEBUG_MAC80211("ASSOC %d\n", bss_conf->assoc); + /* This should never happen as this function should + * never be called from interrupt context. */ + if (WARN_ON_ONCE(in_interrupt())) + return; if (bss_conf->assoc) { priv->assoc_id = bss_conf->aid; priv->beacon_int = bss_conf->beacon_int; @@ -6743,7 +6754,9 @@ static void iwl4965_bss_info_changed(struct ieee80211_hw *hw, priv->assoc_capability = bss_conf->assoc_capability; priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN_AFTER_ASSOC; - queue_work(priv->workqueue, &priv->post_associate.work); + mutex_lock(&priv->mutex); + iwl4965_post_associate(priv); + mutex_unlock(&priv->mutex); } else { priv->assoc_id = 0; IWL_DEBUG_MAC80211("DISASSOC %d\n", bss_conf->assoc); -- cgit v1.2.1 From 059ff8266104d4919c693d6bf974c9e350da513e Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Mon, 14 Apr 2008 21:16:14 -0700 Subject: iwlwifi: move shared pointers to iwl_priv Signed-off-by: Tomas Winkler Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965-hw.h | 12 +++---- drivers/net/wireless/iwlwifi/iwl-4965.c | 55 +++++++++++++---------------- drivers/net/wireless/iwlwifi/iwl-4965.h | 11 +++--- drivers/net/wireless/iwlwifi/iwl4965-base.c | 6 ++-- 4 files changed, 40 insertions(+), 44 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h index de7bac149723..3d098da25fc9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h @@ -1554,29 +1554,29 @@ struct iwl4965_sched_queue_byte_cnt_tbl { struct iwl4965_shared { struct iwl4965_sched_queue_byte_cnt_tbl queues_byte_cnt_tbls[IWL_MAX_NUM_QUEUES]; - __le32 val0; + __le32 rb_closed; /* __le32 rb_closed_stts_rb_num:12; */ #define IWL_rb_closed_stts_rb_num_POS 0 #define IWL_rb_closed_stts_rb_num_LEN 12 -#define IWL_rb_closed_stts_rb_num_SYM val0 +#define IWL_rb_closed_stts_rb_num_SYM rb_closed /* __le32 rsrv1:4; */ /* __le32 rb_closed_stts_rx_frame_num:12; */ #define IWL_rb_closed_stts_rx_frame_num_POS 16 #define IWL_rb_closed_stts_rx_frame_num_LEN 12 -#define IWL_rb_closed_stts_rx_frame_num_SYM val0 +#define IWL_rb_closed_stts_rx_frame_num_SYM rb_closed /* __le32 rsrv2:4; */ - __le32 val1; + __le32 frm_finished; /* __le32 frame_finished_stts_rb_num:12; */ #define IWL_frame_finished_stts_rb_num_POS 0 #define IWL_frame_finished_stts_rb_num_LEN 12 -#define IWL_frame_finished_stts_rb_num_SYM val1 +#define IWL_frame_finished_stts_rb_num_SYM frm_finished /* __le32 rsrv3:4; */ /* __le32 frame_finished_stts_rx_frame_num:12; */ #define IWL_frame_finished_stts_rx_frame_num_POS 16 #define IWL_frame_finished_stts_rx_frame_num_LEN 12 -#define IWL_frame_finished_stts_rx_frame_num_SYM val1 +#define IWL_frame_finished_stts_rx_frame_num_SYM frm_finished /* __le32 rsrv4:4; */ __le32 padding1; /* so that allocation will be aligned to 16B */ diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 04fed5e0724a..a10a6e81769f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -274,6 +274,18 @@ static int iwl4965_init_drv(struct iwl_priv *priv) spin_lock_init(&priv->hcmd_lock); spin_lock_init(&priv->lq_mngr.lock); + priv->shared_virt = pci_alloc_consistent(priv->pci_dev, + sizeof(struct iwl4965_shared), + &priv->shared_phys); + + if (!priv->shared_virt) { + ret = -ENOMEM; + goto err; + } + + memset(priv->shared_virt, 0, sizeof(struct iwl4965_shared)); + + for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++) INIT_LIST_HEAD(&priv->ibss_mac_hash[i]); @@ -546,15 +558,15 @@ static int iwl4965_nic_set_pwr_src(struct iwl_priv *priv, int pwr_max) static int iwl4965_rx_init(struct iwl_priv *priv, struct iwl4965_rx_queue *rxq) { - int rc; + int ret; unsigned long flags; unsigned int rb_size; spin_lock_irqsave(&priv->lock, flags); - rc = iwl_grab_nic_access(priv); - if (rc) { + ret = iwl_grab_nic_access(priv); + if (ret) { spin_unlock_irqrestore(&priv->lock, flags); - return rc; + return ret; } if (priv->cfg->mod_params->amsdu_size_8K) @@ -574,15 +586,15 @@ static int iwl4965_rx_init(struct iwl_priv *priv, struct iwl4965_rx_queue *rxq) /* Tell device where in DRAM to update its Rx status */ iwl_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG, - (priv->hw_setting.shared_phys + - offsetof(struct iwl4965_shared, val0)) >> 4); + (priv->shared_phys + + offsetof(struct iwl4965_shared, rb_closed)) >> 4); /* Enable Rx DMA, enable host interrupt, Rx buffer size 4k, 256 RBDs */ iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL | FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL | rb_size | - /*0x10 << 4 | */ + /* 0x10 << 4 | */ (RX_QUEUE_SIZE_LOG << FH_RCSR_RX_CONFIG_RBDCB_SIZE_BITSHIFT)); @@ -1966,7 +1978,7 @@ int iwl4965_alive_notify(struct iwl_priv *priv) /* Tel 4965 where to find Tx byte count tables */ iwl_write_prph(priv, IWL49_SCD_DRAM_BASE_ADDR, - (priv->hw_setting.shared_phys + + (priv->shared_phys + offsetof(struct iwl4965_shared, queues_byte_cnt_tbls)) >> 10); /* Disable chain mode for all queues */ @@ -2024,29 +2036,14 @@ int iwl4965_alive_notify(struct iwl_priv *priv) */ int iwl4965_hw_set_hw_setting(struct iwl_priv *priv) { - int ret = 0; if ((priv->cfg->mod_params->num_of_queues > IWL_MAX_NUM_QUEUES) || (priv->cfg->mod_params->num_of_queues < IWL_MIN_NUM_QUEUES)) { IWL_ERROR("invalid queues_num, should be between %d and %d\n", IWL_MIN_NUM_QUEUES, IWL_MAX_NUM_QUEUES); - ret = -EINVAL; - goto out; - } - - /* Allocate area for Tx byte count tables and Rx queue status */ - priv->hw_setting.shared_virt = - pci_alloc_consistent(priv->pci_dev, - sizeof(struct iwl4965_shared), - &priv->hw_setting.shared_phys); - - if (!priv->hw_setting.shared_virt) { - ret = -ENOMEM; - goto out; + return -EINVAL; } - memset(priv->hw_setting.shared_virt, 0, sizeof(struct iwl4965_shared)); - priv->hw_setting.max_txq_num = priv->cfg->mod_params->num_of_queues; priv->hw_setting.tx_cmd_len = sizeof(struct iwl4965_tx_cmd); priv->hw_setting.max_rxq_size = RX_QUEUE_SIZE; @@ -2061,8 +2058,7 @@ int iwl4965_hw_set_hw_setting(struct iwl_priv *priv) priv->hw_setting.tx_ant_num = 2; -out: - return ret; + return 0; } /** @@ -3014,9 +3010,8 @@ void iwl4965_hw_build_tx_cmd_rate(struct iwl_priv *priv, int iwl4965_hw_get_rx_read(struct iwl_priv *priv) { - struct iwl4965_shared *shared_data = priv->hw_setting.shared_virt; - - return IWL_GET_BITS(*shared_data, rb_closed_stts_rb_num); + struct iwl4965_shared *s = priv->shared_virt; + return le32_to_cpu(s->rb_closed) & 0xFFF; } int iwl4965_hw_get_temperature(struct iwl_priv *priv) @@ -3149,7 +3144,7 @@ static void iwl4965_txq_update_byte_cnt_tbl(struct iwl_priv *priv, { int len; int txq_id = txq->q.id; - struct iwl4965_shared *shared_data = priv->hw_setting.shared_virt; + struct iwl4965_shared *shared_data = priv->shared_virt; len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE; diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index 17c4bcfe113b..e5ab4c01ec9b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -576,8 +576,6 @@ struct iwl4965_ibss_seq { * @max_rxq_log: Log-base-2 of max_rxq_size * @max_stations: * @bcast_sta_id: - * @shared_virt: Pointer to driver/uCode shared Tx Byte Counts and Rx status - * @shared_phys: Physical Pointer to Tx Byte Counts and Rx status */ struct iwl4965_driver_hw_info { u16 max_txq_num; @@ -589,8 +587,6 @@ struct iwl4965_driver_hw_info { u16 max_rxq_log; u8 max_stations; u8 bcast_sta_id; - void *shared_virt; - dma_addr_t shared_phys; }; #define HT_SHORT_GI_20MHZ_ONLY (1 << 0) @@ -1147,9 +1143,14 @@ struct iwl_priv { /* Last Rx'd beacon timestamp */ u64 timestamp; u16 beacon_int; - struct iwl4965_driver_hw_info hw_setting; struct ieee80211_vif *vif; + struct iwl4965_driver_hw_info hw_setting; + /* driver/uCode shared Tx Byte Counts and Rx status */ + void *shared_virt; + /* Physical Pointer to Tx Byte Counts and Rx status */ + dma_addr_t shared_phys; + /* Current association information needed to configure the * hardware */ u16 assoc_id; diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 1f343409c904..5ec0af4788e4 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -1219,11 +1219,11 @@ static int iwl4965_send_beacon_cmd(struct iwl_priv *priv) static void iwl4965_unset_hw_setting(struct iwl_priv *priv) { - if (priv->hw_setting.shared_virt) + if (priv->shared_virt) pci_free_consistent(priv->pci_dev, sizeof(struct iwl4965_shared), - priv->hw_setting.shared_virt, - priv->hw_setting.shared_phys); + priv->shared_virt, + priv->shared_phys); } /** -- cgit v1.2.1 From ba380013b681e91e059f95b51002f8d43024b371 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Tue, 15 Apr 2008 21:13:36 +0200 Subject: b43: Add fastpath to b43_mac_suspend() This adds a fastpath for the common workloads to the MAC suspend flushing. In common workloads the FIFO flush will take between 100 and 200 microseconds. So we want to avoid calling msleep() in the common case, as it will waste over 800 microseconds + scheduler overhead. This fastpath will hit in workloads where only small chunks of data are transmitted (downloading a file) or when a TX rate bigger or equal to 24MBit/s is used when transmitting lots of stuff (iperf). So in the commonly used workloads it will basically always hit. In case the fastpath is not hit, there's no real performance or latency disadvantage from that. And yes, I measured this. So this is not one of these bad Programmer Likeliness Assumptions that are always wrong. ;) Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 345c34bdae9a..cf5c046c9fa8 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -2343,6 +2343,13 @@ static void b43_mac_suspend(struct b43_wldev *dev) & ~B43_MACCTL_ENABLED); /* force pci to flush the write */ b43_read32(dev, B43_MMIO_MACCTL); + for (i = 35; i; i--) { + tmp = b43_read32(dev, B43_MMIO_GEN_IRQ_REASON); + if (tmp & B43_IRQ_MAC_SUSPENDED) + goto out; + udelay(10); + } + /* Hm, it seems this will take some time. Use msleep(). */ for (i = 40; i; i--) { tmp = b43_read32(dev, B43_MMIO_GEN_IRQ_REASON); if (tmp & B43_IRQ_MAC_SUSPENDED) -- cgit v1.2.1 From 49ea85961cf8b60b5387cc1c1bc06fe4b6a31ee4 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Tue, 15 Apr 2008 16:01:37 -0700 Subject: iwlwifi: remove the statistics work This patch does 3 things 1) It removes the statistics work. The request statistics command is sent in ASYNC mode in this flow, the mutex is uneeded, so the request statistics function can't go to sleep. No need for a workqueue anymore. 2) iwl4965_send_statistics_request has been renamed to iwl_send_statistics_request and moved to iwl-core.c 3) A request for statistics is sent in alive_notify, the makes the uCode sends statistics notification periodically starting from association. Signed-off-by: Emmanuel Grumbach Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965.c | 29 ++++++----------------------- drivers/net/wireless/iwlwifi/iwl-4965.h | 2 -- drivers/net/wireless/iwlwifi/iwl-core.c | 12 ++++++++++++ drivers/net/wireless/iwlwifi/iwl-core.h | 2 ++ drivers/net/wireless/iwlwifi/iwl4965-base.c | 9 +-------- 5 files changed, 21 insertions(+), 33 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index a10a6e81769f..3df70f89f11b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -976,40 +976,21 @@ int iwl4965_hw_nic_reset(struct iwl_priv *priv) /** * iwl4965_bg_statistics_periodic - Timer callback to queue statistics * - * This callback is provided in order to queue the statistics_work - * in work_queue context (v. softirq) + * This callback is provided in order to send a statistics request. * * This timer function is continually reset to execute within * REG_RECALIB_PERIOD seconds since the last STATISTICS_NOTIFICATION * was received. We need to ensure we receive the statistics in order - * to update the temperature used for calibrating the TXPOWER. However, - * we can't send the statistics command from softirq context (which - * is the context which timers run at) so we have to queue off the - * statistics_work to actually send the command to the hardware. + * to update the temperature used for calibrating the TXPOWER. */ static void iwl4965_bg_statistics_periodic(unsigned long data) { struct iwl_priv *priv = (struct iwl_priv *)data; - queue_work(priv->workqueue, &priv->statistics_work); -} - -/** - * iwl4965_bg_statistics_work - Send the statistics request to the hardware. - * - * This is queued by iwl4965_bg_statistics_periodic. - */ -static void iwl4965_bg_statistics_work(struct work_struct *work) -{ - struct iwl_priv *priv = container_of(work, struct iwl_priv, - statistics_work); - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; - mutex_lock(&priv->mutex); - iwl4965_send_statistics_request(priv); - mutex_unlock(&priv->mutex); + iwl_send_statistics_request(priv, CMD_ASYNC); } #define CT_LIMIT_CONST 259 @@ -2026,6 +2007,9 @@ int iwl4965_alive_notify(struct iwl_priv *priv) iwl_release_nic_access(priv); spin_unlock_irqrestore(&priv->lock, flags); + /* Ask for statistics now, the uCode will send statistics notification + * periodically after association */ + iwl_send_statistics_request(priv, CMD_ASYNC); return ret; } @@ -4903,7 +4887,6 @@ void iwl4965_hw_rx_handler_setup(struct iwl_priv *priv) void iwl4965_hw_setup_deferred_work(struct iwl_priv *priv) { INIT_WORK(&priv->txpower_work, iwl4965_bg_txpower_work); - INIT_WORK(&priv->statistics_work, iwl4965_bg_statistics_work); #ifdef CONFIG_IWL4965_SENSITIVITY INIT_WORK(&priv->sensitivity_work, iwl4965_bg_sensitivity_work); #endif diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index e5ab4c01ec9b..c8e73a5212af 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -638,7 +638,6 @@ extern unsigned int iwl4965_fill_beacon_frame(struct iwl_priv *priv, const u8 *dest, int left); extern int iwl4965_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl4965_rx_queue *q); -extern int iwl4965_send_statistics_request(struct iwl_priv *priv); extern void iwl4965_set_decrypted_flag(struct iwl_priv *priv, struct sk_buff *skb, u32 decrypt_res, struct ieee80211_rx_status *stats); @@ -1206,7 +1205,6 @@ struct iwl_priv { #ifdef CONFIG_IWL4965_SENSITIVITY struct work_struct sensitivity_work; #endif - struct work_struct statistics_work; struct timer_list statistics_periodic; }; /*iwl_priv */ diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index d8a226e68ed1..88d62462ed4a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -277,3 +277,15 @@ int iwlcore_low_level_notify(struct iwl_priv *priv, } EXPORT_SYMBOL(iwlcore_low_level_notify); +int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags) +{ + u32 stat_flags = 0; + struct iwl_host_cmd cmd = { + .id = REPLY_STATISTICS_CMD, + .meta.flags = flags, + .len = sizeof(stat_flags), + .data = (u8 *) &stat_flags, + }; + return iwl_send_cmd(priv, &cmd); +} +EXPORT_SYMBOL(iwl_send_statistics_request); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 23c21e38ca8a..aef1b48ea50c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -228,4 +228,6 @@ enum iwlcore_card_notify { int iwlcore_low_level_notify(struct iwl_priv *priv, enum iwlcore_card_notify notify); +extern int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags); + #endif /* __iwl_core_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 5ec0af4788e4..42e519be0206 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -596,13 +596,6 @@ static void iwl4965_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt) } -int iwl4965_send_statistics_request(struct iwl_priv *priv) -{ - u32 flags = 0; - return iwl_send_cmd_pdu(priv, REPLY_STATISTICS_CMD, - sizeof(flags), &flags); -} - /** * iwl4965_rxon_add_station - add station into station table. * @@ -7530,7 +7523,7 @@ static ssize_t show_statistics(struct device *d, return -EAGAIN; mutex_lock(&priv->mutex); - rc = iwl4965_send_statistics_request(priv); + rc = iwl_send_statistics_request(priv, 0); mutex_unlock(&priv->mutex); if (rc) { -- cgit v1.2.1 From 5425e490471d521bae2fce16d22995803b41d90f Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Tue, 15 Apr 2008 16:01:38 -0700 Subject: iwlwifi: hw_setting cleanup 1. This patch renames hw_setting to hw_params 2. Align names of the structure and variables 3. set_hw_params is called from libs_ops Signed-off-by: Tomas Winkler Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965.c | 49 +++++++++++++------------- drivers/net/wireless/iwlwifi/iwl-4965.h | 8 ++--- drivers/net/wireless/iwlwifi/iwl-core.h | 2 ++ drivers/net/wireless/iwlwifi/iwl-debugfs.c | 2 +- drivers/net/wireless/iwlwifi/iwl-sta.c | 4 +-- drivers/net/wireless/iwlwifi/iwl4965-base.c | 54 ++++++++++++++--------------- 6 files changed, 61 insertions(+), 58 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 3df70f89f11b..a1e91dbb92bb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -504,10 +504,10 @@ u8 iwl4965_hw_find_station(struct iwl_priv *priv, const u8 *addr) start = IWL_STA_ID; if (is_broadcast_ether_addr(addr)) - return priv->hw_setting.bcast_sta_id; + return priv->hw_params.bcast_sta_id; spin_lock_irqsave(&priv->sta_lock, flags); - for (i = start; i < priv->hw_setting.max_stations; i++) + for (i = start; i < priv->hw_params.max_stations; i++) if ((priv->stations[i].used) && (!compare_ether_addr (priv->stations[i].sta.sta.addr, addr))) { @@ -702,7 +702,7 @@ static int iwl4965_txq_ctx_reset(struct iwl_priv *priv) /* Alloc and init all (default 16) Tx queues, * including the command queue (#4) */ - for (txq_id = 0; txq_id < priv->hw_setting.max_txq_num; txq_id++) { + for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ? TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; rc = iwl4965_tx_queue_init(priv, &priv->txq[txq_id], slots_num, @@ -908,7 +908,7 @@ void iwl4965_hw_txq_ctx_stop(struct iwl_priv *priv) unsigned long flags; /* Stop each Tx DMA channel, and wait for it to be idle */ - for (txq_id = 0; txq_id < priv->hw_setting.max_txq_num; txq_id++) { + for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { spin_lock_irqsave(&priv->lock, flags); if (iwl_grab_nic_access(priv)) { spin_unlock_irqrestore(&priv->lock, flags); @@ -1954,7 +1954,7 @@ int iwl4965_alive_notify(struct iwl_priv *priv) iwl_write_targ_mem(priv, a, 0); for (; a < priv->scd_base_addr + SCD_TRANSLATE_TBL_OFFSET; a += 4) iwl_write_targ_mem(priv, a, 0); - for (; a < sizeof(u16) * priv->hw_setting.max_txq_num; a += 4) + for (; a < sizeof(u16) * priv->hw_params.max_txq_num; a += 4) iwl_write_targ_mem(priv, a, 0); /* Tel 4965 where to find Tx byte count tables */ @@ -1966,7 +1966,7 @@ int iwl4965_alive_notify(struct iwl_priv *priv) iwl_write_prph(priv, IWL49_SCD_QUEUECHAIN_SEL, 0); /* Initialize each Tx queue (including the command queue) */ - for (i = 0; i < priv->hw_setting.max_txq_num; i++) { + for (i = 0; i < priv->hw_params.max_txq_num; i++) { /* TFD circular buffer read/write indexes */ iwl_write_prph(priv, IWL49_SCD_QUEUE_RDPTR(i), 0); @@ -1989,7 +1989,7 @@ int iwl4965_alive_notify(struct iwl_priv *priv) } iwl_write_prph(priv, IWL49_SCD_INTERRUPT_MASK, - (1 << priv->hw_setting.max_txq_num) - 1); + (1 << priv->hw_params.max_txq_num) - 1); /* Activate all Tx DMA/FIFO channels */ iwl_write_prph(priv, IWL49_SCD_TXFACT, @@ -2014,11 +2014,11 @@ int iwl4965_alive_notify(struct iwl_priv *priv) } /** - * iwl4965_hw_set_hw_setting + * iwl4965_hw_set_hw_params * * Called when initializing driver */ -int iwl4965_hw_set_hw_setting(struct iwl_priv *priv) +int iwl4965_hw_set_hw_params(struct iwl_priv *priv) { if ((priv->cfg->mod_params->num_of_queues > IWL_MAX_NUM_QUEUES) || @@ -2028,19 +2028,19 @@ int iwl4965_hw_set_hw_setting(struct iwl_priv *priv) return -EINVAL; } - priv->hw_setting.max_txq_num = priv->cfg->mod_params->num_of_queues; - priv->hw_setting.tx_cmd_len = sizeof(struct iwl4965_tx_cmd); - priv->hw_setting.max_rxq_size = RX_QUEUE_SIZE; - priv->hw_setting.max_rxq_log = RX_QUEUE_SIZE_LOG; + priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues; + priv->hw_params.tx_cmd_len = sizeof(struct iwl4965_tx_cmd); + priv->hw_params.max_rxq_size = RX_QUEUE_SIZE; + priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG; if (priv->cfg->mod_params->amsdu_size_8K) - priv->hw_setting.rx_buf_size = IWL_RX_BUF_SIZE_8K; + priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_8K; else - priv->hw_setting.rx_buf_size = IWL_RX_BUF_SIZE_4K; - priv->hw_setting.max_pkt_size = priv->hw_setting.rx_buf_size - 256; - priv->hw_setting.max_stations = IWL4965_STATION_COUNT; - priv->hw_setting.bcast_sta_id = IWL4965_BROADCAST_ID; + priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_4K; + priv->hw_params.max_pkt_size = priv->hw_params.rx_buf_size - 256; + priv->hw_params.max_stations = IWL4965_STATION_COUNT; + priv->hw_params.bcast_sta_id = IWL4965_BROADCAST_ID; - priv->hw_setting.tx_ant_num = 2; + priv->hw_params.tx_ant_num = 2; return 0; } @@ -2055,7 +2055,7 @@ void iwl4965_hw_txq_ctx_free(struct iwl_priv *priv) int txq_id; /* Tx queues */ - for (txq_id = 0; txq_id < priv->hw_setting.max_txq_num; txq_id++) + for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) iwl4965_tx_queue_free(priv, &priv->txq[txq_id]); /* Keep-warm buffer */ @@ -3012,7 +3012,7 @@ unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv, tx_beacon_cmd = &frame->u.beacon; memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd)); - tx_beacon_cmd->tx.sta_id = priv->hw_setting.bcast_sta_id; + tx_beacon_cmd->tx.sta_id = priv->hw_params.bcast_sta_id; tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; frame_size = iwl4965_fill_beacon_frame(priv, @@ -3620,7 +3620,7 @@ static void iwl4965_handle_data_packet(struct iwl_priv *priv, int is_data, rx_start->byte_count = amsdu->byte_count; rx_end = (__le32 *) (((u8 *) hdr) + len); } - if (len > priv->hw_setting.max_pkt_size || len < 16) { + if (len > priv->hw_params.max_pkt_size || len < 16) { IWL_WARNING("byte count out of range [16,4K] : %d\n", len); return; } @@ -4515,7 +4515,7 @@ void iwl4965_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap) link_cmd.agg_params.agg_time_limit = cpu_to_le16(4000); /* Update the rate scaling for control frame Tx to AP */ - link_cmd.sta_id = is_ap ? IWL_AP_ID : priv->hw_setting.bcast_sta_id; + link_cmd.sta_id = is_ap ? IWL_AP_ID : priv->hw_params.bcast_sta_id; iwl_send_cmd_pdu_async(priv, REPLY_TX_LINK_QUALITY_CMD, sizeof(link_cmd), &link_cmd, NULL); @@ -4704,7 +4704,7 @@ static int iwl4965_txq_ctx_activate_free(struct iwl_priv *priv) { int txq_id; - for (txq_id = 0; txq_id < priv->hw_setting.max_txq_num; txq_id++) + for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) if (!test_and_set_bit(txq_id, &priv->txq_ctx_active_msk)) return txq_id; return -1; @@ -4908,6 +4908,7 @@ static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = { static struct iwl_lib_ops iwl4965_lib = { .init_drv = iwl4965_init_drv, + .set_hw_params = iwl4965_hw_set_hw_params, .txq_update_byte_cnt_tbl = iwl4965_txq_update_byte_cnt_tbl, .hw_nic_init = iwl4965_hw_nic_init, .is_valid_rtc_data_addr = iwl4965_hw_valid_rtc_data_addr, diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index c8e73a5212af..c127c91010b4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -567,7 +567,7 @@ struct iwl4965_ibss_seq { }; /** - * struct iwl4965_driver_hw_info + * struct iwl_hw_params * @max_txq_num: Max # Tx queues supported * @tx_cmd_len: Size of Tx command (but not including frame itself) * @tx_ant_num: Number of TX antennas @@ -577,7 +577,7 @@ struct iwl4965_ibss_seq { * @max_stations: * @bcast_sta_id: */ -struct iwl4965_driver_hw_info { +struct iwl_hw_params { u16 max_txq_num; u16 tx_cmd_len; u16 tx_ant_num; @@ -675,7 +675,7 @@ extern void iwl4965_hw_rx_handler_setup(struct iwl_priv *priv); extern void iwl4965_hw_setup_deferred_work(struct iwl_priv *priv); extern void iwl4965_hw_cancel_deferred_work(struct iwl_priv *priv); extern int iwl4965_hw_rxq_stop(struct iwl_priv *priv); -extern int iwl4965_hw_set_hw_setting(struct iwl_priv *priv); +extern int iwl4965_hw_set_hw_params(struct iwl_priv *priv); extern int iwl4965_hw_nic_init(struct iwl_priv *priv); extern int iwl4965_hw_nic_stop_master(struct iwl_priv *priv); extern void iwl4965_hw_txq_ctx_free(struct iwl_priv *priv); @@ -1144,7 +1144,7 @@ struct iwl_priv { u16 beacon_int; struct ieee80211_vif *vif; - struct iwl4965_driver_hw_info hw_setting; + struct iwl_hw_params hw_params; /* driver/uCode shared Tx Byte Counts and Rx status */ void *shared_virt; /* Physical Pointer to Tx Byte Counts and Rx status */ diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index aef1b48ea50c..7791d2bd9645 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -89,6 +89,8 @@ struct iwl_hcmd_utils_ops { struct iwl_lib_ops { /* iwlwifi driver (priv) init */ int (*init_drv)(struct iwl_priv *priv); + /* set hw dependant perameters */ + int (*set_hw_params)(struct iwl_priv *priv); void (*txq_update_byte_cnt_tbl)(struct iwl_priv *priv, struct iwl4965_tx_queue *txq, diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index cbea477eb078..0f16f2606f29 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -207,7 +207,7 @@ static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf, { struct iwl_priv *priv = (struct iwl_priv *)file->private_data; struct iwl4965_station_entry *station; - int max_sta = priv->hw_setting.max_stations; + int max_sta = priv->hw_params.max_stations; char *buf; int i, j, pos = 0; ssize_t ret; diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 8765358c1a11..bc2e603efd28 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -157,7 +157,7 @@ static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv, if (keyconf->keylen == WEP_KEY_LEN_128) key_flags |= STA_KEY_FLG_KEY_SIZE_MSK; - if (sta_id == priv->hw_setting.bcast_sta_id) + if (sta_id == priv->hw_params.bcast_sta_id) key_flags |= STA_KEY_MULTICAST_MSK; spin_lock_irqsave(&priv->sta_lock, flags); @@ -198,7 +198,7 @@ static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv, key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); key_flags &= ~STA_KEY_FLG_INVALID; - if (sta_id == priv->hw_setting.bcast_sta_id) + if (sta_id == priv->hw_params.bcast_sta_id) key_flags |= STA_KEY_MULTICAST_MSK; keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 42e519be0206..c71910df62aa 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -398,9 +398,9 @@ static u8 iwl4965_remove_station(struct iwl_priv *priv, const u8 *addr, int is_a if (is_ap) index = IWL_AP_ID; else if (is_broadcast_ether_addr(addr)) - index = priv->hw_setting.bcast_sta_id; + index = priv->hw_params.bcast_sta_id; else - for (i = IWL_STA_ID; i < priv->hw_setting.max_stations; i++) + for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) if (priv->stations[i].used && !compare_ether_addr(priv->stations[i].sta.sta.addr, addr)) { @@ -440,9 +440,9 @@ u8 iwl4965_add_station_flags(struct iwl_priv *priv, const u8 *addr, if (is_ap) index = IWL_AP_ID; else if (is_broadcast_ether_addr(addr)) - index = priv->hw_setting.bcast_sta_id; + index = priv->hw_params.bcast_sta_id; else - for (i = IWL_STA_ID; i < priv->hw_setting.max_stations; i++) { + for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) { if (!compare_ether_addr(priv->stations[i].sta.sta.addr, addr)) { index = i; @@ -483,7 +483,7 @@ u8 iwl4965_add_station_flags(struct iwl_priv *priv, const u8 *addr, #ifdef CONFIG_IWL4965_HT /* BCAST station and IBSS stations do not work in HT mode */ - if (index != priv->hw_setting.bcast_sta_id && + if (index != priv->hw_params.bcast_sta_id && priv->iw_mode != IEEE80211_IF_TYPE_IBSS) iwl4965_set_ht_add_station(priv, index, (struct ieee80211_ht_info *) ht_data); @@ -1210,7 +1210,7 @@ static int iwl4965_send_beacon_cmd(struct iwl_priv *priv) * ******************************************************************************/ -static void iwl4965_unset_hw_setting(struct iwl_priv *priv) +static void iwl4965_unset_hw_params(struct iwl_priv *priv) { if (priv->shared_virt) pci_free_consistent(priv->pci_dev, @@ -2114,7 +2114,7 @@ static int iwl4965_get_sta_id(struct iwl_priv *priv, /* If this frame is broadcast or management, use broadcast station id */ if (((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA) || is_multicast_ether_addr(hdr->addr1)) - return priv->hw_setting.bcast_sta_id; + return priv->hw_params.bcast_sta_id; switch (priv->iw_mode) { @@ -2128,7 +2128,7 @@ static int iwl4965_get_sta_id(struct iwl_priv *priv, sta_id = iwl4965_hw_find_station(priv, hdr->addr1); if (sta_id != IWL_INVALID_STATION) return sta_id; - return priv->hw_setting.bcast_sta_id; + return priv->hw_params.bcast_sta_id; /* If this frame is going out to an IBSS network, find the station, * or create a new station table entry */ @@ -2148,11 +2148,11 @@ static int iwl4965_get_sta_id(struct iwl_priv *priv, "Defaulting to broadcast...\n", print_mac(mac, hdr->addr1)); iwl_print_hex_dump(IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr)); - return priv->hw_setting.bcast_sta_id; + return priv->hw_params.bcast_sta_id; default: IWL_WARNING("Unknown mode of operation: %d", priv->iw_mode); - return priv->hw_setting.bcast_sta_id; + return priv->hw_params.bcast_sta_id; } } @@ -2299,7 +2299,7 @@ static int iwl4965_tx_skb(struct iwl_priv *priv, * of the MAC header (device reads on dword boundaries). * We'll tell device about this padding later. */ - len = priv->hw_setting.tx_cmd_len + + len = priv->hw_params.tx_cmd_len + sizeof(struct iwl_cmd_header) + hdr_len; len_org = len; @@ -3726,7 +3726,7 @@ static void iwl4965_rx_allocate(struct iwl_priv *priv) /* Alloc a new receive buffer */ rxb->skb = - alloc_skb(priv->hw_setting.rx_buf_size, + alloc_skb(priv->hw_params.rx_buf_size, __GFP_NOWARN | GFP_ATOMIC); if (!rxb->skb) { if (net_ratelimit()) @@ -3743,7 +3743,7 @@ static void iwl4965_rx_allocate(struct iwl_priv *priv) /* Get physical address of RB/SKB */ rxb->dma_addr = pci_map_single(priv->pci_dev, rxb->skb->data, - priv->hw_setting.rx_buf_size, PCI_DMA_FROMDEVICE); + priv->hw_params.rx_buf_size, PCI_DMA_FROMDEVICE); list_add_tail(&rxb->list, &rxq->rx_free); rxq->free_count++; } @@ -3786,7 +3786,7 @@ static void iwl4965_rx_queue_free(struct iwl_priv *priv, struct iwl4965_rx_queue if (rxq->pool[i].skb != NULL) { pci_unmap_single(priv->pci_dev, rxq->pool[i].dma_addr, - priv->hw_setting.rx_buf_size, + priv->hw_params.rx_buf_size, PCI_DMA_FROMDEVICE); dev_kfree_skb(rxq->pool[i].skb); } @@ -3838,7 +3838,7 @@ void iwl4965_rx_queue_reset(struct iwl_priv *priv, struct iwl4965_rx_queue *rxq) if (rxq->pool[i].skb != NULL) { pci_unmap_single(priv->pci_dev, rxq->pool[i].dma_addr, - priv->hw_setting.rx_buf_size, + priv->hw_params.rx_buf_size, PCI_DMA_FROMDEVICE); priv->alloc_rxb_skb--; dev_kfree_skb(rxq->pool[i].skb); @@ -3973,7 +3973,7 @@ static void iwl4965_rx_handle(struct iwl_priv *priv) rxq->queue[i] = NULL; pci_dma_sync_single_for_cpu(priv->pci_dev, rxb->dma_addr, - priv->hw_setting.rx_buf_size, + priv->hw_params.rx_buf_size, PCI_DMA_FROMDEVICE); pkt = (struct iwl4965_rx_packet *)rxb->skb->data; @@ -4026,7 +4026,7 @@ static void iwl4965_rx_handle(struct iwl_priv *priv) } pci_unmap_single(priv->pci_dev, rxb->dma_addr, - priv->hw_setting.rx_buf_size, + priv->hw_params.rx_buf_size, PCI_DMA_FROMDEVICE); spin_lock_irqsave(&rxq->lock, flags); list_add_tail(&rxb->list, &priv->rxq.rx_used); @@ -5871,7 +5871,7 @@ static void iwl4965_bg_request_scan(struct work_struct *data) } scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; - scan->tx_cmd.sta_id = priv->hw_setting.bcast_sta_id; + scan->tx_cmd.sta_id = priv->hw_params.bcast_sta_id; scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; @@ -6844,7 +6844,7 @@ static void iwl4965_mac_update_tkip_key(struct ieee80211_hw *hw, key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); key_flags &= ~STA_KEY_FLG_INVALID; - if (sta_id == priv->hw_setting.bcast_sta_id) + if (sta_id == priv->hw_params.bcast_sta_id) key_flags |= STA_KEY_MULTICAST_MSK; spin_lock_irqsave(&priv->sta_lock, flags); @@ -6905,7 +6905,7 @@ static int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, * so far, we are in legacy wep mode (group key only), otherwise we are * in 1X mode. * In legacy wep mode, we use another host command to the uCode */ - if (key->alg == ALG_WEP && sta_id == priv->hw_setting.bcast_sta_id && + if (key->alg == ALG_WEP && sta_id == priv->hw_params.bcast_sta_id && priv->iw_mode != IEEE80211_IF_TYPE_AP) { if (cmd == SET_KEY) is_default_wep_key = !priv->key_mapping_key; @@ -7831,8 +7831,8 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e * 5. Setup HW constants ************************/ /* Device-specific setup */ - if (iwl4965_hw_set_hw_setting(priv)) { - IWL_ERROR("failed to set hw settings\n"); + if (priv->cfg->ops->lib->set_hw_params(priv)) { + IWL_ERROR("failed to set hw parameters\n"); goto out_iounmap; } @@ -7842,7 +7842,7 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e err = iwl_setup(priv); if (err) - goto out_unset_hw_settings; + goto out_unset_hw_params; /* At this point both hw and priv are initialized. */ /********************************** @@ -7868,7 +7868,7 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e err = sysfs_create_group(&pdev->dev.kobj, &iwl4965_attribute_group); if (err) { IWL_ERROR("failed to create sysfs device attributes\n"); - goto out_unset_hw_settings; + goto out_unset_hw_params; } err = iwl_dbgfs_register(priv, DRV_NAME); @@ -7892,8 +7892,8 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e out_remove_sysfs: sysfs_remove_group(&pdev->dev.kobj, &iwl4965_attribute_group); - out_unset_hw_settings: - iwl4965_unset_hw_setting(priv); + out_unset_hw_params: + iwl4965_unset_hw_params(priv); out_iounmap: pci_iounmap(pdev, priv->hw_base); out_pci_release_regions: @@ -7955,7 +7955,7 @@ static void __devexit iwl4965_pci_remove(struct pci_dev *pdev) iwl4965_rx_queue_free(priv, &priv->rxq); iwl4965_hw_txq_ctx_free(priv); - iwl4965_unset_hw_setting(priv); + iwl4965_unset_hw_params(priv); iwlcore_clear_stations_table(priv); -- cgit v1.2.1 From ec35cf2afb0d807c39188e3a9962ffa51f603024 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Tue, 15 Apr 2008 16:01:39 -0700 Subject: iwlwifi: support different num of tx and rx antennas This patch adds infrastructure for supporting different number of tx and rx antennas Signed-off-by: Tomas Winkler Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965-commands.h | 9 ++++----- drivers/net/wireless/iwlwifi/iwl-4965.c | 7 +++++-- drivers/net/wireless/iwlwifi/iwl-4965.h | 7 +++++-- 3 files changed, 14 insertions(+), 9 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h index 65cd8ae363b4..7aa7f0be8963 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h @@ -269,11 +269,10 @@ struct iwl_cmd_header { * 10 B active, A inactive * 11 Both active */ -#define RATE_MCS_ANT_A_POS 14 -#define RATE_MCS_ANT_B_POS 15 -#define RATE_MCS_ANT_A_MSK 0x4000 -#define RATE_MCS_ANT_B_MSK 0x8000 -#define RATE_MCS_ANT_AB_MSK 0xc000 +#define RATE_MCS_ANT_POS 14 +#define RATE_MCS_ANT_A_MSK 0x04000 +#define RATE_MCS_ANT_B_MSK 0x08000 +#define RATE_MCS_ANT_AB_MSK 0x0C000 /** diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index a1e91dbb92bb..e647be7608fc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -410,7 +410,7 @@ void iwl4965_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, int rate_index; control->antenna_sel_tx = - ((rate_n_flags & RATE_MCS_ANT_AB_MSK) >> RATE_MCS_ANT_A_POS); + ((rate_n_flags & RATE_MCS_ANT_AB_MSK) >> RATE_MCS_ANT_POS); if (rate_n_flags & RATE_MCS_HT_MSK) control->flags |= IEEE80211_TXCTL_OFDM_HT; if (rate_n_flags & RATE_MCS_GF_MSK) @@ -2040,7 +2040,10 @@ int iwl4965_hw_set_hw_params(struct iwl_priv *priv) priv->hw_params.max_stations = IWL4965_STATION_COUNT; priv->hw_params.bcast_sta_id = IWL4965_BROADCAST_ID; - priv->hw_params.tx_ant_num = 2; + priv->hw_params.tx_chains_num = 2; + priv->hw_params.rx_chains_num = 2; + priv->hw_params.valid_tx_ant = (IWL_ANTENNA_MAIN | IWL_ANTENNA_AUX); + priv->hw_params.valid_rx_ant = (IWL_ANTENNA_MAIN | IWL_ANTENNA_AUX); return 0; } diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index c127c91010b4..cf909e86ed29 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -580,11 +580,14 @@ struct iwl4965_ibss_seq { struct iwl_hw_params { u16 max_txq_num; u16 tx_cmd_len; - u16 tx_ant_num; + u8 tx_chains_num; + u8 rx_chains_num; + u8 valid_tx_ant; + u8 valid_rx_ant; u16 max_rxq_size; + u16 max_rxq_log; u32 rx_buf_size; u32 max_pkt_size; - u16 max_rxq_log; u8 max_stations; u8 bcast_sta_id; }; -- cgit v1.2.1 From 66c73db7c6f7672e40c0bb1d2689f2d0d0922aad Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Tue, 15 Apr 2008 16:01:40 -0700 Subject: iwlwifi: move the creation of LQ host command to iwlcore This patch moves creation of LQ host command to iwlcore from previous location in rate scaling. Signed-off-by: Tomas Winkler Signed-off-by: Ron Rindjunsky Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965-commands.h | 14 ++--- drivers/net/wireless/iwlwifi/iwl-4965-rs.c | 65 ++++-------------------- drivers/net/wireless/iwlwifi/iwl-4965.c | 2 +- drivers/net/wireless/iwlwifi/iwl-core.h | 3 +- drivers/net/wireless/iwlwifi/iwl-sta.c | 48 +++++++++++++++++ 5 files changed, 67 insertions(+), 65 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h index 7aa7f0be8963..3bcd107e2d71 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h @@ -1413,11 +1413,11 @@ struct iwl4965_txpowertable_cmd { /** - * struct iwl4965_link_qual_general_params + * struct iwl_link_qual_general_params * * Used in REPLY_TX_LINK_QUALITY_CMD */ -struct iwl4965_link_qual_general_params { +struct iwl_link_qual_general_params { u8 flags; /* No entries at or above this (driver chosen) index contain MIMO */ @@ -1444,11 +1444,11 @@ struct iwl4965_link_qual_general_params { } __attribute__ ((packed)); /** - * struct iwl4965_link_qual_agg_params + * struct iwl_link_qual_agg_params * * Used in REPLY_TX_LINK_QUALITY_CMD */ -struct iwl4965_link_qual_agg_params { +struct iwl_link_qual_agg_params { /* Maximum number of uSec in aggregation. * Driver should set this to 4000 (4 milliseconds). */ @@ -1658,14 +1658,14 @@ struct iwl4965_link_qual_agg_params { * legacy), and then repeat the search process. * */ -struct iwl4965_link_quality_cmd { +struct iwl_link_quality_cmd { /* Index of destination/recipient station in uCode's station table */ u8 sta_id; u8 reserved1; __le16 control; /* not used */ - struct iwl4965_link_qual_general_params general_params; - struct iwl4965_link_qual_agg_params agg_params; + struct iwl_link_qual_general_params general_params; + struct iwl_link_qual_agg_params agg_params; /* * Rate info; when using rate-scaling, Tx command's initial_rate_index diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c index 315b0433801e..b608e1ca8b40 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c @@ -150,7 +150,7 @@ struct iwl4965_lq_sta { u16 active_mimo_rate; u16 active_rate_basic; - struct iwl4965_link_quality_cmd lq; + struct iwl_link_quality_cmd lq; struct iwl4965_scale_tbl_info lq_info[LQ_SIZE]; /* "active", "search" */ #ifdef CONFIG_IWL4965_HT struct iwl4965_traffic_load load[TID_MAX_LOAD_COUNT]; @@ -173,7 +173,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, struct sta_info *sta); static void rs_fill_link_cmd(struct iwl4965_lq_sta *lq_sta, struct iwl4965_rate *tx_mcs, - struct iwl4965_link_quality_cmd *tbl); + struct iwl_link_quality_cmd *tbl); #ifdef CONFIG_MAC80211_DEBUGFS @@ -230,58 +230,11 @@ static s32 expected_tpt_mimo40MHzSGI[IWL_RATE_COUNT] = { 0, 0, 0, 0, 131, 131, 191, 222, 242, 270, 284, 289, 293 }; -static int iwl4965_lq_sync_callback(struct iwl_priv *priv, - struct iwl_cmd *cmd, struct sk_buff *skb) -{ - /*We didn't cache the SKB; let the caller free it */ - return 1; -} - static inline u8 iwl4965_rate_get_rate(u32 rate_n_flags) { return (u8)(rate_n_flags & 0xFF); } -static int rs_send_lq_cmd(struct iwl_priv *priv, - struct iwl4965_link_quality_cmd *lq, u8 flags) -{ -#ifdef CONFIG_IWLWIFI_DEBUG - int i; -#endif - struct iwl_host_cmd cmd = { - .id = REPLY_TX_LINK_QUALITY_CMD, - .len = sizeof(struct iwl4965_link_quality_cmd), - .meta.flags = flags, - .data = lq, - }; - - if ((lq->sta_id == 0xFF) && - (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)) - return -EINVAL; - - if (lq->sta_id == 0xFF) - lq->sta_id = IWL_AP_ID; - - IWL_DEBUG_RATE("lq station id 0x%x\n", lq->sta_id); - IWL_DEBUG_RATE("lq dta 0x%X 0x%X\n", - lq->general_params.single_stream_ant_msk, - lq->general_params.dual_stream_ant_msk); -#ifdef CONFIG_IWLWIFI_DEBUG - for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) - IWL_DEBUG_RATE("lq index %d 0x%X\n", - i, lq->rs_table[i].rate_n_flags); -#endif - - if (flags & CMD_ASYNC) - cmd.meta.u.callback = iwl4965_lq_sync_callback; - - if (iwl_is_associated(priv) && priv->assoc_station_added && - priv->lq_mngr.lq_ready) - return iwl_send_cmd(priv, &cmd); - - return 0; -} - static void rs_rate_scale_clear_window(struct iwl4965_rate_scale_data *window) { window->data = 0; @@ -819,7 +772,7 @@ static void rs_tx_status(void *priv_rate, struct net_device *dev, u8 retries; int rs_index, index = 0; struct iwl4965_lq_sta *lq_sta; - struct iwl4965_link_quality_cmd *table; + struct iwl_link_quality_cmd *table; struct sta_info *sta; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct iwl_priv *priv = (struct iwl_priv *)priv_rate; @@ -1879,7 +1832,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, if (update_lq) { rs_mcs_from_tbl(&mcs_rate, tbl, index, is_green); rs_fill_link_cmd(lq_sta, &mcs_rate, &lq_sta->lq); - rs_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); + iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); } goto out; @@ -2044,7 +1997,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, if (update_lq) { rs_mcs_from_tbl(&mcs_rate, tbl, index, is_green); rs_fill_link_cmd(lq_sta, &mcs_rate, &lq_sta->lq); - rs_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); + iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); } /* Should we stay with this modulation mode, or search for a new one? */ @@ -2084,7 +2037,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, tbl->current_rate.rate_n_flags, index); rs_fill_link_cmd(lq_sta, &tbl->current_rate, &lq_sta->lq); - rs_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); + iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); } /* If the "active" (non-search) mode was legacy, @@ -2197,7 +2150,7 @@ static void rs_initialize_lq(struct iwl_priv *priv, tbl->current_rate.rate_n_flags = mcs_rate.rate_n_flags; rs_get_expected_tpt_table(lq_sta, tbl); rs_fill_link_cmd(lq_sta, &mcs_rate, &lq_sta->lq); - rs_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); + iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); out: return; } @@ -2392,7 +2345,7 @@ static void rs_rate_init(void *priv_rate, void *priv_sta, static void rs_fill_link_cmd(struct iwl4965_lq_sta *lq_sta, struct iwl4965_rate *tx_mcs, - struct iwl4965_link_quality_cmd *lq_cmd) + struct iwl_link_quality_cmd *lq_cmd) { int index = 0; int rate_idx; @@ -2591,7 +2544,7 @@ static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file, if (lq_sta->dbg_fixed.rate_n_flags) { rs_fill_link_cmd(lq_sta, &lq_sta->dbg_fixed, &lq_sta->lq); - rs_send_lq_cmd(lq_sta->drv, &lq_sta->lq, CMD_ASYNC); + iwl_send_lq_cmd(lq_sta->drv, &lq_sta->lq, CMD_ASYNC); } return count; diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index e647be7608fc..8c8d7cffccfb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -4484,7 +4484,7 @@ static int iwl4965_tx_queue_agg_enable(struct iwl_priv *priv, int txq_id, void iwl4965_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap) { int i, r; - struct iwl4965_link_quality_cmd link_cmd = { + struct iwl_link_quality_cmd link_cmd = { .reserved1 = 0, }; u16 rate_flags; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 7791d2bd9645..0ff0978d6801 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -231,5 +231,6 @@ enum iwlcore_card_notify { int iwlcore_low_level_notify(struct iwl_priv *priv, enum iwlcore_card_notify notify); extern int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags); - +int iwl_send_lq_cmd(struct iwl_priv *priv, + struct iwl_link_quality_cmd *lq, u8 flags); #endif /* __iwl_core_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index bc2e603efd28..0ccd1567f51f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -303,3 +303,51 @@ int iwl_set_dynamic_key(struct iwl_priv *priv, return ret; } +#ifdef CONFIG_IWLWIFI_DEBUG +static void iwl_dump_lq_cmd(struct iwl_priv *priv, + struct iwl_link_quality_cmd *lq) +{ + int i; + IWL_DEBUG_RATE("lq station id 0x%x\n", lq->sta_id); + IWL_DEBUG_RATE("lq dta 0x%X 0x%X\n", + lq->general_params.single_stream_ant_msk, + lq->general_params.dual_stream_ant_msk); + + for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) + IWL_DEBUG_RATE("lq index %d 0x%X\n", + i, lq->rs_table[i].rate_n_flags); +} +#else +static inline void iwl_dump_lq_cmd(struct iwl_priv *priv, + struct iwl_link_quality_cmd *lq) +{ +} +#endif + +int iwl_send_lq_cmd(struct iwl_priv *priv, + struct iwl_link_quality_cmd *lq, u8 flags) +{ + struct iwl_host_cmd cmd = { + .id = REPLY_TX_LINK_QUALITY_CMD, + .len = sizeof(struct iwl_link_quality_cmd), + .meta.flags = flags, + .data = lq, + }; + + if ((lq->sta_id == 0xFF) && + (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)) + return -EINVAL; + + if (lq->sta_id == 0xFF) + lq->sta_id = IWL_AP_ID; + + iwl_dump_lq_cmd(priv,lq); + + if (iwl_is_associated(priv) && priv->assoc_station_added && + priv->lq_mngr.lq_ready) + return iwl_send_cmd(priv, &cmd); + + return 0; +} +EXPORT_SYMBOL(iwl_send_lq_cmd); + -- cgit v1.2.1 From fed9017e03f23098137716bd6010772ac1aa8a80 Mon Sep 17 00:00:00 2001 From: Ron Rindjunsky Date: Tue, 15 Apr 2008 16:01:41 -0700 Subject: iwlwifi: move HW device registration This patch moves the HW device registration from the iwl-4965.c file, which implies a HW specific support, to a more general location. Signed-off-by: Ron Rindjunsky Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965.c | 10 +--------- drivers/net/wireless/iwlwifi/iwl-4965.h | 6 +++--- drivers/net/wireless/iwlwifi/iwl4965-base.c | 22 +++++++++++++++------- 3 files changed, 19 insertions(+), 19 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 8c8d7cffccfb..4a40109d4aa0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -4930,7 +4930,7 @@ static struct iwl_ops iwl4965_ops = { .utils = &iwl4965_hcmd_utils, }; -static struct iwl_cfg iwl4965_agn_cfg = { +struct iwl_cfg iwl4965_agn_cfg = { .name = "4965AGN", .fw_name = "iwlwifi-4965" IWL4965_UCODE_API ".ucode", .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, @@ -4938,14 +4938,6 @@ static struct iwl_cfg iwl4965_agn_cfg = { .mod_params = &iwl4965_mod_params, }; -struct pci_device_id iwl4965_hw_card_ids[] = { - {IWL_PCI_DEVICE(0x4229, PCI_ANY_ID, iwl4965_agn_cfg)}, - {IWL_PCI_DEVICE(0x4230, PCI_ANY_ID, iwl4965_agn_cfg)}, - {0} -}; - -MODULE_DEVICE_TABLE(pci, iwl4965_hw_card_ids); - module_param_named(antenna, iwl4965_mod_params.antenna, int, 0444); MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); module_param_named(disable, iwl4965_mod_params.disable, int, 0444); diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index cf909e86ed29..ddcbad59092b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -36,9 +36,6 @@ #include #include -/* Hardware specific file defines the PCI IDs table for that hardware module */ -extern struct pci_device_id iwl4965_hw_card_ids[]; - #define DRV_NAME "iwl4965" #include "iwl-rfkill.h" #include "iwl-eeprom.h" @@ -48,6 +45,9 @@ extern struct pci_device_id iwl4965_hw_card_ids[]; #include "iwl-debug.h" #include "iwl-led.h" +/* configuration for the iwl4965 */ +extern struct iwl_cfg iwl4965_agn_cfg; + /* Change firmware file name, using "-" and incrementing number, * *only* when uCode interface or architecture changes so that it * is not compatible with earlier drivers. diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index c71910df62aa..249af4156c13 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -8020,9 +8020,17 @@ static int iwl4965_pci_resume(struct pci_dev *pdev) * *****************************************************************************/ -static struct pci_driver iwl4965_driver = { +/* Hardware specific file defines the PCI IDs table for that hardware module */ +static struct pci_device_id iwl_hw_card_ids[] = { + {IWL_PCI_DEVICE(0x4229, PCI_ANY_ID, iwl4965_agn_cfg)}, + {IWL_PCI_DEVICE(0x4230, PCI_ANY_ID, iwl4965_agn_cfg)}, + {0} +}; +MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids); + +static struct pci_driver iwl_driver = { .name = DRV_NAME, - .id_table = iwl4965_hw_card_ids, + .id_table = iwl_hw_card_ids, .probe = iwl4965_pci_probe, .remove = __devexit_p(iwl4965_pci_remove), #ifdef CONFIG_PM @@ -8044,13 +8052,13 @@ static int __init iwl4965_init(void) return ret; } - ret = pci_register_driver(&iwl4965_driver); + ret = pci_register_driver(&iwl_driver); if (ret) { IWL_ERROR("Unable to initialize PCI module\n"); goto error_register; } #ifdef CONFIG_IWLWIFI_DEBUG - ret = driver_create_file(&iwl4965_driver.driver, &driver_attr_debug_level); + ret = driver_create_file(&iwl_driver.driver, &driver_attr_debug_level); if (ret) { IWL_ERROR("Unable to create driver sysfs file\n"); goto error_debug; @@ -8061,7 +8069,7 @@ static int __init iwl4965_init(void) #ifdef CONFIG_IWLWIFI_DEBUG error_debug: - pci_unregister_driver(&iwl4965_driver); + pci_unregister_driver(&iwl_driver); #endif error_register: iwl4965_rate_control_unregister(); @@ -8071,9 +8079,9 @@ error_register: static void __exit iwl4965_exit(void) { #ifdef CONFIG_IWLWIFI_DEBUG - driver_remove_file(&iwl4965_driver.driver, &driver_attr_debug_level); + driver_remove_file(&iwl_driver.driver, &driver_attr_debug_level); #endif - pci_unregister_driver(&iwl4965_driver); + pci_unregister_driver(&iwl_driver); iwl4965_rate_control_unregister(); } -- cgit v1.2.1 From 3c424c281a9887733ab936477c327cdb2a7ae367 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Tue, 15 Apr 2008 16:01:42 -0700 Subject: iwlwifi: introduce host commands callbacks This patch adds place holder for host command handlers for supporting different implementations per HW Signed-off-by: Tomas Winkler Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965.c | 5 +++++ drivers/net/wireless/iwlwifi/iwl-core.h | 3 +++ 2 files changed, 8 insertions(+) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 4a40109d4aa0..9fa803ad9cf7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -4905,6 +4905,10 @@ void iwl4965_hw_cancel_deferred_work(struct iwl_priv *priv) cancel_delayed_work(&priv->init_alive_start); } + +static struct iwl_hcmd_ops iwl4965_hcmd = { +}; + static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = { .enqueue_hcmd = iwl4965_enqueue_hcmd, }; @@ -4927,6 +4931,7 @@ static struct iwl_lib_ops iwl4965_lib = { static struct iwl_ops iwl4965_ops = { .lib = &iwl4965_lib, + .hcmd = &iwl4965_hcmd, .utils = &iwl4965_hcmd_utils, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 0ff0978d6801..64bab66d05d8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -82,6 +82,8 @@ struct iwl_cmd; #define IWL_SKU_A 0x2 #define IWL_SKU_N 0x8 +struct iwl_hcmd_ops { +}; struct iwl_hcmd_utils_ops { int (*enqueue_hcmd)(struct iwl_priv *priv, struct iwl_host_cmd *cmd); }; @@ -111,6 +113,7 @@ struct iwl_lib_ops { struct iwl_ops { const struct iwl_lib_ops *lib; + const struct iwl_hcmd_ops *hcmd; const struct iwl_hcmd_utils_ops *utils; }; -- cgit v1.2.1 From 7e8c519ecbd44cbe017f1749eb1f0f87d86d6ea2 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Tue, 15 Apr 2008 16:01:43 -0700 Subject: iwlwifi: move rxon associated command to hcmd This patch run rxon associated command from hcmd handler Signed-off-by: Tomas Winkler Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965.c | 41 +++++++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-core.c | 1 + drivers/net/wireless/iwlwifi/iwl-core.h | 7 +++++ drivers/net/wireless/iwlwifi/iwl4965-base.c | 43 ++--------------------------- 4 files changed, 51 insertions(+), 41 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 9fa803ad9cf7..2e747129f6b0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2884,6 +2884,46 @@ out: return ret; } +static int iwl4965_send_rxon_assoc(struct iwl_priv *priv) +{ + int ret = 0; + struct iwl4965_rxon_assoc_cmd rxon_assoc; + const struct iwl4965_rxon_cmd *rxon1 = &priv->staging_rxon; + const struct iwl4965_rxon_cmd *rxon2 = &priv->active_rxon; + + if ((rxon1->flags == rxon2->flags) && + (rxon1->filter_flags == rxon2->filter_flags) && + (rxon1->cck_basic_rates == rxon2->cck_basic_rates) && + (rxon1->ofdm_ht_single_stream_basic_rates == + rxon2->ofdm_ht_single_stream_basic_rates) && + (rxon1->ofdm_ht_dual_stream_basic_rates == + rxon2->ofdm_ht_dual_stream_basic_rates) && + (rxon1->rx_chain == rxon2->rx_chain) && + (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) { + IWL_DEBUG_INFO("Using current RXON_ASSOC. Not resending.\n"); + return 0; + } + + rxon_assoc.flags = priv->staging_rxon.flags; + rxon_assoc.filter_flags = priv->staging_rxon.filter_flags; + rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates; + rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates; + rxon_assoc.reserved = 0; + rxon_assoc.ofdm_ht_single_stream_basic_rates = + priv->staging_rxon.ofdm_ht_single_stream_basic_rates; + rxon_assoc.ofdm_ht_dual_stream_basic_rates = + priv->staging_rxon.ofdm_ht_dual_stream_basic_rates; + rxon_assoc.rx_chain_select_flags = priv->staging_rxon.rx_chain; + + ret = iwl_send_cmd_pdu_async(priv, REPLY_RXON_ASSOC, + sizeof(rxon_assoc), &rxon_assoc, NULL); + if (ret) + return ret; + + return ret; +} + + int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel) { int rc; @@ -4907,6 +4947,7 @@ void iwl4965_hw_cancel_deferred_work(struct iwl_priv *priv) static struct iwl_hcmd_ops iwl4965_hcmd = { + .rxon_assoc = iwl4965_send_rxon_assoc, }; static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = { diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 88d62462ed4a..2dfd982d7d1f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -289,3 +289,4 @@ int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags) return iwl_send_cmd(priv, &cmd); } EXPORT_SYMBOL(iwl_send_statistics_request); + diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 64bab66d05d8..e22563ad352d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -83,6 +83,7 @@ struct iwl_cmd; #define IWL_SKU_N 0x8 struct iwl_hcmd_ops { + int (*rxon_assoc)(struct iwl_priv *priv); }; struct iwl_hcmd_utils_ops { int (*enqueue_hcmd)(struct iwl_priv *priv, struct iwl_host_cmd *cmd); @@ -236,4 +237,10 @@ int iwlcore_low_level_notify(struct iwl_priv *priv, extern int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags); int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_link_quality_cmd *lq, u8 flags); + +static inline int iwl_send_rxon_assoc(struct iwl_priv *priv) +{ + return priv->cfg->ops->hcmd->rxon_assoc(priv); +} + #endif /* __iwl_core_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 249af4156c13..745b462103bd 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -749,45 +749,6 @@ static int iwl4965_full_rxon_required(struct iwl_priv *priv) return 0; } -static int iwl4965_send_rxon_assoc(struct iwl_priv *priv) -{ - int ret = 0; - struct iwl4965_rxon_assoc_cmd rxon_assoc; - const struct iwl4965_rxon_cmd *rxon1 = &priv->staging_rxon; - const struct iwl4965_rxon_cmd *rxon2 = &priv->active_rxon; - - if ((rxon1->flags == rxon2->flags) && - (rxon1->filter_flags == rxon2->filter_flags) && - (rxon1->cck_basic_rates == rxon2->cck_basic_rates) && - (rxon1->ofdm_ht_single_stream_basic_rates == - rxon2->ofdm_ht_single_stream_basic_rates) && - (rxon1->ofdm_ht_dual_stream_basic_rates == - rxon2->ofdm_ht_dual_stream_basic_rates) && - (rxon1->rx_chain == rxon2->rx_chain) && - (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) { - IWL_DEBUG_INFO("Using current RXON_ASSOC. Not resending.\n"); - return 0; - } - - rxon_assoc.flags = priv->staging_rxon.flags; - rxon_assoc.filter_flags = priv->staging_rxon.filter_flags; - rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates; - rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates; - rxon_assoc.reserved = 0; - rxon_assoc.ofdm_ht_single_stream_basic_rates = - priv->staging_rxon.ofdm_ht_single_stream_basic_rates; - rxon_assoc.ofdm_ht_dual_stream_basic_rates = - priv->staging_rxon.ofdm_ht_dual_stream_basic_rates; - rxon_assoc.rx_chain_select_flags = priv->staging_rxon.rx_chain; - - ret = iwl_send_cmd_pdu_async(priv, REPLY_RXON_ASSOC, - sizeof(rxon_assoc), &rxon_assoc, NULL); - if (ret) - return ret; - - return ret; -} - /** * iwl4965_commit_rxon - commit staging_rxon to hardware * @@ -819,7 +780,7 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv) * iwl4965_rxon_assoc_cmd which is used to reconfigure filter * and other flags for the current radio configuration. */ if (!iwl4965_full_rxon_required(priv)) { - rc = iwl4965_send_rxon_assoc(priv); + rc = iwl_send_rxon_assoc(priv); if (rc) { IWL_ERROR("Error setting RXON_ASSOC " "configuration (%d).\n", rc); @@ -6756,7 +6717,7 @@ static void iwl4965_bss_info_changed(struct ieee80211_hw *hw, } } else if (changes && iwl_is_associated(priv) && priv->assoc_id) { IWL_DEBUG_MAC80211("Associated Changes %d\n", changes); - iwl4965_send_rxon_assoc(priv); + iwl_send_rxon_assoc(priv); } } -- cgit v1.2.1 From 77bab6024c69de781464c6ad094db6996d996938 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Tue, 15 Apr 2008 16:01:44 -0700 Subject: iwlwifi: Fix TKIP update key and get_free_ucode_key This patch fixes a bug in update_tkip_key: only one key needs to be allocated in uCode, every time it is updated, the old one will be overwritten Signed-off-by: Emmanuel Grumbach Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-sta.c | 4 +++- drivers/net/wireless/iwlwifi/iwl4965-base.c | 2 -- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 0ccd1567f51f..e4fdfaa2b9b2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -43,7 +43,7 @@ int iwl_get_free_ucode_key_index(struct iwl_priv *priv) int i; for (i = 0; i < STA_KEY_MAX_NUM; i++) - if (test_and_set_bit(i, &priv->ucode_key_table)) + if (!test_and_set_bit(i, &priv->ucode_key_table)) return i; return -1; @@ -243,6 +243,8 @@ static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv, priv->stations[sta_id].keyinfo.alg = keyconf->alg; priv->stations[sta_id].keyinfo.conf = keyconf; priv->stations[sta_id].keyinfo.keylen = 16; + priv->stations[sta_id].sta.key.key_offset = + iwl_get_free_ucode_key_index(priv); /* This copy is acutally not needed: we get the key with each TX */ memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, 16); diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 745b462103bd..0eb4220f035f 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -6810,8 +6810,6 @@ static void iwl4965_mac_update_tkip_key(struct ieee80211_hw *hw, spin_lock_irqsave(&priv->sta_lock, flags); - priv->stations[sta_id].sta.key.key_offset = - iwl_get_free_ucode_key_index(priv); priv->stations[sta_id].sta.key.key_flags = key_flags; priv->stations[sta_id].sta.key.tkip_rx_tsc_byte2 = (u8) iv32; -- cgit v1.2.1 From dfe7d458408188718089f41d0e2330fed13697e2 Mon Sep 17 00:00:00 2001 From: Ron Rindjunsky Date: Tue, 15 Apr 2008 16:01:45 -0700 Subject: iwlwifi: arrange max number of Tx queues This patch increases the max possible number of Tx queues, but leaves current used number of queues as HW dependent Signed-off-by: Ron Rindjunsky Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945-hw.h | 2 +- drivers/net/wireless/iwlwifi/iwl-3945.h | 2 ++ drivers/net/wireless/iwlwifi/iwl-4965-hw.h | 10 +++++----- drivers/net/wireless/iwlwifi/iwl-4965.c | 8 ++++---- drivers/net/wireless/iwlwifi/iwl-4965.h | 2 ++ drivers/net/wireless/iwlwifi/iwl3945-base.c | 6 +++--- 6 files changed, 17 insertions(+), 13 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h index 368da9852aab..ad612a8719f4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h @@ -456,7 +456,7 @@ struct iwl3945_eeprom { /* Size of uCode instruction memory in bootstrap state machine */ #define IWL_MAX_BSM_SIZE ALM_RTC_INST_SIZE -#define IWL_MAX_NUM_QUEUES 8 +#define IWL39_MAX_NUM_QUEUES 8 static inline int iwl3945_hw_valid_rtc_data_addr(u32 addr) { diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 3dc7f0fbf02f..45c1c5533bf0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -687,6 +687,8 @@ enum { #endif +#define IWL_MAX_NUM_QUEUES IWL39_MAX_NUM_QUEUES + struct iwl3945_priv { /* ieee device used by generic ieee processing code */ diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h index 3d098da25fc9..1a66b508a8ea 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h @@ -1385,10 +1385,10 @@ static inline __le32 iwl4965_hw_set_rate_n_flags(u8 rate, u16 flags) * up to 7 DMA channels (FIFOs). Each Tx queue is supported by a circular array * in DRAM containing 256 Transmit Frame Descriptors (TFDs). */ -#define IWL4965_MAX_WIN_SIZE 64 -#define IWL4965_QUEUE_SIZE 256 -#define IWL4965_NUM_FIFOS 7 -#define IWL_MAX_NUM_QUEUES 16 +#define IWL4965_MAX_WIN_SIZE 64 +#define IWL4965_QUEUE_SIZE 256 +#define IWL4965_NUM_FIFOS 7 +#define IWL4965_MAX_NUM_QUEUES 16 /** @@ -1553,7 +1553,7 @@ struct iwl4965_sched_queue_byte_cnt_tbl { */ struct iwl4965_shared { struct iwl4965_sched_queue_byte_cnt_tbl - queues_byte_cnt_tbls[IWL_MAX_NUM_QUEUES]; + queues_byte_cnt_tbls[IWL4965_MAX_NUM_QUEUES]; __le32 rb_closed; /* __le32 rb_closed_stts_rb_num:12; */ diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 2e747129f6b0..b072523c63ee 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -46,7 +46,7 @@ /* module parameters */ static struct iwl_mod_params iwl4965_mod_params = { - .num_of_queues = IWL_MAX_NUM_QUEUES, + .num_of_queues = IWL4965_MAX_NUM_QUEUES, .enable_qos = 1, .amsdu_size_8K = 1, /* the rest are 0 by default */ @@ -2021,10 +2021,10 @@ int iwl4965_alive_notify(struct iwl_priv *priv) int iwl4965_hw_set_hw_params(struct iwl_priv *priv) { - if ((priv->cfg->mod_params->num_of_queues > IWL_MAX_NUM_QUEUES) || + if ((priv->cfg->mod_params->num_of_queues > IWL4965_MAX_NUM_QUEUES) || (priv->cfg->mod_params->num_of_queues < IWL_MIN_NUM_QUEUES)) { IWL_ERROR("invalid queues_num, should be between %d and %d\n", - IWL_MIN_NUM_QUEUES, IWL_MAX_NUM_QUEUES); + IWL_MIN_NUM_QUEUES, IWL4965_MAX_NUM_QUEUES); return -EINVAL; } @@ -4362,7 +4362,7 @@ static void iwl4965_rx_reply_compressed_ba(struct iwl_priv *priv, * (in Tx queue's circular buffer) of first TFD/frame in window */ u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn); - if (scd_flow >= ARRAY_SIZE(priv->txq)) { + if (scd_flow >= priv->hw_params.max_txq_num) { IWL_ERROR("BUG_ON scd_flow is bigger than number of queues"); return; } diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index ddcbad59092b..9ed13cb0a2a9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -941,6 +941,8 @@ enum { #endif +#define IWL_MAX_NUM_QUEUES 20 /* FIXME: do dynamic allocation */ + struct iwl_priv { /* ieee device used by generic ieee processing code */ diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 29a9ecdcbf35..1a5678fe4224 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -70,7 +70,7 @@ static int iwl3945_param_disable; /* def: 0 = enable radio */ static int iwl3945_param_antenna; /* def: 0 = both antennas (use diversity) */ int iwl3945_param_hwcrypto; /* def: 0 = use software encryption */ static int iwl3945_param_qos_enable = 1; /* def: 1 = use quality of service */ -int iwl3945_param_queues_num = IWL_MAX_NUM_QUEUES; /* def: 8 Tx queues */ +int iwl3945_param_queues_num = IWL39_MAX_NUM_QUEUES; /* def: 8 Tx queues */ /* * module name, copyright, version, etc. @@ -7974,10 +7974,10 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e iwl3945_hw_ops.hw_scan = NULL; } - if ((iwl3945_param_queues_num > IWL_MAX_NUM_QUEUES) || + if ((iwl3945_param_queues_num > IWL39_MAX_NUM_QUEUES) || (iwl3945_param_queues_num < IWL_MIN_NUM_QUEUES)) { IWL_ERROR("invalid queues_num, should be between %d and %d\n", - IWL_MIN_NUM_QUEUES, IWL_MAX_NUM_QUEUES); + IWL_MIN_NUM_QUEUES, IWL39_MAX_NUM_QUEUES); err = -EINVAL; goto out; } -- cgit v1.2.1 From 59003835020ed696e941df2f8a50210bdc6e246c Mon Sep 17 00:00:00 2001 From: Mohamed Abbas Date: Tue, 15 Apr 2008 16:01:46 -0700 Subject: iwlwifi: fix unload warning and error This patch fix the error we get when unload the driver, No space for Tx. The cause of this problem is related to receiving late SW rfkill from rfkill subsystem during the driver teardown causing this error. Signed-off-by: Mohamed Abbas Signed-off-by: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-rfkill.c | 3 +++ drivers/net/wireless/iwlwifi/iwl4965-base.c | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.c b/drivers/net/wireless/iwlwifi/iwl-rfkill.c index 8f38c24491cd..5980a5621cb8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rfkill.c +++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.c @@ -47,6 +47,9 @@ static int iwl_rfkill_soft_rf_kill(void *data, enum rfkill_state state) if (!priv->rfkill_mngr.rfkill) return 0; + if (test_bit(STATUS_EXIT_PENDING, &priv->status)) + return 0; + IWL_DEBUG_RF_KILL("we recieved soft RFKILL set to state %d\n", state); mutex_lock(&priv->mutex); diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 0eb4220f035f..dae881e47293 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -2427,7 +2427,8 @@ void iwl4965_radio_kill_sw(struct iwl_priv *priv, int disable_radio) CSR_UCODE_SW_BIT_RFKILL); spin_unlock_irqrestore(&priv->lock, flags); /* call the host command only if no hw rf-kill set */ - if (!test_bit(STATUS_RF_KILL_HW, &priv->status)) + if (!test_bit(STATUS_RF_KILL_HW, &priv->status) && + iwl_is_ready(priv)) iwl4965_send_card_state(priv, CARD_STATE_CMD_DISABLE, 0); -- cgit v1.2.1 From fcc76c6b3367e654377d61403f4945ac85c4b651 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Tue, 15 Apr 2008 16:01:47 -0700 Subject: iwlwifi: Use HW acceleration decryption by default This patch reverses the hw_crypto logic and makes HW crypto a default. Giving swcrypto=1 as parameter to the module disables HW crypto. Signed-off-by: Emmanuel Grumbach Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965.c | 7 +++---- drivers/net/wireless/iwlwifi/iwl-core.h | 2 +- drivers/net/wireless/iwlwifi/iwl4965-base.c | 4 ++-- 3 files changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index b072523c63ee..17f629fb96ff 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -3691,7 +3691,7 @@ static void iwl4965_handle_data_packet(struct iwl_priv *priv, int is_data, stats->flag = 0; hdr = (struct ieee80211_hdr *)rxb->skb->data; - if (priv->cfg->mod_params->hw_crypto) + if (!priv->cfg->mod_params->sw_crypto) iwl4965_set_decrypted_flag(priv, rxb->skb, ampdu_status, stats); if (priv->add_radiotap) @@ -4988,9 +4988,8 @@ module_param_named(antenna, iwl4965_mod_params.antenna, int, 0444); MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); module_param_named(disable, iwl4965_mod_params.disable, int, 0444); MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])"); -module_param_named(hwcrypto, iwl4965_mod_params.hw_crypto, int, 0444); -MODULE_PARM_DESC(hwcrypto, - "using hardware crypto engine (default 0 [software])\n"); +module_param_named(swcrypto, iwl4965_mod_params.sw_crypto, int, 0444); +MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])\n"); module_param_named(debug, iwl4965_mod_params.debug, int, 0444); MODULE_PARM_DESC(debug, "debug output mask"); module_param_named( diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index e22563ad352d..7193d97630dc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -120,7 +120,7 @@ struct iwl_ops { struct iwl_mod_params { int disable; /* def: 0 = enable radio */ - int hw_crypto; /* def: 0 = using software encryption */ + int sw_crypto; /* def: 0 = using hardware encryption */ int debug; /* def: 0 = minimal debug log messages */ int disable_hw_scan; /* def: 0 = use h/w scan */ int num_of_queues; /* def: HW dependent */ diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index dae881e47293..d7e2358a213a 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -835,7 +835,7 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv) le16_to_cpu(priv->staging_rxon.channel), print_mac(mac, priv->staging_rxon.bssid_addr)); - iwl4965_set_rxon_hwcrypto(priv, priv->cfg->mod_params->hw_crypto); + iwl4965_set_rxon_hwcrypto(priv, !priv->cfg->mod_params->sw_crypto); /* Apply the new configuration */ rc = iwl_send_cmd_pdu(priv, REPLY_RXON, sizeof(struct iwl4965_rxon_cmd), &priv->staging_rxon); @@ -6840,7 +6840,7 @@ static int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, IWL_DEBUG_MAC80211("enter\n"); - if (!priv->cfg->mod_params->hw_crypto) { + if (priv->cfg->mod_params->sw_crypto) { IWL_DEBUG_MAC80211("leave - hwcrypto disabled\n"); return -EOPNOTSUPP; } -- cgit v1.2.1 From 136bfc798fe5378c7c1b5f5294abcfd1428438b3 Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Wed, 16 Apr 2008 18:42:48 +0300 Subject: ath5k: Add RF2425 initvals *Add RF2425 initvals (still no rx/tx) This was on my laptop for a long time so it has to go out even if it still doesn't work, i hope i'll get my hands on an eeepc so i can work this out. base.c Changes-licensed-under: 3-clause-BSD rest Changes-licensed-under: ISC Signed-off-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/ath5k.h | 1 + drivers/net/wireless/ath5k/base.c | 1 + drivers/net/wireless/ath5k/hw.c | 20 +-- drivers/net/wireless/ath5k/initvals.c | 234 ++++++++++++++++++++++++++++++++++ drivers/net/wireless/ath5k/phy.c | 123 +++++++++++++++++- 5 files changed, 365 insertions(+), 14 deletions(-) (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath5k/ath5k.h b/drivers/net/wireless/ath5k/ath5k.h index b21830771ea5..d0d70b32e78b 100644 --- a/drivers/net/wireless/ath5k/ath5k.h +++ b/drivers/net/wireless/ath5k/ath5k.h @@ -142,6 +142,7 @@ enum ath5k_radio { AR5K_RF5112 = 2, AR5K_RF2413 = 3, AR5K_RF5413 = 4, + AR5K_RF2425 = 5, }; /* diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index 8862d245c82b..dfd202ddcff3 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -126,6 +126,7 @@ static struct ath5k_srev_name srev_names[] = { { "5414", AR5K_VERSION_VER, AR5K_SREV_VER_AR5414 }, { "5416", AR5K_VERSION_VER, AR5K_SREV_VER_AR5416 }, { "5418", AR5K_VERSION_VER, AR5K_SREV_VER_AR5418 }, + { "2425", AR5K_VERSION_VER, AR5K_SREV_VER_AR2425 }, { "xxxxx", AR5K_VERSION_VER, AR5K_SREV_UNKNOWN }, { "5110", AR5K_VERSION_RAD, AR5K_SREV_RAD_5110 }, { "5111", AR5K_VERSION_RAD, AR5K_SREV_RAD_5111 }, diff --git a/drivers/net/wireless/ath5k/hw.c b/drivers/net/wireless/ath5k/hw.c index ff579a223621..9e16bc09f1fd 100644 --- a/drivers/net/wireless/ath5k/hw.c +++ b/drivers/net/wireless/ath5k/hw.c @@ -204,15 +204,16 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) CHANNEL_2GHZ); /* Return on unsuported chips (unsupported eeprom etc) */ - if(srev >= AR5K_SREV_VER_AR5416){ + if (srev >= AR5K_SREV_VER_AR5416) { ATH5K_ERR(sc, "Device not yet supported.\n"); ret = -ENODEV; goto err_free; } /* Identify single chip solutions */ - if((srev <= AR5K_SREV_VER_AR5414) && - (srev >= AR5K_SREV_VER_AR2413)) { + if (((srev <= AR5K_SREV_VER_AR5414) && + (srev >= AR5K_SREV_VER_AR2413)) || + (srev == AR5K_SREV_VER_AR2425)) { ah->ah_single_chip = true; } else { ah->ah_single_chip = false; @@ -241,19 +242,19 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC1) { ah->ah_radio = AR5K_RF2413; ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A; - } else { + } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC2) { ah->ah_radio = AR5K_RF5413; if (ah->ah_mac_srev <= AR5K_SREV_VER_AR5424 && ah->ah_mac_srev >= AR5K_SREV_VER_AR2424) ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5424; - else if (ah->ah_mac_srev >= AR5K_SREV_VER_AR2425) - ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112; else ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A; - + } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5133) { + ah->ah_radio = AR5K_RF2425; + ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112; } ah->ah_phy = AR5K_PHY(0); @@ -391,7 +392,7 @@ static int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND | bus_flags); if (ret) { - ATH5K_ERR(ah->ah_sc, "failed to reset the MAC Chip + PCI\n"); + ATH5K_ERR(ah->ah_sc, "failed to reset the MAC Chip\n"); return -EIO; } @@ -655,7 +656,8 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, if (ah->ah_radio != AR5K_RF5111 && ah->ah_radio != AR5K_RF5112 && ah->ah_radio != AR5K_RF5413 && - ah->ah_radio != AR5K_RF2413) { + ah->ah_radio != AR5K_RF2413 && + ah->ah_radio != AR5K_RF2425) { ATH5K_ERR(ah->ah_sc, "invalid phy radio: %u\n", ah->ah_radio); return -EINVAL; diff --git a/drivers/net/wireless/ath5k/initvals.c b/drivers/net/wireless/ath5k/initvals.c index fdbab2f08178..04c84e9da89d 100644 --- a/drivers/net/wireless/ath5k/initvals.c +++ b/drivers/net/wireless/ath5k/initvals.c @@ -1282,6 +1282,213 @@ static const struct ath5k_ini_mode rf2413_ini_mode_end[] = { { 0xf3307ff0, 0xf3307ff0, 0xf3307ff0 } }, }; +/* Initial mode-specific settings for RF2425 (Written after ar5212_ini) */ +/* XXX: No dumps for turbog yet, so turbog is the same with g here with some + * minor tweaking based on dumps from other chips */ +static const struct ath5k_ini_mode rf2425_ini_mode_end[] = { + { AR5K_TXCFG, + /* g gTurbo */ + { 0x00000015, 0x00000015 } }, + { AR5K_USEC_5211, + { 0x12e013ab, 0x098813cf } }, + { AR5K_PHY_TURBO, + { 0x00000000, 0x00000003 } }, + { AR5K_PHY(10), + { 0x0a020001, 0x0a020001 } }, + { AR5K_PHY(13), + { 0x00000e0e, 0x00000e0e } }, + { AR5K_PHY(14), + { 0x0000000b, 0x0000000b } }, + { AR5K_PHY(17), + { 0x13721422, 0x13721422 } }, + { AR5K_PHY(18), + { 0x00199a65, 0x00199a65 } }, + { AR5K_PHY(20), + { 0x0c98b0da, 0x0c98b0da } }, + { AR5K_PHY_SIG, + { 0x7ec80d2e, 0x7ec80d2e } }, + { AR5K_PHY_AGCCOARSE, + { 0x3139605e, 0x3139605e } }, + { AR5K_PHY(27), + { 0x050cb081, 0x050cb081 } }, + { AR5K_PHY_RX_DELAY, + { 0x00000898, 0x000007d0 } }, + { AR5K_PHY_FRAME_CTL_5211, + { 0xf7b81000, 0xf7b81000 } }, + { AR5K_PHY_CCKTXCTL, + { 0x00000000, 0x00000000 } }, + { AR5K_PHY(642), + { 0xd03e6788, 0xd03e6788 } }, + { AR5K_PHY_GAIN_2GHZ, + { 0x0052c140, 0x0052c140 } }, + { 0xa21c, + { 0x1883800a, 0x1883800a } }, + { 0xa324, + { 0xa7cfa7cf, 0xa7cfa7cf } }, + { 0xa328, + { 0xa7cfa7cf, 0xa7cfa7cf } }, + { 0xa32c, + { 0xa7cfa7cf, 0xa7cfa7cf } }, + { 0xa330, + { 0xa7cfa7cf, 0xa7cfa7cf } }, + { 0xa334, + { 0xa7cfa7cf, 0xa7cfa7cf } }, + { AR5K_DCU_FP, + { 0x000003e0, 0x000003e0 } }, + { 0x8060, + { 0x0000000f, 0x0000000f } }, + { 0x809c, + { 0x00000000, 0x00000000 } }, + { 0x80a0, + { 0x00000000, 0x00000000 } }, + { 0x8118, + { 0x00000000, 0x00000000 } }, + { 0x811c, + { 0x00000000, 0x00000000 } }, + { 0x8120, + { 0x00000000, 0x00000000 } }, + { 0x8124, + { 0x00000000, 0x00000000 } }, + { 0x8128, + { 0x00000000, 0x00000000 } }, + { 0x812c, + { 0x00000000, 0x00000000 } }, + { 0x8130, + { 0x00000000, 0x00000000 } }, + { 0x8134, + { 0x00000000, 0x00000000 } }, + { 0x8138, + { 0x00000000, 0x00000000 } }, + { 0x813c, + { 0x00000000, 0x00000000 } }, + { 0x8140, + { 0x800003f9, 0x800003f9 } }, + { 0x8144, + { 0x00000000, 0x00000000 } }, + { AR5K_PHY_AGC, + { 0x00000000, 0x00000000 } }, + { AR5K_PHY(11), + { 0x0000a000, 0x0000a000 } }, + { AR5K_PHY(15), + { 0x00200400, 0x00200400 } }, + { AR5K_PHY(19), + { 0x1284233c, 0x1284233c } }, + { AR5K_PHY_SCR, + { 0x0000001f, 0x0000001f } }, + { AR5K_PHY_SLMT, + { 0x00000080, 0x00000080 } }, + { AR5K_PHY_SCAL, + { 0x0000000e, 0x0000000e } }, + { AR5K_PHY(86), + { 0x00081fff, 0x00081fff } }, + { AR5K_PHY(96), + { 0x00000000, 0x00000000 } }, + { AR5K_PHY(97), + { 0x02800000, 0x02800000 } }, + { AR5K_PHY(104), + { 0x00000000, 0x00000000 } }, + { AR5K_PHY(119), + { 0xfebadbe8, 0xfebadbe8 } }, + { AR5K_PHY(120), + { 0x00000000, 0x00000000 } }, + { AR5K_PHY(121), + { 0xaaaaaaaa, 0xaaaaaaaa } }, + { AR5K_PHY(122), + { 0x3c466478, 0x3c466478 } }, + { AR5K_PHY(123), + { 0x000000aa, 0x000000aa } }, + { AR5K_PHY_SCLOCK, + { 0x0000000c, 0x0000000c } }, + { AR5K_PHY_SDELAY, + { 0x000000ff, 0x000000ff } }, + { AR5K_PHY_SPENDING, + { 0x00000014, 0x00000014 } }, + { 0xa228, + { 0x000009b5, 0x000009b5 } }, + { AR5K_PHY_TXPOWER_RATE3, + { 0x20202020, 0x20202020 } }, + { AR5K_PHY_TXPOWER_RATE4, + { 0x20202020, 0x20202020 } }, + { 0xa23c, + { 0x93c889af, 0x93c889af } }, + { 0xa24c, + { 0x00000001, 0x00000001 } }, + { 0xa250, + { 0x0000a000, 0x0000a000 } }, + { 0xa254, + { 0x00000000, 0x00000000 } }, + { 0xa258, + { 0x0cc75380, 0x0cc75380 } }, + { 0xa25c, + { 0x0f0f0f01, 0x0f0f0f01 } }, + { 0xa260, + { 0x5f690f01, 0x5f690f01 } }, + { 0xa264, + { 0x00418a11, 0x00418a11 } }, + { 0xa268, + { 0x00000000, 0x00000000 } }, + { 0xa26c, + { 0x0c30c166, 0x0c30c166 } }, + { 0xa270, + { 0x00820820, 0x00820820 } }, + { 0xa274, + { 0x081a3caa, 0x081a3caa } }, + { 0xa278, + { 0x1ce739ce, 0x1ce739ce } }, + { 0xa27c, + { 0x051701ce, 0x051701ce } }, + { 0xa300, + { 0x16010000, 0x16010000 } }, + { 0xa304, + { 0x2c032402, 0x2c032402 } }, + { 0xa308, + { 0x48433e42, 0x48433e42 } }, + { 0xa30c, + { 0x5a0f500b, 0x5a0f500b } }, + { 0xa310, + { 0x6c4b624a, 0x6c4b624a } }, + { 0xa314, + { 0x7e8b748a, 0x7e8b748a } }, + { 0xa318, + { 0x96cf8ccb, 0x96cf8ccb } }, + { 0xa31c, + { 0xa34f9d0f, 0xa34f9d0f } }, + { 0xa320, + { 0xa7cfa58f, 0xa7cfa58f } }, + { 0xa348, + { 0x3fffffff, 0x3fffffff } }, + { 0xa34c, + { 0x3fffffff, 0x3fffffff } }, + { 0xa350, + { 0x3fffffff, 0x3fffffff } }, + { 0xa354, + { 0x0003ffff, 0x0003ffff } }, + { 0xa358, + { 0x79a8aa1f, 0x79a8aa1f } }, + { 0xa35c, + { 0x066c420f, 0x066c420f } }, + { 0xa360, + { 0x0f282207, 0x0f282207 } }, + { 0xa364, + { 0x17601685, 0x17601685 } }, + { 0xa368, + { 0x1f801104, 0x1f801104 } }, + { 0xa36c, + { 0x37a00c03, 0x37a00c03 } }, + { 0xa370, + { 0x3fc40883, 0x3fc40883 } }, + { 0xa374, + { 0x57c00803, 0x57c00803 } }, + { 0xa378, + { 0x5fd80682, 0x5fd80682 } }, + { 0xa37c, + { 0x7fe00482, 0x7fe00482 } }, + { 0xa380, + { 0x7f3c7bba, 0x7f3c7bba } }, + { 0xa384, + { 0xf3307ff0, 0xf3307ff0 } }, +}; + /* * Initial BaseBand Gain settings for RF5111/5112 (AR5210 comes with * RF5110 only so initial BB Gain settings are included in AR5K_AR5210_INI) @@ -1542,7 +1749,34 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel) ARRAY_SIZE(rf5112_ini_bbgain), rf5112_ini_bbgain, change_channel); + } else if (ah->ah_radio == AR5K_RF2425) { + + if (mode < 2) { + ATH5K_ERR(ah->ah_sc, + "unsupported channel mode: %d\n", mode); + return -EINVAL; + } + + /* Map b to g */ + if (mode == 2) + mode = 0; + else + mode = mode - 3; + + /* Override a setting from ar5212_ini */ + ath5k_hw_reg_write(ah, 0x018830c6, AR5K_PHY(648)); + + ath5k_hw_ini_mode_registers(ah, + ARRAY_SIZE(rf2425_ini_mode_end), + rf2425_ini_mode_end, mode); + + /* Baseband gain table */ + ath5k_hw_ini_registers(ah, + ARRAY_SIZE(rf5112_ini_bbgain), + rf5112_ini_bbgain, change_channel); + } + /* For AR5211 */ } else if (ah->ah_version == AR5K_AR5211) { diff --git a/drivers/net/wireless/ath5k/phy.c b/drivers/net/wireless/ath5k/phy.c index 890ecce8bedc..afd8689e5c03 100644 --- a/drivers/net/wireless/ath5k/phy.c +++ b/drivers/net/wireless/ath5k/phy.c @@ -669,6 +669,7 @@ static const struct ath5k_ini_rf rfregs_5413[] = { /* RF2413/2414 mode-specific init registers */ static const struct ath5k_ini_rf rfregs_2413[] = { { 1, AR5K_RF_BUFFER_CONTROL_4, + /* mode b mode g mode gTurbo */ { 0x00000020, 0x00000020, 0x00000020 } }, { 2, AR5K_RF_BUFFER_CONTROL_3, { 0x02001408, 0x02001408, 0x02001408 } }, @@ -736,6 +737,83 @@ static const struct ath5k_ini_rf rfregs_2413[] = { { 0x0000000e, 0x0000000e, 0x0000000e } }, }; +/* RF2425 mode-specific init registers */ +static const struct ath5k_ini_rf rfregs_2425[] = { + { 1, AR5K_RF_BUFFER_CONTROL_4, + /* mode g mode gTurbo */ + { 0x00000020, 0x00000020 } }, + { 2, AR5K_RF_BUFFER_CONTROL_3, + { 0x02001408, 0x02001408 } }, + { 3, AR5K_RF_BUFFER_CONTROL_6, + { 0x00e020c0, 0x00e020c0 } }, + { 6, AR5K_RF_BUFFER, + { 0x10000000, 0x10000000 } }, + { 6, AR5K_RF_BUFFER, + { 0x00000000, 0x00000000 } }, + { 6, AR5K_RF_BUFFER, + { 0x00000000, 0x00000000 } }, + { 6, AR5K_RF_BUFFER, + { 0x00000000, 0x00000000 } }, + { 6, AR5K_RF_BUFFER, + { 0x00000000, 0x00000000 } }, + { 6, AR5K_RF_BUFFER, + { 0x00000000, 0x00000000 } }, + { 6, AR5K_RF_BUFFER, + { 0x00000000, 0x00000000 } }, + { 6, AR5K_RF_BUFFER, + { 0x00000000, 0x00000000 } }, + { 6, AR5K_RF_BUFFER, + { 0x00000000, 0x00000000 } }, + { 6, AR5K_RF_BUFFER, + { 0x00000000, 0x00000000 } }, + { 6, AR5K_RF_BUFFER, + { 0x00000000, 0x00000000 } }, + { 6, AR5K_RF_BUFFER, + { 0x002a0000, 0x002a0000 } }, + { 6, AR5K_RF_BUFFER, + { 0x00000000, 0x00000000 } }, + { 6, AR5K_RF_BUFFER, + { 0x00000000, 0x00000000 } }, + { 6, AR5K_RF_BUFFER, + { 0x00100000, 0x00100000 } }, + { 6, AR5K_RF_BUFFER, + { 0x00020000, 0x00020000 } }, + { 6, AR5K_RF_BUFFER, + { 0x00730000, 0x00730000 } }, + { 6, AR5K_RF_BUFFER, + { 0x00f80000, 0x00f80000 } }, + { 6, AR5K_RF_BUFFER, + { 0x00e70000, 0x00e70000 } }, + { 6, AR5K_RF_BUFFER, + { 0x00140000, 0x00140000 } }, + { 6, AR5K_RF_BUFFER, + { 0x00910040, 0x00910040 } }, + { 6, AR5K_RF_BUFFER, + { 0x0007001a, 0x0007001a } }, + { 6, AR5K_RF_BUFFER, + { 0x00410000, 0x00410000 } }, + { 6, AR5K_RF_BUFFER, + { 0x00810060, 0x00810060 } }, + { 6, AR5K_RF_BUFFER, + { 0x00020803, 0x00020803 } }, + { 6, AR5K_RF_BUFFER, + { 0x00000000, 0x00000000 } }, + { 6, AR5K_RF_BUFFER, + { 0x00000000, 0x00000000 } }, + { 6, AR5K_RF_BUFFER, + { 0x00001660, 0x00001660 } }, + { 6, AR5K_RF_BUFFER, + { 0x00001688, 0x00001688 } }, + { 6, AR5K_RF_BUFFER_CONTROL_1, + { 0x00000001, 0x00000001 } }, + { 7, AR5K_RF_BUFFER, + { 0x00006400, 0x00006400 } }, + { 7, AR5K_RF_BUFFER, + { 0x00000800, 0x00000800 } }, + { 7, AR5K_RF_BUFFER_CONTROL_2, + { 0x0000000e, 0x0000000e } }, +}; + /* Initial RF Gain settings for RF5112 */ static const struct ath5k_ini_rfgain rfgain_5112[] = { /* 5Ghz 2Ghz */ @@ -1348,7 +1426,8 @@ static int ath5k_hw_rf5112_rfregs(struct ath5k_hw *ah, } /* - * Initialize RF5413/5414 + * Initialize RF5413/5414 and future chips + * (until we come up with a better solution) */ static int ath5k_hw_rf5413_rfregs(struct ath5k_hw *ah, struct ieee80211_channel *channel, unsigned int mode) @@ -1362,19 +1441,41 @@ static int ath5k_hw_rf5413_rfregs(struct ath5k_hw *ah, rf = ah->ah_rf_banks; - if (ah->ah_radio == AR5K_RF5413) { + switch (ah->ah_radio) { + case AR5K_RF5413: rf_ini = rfregs_5413; rf_size = ARRAY_SIZE(rfregs_5413); - } else if (ah->ah_radio == AR5K_RF2413) { + break; + case AR5K_RF2413: rf_ini = rfregs_2413; rf_size = ARRAY_SIZE(rfregs_2413); + if (mode < 2) { ATH5K_ERR(ah->ah_sc, "invalid channel mode: %i\n", mode); return -EINVAL; } + mode = mode - 2; - } else { + break; + case AR5K_RF2425: + rf_ini = rfregs_2425; + rf_size = ARRAY_SIZE(rfregs_2425); + + if (mode < 2) { + ATH5K_ERR(ah->ah_sc, + "invalid channel mode: %i\n", mode); + return -EINVAL; + } + + /* Map b to g */ + if (mode == 2) + mode = 0; + else + mode = mode - 3; + + break; + default: return -EINVAL; } @@ -1439,6 +1540,10 @@ int ath5k_hw_rfregs(struct ath5k_hw *ah, struct ieee80211_channel *channel, ah->ah_rf_banks_size = sizeof(rfregs_2413); func = ath5k_hw_rf5413_rfregs; break; + case AR5K_RF2425: + ah->ah_rf_banks_size = sizeof(rfregs_2425); + func = ath5k_hw_rf5413_rfregs; + break; default: return -EINVAL; } @@ -1482,6 +1587,11 @@ int ath5k_hw_rfgain(struct ath5k_hw *ah, unsigned int freq) size = ARRAY_SIZE(rfgain_2413); freq = 0; /* only 2Ghz */ break; + case AR5K_RF2425: + ath5k_rfg = rfgain_2413; + size = ARRAY_SIZE(rfgain_2413); + freq = 0; /* only 2Ghz */ + break; default: return -EINVAL; } @@ -2181,8 +2291,11 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, * transmit anything if we call * this funtion, so we skip it * until we fix txpower. + * + * XXX: Assume same for RF2425 + * to be safe. */ - if (ah->ah_radio == AR5K_RF2413) + if ((ah->ah_radio == AR5K_RF2413) || (ah->ah_radio == AR5K_RF2425)) return 0; /* Reset TX power values */ -- cgit v1.2.1 From 194828a292db3cf421ae7f82232f2fc655fbbc3c Mon Sep 17 00:00:00 2001 From: Nick Kossifidis Date: Wed, 16 Apr 2008 18:49:02 +0300 Subject: ath5k: Misc fixes/cleanups *Handle MIB interrupts and pass low level stats to mac80211 *Add Power On Self Test function *Update to match recent dumps *Let RF2425 attach so we can further test it *Remove unused files regdom.c and regdom.h base.c Changes-licensed-under: 3-clause-BSD rest Changes-licensed-under: ISC Signed-off-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/ath5k.h | 10 +- drivers/net/wireless/ath5k/base.c | 13 +- drivers/net/wireless/ath5k/hw.c | 138 +++++++++- drivers/net/wireless/ath5k/regdom.c | 121 --------- drivers/net/wireless/ath5k/regdom.h | 500 ------------------------------------ 5 files changed, 139 insertions(+), 643 deletions(-) delete mode 100644 drivers/net/wireless/ath5k/regdom.c delete mode 100644 drivers/net/wireless/ath5k/regdom.h (limited to 'drivers/net/wireless') diff --git a/drivers/net/wireless/ath5k/ath5k.h b/drivers/net/wireless/ath5k/ath5k.h index d0d70b32e78b..ba35c30d203c 100644 --- a/drivers/net/wireless/ath5k/ath5k.h +++ b/drivers/net/wireless/ath5k/ath5k.h @@ -450,14 +450,6 @@ struct ath5k_rx_status { #define AR5K_RXKEYIX_INVALID ((u8) - 1) #define AR5K_TXKEYIX_INVALID ((u32) - 1) -struct ath5k_mib_stats { - u32 ackrcv_bad; - u32 rts_bad; - u32 rts_good; - u32 fcs_bad; - u32 beacons; -}; - /**************************\ BEACON TIMERS DEFINITIONS @@ -1070,6 +1062,7 @@ extern int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase); extern bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah); extern int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask); extern enum ath5k_int ath5k_hw_set_intr(struct ath5k_hw *ah, enum ath5k_int new_mask); +extern void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, struct ieee80211_low_level_stats *stats); /* EEPROM access functions */ extern int ath5k_hw_set_regdomain(struct ath5k_hw *ah, u16 regdomain); /* Protocol Control Unit Functions */ @@ -1098,7 +1091,6 @@ extern int ath5k_hw_set_beacon_timers(struct ath5k_hw *ah, const struct ath5k_be extern void ath5k_hw_reset_beacon(struct ath5k_hw *ah); extern int ath5k_hw_beaconq_finish(struct ath5k_hw *ah, unsigned long phys_addr); #endif -extern void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, struct ath5k_mib_stats *statistics); /* ACK bit rate */ void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high); /* ACK/CTS Timeouts */ diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index dfd202ddcff3..e18305b781c9 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -2342,7 +2342,8 @@ ath5k_init(struct ath5k_softc *sc) * Enable interrupts. */ sc->imask = AR5K_INT_RX | AR5K_INT_TX | AR5K_INT_RXEOL | - AR5K_INT_RXORN | AR5K_INT_FATAL | AR5K_INT_GLOBAL; + AR5K_INT_RXORN | AR5K_INT_FATAL | AR5K_INT_GLOBAL | + AR5K_INT_MIB; ath5k_hw_set_intr(sc->ah, sc->imask); /* Set ack to be sent at low bit-rates */ @@ -2522,7 +2523,11 @@ ath5k_intr(int irq, void *dev_id) if (status & AR5K_INT_BMISS) { } if (status & AR5K_INT_MIB) { - /* TODO */ + /* + * These stats are also used for ANI i think + * so how about updating them more often ? + */ + ath5k_hw_update_mib_counters(ah, &sc->ll_stats); } } } while (ath5k_hw_is_intr_pending(ah) && counter-- > 0); @@ -3015,6 +3020,10 @@ ath5k_get_stats(struct ieee80211_hw *hw, struct ieee80211_low_level_stats *stats) { struct ath5k_softc *sc = hw->priv; + struct ath5k_hw *ah = sc->ah; + + /* Force update */ + ath5k_hw_update_mib_counters(ah, &sc->ll_stats); memcpy(stats, &sc->ll_stats, sizeof(sc->ll_stats)); diff --git a/drivers/net/wireless/ath5k/hw.c b/drivers/net/wireless/ath5k/hw.c index 9e16bc09f1fd..87e782291a01 100644 --- a/drivers/net/wireless/ath5k/hw.c +++ b/drivers/net/wireless/ath5k/hw.c @@ -119,12 +119,70 @@ int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val, Attach/Detach Functions \***************************************/ +/* + * Power On Self Test helper function + */ +static int ath5k_hw_post(struct ath5k_hw *ah) +{ + + int i, c; + u16 cur_reg; + u16 regs[2] = {AR5K_STA_ID0, AR5K_PHY(8)}; + u32 var_pattern; + u32 static_pattern[4] = { + 0x55555555, 0xaaaaaaaa, + 0x66666666, 0x99999999 + }; + u32 init_val; + u32 cur_val; + + for (c = 0; c < 2; c++) { + + cur_reg = regs[c]; + init_val = ath5k_hw_reg_read(ah, cur_reg); + + for (i = 0; i < 256; i++) { + var_pattern = i << 16 | i; + ath5k_hw_reg_write(ah, var_pattern, cur_reg); + cur_val = ath5k_hw_reg_read(ah, cur_reg); + + if (cur_val != var_pattern) { + ATH5K_ERR(ah->ah_sc, "POST Failed !!!\n"); + return -EAGAIN; + } + + /* Found on ndiswrapper dumps */ + var_pattern = 0x0039080f; + ath5k_hw_reg_write(ah, var_pattern, cur_reg); + } + + for (i = 0; i < 4; i++) { + var_pattern = static_pattern[i]; + ath5k_hw_reg_write(ah, var_pattern, cur_reg); + cur_val = ath5k_hw_reg_read(ah, cur_reg); + + if (cur_val != var_pattern) { + ATH5K_ERR(ah->ah_sc, "POST Failed !!!\n"); + return -EAGAIN; + } + + /* Found on ndiswrapper dumps */ + var_pattern = 0x003b080f; + ath5k_hw_reg_write(ah, var_pattern, cur_reg); + } + } + + return 0; + +} + /* * Check if the device is supported and initialize the needed structs */ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) { struct ath5k_hw *ah; + struct pci_dev *pdev = sc->pdev; u8 mac[ETH_ALEN]; int ret; u32 srev; @@ -204,10 +262,13 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) CHANNEL_2GHZ); /* Return on unsuported chips (unsupported eeprom etc) */ - if (srev >= AR5K_SREV_VER_AR5416) { + if ((srev >= AR5K_SREV_VER_AR5416) && + (srev < AR5K_SREV_VER_AR2425)) { ATH5K_ERR(sc, "Device not yet supported.\n"); ret = -ENODEV; goto err_free; + } else if (srev == AR5K_SREV_VER_AR2425) { + ATH5K_WARN(sc, "Support for RF2425 is under development.\n"); } /* Identify single chip solutions */ @@ -251,14 +312,57 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version) ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5424; else ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112A; - - } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5133) { + /* + * Register returns 0x4 for radio revision + * so ath5k_hw_radio_revision doesn't parse the value + * correctly. For now we are based on mac's srev to + * identify RF2425 radio. + */ + } else if (srev == AR5K_SREV_VER_AR2425) { ah->ah_radio = AR5K_RF2425; ah->ah_phy_spending = AR5K_PHY_SPENDING_RF5112; } ah->ah_phy = AR5K_PHY(0); + /* + * Identify AR5212-based PCI-E cards + * And write some initial settings. + * + * (doing a "strings" on ndis driver + * -ar5211.sys- reveals the following + * pci-e related functions: + * + * pcieClockReq + * pcieRxErrNotify + * pcieL1SKPEnable + * pcieAspm + * pcieDisableAspmOnRfWake + * pciePowerSaveEnable + * + * I guess these point to ClockReq but + * i'm not sure.) + */ + if ((ah->ah_version == AR5K_AR5212) && (pdev->is_pcie)) { + ath5k_hw_reg_write(ah, 0x9248fc00, 0x4080); + ath5k_hw_reg_write(ah, 0x24924924, 0x4080); + ath5k_hw_reg_write(ah, 0x28000039, 0x4080); + ath5k_hw_reg_write(ah, 0x53160824, 0x4080); + ath5k_hw_reg_write(ah, 0xe5980579, 0x4080); + ath5k_hw_reg_write(ah, 0x001defff, 0x4080); + ath5k_hw_reg_write(ah, 0x1aaabe40, 0x4080); + ath5k_hw_reg_write(ah, 0xbe105554, 0x4080); + ath5k_hw_reg_write(ah, 0x000e3007, 0x4080); + ath5k_hw_reg_write(ah, 0x00000000, 0x4084); + } + + /* + * POST + */ + ret = ath5k_hw_post(ah); + if (ret) + goto err_free; + /* * Get card capabilities, values, ... */ @@ -2851,15 +2955,19 @@ int ath5k_hw_beaconq_finish(struct ath5k_hw *ah, unsigned long phys_addr) * Update mib counters (statistics) */ void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, - struct ath5k_mib_stats *statistics) + struct ieee80211_low_level_stats *stats) { ATH5K_TRACE(ah->ah_sc); + /* Read-And-Clear */ - statistics->ackrcv_bad += ath5k_hw_reg_read(ah, AR5K_ACK_FAIL); - statistics->rts_bad += ath5k_hw_reg_read(ah, AR5K_RTS_FAIL); - statistics->rts_good += ath5k_hw_reg_read(ah, AR5K_RTS_OK); - statistics->fcs_bad += ath5k_hw_reg_read(ah, AR5K_FCS_FAIL); - statistics->beacons += ath5k_hw_reg_read(ah, AR5K_BEACON_CNT); + stats->dot11ACKFailureCount += ath5k_hw_reg_read(ah, AR5K_ACK_FAIL); + stats->dot11RTSFailureCount += ath5k_hw_reg_read(ah, AR5K_RTS_FAIL); + stats->dot11RTSSuccessCount += ath5k_hw_reg_read(ah, AR5K_RTS_OK); + stats->dot11FCSErrorCount += ath5k_hw_reg_read(ah, AR5K_FCS_FAIL); + + /* XXX: Should we use this to track beacon count ? + * -we read it anyway to clear the register */ + ath5k_hw_reg_read(ah, AR5K_BEACON_CNT); /* Reset profile count registers on 5212*/ if (ah->ah_version == AR5K_AR5212) { @@ -2960,8 +3068,16 @@ int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry) for (i = 0; i < AR5K_KEYCACHE_SIZE; i++) ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_OFF(entry, i)); - /* Set NULL encryption on non-5210*/ - if (ah->ah_version != AR5K_AR5210) + /* + * Set NULL encryption on AR5212+ + * + * Note: AR5K_KEYTABLE_TYPE -> AR5K_KEYTABLE_OFF(entry, 5) + * AR5K_KEYTABLE_TYPE_NULL -> 0x00000007 + * + * Note2: Windows driver (ndiswrapper) sets this to + * 0x00000714 instead of 0x00000007 + */ + if (ah->ah_version > AR5K_AR5211) ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL, AR5K_KEYTABLE_TYPE(entry)); diff --git a/drivers/net/wireless/ath5k/regdom.c b/drivers/net/wireless/ath5k/regdom.c deleted file mode 100644 index e851957dacfd..000000000000 --- a/drivers/net/wireless/ath5k/regdom.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (c) 2004, 2005 Reyk Floeter - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * Basic regulation domain extensions for the IEEE 802.11 stack - */ - -#include -#include - -#include "regdom.h" - -static const struct ath5k_regdommap { - enum ath5k_regdom dmn; - enum ath5k_regdom dmn5; - enum ath5k_regdom dmn2; -} r_map[] = { - { DMN_DEFAULT, DMN_DEBUG, DMN_DEBUG }, - { DMN_NULL_WORLD, DMN_NULL, DMN_WORLD }, - { DMN_NULL_ETSIB, DMN_NULL, DMN_ETSIB }, - { DMN_NULL_ETSIC, DMN_NULL, DMN_ETSIC }, - { DMN_FCC1_FCCA, DMN_FCC1, DMN_FCCA }, - { DMN_FCC1_WORLD, DMN_FCC1, DMN_WORLD }, - { DMN_FCC2_FCCA, DMN_FCC2, DMN_FCCA }, - { DMN_FCC2_WORLD, DMN_FCC2, DMN_WORLD }, - { DMN_FCC2_ETSIC, DMN_FCC2, DMN_ETSIC }, - { DMN_FRANCE_NULL, DMN_ETSI3, DMN_ETSI3 }, - { DMN_FCC3_FCCA, DMN_FCC3, DMN_WORLD }, - { DMN_ETSI1_WORLD, DMN_ETSI1, DMN_WORLD }, - { DMN_ETSI3_ETSIA, DMN_ETSI3, DMN_WORLD }, - { DMN_ETSI2_WORLD, DMN_ETSI2, DMN_WORLD }, - { DMN_ETSI3_WORLD, DMN_ETSI3, DMN_WORLD }, - { DMN_ETSI4_WORLD, DMN_ETSI4, DMN_WORLD }, - { DMN_ETSI4_ETSIC, DMN_ETSI4, DMN_ETSIC }, - { DMN_ETSI5_WORLD, DMN_ETSI5, DMN_WORLD }, - { DMN_ETSI6_WORLD, DMN_ETSI6, DMN_WORLD }, - { DMN_ETSI_NULL, DMN_ETSI1, DMN_ETSI1 }, - { DMN_MKK1_MKKA, DMN_MKK1, DMN_MKKA }, - { DMN_MKK1_MKKB, DMN_MKK1, DMN_MKKA }, - { DMN_APL4_WORLD, DMN_APL4, DMN_WORLD }, - { DMN_MKK2_MKKA, DMN_MKK2, DMN_MKKA }, - { DMN_APL_NULL, DMN_APL1, DMN_NULL }, - { DMN_APL2_WORLD, DMN_APL2, DMN_WORLD }, - { DMN_APL2_APLC, DMN_APL2, DMN_WORLD }, - { DMN_APL3_WORLD, DMN_APL3, DMN_WORLD }, - { DMN_MKK1_FCCA, DMN_MKK1, DMN_FCCA }, - { DMN_APL2_APLD, DMN_APL2, DMN_APLD }, - { DMN_MKK1_MKKA1, DMN_MKK1, DMN_MKKA }, - { DMN_MKK1_MKKA2, DMN_MKK1, DMN_MKKA }, - { DMN_APL1_WORLD, DMN_APL1, DMN_WORLD }, - { DMN_APL1_FCCA, DMN_APL1, DMN_FCCA }, - { DMN_APL1_APLA, DMN_APL1, DMN_WORLD }, - { DMN_APL1_ETSIC, DMN_APL1, DMN_ETSIC }, - { DMN_APL2_ETSIC, DMN_APL2, DMN_ETSIC }, - { DMN_APL5_WORLD, DMN_APL5, DMN_WORLD }, - { DMN_WOR0_WORLD, DMN_WORLD, DMN_WORLD }, - { DMN_WOR1_WORLD, DMN_WORLD, DMN_WORLD }, - { DMN_WOR2_WORLD, DMN_WORLD, DMN_WORLD }, - { DMN_WOR3_WORLD, DMN_WORLD, DMN_WORLD }, - { DMN_WOR4_WORLD, DMN_WORLD, DMN_WORLD }, - { DMN_WOR5_ETSIC, DMN_WORLD, DMN_WORLD }, - { DMN_WOR01_WORLD, DMN_WORLD, DMN_WORLD }, - { DMN_WOR02_WORLD, DMN_WORLD, DMN_WORLD }, - { DMN_EU1_WORLD, DMN_ETSI1, DMN_WORLD }, - { DMN_WOR9_WORLD, DMN_WORLD, DMN_WORLD }, - { DMN_WORA_WORLD, DMN_WORLD, DMN_WORLD }, -}; - -enum ath5k_regdom ath5k_regdom2flag(enum ath5k_regdom dmn, u16 mhz) -{ - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(r_map); i++) { - if (r_map[i].dmn == dmn) { - if (mhz >= 2000 && mhz <= 3000) - return r_map[i].dmn2; - if (mhz >= IEEE80211_CHANNELS_5GHZ_MIN && - mhz <= IEEE80211_CHANNELS_5GHZ_MAX) - return r_map[i].dmn5; - } - } - - return DMN_DEBUG; -} - -u16 ath5k_regdom_from_ieee(enum ath5k_regdom ieee) -{ - u32 regdomain = (u32)ieee; - - /* - * Use the default regulation domain if the value is empty - * or not supported by the net80211 regulation code. - */ - if (ath5k_regdom2flag(regdomain, IEEE80211_CHANNELS_5GHZ_MIN) == - DMN_DEBUG) - return (u16)AR5K_TUNE_REGDOMAIN; - - /* It is supported, just return the value */ - return regdomain; -} - -enum ath5k_regdom ath5k_regdom_to_ieee(u16 regdomain) -{ - enum ath5k_regdom ieee = (enum ath5k_regdom)regdomain; - - return ieee; -} - diff --git a/drivers/net/wireless/ath5k/regdom.h b/drivers/net/wireless/ath5k/regdom.h deleted file mode 100644 index f7d3c66e594e..000000000000 --- a/drivers/net/wireless/ath5k/regdom.h +++ /dev/null @@ -1,500 +0,0 @@ -/* - * Copyright (c) 2004, 2005 Reyk Floeter - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef _IEEE80211_REGDOMAIN_H_ -#define _IEEE80211_REGDOMAIN_H_ - -#include - -/* Default regulation domain if stored value EEPROM value is invalid */ -#define AR5K_TUNE_REGDOMAIN DMN_FCC2_FCCA /* Canada */ -#define AR5K_TUNE_CTRY CTRY_DEFAULT - - -enum ath5k_regdom { - DMN_DEFAULT = 0x00, - DMN_NULL_WORLD = 0x03, - DMN_NULL_ETSIB = 0x07, - DMN_NULL_ETSIC = 0x08, - DMN_FCC1_FCCA = 0x10, - DMN_FCC1_WORLD = 0x11, - DMN_FCC2_FCCA = 0x20, - DMN_FCC2_WORLD = 0x21, - DMN_FCC2_ETSIC = 0x22, - DMN_FRANCE_NULL = 0x31, - DMN_FCC3_FCCA = 0x3A, - DMN_ETSI1_WORLD = 0x37, - DMN_ETSI3_ETSIA = 0x32, - DMN_ETSI2_WORLD = 0x35, - DMN_ETSI3_WORLD = 0x36, - DMN_ETSI4_WORLD = 0x30, - DMN_ETSI4_ETSIC = 0x38, - DMN_ETSI5_WORLD = 0x39, - DMN_ETSI6_WORLD = 0x34, - DMN_ETSI_NULL = 0x33, - DMN_MKK1_MKKA = 0x40, - DMN_MKK1_MKKB = 0x41, - DMN_APL4_WORLD = 0x42, - DMN_MKK2_MKKA = 0x43, - DMN_APL_NULL = 0x44, - DMN_APL2_WORLD = 0x45, - DMN_APL2_APLC = 0x46, - DMN_APL3_WORLD = 0x47, - DMN_MKK1_FCCA = 0x48, - DMN_APL2_APLD = 0x49, - DMN_MKK1_MKKA1 = 0x4A, - DMN_MKK1_MKKA2 = 0x4B, - DMN_APL1_WORLD = 0x52, - DMN_APL1_FCCA = 0x53, - DMN_APL1_APLA = 0x54, - DMN_APL1_ETSIC = 0x55, - DMN_APL2_ETSIC = 0x56, - DMN_APL5_WORLD = 0x58, - DMN_WOR0_WORLD = 0x60, - DMN_WOR1_WORLD = 0x61, - DMN_WOR2_WORLD = 0x62, - DMN_WOR3_WORLD = 0x63, - DMN_WOR4_WORLD = 0x64, - DMN_WOR5_ETSIC = 0x65, - DMN_WOR01_WORLD = 0x66, - DMN_WOR02_WORLD = 0x67, - DMN_EU1_WORLD = 0x68, - DMN_WOR9_WORLD = 0x69, - DMN_WORA_WORLD = 0x6A, - - DMN_APL1 = 0xf0000001, - DMN_APL2 = 0xf0000002, - DMN_APL3 = 0xf0000004, - DMN_APL4 = 0xf0000008, - DMN_APL5 = 0xf0000010, - DMN_ETSI1 = 0xf0000020, - DMN_ETSI2 = 0xf0000040, - DMN_ETSI3 = 0xf0000080, - DMN_ETSI4 = 0xf0000100, - DMN_ETSI5 = 0xf0000200, - DMN_ETSI6 = 0xf0000400, - DMN_ETSIA = 0xf0000800, - DMN_ETSIB = 0xf0001000, - DMN_ETSIC = 0xf0002000, - DMN_FCC1 = 0xf0004000, - DMN_FCC2 = 0xf0008000, - DMN_FCC3 = 0xf0010000, - DMN_FCCA = 0xf0020000, - DMN_APLD = 0xf0040000, - DMN_MKK1 = 0xf0080000, - DMN_MKK2 = 0xf0100000, - DMN_MKKA = 0xf0200000, - DMN_NULL = 0xf0400000, - DMN_WORLD = 0xf0800000, - DMN_DEBUG = 0xf1000000 /* used for debugging */ -}; - -#define IEEE80211_DMN(_d) ((_d) & ~0xf0000000) - -enum ath5k_countrycode { - CTRY_DEFAULT = 0, /* Default domain (NA) */ - CTRY_ALBANIA = 8, /* Albania */ - CTRY_ALGERIA = 12, /* Algeria */ - CTRY_ARGENTINA = 32, /* Argentina */ - CTRY_ARMENIA = 51, /* Armenia */ - CTRY_AUSTRALIA = 36, /* Australia */ - CTRY_AUSTRIA = 40, /* Austria */ - CTRY_AZERBAIJAN = 31, /* Azerbaijan */ - CTRY_BAHRAIN = 48, /* Bahrain */ - CTRY_BELARUS = 112, /* Belarus */ - CTRY_BELGIUM = 56, /* Belgium */ - CTRY_BELIZE = 84, /* Belize */ - CTRY_BOLIVIA = 68, /* Bolivia */ - CTRY_BRAZIL = 76, /* Brazil */ - CTRY_BRUNEI_DARUSSALAM = 96, /* Brunei Darussalam */ - CTRY_BULGARIA = 100, /* Bulgaria */ - CTRY_CANADA = 124, /* Canada */ - CTRY_CHILE = 152, /* Chile */ - CTRY_CHINA = 156, /* People's Republic of China */ - CTRY_COLOMBIA = 170, /* Colombia */ - CTRY_COSTA_RICA = 188, /* Costa Rica */ - CTRY_CROATIA = 191, /* Croatia */ - CTRY_CYPRUS = 196, /* Cyprus */ - CTRY_CZECH = 203, /* Czech Republic */ - CTRY_DENMARK = 208, /* Denmark */ - CTRY_DOMINICAN_REPUBLIC = 214, /* Dominican Republic */ - CTRY_ECUADOR = 218, /* Ecuador */ - CTRY_EGYPT = 818, /* Egypt */ - CTRY_EL_SALVADOR = 222, /* El Salvador */ - CTRY_ESTONIA = 233, /* Estonia */ - CTRY_FAEROE_ISLANDS = 234, /* Faeroe Islands */ - CTRY_FINLAND = 246, /* Finland */ - CTRY_FRANCE = 250, /* France */ - CTRY_FRANCE2 = 255, /* France2 */ - CTRY_GEORGIA = 268, /* Georgia */ - CTRY_GERMANY = 276, /* Germany */ - CTRY_GREECE = 300, /* Greece */ - CTRY_GUATEMALA = 320, /* Guatemala */ - CTRY_HONDURAS = 340, /* Honduras */ - CTRY_HONG_KONG = 344, /* Hong Kong S.A.R., P.R.C. */ - CTRY_HUNGARY = 348, /* Hungary */ - CTRY_ICELAND = 352, /* Iceland */ - CTRY_INDIA = 356, /* India */ - CTRY_INDONESIA = 360, /* Indonesia */ - CTRY_IRAN = 364, /* Iran */ - CTRY_IRAQ = 368, /* Iraq */ - CTRY_IRELAND = 372, /* Ireland */ - CTRY_ISRAEL = 376, /* Israel */ - CTRY_ITALY = 380, /* Italy */ - CTRY_JAMAICA = 388, /* Jamaica */ - CTRY_JAPAN = 392, /* Japan */ - CTRY_JAPAN1 = 393, /* Japan (JP1) */ - CTRY_JAPAN2 = 394, /* Japan (JP0) */ - CTRY_JAPAN3 = 395, /* Japan (JP1-1) */ - CTRY_JAPAN4 = 396, /* Japan (JE1) */ - CTRY_JAPAN5 = 397, /* Japan (JE2) */ - CTRY_JORDAN = 400, /* Jordan */ - CTRY_KAZAKHSTAN = 398, /* Kazakhstan */ - CTRY_KENYA = 404, /* Kenya */ - CTRY_KOREA_NORTH = 408, /* North Korea */ - CTRY_KOREA_ROC = 410, /* South Korea */ - CTRY_KOREA_ROC2 = 411, /* South Korea */ - CTRY_KUWAIT = 414, /* Kuwait */ - CTRY_LATVIA = 428, /* Latvia */ - CTRY_LEBANON = 422, /* Lebanon */ - CTRY_LIBYA = 434, /* Libya */ - CTRY_LIECHTENSTEIN = 438, /* Liechtenstein */ - CTRY_LITHUANIA = 440, /* Lithuania */ - CTRY_LUXEMBOURG = 442, /* Luxembourg */ - CTRY_MACAU = 446, /* Macau */ - CTRY_MACEDONIA = 807, /* Republic of Macedonia */ - CTRY_MALAYSIA = 458, /* Malaysia */ - CTRY_MEXICO = 484, /* Mexico */ - CTRY_MONACO = 492, /* Principality of Monaco */ - CTRY_MOROCCO = 504, /* Morocco */ - CTRY_NETHERLANDS = 528, /* Netherlands */ - CTRY_NEW_ZEALAND = 554, /* New Zealand */ - CTRY_NICARAGUA = 558, /* Nicaragua */ - CTRY_NORWAY = 578, /* Norway */ - CTRY_OMAN = 512, /* Oman */ - CTRY_PAKISTAN = 586, /* Islamic Republic of Pakistan */ - CTRY_PANAMA = 591, /* Panama */ - CTRY_PARAGUAY = 600, /* Paraguay */ - CTRY_PERU = 604, /* Peru */ - CTRY_PHILIPPINES = 608, /* Republic of the Philippines */ - CTRY_POLAND = 616, /* Poland */ - CTRY_PORTUGAL = 620, /* Portugal */ - CTRY_PUERTO_RICO = 630, /* Puerto Rico */ - CTRY_QATAR = 634, /* Qatar */ - CTRY_ROMANIA = 642, /* Romania */ - CTRY_RUSSIA = 643, /* Russia */ - CTRY_SAUDI_ARABIA = 682, /* Saudi Arabia */ - CTRY_SINGAPORE = 702, /* Singapore */ - CTRY_SLOVAKIA = 703, /* Slovak Republic */ - CTRY_SLOVENIA = 705, /* Slovenia */ - CTRY_SOUTH_AFRICA = 710, /* South Africa */ - CTRY_SPAIN = 724, /* Spain */ - CTRY_SRI_LANKA = 728, /* Sri Lanka */ - CTRY_SWEDEN = 752, /* Sweden */ - CTRY_SWITZERLAND = 756, /* Switzerland */ - CTRY_SYRIA = 760, /* Syria */ - CTRY_TAIWAN = 158, /* Taiwan */ - CTRY_THAILAND = 764, /* Thailand */ - CTRY_TRINIDAD_Y_TOBAGO = 780, /* Trinidad y Tobago */ - CTRY_TUNISIA = 788, /* Tunisia */ - CTRY_TURKEY = 792, /* Turkey */ - CTRY_UAE = 784, /* U.A.E. */ - CTRY_UKRAINE = 804, /* Ukraine */ - CTRY_UNITED_KINGDOM = 826, /* United Kingdom */ - CTRY_UNITED_STATES = 840, /* United States */ - CTRY_URUGUAY = 858, /* Uruguay */ - CTRY_UZBEKISTAN = 860, /* Uzbekistan */ - CTRY_VENEZUELA = 862, /* Venezuela */ - CTRY_VIET_NAM = 704, /* Viet Nam */ - CTRY_YEMEN = 887, /* Yemen */ - CTRY_ZIMBABWE = 716, /* Zimbabwe */ -}; - -#define IEEE80211_CHANNELS_2GHZ_MIN 2412 /* 2GHz channel 1 */ -#define IEEE80211_CHANNELS_2GHZ_MAX 2732 /* 2GHz channel 26 */ -#define IEEE80211_CHANNELS_5GHZ_MIN 5005 /* 5GHz channel 1 */ -#define IEEE80211_CHANNELS_5GHZ_MAX 6100 /* 5GHz channel 220 */ - -struct ath5k_regchannel { - u16 chan; - enum ath5k_regdom domain; - u32 mode; -}; - -#define IEEE80211_CHANNELS_2GHZ { \ -/*2412*/ { 1, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2417*/ { 2, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2422*/ { 3, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2427*/ { 4, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2432*/ { 5, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2437*/ { 6, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2442*/ { 7, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2447*/ { 8, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2452*/ { 9, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2457*/ { 10, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2462*/ { 11, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2467*/ { 12, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2472*/ { 13, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \ - \ -/*2432*/ { 5, DMN_ETSIB, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2437*/ { 6, DMN_ETSIB, CHANNEL_CCK|CHANNEL_OFDM|CHANNEL_TURBO }, \ -/*2442*/ { 7, DMN_ETSIB, CHANNEL_CCK|CHANNEL_OFDM }, \ - \ -/*2412*/ { 1, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2417*/ { 2, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2422*/ { 3, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2427*/ { 4, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2432*/ { 5, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2437*/ { 6, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM|CHANNEL_TURBO }, \ -/*2442*/ { 7, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2447*/ { 8, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2452*/ { 9, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2457*/ { 10, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2462*/ { 11, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2467*/ { 12, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2472*/ { 13, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \ - \ -/*2412*/ { 1, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2417*/ { 2, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2422*/ { 3, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2427*/ { 4, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2432*/ { 5, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2437*/ { 6, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM|CHANNEL_TURBO }, \ -/*2442*/ { 7, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2447*/ { 8, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2452*/ { 9, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2457*/ { 10, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2462*/ { 11, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \ - \ -/*2412*/ { 1, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2417*/ { 2, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2422*/ { 3, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2427*/ { 4, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2432*/ { 5, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2437*/ { 6, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2442*/ { 7, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2447*/ { 8, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2452*/ { 9, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2457*/ { 10, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2462*/ { 11, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2467*/ { 12, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2472*/ { 13, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2484*/ { 14, DMN_MKKA, CHANNEL_CCK }, \ - \ -/*2412*/ { 1, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2417*/ { 2, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2422*/ { 3, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2427*/ { 4, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2432*/ { 5, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2437*/ { 6, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM|CHANNEL_TURBO }, \ -/*2442*/ { 7, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2447*/ { 8, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2452*/ { 9, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2457*/ { 10, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2462*/ { 11, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2467*/ { 12, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \ -/*2472*/ { 13, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \ -} - -#define IEEE80211_CHANNELS_5GHZ { \ -/*5745*/ { 149, DMN_APL1, CHANNEL_OFDM }, \ -/*5765*/ { 153, DMN_APL1, CHANNEL_OFDM }, \ -/*5785*/ { 157, DMN_APL1, CHANNEL_OFDM }, \ -/*5805*/ { 161, DMN_APL1, CHANNEL_OFDM }, \ -/*5825*/ { 165, DMN_APL1, CHANNEL_OFDM }, \ - \ -/*5745*/ { 149, DMN_APL2, CHANNEL_OFDM }, \ -/*5765*/ { 153, DMN_APL2, CHANNEL_OFDM }, \ -/*5785*/ { 157, DMN_APL2, CHANNEL_OFDM }, \ -/*5805*/ { 161, DMN_APL2, CHANNEL_OFDM }, \ - \ -/*5280*/ { 56, DMN_APL3, CHANNEL_OFDM }, \ -/*5300*/ { 60, DMN_APL3, CHANNEL_OFDM }, \ -/*5320*/ { 64, DMN_APL3, CHANNEL_OFDM }, \ -/*5745*/ { 149, DMN_APL3, CHANNEL_OFDM }, \ -/*5765*/ { 153, DMN_APL3, CHANNEL_OFDM }, \ -/*5785*/ { 157, DMN_APL3, CHANNEL_OFDM }, \ -/*5805*/ { 161, DMN_APL3, CHANNEL_OFDM }, \ - \ -/*5180*/ { 36, DMN_APL4, CHANNEL_OFDM }, \ -/*5200*/ { 40, DMN_APL4, CHANNEL_OFDM }, \ -/*5220*/ { 44, DMN_APL4, CHANNEL_OFDM }, \ -/*5240*/ { 48, DMN_APL4, CHANNEL_OFDM }, \ -/*5745*/ { 149, DMN_APL4, CHANNEL_OFDM }, \ -/*5765*/ { 153, DMN_APL4, CHANNEL_OFDM }, \ -/*5785*/ { 157, DMN_APL4, CHANNEL_OFDM }, \ -/*5805*/ { 161, DMN_APL4, CHANNEL_OFDM }, \ -/*5825*/ { 165, DMN_APL4, CHANNEL_OFDM }, \ - \ -/*5745*/ { 149, DMN_APL5, CHANNEL_OFDM }, \ -/*5765*/ { 153, DMN_APL5, CHANNEL_OFDM }, \ -/*5785*/ { 157, DMN_APL5, CHANNEL_OFDM }, \ -/*5805*/ { 161, DMN_APL5, CHANNEL_OFDM }, \ -/*5825*/ { 165, DMN_APL5, CHANNEL_OFDM }, \ - \ -/*5180*/ { 36, DMN_ETSI1, CHANNEL_OFDM }, \ -/*5200*/ { 40, DMN_ETSI1, CHANNEL_OFDM }, \ -/*5220*/ { 44, DMN_ETSI1, CHANNEL_OFDM }, \ -/*5240*/ { 48, DMN_ETSI1, CHANNEL_OFDM }, \ -/*5260*/ { 52, DMN_ETSI1, CHANNEL_OFDM }, \ -/*5280*/ { 56, DMN_ETSI1, CHANNEL_OFDM }, \ -/*5300*/ { 60, DMN_ETSI1, CHANNEL_OFDM }, \ -/*5320*/ { 64, DMN_ETSI1, CHANNEL_OFDM }, \ -/*5500*/ { 100, DMN_ETSI1, CHANNEL_OFDM }, \ -/*5520*/ { 104, DMN_ETSI1, CHANNEL_OFDM }, \ -/*5540*/ { 108, DMN_ETSI1, CHANNEL_OFDM }, \ -/*5560*/ { 112, DMN_ETSI1, CHANNEL_OFDM }, \ -/*5580*/ { 116, DMN_ETSI1, CHANNEL_OFDM }, \ -/*5600*/ { 120, DMN_ETSI1, CHANNEL_OFDM }, \ -/*5620*/ { 124, DMN_ETSI1, CHANNEL_OFDM }, \ -/*5640*/ { 128, DMN_ETSI1, CHANNEL_OFDM }, \ -/*5660*/ { 132, DMN_ETSI1, CHANNEL_OFDM }, \ -/*5680*/ { 136, DMN_ETSI1, CHANNEL_OFDM }, \ -/*5700*/ { 140, DMN_ETSI1, CHANNEL_OFDM }, \ - \ -/*5180*/ { 36, DMN_ETSI2, CHANNEL_OFDM }, \ -/*5200*/ { 40, DMN_ETSI2, CHANNEL_OFDM }, \ -/*5220*/ { 44, DMN_ETSI2, CHANNEL_OFDM }, \ -/*5240*/ { 48, DMN_ETSI2, CHANNEL_OFDM }, \ - \ -/*5180*/ { 36, DMN_ETSI3, CHANNEL_OFDM }, \ -/*5200*/ { 40, DMN_ETSI3, CHANNEL_OFDM }, \ -/*5220*/ { 44, DMN_ETSI3, CHANNEL_OFDM }, \ -/*5240*/ { 48, DMN_ETSI3, CHANNEL_OFDM }, \ -/*5260*/ { 52, DMN_ETSI3, CHANNEL_OFDM }, \ -/*5280*/ { 56, DMN_ETSI3, CHANNEL_OFDM }, \ -/*5300*/ { 60, DMN_ETSI3, CHANNEL_OFDM }, \ -/*5320*/ { 64, DMN_ETSI3, CHANNEL_OFDM }, \ - \ -/*5180*/ { 36, DMN_ETSI4, CHANNEL_OFDM }, \ -/*5200*/ { 40, DMN_ETSI4, CHANNEL_OFDM }, \ -/*5220*/ { 44, DMN_ETSI4, CHANNEL_OFDM }, \ -/*5240*/ { 48, DMN_ETSI4, CHANNEL_OFDM }, \ -/*5260*/ { 52, DMN_ETSI4, CHANNEL_OFDM }, \ -/*5280*/ { 56, DMN_ETSI4, CHANNEL_OFDM }, \ -/*5300*/ { 60, DMN_ETSI4, CHANNEL_OFDM }, \ -/*5320*/ { 64, DMN_ETSI4, CHANNEL_OFDM }, \ - \ -/*5180*/ { 36, DMN_ETSI5, CHANNEL_OFDM }, \ -/*5200*/ { 40, DMN_ETSI5, CHANNEL_OFDM }, \ -/*5220*/ { 44, DMN_ETSI5, CHANNEL_OFDM }, \ -/*5240*/ { 48, DMN_ETSI5, CHANNEL_OFDM }, \ - \ -/*5180*/ { 36, DMN_ETSI6, CHANNEL_OFDM }, \ -/*5200*/ { 40, DMN_ETSI6, CHANNEL_OFDM }, \ -/*5220*/ { 44, DMN_ETSI6, CHANNEL_OFDM }, \ -/*5240*/ { 48, DMN_ETSI6, CHANNEL_OFDM }, \ -/*5260*/ { 52, DMN_ETSI6, CHANNEL_OFDM }, \ -/*5280*/ { 56, DMN_ETSI6, CHANNEL_OFDM }, \ -/*5500*/ { 100, DMN_ETSI6, CHANNEL_OFDM }, \ -/*5520*/ { 104, DMN_ETSI6, CHANNEL_OFDM }, \ -/*5540*/ { 108, DMN_ETSI6, CHANNEL_OFDM }, \ -/*5560*/ { 112, DMN_ETSI6, CHANNEL_OFDM }, \ -/*5580*/ { 116, DMN_ETSI6, CHANNEL_OFDM }, \ -/*5600*/ { 120, DMN_ETSI6, CHANNEL_OFDM }, \ -/*5620*/ { 124, DMN_ETSI6, CHANNEL_OFDM }, \ -/*5640*/ { 128, DMN_ETSI6, CHANNEL_OFDM }, \ -/*5660*/ { 132, DMN_ETSI6, CHANNEL_OFDM }, \ -/*5680*/ { 136, DMN_ETSI6, CHANNEL_OFDM }, \ -/*5700*/ { 140, DMN_ETSI6, CHANNEL_OFDM }, \ - \ -/*5180*/ { 36, DMN_FCC1, CHANNEL_OFDM }, \ -/*5200*/ { 40, DMN_FCC1, CHANNEL_OFDM }, \ -/*5210*/ { 42, DMN_FCC1, CHANNEL_OFDM|CHANNEL_TURBO }, \ -/*5220*/ { 44, DMN_FCC1, CHANNEL_OFDM }, \ -/*5240*/ { 48, DMN_FCC1, CHANNEL_OFDM }, \ -/*5250*/ { 50, DMN_FCC1, CHANNEL_OFDM|CHANNEL_TURBO }, \ -/*5260*/ { 52, DMN_FCC1, CHANNEL_OFDM }, \ -/*5280*/ { 56, DMN_FCC1, CHANNEL_OFDM }, \ -/*5290*/ { 58, DMN_FCC1, CHANNEL_OFDM|CHANNEL_TURBO }, \ -/*5300*/ { 60, DMN_FCC1, CHANNEL_OFDM }, \ -/*5320*/ { 64, DMN_FCC1, CHANNEL_OFDM }, \ -/*5745*/ { 149, DMN_FCC1, CHANNEL_OFDM }, \ -/*5760*/ { 152, DMN_FCC1, CHANNEL_OFDM|CHANNEL_TURBO }, \ -/*5765*/ { 153, DMN_FCC1, CHANNEL_OFDM }, \ -/*5785*/ { 157, DMN_FCC1, CHANNEL_OFDM }, \ -/*5800*/ { 160, DMN_FCC1, CHANNEL_OFDM|CHANNEL_TURBO }, \ -/*5805*/ { 161, DMN_FCC1, CHANNEL_OFDM }, \ -/*5825*/ { 165, DMN_FCC1, CHANNEL_OFDM }, \ - \ -/*5180*/ { 36, DMN_FCC2, CHANNEL_OFDM }, \ -/*5200*/ { 40, DMN_FCC2, CHANNEL_OFDM }, \ -/*5220*/ { 44, DMN_FCC2, CHANNEL_OFDM }, \ -/*5240*/ { 48, DMN_FCC2, CHANNEL_OFDM }, \ -/*5260*/ { 52, DMN_FCC2, CHANNEL_OFDM }, \ -/*5280*/ { 56, DMN_FCC2, CHANNEL_OFDM }, \ -/*5300*/ { 60, DMN_FCC2, CHANNEL_OFDM }, \ -/*5320*/ { 64, DMN_FCC2, CHANNEL_OFDM }, \ -/*5745*/ { 149, DMN_FCC2, CHANNEL_OFDM }, \ -/*5765*/ { 153, DMN_FCC2, CHANNEL_OFDM }, \ -/*5785*/ { 157, DMN_FCC2, CHANNEL_OFDM }, \ -/*5805*/ { 161, DMN_FCC2, CHANNEL_OFDM }, \ -/*5825*/ { 165, DMN_FCC2, CHANNEL_OFDM }, \ - \ -/*5180*/ { 36, DMN_FCC3, CHANNEL_OFDM }, \ -/*5200*/ { 40, DMN_FCC3, CHANNEL_OFDM }, \ -/*5210*/ { 42, DMN_FCC3, CHANNEL_OFDM|CHANNEL_TURBO }, \ -/*5220*/ { 44, DMN_FCC3, CHANNEL_OFDM }, \ -/*5240*/ { 48, DMN_FCC3, CHANNEL_OFDM }, \ -/*5250*/ { 50, DMN_FCC3, CHANNEL_OFDM|CHANNEL_TURBO }, \ -/*5260*/ { 52, DMN_FCC3, CHANNEL_OFDM }, \ -/*5280*/ { 56, DMN_FCC3, CHANNEL_OFDM }, \ -/*5290*/ { 58, DMN_FCC3, CHANNEL_OFDM|CHANNEL_TURBO }, \ -/*5300*/ { 60, DMN_FCC3, CHANNEL_OFDM }, \ -/*5320*/ { 64, DMN_FCC3, CHANNEL_OFDM }, \ -/*5500*/ { 100, DMN_FCC3, CHANNEL_OFDM }, \ -/*5520*/ { 104, DMN_FCC3, CHANNEL_OFDM }, \ -/*5540*/ { 108, DMN_FCC3, CHANNEL_OFDM }, \ -/*5560*/ { 112, DMN_FCC3, CHANNEL_OFDM }, \ -/*5580*/ { 116, DMN_FCC3, CHANNEL_OFDM }, \ -/*5600*/ { 120, DMN_FCC3, CHANNEL_OFDM }, \ -/*5620*/ { 124, DMN_FCC3, CHANNEL_OFDM }, \ -/*5640*/ { 128, DMN_FCC3, CHANNEL_OFDM }, \ -/*5660*/ { 132, DMN_FCC3, CHANNEL_OFDM }, \ -/*5680*/ { 136, DMN_FCC3, CHANNEL_OFDM }, \ -/*5700*/ { 140, DMN_FCC3, CHANNEL_OFDM }, \ -/*5745*/ { 149, DMN_FCC3, CHANNEL_OFDM }, \ -/*5760*/ { 152, DMN_FCC3, CHANNEL_OFDM|CHANNEL_TURBO }, \ -/*5765*/ { 153, DMN_FCC3, CHANNEL_OFDM }, \ -/*5785*/ { 157, DMN_FCC3, CHANNEL_OFDM }, \ -/*5800*/ { 160, DMN_FCC3, CHANNEL_OFDM|CHANNEL_TURBO }, \ -/*5805*/ { 161, DMN_FCC3, CHANNEL_OFDM }, \ -/*5825*/ { 165, DMN_FCC3, CHANNEL_OFDM }, \ - \ -/*5170*/ { 34, DMN_MKK1, CHANNEL_OFDM }, \ -/*5190*/ { 38, DMN_MKK1, CHANNEL_OFDM }, \ -/*5210*/ { 42, DMN_MKK1, CHANNEL_OFDM }, \ -/*5230*/ { 46, DMN_MKK1, CHANNEL_OFDM }, \ - \ -/*5040*/ { 8, DMN_MKK2, CHANNEL_OFDM }, \ -/*5060*/ { 12, DMN_MKK2, CHANNEL_OFDM }, \ -/*5080*/ { 16, DMN_MKK2, CHANNEL_OFDM }, \ -/*5170*/ { 34, DMN_MKK2, CHANNEL_OFDM }, \ -/*5190*/ { 38, DMN_MKK2, CHANNEL_OFDM }, \ -/*5210*/ { 42, DMN_MKK2, CHANNEL_OFDM }, \ -/*5230*/ { 46, DMN_MKK2, CHANNEL_OFDM }, \ - \ -/*5180*/ { 36, DMN_WORLD, CHANNEL_OFDM }, \ -/*5200*/ { 40, DMN_WORLD, CHANNEL_OFDM }, \ -/*5220*/ { 44, DMN_WORLD, CHANNEL_OFDM }, \ -/*5240*/ { 48, DMN_WORLD, CHANNEL_OFDM }, \ -} - -enum ath5k_regdom ath5k_regdom2flag(enum ath5k_regdom, u16); -u16 ath5k_regdom_from_ieee(enum ath5k_regdom ieee); -enum ath5k_regdom ath5k_regdom_to_ieee(u16 regdomain); - -#endif -- cgit v1.2.1