From 7314c2b377afaf367f2966bd9ea67bf83350e29b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 22 Sep 2010 18:01:55 +0200 Subject: [PATCH 001/127] iwlagn: rename iwl_commit_rxon iwl_commit_rxon really should be named iwlagn_commit_rxon, so rename it. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-4965.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-agn.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-agn.h | 3 +++ drivers/net/wireless/iwlwifi/iwl-core.h | 1 - 5 files changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 834c2f9c15d7..09db9407aa54 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2216,7 +2216,7 @@ static void iwl4965_cancel_deferred_work(struct iwl_priv *priv) static struct iwl_hcmd_ops iwl4965_hcmd = { .rxon_assoc = iwl4965_send_rxon_assoc, - .commit_rxon = iwl_commit_rxon, + .commit_rxon = iwlagn_commit_rxon, .set_rxon_chain = iwl_set_rxon_chain, .send_bt_config = iwl_send_bt_config, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c index 9ca6c91eaae6..901452ee623a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c @@ -360,7 +360,7 @@ static int iwlagn_set_pan_params(struct iwl_priv *priv) struct iwl_hcmd_ops iwlagn_hcmd = { .rxon_assoc = iwlagn_send_rxon_assoc, - .commit_rxon = iwl_commit_rxon, + .commit_rxon = iwlagn_commit_rxon, .set_rxon_chain = iwl_set_rxon_chain, .set_tx_ant = iwlagn_send_tx_ant_config, .send_bt_config = iwl_send_bt_config, @@ -369,7 +369,7 @@ struct iwl_hcmd_ops iwlagn_hcmd = { struct iwl_hcmd_ops iwlagn_bt_hcmd = { .rxon_assoc = iwlagn_send_rxon_assoc, - .commit_rxon = iwl_commit_rxon, + .commit_rxon = iwlagn_commit_rxon, .set_rxon_chain = iwl_set_rxon_chain, .set_tx_ant = iwlagn_send_tx_ant_config, .send_bt_config = iwlagn_send_advance_bt_config, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index a6dce616ee3c..b59ce92730c7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -91,14 +91,14 @@ static int iwlagn_ant_coupling; static bool iwlagn_bt_ch_announce = 1; /** - * iwl_commit_rxon - commit staging_rxon to hardware + * iwlagn_commit_rxon - commit staging_rxon to hardware * * The RXON command in staging_rxon is committed to the hardware and * the active_rxon structure is updated with the new data. This * function correctly transitions out of the RXON_ASSOC_MSK state if * a HW tune is required based on the RXON structure changes. */ -int iwl_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) +int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) { /* cast away the const for active_rxon in this function */ struct iwl_rxon_cmd *active_rxon = (void *)&ctx->active; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index eb3812a35862..2a1c83bda919 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -129,6 +129,9 @@ void iwlagn_txq_set_sched(struct iwl_priv *priv, u32 mask); void iwl_free_tfds_in_queue(struct iwl_priv *priv, int sta_id, int tid, int freed); +/* RXON */ +int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx); + /* uCode */ int iwlagn_load_ucode(struct iwl_priv *priv); void iwlagn_rx_calib_result(struct iwl_priv *priv, diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 6228b1c2ec96..d6d5bb0f0eb0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -432,7 +432,6 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf, u32 changes); -int iwl_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx); int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif); void iwl_mac_remove_interface(struct ieee80211_hw *hw, From a77029ee3fc03a37238b73892e55b789273991aa Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 22 Sep 2010 18:01:56 +0200 Subject: [PATCH 002/127] iwlwifi: introduce post_scan hook The different drivers need to do different things after a scan, so create a post_scan hook to allow them to do this. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-3945.c | 1 + drivers/net/wireless/iwlwifi/iwl-3945.h | 1 + drivers/net/wireless/iwlwifi/iwl-4965.c | 13 +++++++++++++ drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c | 1 + drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 16 ++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-agn.h | 1 + drivers/net/wireless/iwlwifi/iwl-core.h | 1 + drivers/net/wireless/iwlwifi/iwl-scan.c | 11 +---------- drivers/net/wireless/iwlwifi/iwl3945-base.c | 12 ++++++++++++ 9 files changed, 47 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index cfdff5487e3c..87943a8da797 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -2713,6 +2713,7 @@ static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = { .build_addsta_hcmd = iwl3945_build_addsta_hcmd, .tx_cmd_protection = iwlcore_tx_cmd_protection, .request_scan = iwl3945_request_scan, + .post_scan = iwl3945_post_scan, }; static const struct iwl_ops iwl3945_ops = { diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 98509c5e708d..7ad4aff5a550 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -296,6 +296,7 @@ extern int iwl3945_rs_next_rate(struct iwl_priv *priv, int rate); /* scanning */ int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif); +void iwl3945_post_scan(struct iwl_priv *priv); /* Requires full declaration of iwl_priv before including */ #include "iwl-io.h" diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 09db9407aa54..e161f5d7044d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2221,6 +2221,18 @@ static struct iwl_hcmd_ops iwl4965_hcmd = { .send_bt_config = iwl_send_bt_config, }; +static void iwl4965_post_scan(struct iwl_priv *priv) +{ + struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; + + /* + * Since setting the RXON may have been deferred while + * performing the scan, fire one off if needed + */ + if (memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging))) + iwlcore_commit_rxon(priv, ctx); +} + static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = { .get_hcmd_size = iwl4965_get_hcmd_size, .build_addsta_hcmd = iwl4965_build_addsta_hcmd, @@ -2229,6 +2241,7 @@ static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = { .tx_cmd_protection = iwlcore_tx_cmd_protection, .calc_rssi = iwl4965_calc_rssi, .request_scan = iwlagn_request_scan, + .post_scan = iwl4965_post_scan, }; static struct iwl_lib_ops iwl4965_lib = { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c index 901452ee623a..634177d827d3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c @@ -384,4 +384,5 @@ struct iwl_hcmd_utils_ops iwlagn_hcmd_utils = { .tx_cmd_protection = iwlagn_tx_cmd_protection, .calc_rssi = iwlagn_calc_rssi, .request_scan = iwlagn_request_scan, + .post_scan = iwlagn_post_scan, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index f5445d575fec..3fa2c5c3706a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -1565,6 +1565,22 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) return ret; } +void iwlagn_post_scan(struct iwl_priv *priv) +{ + struct iwl_rxon_context *ctx; + + /* + * Since setting the RXON may have been deferred while + * performing the scan, fire one off if needed + */ + for_each_context(priv, ctx) + if (memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging))) + iwlagn_commit_rxon(priv, ctx); + + if (priv->cfg->ops->hcmd->set_pan_params) + priv->cfg->ops->hcmd->set_pan_params(priv); +} + int iwlagn_manage_ibss_station(struct iwl_priv *priv, struct ieee80211_vif *vif, bool add) { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 2a1c83bda919..960fe2e5e579 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -227,6 +227,7 @@ void iwl_reply_statistics(struct iwl_priv *priv, /* scan */ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif); +void iwlagn_post_scan(struct iwl_priv *priv); /* station mgmt */ int iwlagn_manage_ibss_station(struct iwl_priv *priv, diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index d6d5bb0f0eb0..09908f604e28 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -112,6 +112,7 @@ struct iwl_hcmd_utils_ops { int (*calc_rssi)(struct iwl_priv *priv, struct iwl_rx_phy_res *rx_resp); int (*request_scan)(struct iwl_priv *priv, struct ieee80211_vif *vif); + void (*post_scan)(struct iwl_priv *priv); }; struct iwl_apm_ops { diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index eaae49ee0c60..a7e8c7f969f4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -559,7 +559,6 @@ static void iwl_bg_scan_completed(struct work_struct *work) struct iwl_priv *priv = container_of(work, struct iwl_priv, scan_completed); bool aborted; - struct iwl_rxon_context *ctx; IWL_DEBUG_SCAN(priv, "Completed %sscan.\n", priv->is_internal_short_scan ? "internal short " : ""); @@ -609,15 +608,7 @@ out_settings: * performing the scan, fire one off */ iwl_set_tx_power(priv, priv->tx_power_user_lmt, true); - /* - * Since setting the RXON may have been deferred while - * performing the scan, fire one off if needed - */ - for_each_context(priv, ctx) - iwlcore_commit_rxon(priv, ctx); - - if (priv->cfg->ops->hcmd->set_pan_params) - priv->cfg->ops->hcmd->set_pan_params(priv); + priv->cfg->ops->utils->post_scan(priv); out: mutex_unlock(&priv->mutex); diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 43db5f38e3e6..db148d05af1a 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2983,6 +2983,18 @@ int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) return ret; } +void iwl3945_post_scan(struct iwl_priv *priv) +{ + struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; + + /* + * Since setting the RXON may have been deferred while + * performing the scan, fire one off if needed + */ + if (memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging))) + iwlcore_commit_rxon(priv, ctx); +} + static void iwl3945_bg_restart(struct work_struct *data) { struct iwl_priv *priv = container_of(data, struct iwl_priv, restart); From 8289e07b8a4b588e167bc84f93419458fd6efa3e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 22 Sep 2010 18:01:57 +0200 Subject: [PATCH 003/127] iwl3945: use iwl3945_commit_rxon There's no need to go via the indirect function call from within the 3945 subdriver. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-3945.c | 3 +-- drivers/net/wireless/iwlwifi/iwl-3945.h | 3 +++ drivers/net/wireless/iwlwifi/iwl3945-base.c | 16 ++++++++-------- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 87943a8da797..ef670879e359 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -1763,8 +1763,7 @@ static int iwl3945_send_rxon_assoc(struct iwl_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 iwl3945_commit_rxon(struct iwl_priv *priv, - struct iwl_rxon_context *ctx) +int iwl3945_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx) { /* cast away the const for active_rxon in this function */ struct iwl3945_rxon_cmd *active_rxon = (void *)&ctx->active; diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 7ad4aff5a550..77e8e1970350 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -271,6 +271,9 @@ extern void iwl3945_post_associate(struct iwl_priv *priv, extern void iwl3945_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif); +extern int iwl3945_commit_rxon(struct iwl_priv *priv, + struct iwl_rxon_context *ctx); + /** * iwl3945_hw_find_station - Find station id for a given BSSID * @bssid: MAC address of station ID to find diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index db148d05af1a..64eb049140dc 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2547,7 +2547,7 @@ static void iwl3945_alive_start(struct iwl_priv *priv) priv->cfg->ops->hcmd->send_bt_config(priv); /* Configure the adapter for unassociated operation */ - iwlcore_commit_rxon(priv, ctx); + iwl3945_commit_rxon(priv, ctx); iwl3945_reg_txpower_periodic(priv); @@ -2992,7 +2992,7 @@ void iwl3945_post_scan(struct iwl_priv *priv) * performing the scan, fire one off if needed */ if (memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging))) - iwlcore_commit_rxon(priv, ctx); + iwl3945_commit_rxon(priv, ctx); } static void iwl3945_bg_restart(struct work_struct *data) @@ -3061,7 +3061,7 @@ void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif) conf = ieee80211_get_hw_conf(priv->hw); ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwlcore_commit_rxon(priv, ctx); + iwl3945_commit_rxon(priv, ctx); rc = iwl_send_rxon_timing(priv, ctx); if (rc) @@ -3087,7 +3087,7 @@ void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif) ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK; } - iwlcore_commit_rxon(priv, ctx); + iwl3945_commit_rxon(priv, ctx); switch (vif->type) { case NL80211_IFTYPE_STATION: @@ -3226,7 +3226,7 @@ void iwl3945_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) /* RXON - unassoc (to set timing command) */ ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwlcore_commit_rxon(priv, ctx); + iwl3945_commit_rxon(priv, ctx); /* RXON Timing */ rc = iwl_send_rxon_timing(priv, ctx); @@ -3253,7 +3253,7 @@ void iwl3945_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) } /* restore RXON assoc */ ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK; - iwlcore_commit_rxon(priv, ctx); + iwl3945_commit_rxon(priv, ctx); } iwl3945_send_beacon_cmd(priv); @@ -3519,7 +3519,7 @@ static ssize_t store_flags(struct device *d, IWL_DEBUG_INFO(priv, "Committing rxon.flags = 0x%04X\n", flags); ctx->staging.flags = cpu_to_le32(flags); - iwlcore_commit_rxon(priv, ctx); + iwl3945_commit_rxon(priv, ctx); } } mutex_unlock(&priv->mutex); @@ -3557,7 +3557,7 @@ static ssize_t store_filter_flags(struct device *d, "0x%04X\n", filter_flags); ctx->staging.filter_flags = cpu_to_le32(filter_flags); - iwlcore_commit_rxon(priv, ctx); + iwl3945_commit_rxon(priv, ctx); } } mutex_unlock(&priv->mutex); From 5de33068a2f841536ca8632534e3e193d5b2607f Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 22 Sep 2010 18:01:58 +0200 Subject: [PATCH 004/127] iwlwifi: move chain settings to agn The core module doesn't need to carry around the code for chain settings that is used for HT drivers (agn) only. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-4965.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c | 4 +- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 140 +++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-agn.h | 1 + drivers/net/wireless/iwlwifi/iwl-core.c | 141 -------------------- drivers/net/wireless/iwlwifi/iwl-core.h | 1 - 6 files changed, 144 insertions(+), 145 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index e161f5d7044d..20626c997b4e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2217,7 +2217,7 @@ static void iwl4965_cancel_deferred_work(struct iwl_priv *priv) static struct iwl_hcmd_ops iwl4965_hcmd = { .rxon_assoc = iwl4965_send_rxon_assoc, .commit_rxon = iwlagn_commit_rxon, - .set_rxon_chain = iwl_set_rxon_chain, + .set_rxon_chain = iwlagn_set_rxon_chain, .send_bt_config = iwl_send_bt_config, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c index 634177d827d3..ffb2f4111ad0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c @@ -361,7 +361,7 @@ static int iwlagn_set_pan_params(struct iwl_priv *priv) struct iwl_hcmd_ops iwlagn_hcmd = { .rxon_assoc = iwlagn_send_rxon_assoc, .commit_rxon = iwlagn_commit_rxon, - .set_rxon_chain = iwl_set_rxon_chain, + .set_rxon_chain = iwlagn_set_rxon_chain, .set_tx_ant = iwlagn_send_tx_ant_config, .send_bt_config = iwl_send_bt_config, .set_pan_params = iwlagn_set_pan_params, @@ -370,7 +370,7 @@ struct iwl_hcmd_ops iwlagn_hcmd = { struct iwl_hcmd_ops iwlagn_bt_hcmd = { .rxon_assoc = iwlagn_send_rxon_assoc, .commit_rxon = iwlagn_commit_rxon, - .set_rxon_chain = iwl_set_rxon_chain, + .set_rxon_chain = iwlagn_set_rxon_chain, .set_tx_ant = iwlagn_send_tx_ant_config, .send_bt_config = iwlagn_send_advance_bt_config, .set_pan_params = iwlagn_set_pan_params, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 3fa2c5c3706a..0b45bced9c0c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -2065,3 +2065,143 @@ void iwlagn_bt_cancel_deferred_work(struct iwl_priv *priv) { cancel_work_sync(&priv->bt_traffic_change_work); } + +static bool is_single_rx_stream(struct iwl_priv *priv) +{ + return priv->current_ht_config.smps == IEEE80211_SMPS_STATIC || + priv->current_ht_config.single_chain_sufficient; +} + +#define IWL_NUM_RX_CHAINS_MULTIPLE 3 +#define IWL_NUM_RX_CHAINS_SINGLE 2 +#define IWL_NUM_IDLE_CHAINS_DUAL 2 +#define IWL_NUM_IDLE_CHAINS_SINGLE 1 + +/* + * Determine how many receiver/antenna chains to use. + * + * More provides better reception via diversity. Fewer saves power + * at the expense of throughput, but only when not in powersave to + * start with. + * + * 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 iwl_get_active_rx_chain_count(struct iwl_priv *priv) +{ + if (priv->cfg->bt_params && + priv->cfg->bt_params->advanced_bt_coexist && + (priv->bt_full_concurrent || + priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)) { + /* + * only use chain 'A' in bt high traffic load or + * full concurrency mode + */ + return IWL_NUM_RX_CHAINS_SINGLE; + } + /* # of Rx chains to use when expecting MIMO. */ + if (is_single_rx_stream(priv)) + return IWL_NUM_RX_CHAINS_SINGLE; + else + return IWL_NUM_RX_CHAINS_MULTIPLE; +} + +/* + * When we are in power saving mode, unless device support spatial + * multiplexing power save, use the active count for rx chain count. + */ +static int iwl_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt) +{ + /* # Rx chains when idling, depending on SMPS mode */ + switch (priv->current_ht_config.smps) { + case IEEE80211_SMPS_STATIC: + case IEEE80211_SMPS_DYNAMIC: + return IWL_NUM_IDLE_CHAINS_SINGLE; + case IEEE80211_SMPS_OFF: + return active_cnt; + default: + WARN(1, "invalid SMPS mode %d", + priv->current_ht_config.smps); + return active_cnt; + } +} + +/* up to 4 chains */ +static u8 iwl_count_chain_bitmap(u32 chain_bitmap) +{ + u8 res; + res = (chain_bitmap & BIT(0)) >> 0; + res += (chain_bitmap & BIT(1)) >> 1; + res += (chain_bitmap & BIT(2)) >> 2; + res += (chain_bitmap & BIT(3)) >> 3; + return res; +} + +/** + * iwlagn_set_rxon_chain - Set up Rx chain usage in "staging" RXON image + * + * 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 iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx) +{ + bool is_single = is_single_rx_stream(priv); + bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status); + u8 idle_rx_cnt, active_rx_cnt, valid_rx_cnt; + u32 active_chains; + u16 rx_chain; + + /* Tell uCode which antennas are actually connected. + * Before first association, we assume all antennas are connected. + * Just after first association, iwl_chain_noise_calibration() + * checks which antennas actually *are* connected. */ + if (priv->chain_noise_data.active_chains) + active_chains = priv->chain_noise_data.active_chains; + else + active_chains = priv->hw_params.valid_rx_ant; + + if (priv->cfg->bt_params && + priv->cfg->bt_params->advanced_bt_coexist && + (priv->bt_full_concurrent || + priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)) { + /* + * only use chain 'A' in bt high traffic load or + * full concurrency mode + */ + active_chains = first_antenna(active_chains); + } + + rx_chain = active_chains << RXON_RX_CHAIN_VALID_POS; + + /* How many receivers should we use? */ + active_rx_cnt = iwl_get_active_rx_chain_count(priv); + idle_rx_cnt = iwl_get_idle_rx_chain_count(priv, active_rx_cnt); + + + /* correct rx chain count according hw settings + * and chain noise calibration + */ + valid_rx_cnt = iwl_count_chain_bitmap(active_chains); + if (valid_rx_cnt < active_rx_cnt) + active_rx_cnt = valid_rx_cnt; + + if (valid_rx_cnt < idle_rx_cnt) + idle_rx_cnt = valid_rx_cnt; + + rx_chain |= active_rx_cnt << RXON_RX_CHAIN_MIMO_CNT_POS; + rx_chain |= idle_rx_cnt << RXON_RX_CHAIN_CNT_POS; + + ctx->staging.rx_chain = cpu_to_le16(rx_chain); + + if (!is_single && (active_rx_cnt >= IWL_NUM_RX_CHAINS_SINGLE) && is_cam) + ctx->staging.rx_chain |= RXON_RX_CHAIN_MIMO_FORCE_MSK; + else + ctx->staging.rx_chain &= ~RXON_RX_CHAIN_MIMO_FORCE_MSK; + + IWL_DEBUG_ASSOC(priv, "rx_chain=0x%X active=%d idle=%d\n", + ctx->staging.rx_chain, + active_rx_cnt, idle_rx_cnt); + + WARN_ON(active_rx_cnt == 0 || idle_rx_cnt == 0 || + active_rx_cnt < idle_rx_cnt); +} diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 960fe2e5e579..5d5cacb54eb7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -131,6 +131,7 @@ void iwl_free_tfds_in_queue(struct iwl_priv *priv, /* RXON */ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx); +void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx); /* uCode */ int iwlagn_load_ucode(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 516c55ae38aa..dd7c3cbd2f6b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -439,12 +439,6 @@ void iwlcore_tx_cmd_protection(struct iwl_priv *priv, EXPORT_SYMBOL(iwlcore_tx_cmd_protection); -static bool is_single_rx_stream(struct iwl_priv *priv) -{ - return priv->current_ht_config.smps == IEEE80211_SMPS_STATIC || - priv->current_ht_config.single_chain_sufficient; -} - static bool iwl_is_channel_extension(struct iwl_priv *priv, enum ieee80211_band band, u16 channel, u8 extension_chan_offset) @@ -834,141 +828,6 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf) } EXPORT_SYMBOL(iwl_set_rxon_ht); -#define IWL_NUM_RX_CHAINS_MULTIPLE 3 -#define IWL_NUM_RX_CHAINS_SINGLE 2 -#define IWL_NUM_IDLE_CHAINS_DUAL 2 -#define IWL_NUM_IDLE_CHAINS_SINGLE 1 - -/* - * Determine how many receiver/antenna chains to use. - * - * More provides better reception via diversity. Fewer saves power - * at the expense of throughput, but only when not in powersave to - * start with. - * - * 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 iwl_get_active_rx_chain_count(struct iwl_priv *priv) -{ - if (priv->cfg->bt_params && - priv->cfg->bt_params->advanced_bt_coexist && - (priv->bt_full_concurrent || - priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)) { - /* - * only use chain 'A' in bt high traffic load or - * full concurrency mode - */ - return IWL_NUM_RX_CHAINS_SINGLE; - } - /* # of Rx chains to use when expecting MIMO. */ - if (is_single_rx_stream(priv)) - return IWL_NUM_RX_CHAINS_SINGLE; - else - return IWL_NUM_RX_CHAINS_MULTIPLE; -} - -/* - * When we are in power saving mode, unless device support spatial - * multiplexing power save, use the active count for rx chain count. - */ -static int iwl_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt) -{ - /* # Rx chains when idling, depending on SMPS mode */ - switch (priv->current_ht_config.smps) { - case IEEE80211_SMPS_STATIC: - case IEEE80211_SMPS_DYNAMIC: - return IWL_NUM_IDLE_CHAINS_SINGLE; - case IEEE80211_SMPS_OFF: - return active_cnt; - default: - WARN(1, "invalid SMPS mode %d", - priv->current_ht_config.smps); - return active_cnt; - } -} - -/* up to 4 chains */ -static u8 iwl_count_chain_bitmap(u32 chain_bitmap) -{ - u8 res; - res = (chain_bitmap & BIT(0)) >> 0; - res += (chain_bitmap & BIT(1)) >> 1; - res += (chain_bitmap & BIT(2)) >> 2; - res += (chain_bitmap & BIT(3)) >> 3; - return res; -} - -/** - * iwl_set_rxon_chain - Set up Rx chain usage in "staging" RXON image - * - * 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 iwl_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx) -{ - bool is_single = is_single_rx_stream(priv); - bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status); - u8 idle_rx_cnt, active_rx_cnt, valid_rx_cnt; - u32 active_chains; - u16 rx_chain; - - /* Tell uCode which antennas are actually connected. - * Before first association, we assume all antennas are connected. - * Just after first association, iwl_chain_noise_calibration() - * checks which antennas actually *are* connected. */ - if (priv->chain_noise_data.active_chains) - active_chains = priv->chain_noise_data.active_chains; - else - active_chains = priv->hw_params.valid_rx_ant; - - if (priv->cfg->bt_params && - priv->cfg->bt_params->advanced_bt_coexist && - (priv->bt_full_concurrent || - priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)) { - /* - * only use chain 'A' in bt high traffic load or - * full concurrency mode - */ - active_chains = first_antenna(active_chains); - } - - rx_chain = active_chains << RXON_RX_CHAIN_VALID_POS; - - /* How many receivers should we use? */ - active_rx_cnt = iwl_get_active_rx_chain_count(priv); - idle_rx_cnt = iwl_get_idle_rx_chain_count(priv, active_rx_cnt); - - - /* correct rx chain count according hw settings - * and chain noise calibration - */ - valid_rx_cnt = iwl_count_chain_bitmap(active_chains); - if (valid_rx_cnt < active_rx_cnt) - active_rx_cnt = valid_rx_cnt; - - if (valid_rx_cnt < idle_rx_cnt) - idle_rx_cnt = valid_rx_cnt; - - rx_chain |= active_rx_cnt << RXON_RX_CHAIN_MIMO_CNT_POS; - rx_chain |= idle_rx_cnt << RXON_RX_CHAIN_CNT_POS; - - ctx->staging.rx_chain = cpu_to_le16(rx_chain); - - if (!is_single && (active_rx_cnt >= IWL_NUM_RX_CHAINS_SINGLE) && is_cam) - ctx->staging.rx_chain |= RXON_RX_CHAIN_MIMO_FORCE_MSK; - else - ctx->staging.rx_chain &= ~RXON_RX_CHAIN_MIMO_FORCE_MSK; - - IWL_DEBUG_ASSOC(priv, "rx_chain=0x%X active=%d idle=%d\n", - ctx->staging.rx_chain, - active_rx_cnt, idle_rx_cnt); - - WARN_ON(active_rx_cnt == 0 || idle_rx_cnt == 0 || - active_rx_cnt < idle_rx_cnt); -} -EXPORT_SYMBOL(iwl_set_rxon_chain); - /* Return valid, unused, channel for a passive scan to reset the RF */ u8 iwl_get_single_channel_number(struct iwl_priv *priv, enum ieee80211_band band) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 09908f604e28..50a3c26e1412 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -407,7 +407,6 @@ void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, struct iwl_rxon_context *ctx, int hw_decrypt); int iwl_check_rxon_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx); int iwl_full_rxon_required(struct iwl_priv *priv, struct iwl_rxon_context *ctx); -void iwl_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx); int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch, struct iwl_rxon_context *ctx); void iwl_set_flags_for_band(struct iwl_priv *priv, From 575ccfd0f47e5d791246cb03c07d636190322fa1 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 22 Sep 2010 18:01:59 +0200 Subject: [PATCH 005/127] iwlwifi: rename iwl_mac_beacon_update Rename iwl_mac_beacon_update to iwlcore_beacon_update and make the calling convention a bit different. The old name with _mac_ indicated that it was a mac80211 callback, but that's no longer true. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-core.c | 35 ++++++++++++------------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index dd7c3cbd2f6b..71f245f3f0f6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1617,25 +1617,25 @@ static inline void iwl_set_no_assoc(struct iwl_priv *priv, iwlcore_commit_rxon(priv, ctx); } -static int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) +static void iwlcore_beacon_update(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) { struct iwl_priv *priv = hw->priv; unsigned long flags; __le64 timestamp; + struct sk_buff *skb = ieee80211_beacon_get(hw, vif); - IWL_DEBUG_MAC80211(priv, "enter\n"); + if (!skb) + return; + + IWL_DEBUG_ASSOC(priv, "enter\n"); lockdep_assert_held(&priv->mutex); if (!priv->beacon_ctx) { IWL_ERR(priv, "update beacon but no beacon context!\n"); dev_kfree_skb(skb); - return -EINVAL; - } - - if (!iwl_is_ready_rf(priv)) { - IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n"); - return -EIO; + return; } spin_lock_irqsave(&priv->lock, flags); @@ -1648,12 +1648,16 @@ static int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp; priv->timestamp = le64_to_cpu(timestamp); - IWL_DEBUG_MAC80211(priv, "leave\n"); + IWL_DEBUG_ASSOC(priv, "leave\n"); + spin_unlock_irqrestore(&priv->lock, flags); - priv->cfg->ops->lib->post_associate(priv, priv->beacon_ctx->vif); + if (!iwl_is_ready_rf(priv)) { + IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n"); + return; + } - return 0; + priv->cfg->ops->lib->post_associate(priv, priv->beacon_ctx->vif); } void iwl_bss_info_changed(struct ieee80211_hw *hw, @@ -1735,13 +1739,8 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, * mac80211 decides to do both changes at once because * it will invoke post_associate. */ - if (vif->type == NL80211_IFTYPE_ADHOC && - changes & BSS_CHANGED_BEACON) { - struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); - - if (beacon) - iwl_mac_beacon_update(hw, beacon); - } + if (vif->type == NL80211_IFTYPE_ADHOC && changes & BSS_CHANGED_BEACON) + iwlcore_beacon_update(hw, vif); if (changes & BSS_CHANGED_ERP_PREAMBLE) { IWL_DEBUG_MAC80211(priv, "ERP_PREAMBLE %d\n", From d3f5ba958d6c425a87535c6fa2a69ca90eb6e930 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 22 Sep 2010 18:02:00 +0200 Subject: [PATCH 006/127] iwlwifi: remove verify_signature eeprom operation All drivers share the same implementation, so there's no need to call this via a function pointer nor to export it. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-1000.c | 1 - drivers/net/wireless/iwlwifi/iwl-3945.c | 1 - drivers/net/wireless/iwlwifi/iwl-4965.c | 1 - drivers/net/wireless/iwlwifi/iwl-5000.c | 2 -- drivers/net/wireless/iwlwifi/iwl-6000.c | 2 -- drivers/net/wireless/iwlwifi/iwl-eeprom.c | 5 ++--- drivers/net/wireless/iwlwifi/iwl-eeprom.h | 1 - 7 files changed, 2 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 134f54541330..8c2db55df426 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -209,7 +209,6 @@ static struct iwl_lib_ops iwl1000_lib = { EEPROM_REG_BAND_24_HT40_CHANNELS, EEPROM_REG_BAND_52_HT40_CHANNELS }, - .verify_signature = iwlcore_eeprom_verify_signature, .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, .release_semaphore = iwlcore_eeprom_release_semaphore, .calib_version = iwlagn_eeprom_calib_version, diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index ef670879e359..a7dbb2806b1a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -2686,7 +2686,6 @@ static struct iwl_lib_ops iwl3945_lib = { EEPROM_REGULATORY_BAND_NO_HT40, EEPROM_REGULATORY_BAND_NO_HT40, }, - .verify_signature = iwlcore_eeprom_verify_signature, .acquire_semaphore = iwl3945_eeprom_acquire_semaphore, .release_semaphore = iwl3945_eeprom_release_semaphore, .query_addr = iwlcore_eeprom_query_addr, diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 20626c997b4e..08d2dbc4efb3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2280,7 +2280,6 @@ static struct iwl_lib_ops iwl4965_lib = { EEPROM_4965_REGULATORY_BAND_24_HT40_CHANNELS, EEPROM_4965_REGULATORY_BAND_52_HT40_CHANNELS }, - .verify_signature = iwlcore_eeprom_verify_signature, .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, .release_semaphore = iwlcore_eeprom_release_semaphore, .calib_version = iwl4965_eeprom_calib_version, diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 1b25ad63b5c1..ddbbb9320aca 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -384,7 +384,6 @@ static struct iwl_lib_ops iwl5000_lib = { EEPROM_REG_BAND_24_HT40_CHANNELS, EEPROM_REG_BAND_52_HT40_CHANNELS }, - .verify_signature = iwlcore_eeprom_verify_signature, .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, .release_semaphore = iwlcore_eeprom_release_semaphore, .calib_version = iwlagn_eeprom_calib_version, @@ -456,7 +455,6 @@ static struct iwl_lib_ops iwl5150_lib = { EEPROM_REG_BAND_24_HT40_CHANNELS, EEPROM_REG_BAND_52_HT40_CHANNELS }, - .verify_signature = iwlcore_eeprom_verify_signature, .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, .release_semaphore = iwlcore_eeprom_release_semaphore, .calib_version = iwlagn_eeprom_calib_version, diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 6261aec5ebdc..198cd8f40de3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -323,7 +323,6 @@ static struct iwl_lib_ops iwl6000_lib = { EEPROM_6000_REG_BAND_24_HT40_CHANNELS, EEPROM_REG_BAND_52_HT40_CHANNELS }, - .verify_signature = iwlcore_eeprom_verify_signature, .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, .release_semaphore = iwlcore_eeprom_release_semaphore, .calib_version = iwlagn_eeprom_calib_version, @@ -398,7 +397,6 @@ static struct iwl_lib_ops iwl6000g2b_lib = { EEPROM_6000_REG_BAND_24_HT40_CHANNELS, EEPROM_REG_BAND_52_HT40_CHANNELS }, - .verify_signature = iwlcore_eeprom_verify_signature, .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, .release_semaphore = iwlcore_eeprom_release_semaphore, .calib_version = iwlagn_eeprom_calib_version, diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index 88f4a80d4733..bd51b06288eb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -214,7 +214,7 @@ static const struct iwl_txpwr_section enhinfo[] = { * ******************************************************************************/ -int iwlcore_eeprom_verify_signature(struct iwl_priv *priv) +static int iwl_eeprom_verify_signature(struct iwl_priv *priv) { u32 gp = iwl_read32(priv, CSR_EEPROM_GP) & CSR_EEPROM_GP_VALID_MSK; int ret = 0; @@ -246,7 +246,6 @@ int iwlcore_eeprom_verify_signature(struct iwl_priv *priv) } return ret; } -EXPORT_SYMBOL(iwlcore_eeprom_verify_signature); static void iwl_set_otp_access(struct iwl_priv *priv, enum iwl_access_mode mode) { @@ -523,7 +522,7 @@ int iwl_eeprom_init(struct iwl_priv *priv) priv->cfg->ops->lib->apm_ops.init(priv); - ret = priv->cfg->ops->lib->eeprom_ops.verify_signature(priv); + ret = iwl_eeprom_verify_signature(priv); if (ret < 0) { IWL_ERR(priv, "EEPROM not found, EEPROM_GP=0x%08x\n", gp); ret = -ENOENT; diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h index a4772aff51fe..2ae0a11e523b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h @@ -493,7 +493,6 @@ struct iwl_eeprom_calib_info { struct iwl_eeprom_ops { const u32 regulatory_bands[7]; - int (*verify_signature) (struct iwl_priv *priv); int (*acquire_semaphore) (struct iwl_priv *priv); void (*release_semaphore) (struct iwl_priv *priv); u16 (*calib_version) (struct iwl_priv *priv); From a30e3112a8bcb5bc1caa48547e597de3992e1b21 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 22 Sep 2010 18:02:01 +0200 Subject: [PATCH 007/127] iwlwifi: move agn specific station code there By duplicating a little bit of code between 3945 and agn, we can move a lot of code into an agn specific station management file and thus reduce the amount of code in core that is dead to 3945. before: text data bss dec hex filename 212886 3872 96 216854 34f16 iwlcore.ko 620542 10448 304 631294 9a1fe iwlagn.ko 314013 3264 196 317473 4d821 iwl3945.ko after: text data bss dec hex filename 202857 3872 92 206821 327e5 iwlcore.ko 629102 10448 308 639858 9c372 iwlagn.ko 314240 3264 196 317700 4d904 iwl3945.ko delta: -10029 iwlcore.ko 8560 iwlagn.ko 227 iwl3945.ko so it's a net win even if you have both loaded, likely because a lot of EXPORT_SYMBOLs go away. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/Makefile | 2 +- drivers/net/wireless/iwlwifi/iwl-3945.c | 32 +- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 6 +- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 1 + drivers/net/wireless/iwlwifi/iwl-agn-sta.c | 716 +++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn.h | 31 + drivers/net/wireless/iwlwifi/iwl-core.h | 2 - drivers/net/wireless/iwlwifi/iwl-sta.c | 727 +------------------- drivers/net/wireless/iwlwifi/iwl-sta.h | 35 +- drivers/net/wireless/iwlwifi/iwl3945-base.c | 25 +- 11 files changed, 824 insertions(+), 755 deletions(-) create mode 100644 drivers/net/wireless/iwlwifi/iwl-agn-sta.c diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 493163925a45..b4b24b67892c 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile @@ -12,7 +12,7 @@ obj-$(CONFIG_IWLAGN) += iwlagn.o iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o iwl-agn-ict.o iwlagn-objs += iwl-agn-ucode.o iwl-agn-hcmd.o iwl-agn-tx.o iwlagn-objs += iwl-agn-lib.o iwl-agn-rx.o iwl-agn-calib.o -iwlagn-objs += iwl-agn-tt.o +iwlagn-objs += iwl-agn-tt.o iwl-agn-sta.o iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-agn-debugfs.o iwlagn-$(CONFIG_IWL4965) += iwl-4965.o diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index a7dbb2806b1a..4b3eb785dcb2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -2299,6 +2299,32 @@ static u16 iwl3945_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data) return (u16)sizeof(struct iwl3945_addsta_cmd); } +static int iwl3945_add_bssid_station(struct iwl_priv *priv, + const u8 *addr, u8 *sta_id_r) +{ + struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; + int ret; + u8 sta_id; + unsigned long flags; + + if (sta_id_r) + *sta_id_r = IWL_INVALID_STATION; + + ret = iwl_add_station_common(priv, ctx, addr, 0, NULL, &sta_id); + if (ret) { + IWL_ERR(priv, "Unable to add station %pM\n", addr); + return ret; + } + + if (sta_id_r) + *sta_id_r = sta_id; + + spin_lock_irqsave(&priv->sta_lock, flags); + priv->stations[sta_id].used |= IWL_STA_LOCAL; + spin_unlock_irqrestore(&priv->sta_lock, flags); + + return 0; +} static int iwl3945_manage_ibss_station(struct iwl_priv *priv, struct ieee80211_vif *vif, bool add) { @@ -2306,10 +2332,8 @@ static int iwl3945_manage_ibss_station(struct iwl_priv *priv, int ret; if (add) { - ret = iwl_add_bssid_station( - priv, &priv->contexts[IWL_RXON_CTX_BSS], - vif->bss_conf.bssid, false, - &vif_priv->ibss_bssid_sta_id); + ret = iwl3945_add_bssid_station(priv, vif->bss_conf.bssid, + &vif_priv->ibss_bssid_sta_id); if (ret) return ret; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 0b45bced9c0c..3eeab0a99def 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -1587,9 +1587,9 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv, struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; if (add) - return iwl_add_bssid_station(priv, vif_priv->ctx, - vif->bss_conf.bssid, true, - &vif_priv->ibss_bssid_sta_id); + return iwlagn_add_bssid_station(priv, vif_priv->ctx, + vif->bss_conf.bssid, + &vif_priv->ibss_bssid_sta_id); return iwl_remove_station(priv, vif_priv->ibss_bssid_sta_id, vif->bss_conf.bssid); } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index f865685fd5f5..7e5cf1a2b21e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -39,6 +39,7 @@ #include "iwl-dev.h" #include "iwl-sta.h" #include "iwl-core.h" +#include "iwl-agn.h" #define RS_NAME "iwl-agn-rs" diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c new file mode 100644 index 000000000000..35a30d2e0734 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c @@ -0,0 +1,716 @@ +/****************************************************************************** + * + * Copyright(c) 2003 - 2010 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: + * Intel Linux Wireless + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + *****************************************************************************/ + +#include + +#include "iwl-dev.h" +#include "iwl-core.h" +#include "iwl-sta.h" +#include "iwl-agn.h" + +static struct iwl_link_quality_cmd * +iwl_sta_alloc_lq(struct iwl_priv *priv, u8 sta_id) +{ + int i, r; + struct iwl_link_quality_cmd *link_cmd; + u32 rate_flags = 0; + __le32 rate_n_flags; + + link_cmd = kzalloc(sizeof(struct iwl_link_quality_cmd), GFP_KERNEL); + if (!link_cmd) { + IWL_ERR(priv, "Unable to allocate memory for LQ cmd.\n"); + return NULL; + } + /* Set up the rate scaling to start at selected rate, fall back + * all the way down to 1M in IEEE order, and then spin on 1M */ + if (priv->band == IEEE80211_BAND_5GHZ) + r = IWL_RATE_6M_INDEX; + else + r = IWL_RATE_1M_INDEX; + + if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE) + rate_flags |= RATE_MCS_CCK_MSK; + + rate_flags |= first_antenna(priv->hw_params.valid_tx_ant) << + RATE_MCS_ANT_POS; + rate_n_flags = iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags); + for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) + link_cmd->rs_table[i].rate_n_flags = rate_n_flags; + + link_cmd->general_params.single_stream_ant_msk = + first_antenna(priv->hw_params.valid_tx_ant); + + link_cmd->general_params.dual_stream_ant_msk = + priv->hw_params.valid_tx_ant & + ~first_antenna(priv->hw_params.valid_tx_ant); + if (!link_cmd->general_params.dual_stream_ant_msk) { + link_cmd->general_params.dual_stream_ant_msk = ANT_AB; + } else if (num_of_ant(priv->hw_params.valid_tx_ant) == 2) { + link_cmd->general_params.dual_stream_ant_msk = + priv->hw_params.valid_tx_ant; + } + + link_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF; + link_cmd->agg_params.agg_time_limit = + cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF); + + link_cmd->sta_id = sta_id; + + return link_cmd; +} + +/* + * iwlagn_add_bssid_station - Add the special IBSS BSSID station + * + * Function sleeps. + */ +int iwlagn_add_bssid_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx, + const u8 *addr, u8 *sta_id_r) +{ + int ret; + u8 sta_id; + struct iwl_link_quality_cmd *link_cmd; + unsigned long flags; + + if (sta_id_r) + *sta_id_r = IWL_INVALID_STATION; + + ret = iwl_add_station_common(priv, ctx, addr, 0, NULL, &sta_id); + if (ret) { + IWL_ERR(priv, "Unable to add station %pM\n", addr); + return ret; + } + + if (sta_id_r) + *sta_id_r = sta_id; + + spin_lock_irqsave(&priv->sta_lock, flags); + priv->stations[sta_id].used |= IWL_STA_LOCAL; + spin_unlock_irqrestore(&priv->sta_lock, flags); + + /* Set up default rate scaling table in device's station table */ + link_cmd = iwl_sta_alloc_lq(priv, sta_id); + if (!link_cmd) { + IWL_ERR(priv, "Unable to initialize rate scaling for station %pM.\n", + addr); + return -ENOMEM; + } + + ret = iwl_send_lq_cmd(priv, ctx, link_cmd, CMD_SYNC, true); + if (ret) + IWL_ERR(priv, "Link quality command failed (%d)\n", ret); + + spin_lock_irqsave(&priv->sta_lock, flags); + priv->stations[sta_id].lq = link_cmd; + spin_unlock_irqrestore(&priv->sta_lock, flags); + + return 0; +} + +static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, + struct iwl_rxon_context *ctx, + bool 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 = ctx->wep_key_cmd, + .data = wep_cmd, + .flags = CMD_SYNC, + }; + + might_sleep(); + + 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 (ctx->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 = ctx->wep_keys[i].key_size; + memcpy(&wep_cmd->key[i].key[3], ctx->wep_keys[i].key, + ctx->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_restore_default_wep_keys(struct iwl_priv *priv, + struct iwl_rxon_context *ctx) +{ + lockdep_assert_held(&priv->mutex); + + return iwl_send_static_wepkey_cmd(priv, ctx, false); +} + +int iwl_remove_default_wep_key(struct iwl_priv *priv, + struct iwl_rxon_context *ctx, + struct ieee80211_key_conf *keyconf) +{ + int ret; + + lockdep_assert_held(&priv->mutex); + + IWL_DEBUG_WEP(priv, "Removing default WEP key: idx=%d\n", + keyconf->keyidx); + + memset(&ctx->wep_keys[keyconf->keyidx], 0, sizeof(ctx->wep_keys[0])); + if (iwl_is_rfkill(priv)) { + IWL_DEBUG_WEP(priv, "Not sending REPLY_WEPKEY command due to RFKILL.\n"); + /* but keys in device are clear anyway so return success */ + return 0; + } + ret = iwl_send_static_wepkey_cmd(priv, ctx, 1); + IWL_DEBUG_WEP(priv, "Remove default WEP key: idx=%d ret=%d\n", + keyconf->keyidx, ret); + + return ret; +} + +int iwl_set_default_wep_key(struct iwl_priv *priv, + struct iwl_rxon_context *ctx, + struct ieee80211_key_conf *keyconf) +{ + int ret; + + lockdep_assert_held(&priv->mutex); + + if (keyconf->keylen != WEP_KEY_LEN_128 && + keyconf->keylen != WEP_KEY_LEN_64) { + IWL_DEBUG_WEP(priv, "Bad WEP key length %d\n", keyconf->keylen); + return -EINVAL; + } + + keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV; + keyconf->hw_key_idx = HW_KEY_DEFAULT; + priv->stations[ctx->ap_sta_id].keyinfo.cipher = keyconf->cipher; + + ctx->wep_keys[keyconf->keyidx].key_size = keyconf->keylen; + memcpy(&ctx->wep_keys[keyconf->keyidx].key, &keyconf->key, + keyconf->keylen); + + ret = iwl_send_static_wepkey_cmd(priv, ctx, false); + IWL_DEBUG_WEP(priv, "Set default WEP key: len=%d idx=%d ret=%d\n", + keyconf->keylen, keyconf->keyidx, ret); + + return ret; +} + +static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv, + struct iwl_rxon_context *ctx, + struct ieee80211_key_conf *keyconf, + u8 sta_id) +{ + unsigned long flags; + __le16 key_flags = 0; + struct iwl_addsta_cmd sta_cmd; + + lockdep_assert_held(&priv->mutex); + + keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV; + + 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 == ctx->bcast_sta_id) + key_flags |= STA_KEY_MULTICAST_MSK; + + spin_lock_irqsave(&priv->sta_lock, flags); + + priv->stations[sta_id].keyinfo.cipher = keyconf->cipher; + 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); + + if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK) + == STA_KEY_FLG_NO_ENC) + priv->stations[sta_id].sta.key.key_offset = + iwl_get_free_ucode_key_index(priv); + /* else, we are overriding an existing key => no need to allocated room + * in uCode. */ + + WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET, + "no space for a new key"); + + 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; + + memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); + spin_unlock_irqrestore(&priv->sta_lock, flags); + + return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); +} + +static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv, + struct iwl_rxon_context *ctx, + struct ieee80211_key_conf *keyconf, + u8 sta_id) +{ + unsigned long flags; + __le16 key_flags = 0; + struct iwl_addsta_cmd sta_cmd; + + lockdep_assert_held(&priv->mutex); + + 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 == ctx->bcast_sta_id) + key_flags |= STA_KEY_MULTICAST_MSK; + + keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; + + spin_lock_irqsave(&priv->sta_lock, flags); + priv->stations[sta_id].keyinfo.cipher = keyconf->cipher; + 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); + + if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK) + == STA_KEY_FLG_NO_ENC) + priv->stations[sta_id].sta.key.key_offset = + iwl_get_free_ucode_key_index(priv); + /* else, we are overriding an existing key => no need to allocated room + * in uCode. */ + + WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET, + "no space for a new key"); + + 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; + + memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); + spin_unlock_irqrestore(&priv->sta_lock, flags); + + return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); +} + +static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv, + struct iwl_rxon_context *ctx, + struct ieee80211_key_conf *keyconf, + u8 sta_id) +{ + unsigned long flags; + int ret = 0; + __le16 key_flags = 0; + + 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 == ctx->bcast_sta_id) + key_flags |= STA_KEY_MULTICAST_MSK; + + keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; + keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; + + spin_lock_irqsave(&priv->sta_lock, flags); + + priv->stations[sta_id].keyinfo.cipher = keyconf->cipher; + priv->stations[sta_id].keyinfo.keylen = 16; + + if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK) + == STA_KEY_FLG_NO_ENC) + priv->stations[sta_id].sta.key.key_offset = + iwl_get_free_ucode_key_index(priv); + /* else, we are overriding an existing key => no need to allocated room + * in uCode. */ + + WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET, + "no space for a new key"); + + priv->stations[sta_id].sta.key.key_flags = key_flags; + + + /* 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; +} + +void iwl_update_tkip_key(struct iwl_priv *priv, + struct iwl_rxon_context *ctx, + struct ieee80211_key_conf *keyconf, + struct ieee80211_sta *sta, u32 iv32, u16 *phase1key) +{ + u8 sta_id; + unsigned long flags; + int i; + + if (iwl_scan_cancel(priv)) { + /* cancel scan failed, just live w/ bad key and rely + briefly on SW decryption */ + return; + } + + sta_id = iwl_sta_id_or_broadcast(priv, ctx, sta); + if (sta_id == IWL_INVALID_STATION) + return; + + spin_lock_irqsave(&priv->sta_lock, 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; + + iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); + + spin_unlock_irqrestore(&priv->sta_lock, flags); + +} + +int iwl_remove_dynamic_key(struct iwl_priv *priv, + struct iwl_rxon_context *ctx, + struct ieee80211_key_conf *keyconf, + u8 sta_id) +{ + unsigned long flags; + u16 key_flags; + u8 keyidx; + struct iwl_addsta_cmd sta_cmd; + + lockdep_assert_held(&priv->mutex); + + ctx->key_mapping_keys--; + + spin_lock_irqsave(&priv->sta_lock, flags); + key_flags = le16_to_cpu(priv->stations[sta_id].sta.key.key_flags); + keyidx = (key_flags >> STA_KEY_FLG_KEYID_POS) & 0x3; + + IWL_DEBUG_WEP(priv, "Remove dynamic key: idx=%d sta=%d\n", + keyconf->keyidx, sta_id); + + if (keyconf->keyidx != keyidx) { + /* We need to remove a key with index different that the one + * in the uCode. This means that the key we need to remove has + * been replaced by another one with different index. + * Don't do anything and return ok + */ + spin_unlock_irqrestore(&priv->sta_lock, flags); + return 0; + } + + if (priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET) { + IWL_WARN(priv, "Removing wrong key %d 0x%x\n", + keyconf->keyidx, key_flags); + spin_unlock_irqrestore(&priv->sta_lock, flags); + return 0; + } + + if (!test_and_clear_bit(priv->stations[sta_id].sta.key.key_offset, + &priv->ucode_key_table)) + IWL_ERR(priv, "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 iwl_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 | STA_KEY_FLG_INVALID; + priv->stations[sta_id].sta.key.key_offset = WEP_INVALID_OFFSET; + priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; + priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; + + if (iwl_is_rfkill(priv)) { + IWL_DEBUG_WEP(priv, "Not sending REPLY_ADD_STA command because RFKILL enabled.\n"); + spin_unlock_irqrestore(&priv->sta_lock, flags); + return 0; + } + memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); + spin_unlock_irqrestore(&priv->sta_lock, flags); + + return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); +} + +int iwl_set_dynamic_key(struct iwl_priv *priv, struct iwl_rxon_context *ctx, + struct ieee80211_key_conf *keyconf, u8 sta_id) +{ + int ret; + + lockdep_assert_held(&priv->mutex); + + ctx->key_mapping_keys++; + keyconf->hw_key_idx = HW_KEY_DYNAMIC; + + switch (keyconf->cipher) { + case WLAN_CIPHER_SUITE_CCMP: + ret = iwl_set_ccmp_dynamic_key_info(priv, ctx, keyconf, sta_id); + break; + case WLAN_CIPHER_SUITE_TKIP: + ret = iwl_set_tkip_dynamic_key_info(priv, ctx, keyconf, sta_id); + break; + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + ret = iwl_set_wep_dynamic_key_info(priv, ctx, keyconf, sta_id); + break; + default: + IWL_ERR(priv, + "Unknown alg: %s cipher = %x\n", __func__, + keyconf->cipher); + ret = -EINVAL; + } + + IWL_DEBUG_WEP(priv, "Set dynamic key: cipher=%x len=%d idx=%d sta=%d ret=%d\n", + keyconf->cipher, keyconf->keylen, keyconf->keyidx, + sta_id, ret); + + return ret; +} + +/** + * iwlagn_alloc_bcast_station - add broadcast station into driver's station table. + * + * This adds the broadcast station into the driver's station table + * and marks it driver active, so that it will be restored to the + * device at the next best time. + */ +int iwlagn_alloc_bcast_station(struct iwl_priv *priv, + struct iwl_rxon_context *ctx) +{ + struct iwl_link_quality_cmd *link_cmd; + unsigned long flags; + u8 sta_id; + + spin_lock_irqsave(&priv->sta_lock, flags); + sta_id = iwl_prep_station(priv, ctx, iwl_bcast_addr, false, NULL); + if (sta_id == IWL_INVALID_STATION) { + IWL_ERR(priv, "Unable to prepare broadcast station\n"); + spin_unlock_irqrestore(&priv->sta_lock, flags); + + return -EINVAL; + } + + priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE; + priv->stations[sta_id].used |= IWL_STA_BCAST; + spin_unlock_irqrestore(&priv->sta_lock, flags); + + link_cmd = iwl_sta_alloc_lq(priv, sta_id); + if (!link_cmd) { + IWL_ERR(priv, + "Unable to initialize rate scaling for bcast station.\n"); + return -ENOMEM; + } + + spin_lock_irqsave(&priv->sta_lock, flags); + priv->stations[sta_id].lq = link_cmd; + spin_unlock_irqrestore(&priv->sta_lock, flags); + + return 0; +} + +/** + * iwl_update_bcast_station - update broadcast station's LQ command + * + * Only used by iwlagn. Placed here to have all bcast station management + * code together. + */ +static int iwl_update_bcast_station(struct iwl_priv *priv, + struct iwl_rxon_context *ctx) +{ + unsigned long flags; + struct iwl_link_quality_cmd *link_cmd; + u8 sta_id = ctx->bcast_sta_id; + + link_cmd = iwl_sta_alloc_lq(priv, sta_id); + if (!link_cmd) { + IWL_ERR(priv, "Unable to initialize rate scaling for bcast station.\n"); + return -ENOMEM; + } + + spin_lock_irqsave(&priv->sta_lock, flags); + if (priv->stations[sta_id].lq) + kfree(priv->stations[sta_id].lq); + else + IWL_DEBUG_INFO(priv, "Bcast station rate scaling has not been initialized yet.\n"); + priv->stations[sta_id].lq = link_cmd; + spin_unlock_irqrestore(&priv->sta_lock, flags); + + return 0; +} + +int iwl_update_bcast_stations(struct iwl_priv *priv) +{ + struct iwl_rxon_context *ctx; + int ret = 0; + + for_each_context(priv, ctx) { + ret = iwl_update_bcast_station(priv, ctx); + if (ret) + break; + } + + return ret; +} + +/** + * iwl_sta_tx_modify_enable_tid - Enable Tx for this TID in station table + */ +int iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid) +{ + unsigned long flags; + struct iwl_addsta_cmd sta_cmd; + + lockdep_assert_held(&priv->mutex); + + /* Remove "disable" flag, to enable Tx for this TID */ + spin_lock_irqsave(&priv->sta_lock, flags); + priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_TID_DISABLE_TX; + priv->stations[sta_id].sta.tid_disable_tx &= cpu_to_le16(~(1 << tid)); + priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; + memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); + spin_unlock_irqrestore(&priv->sta_lock, flags); + + return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); +} + +int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta, + int tid, u16 ssn) +{ + unsigned long flags; + int sta_id; + struct iwl_addsta_cmd sta_cmd; + + lockdep_assert_held(&priv->mutex); + + sta_id = iwl_sta_id(sta); + if (sta_id == IWL_INVALID_STATION) + return -ENXIO; + + spin_lock_irqsave(&priv->sta_lock, flags); + priv->stations[sta_id].sta.station_flags_msk = 0; + priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_ADDBA_TID_MSK; + priv->stations[sta_id].sta.add_immediate_ba_tid = (u8)tid; + priv->stations[sta_id].sta.add_immediate_ba_ssn = cpu_to_le16(ssn); + priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; + memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); + spin_unlock_irqrestore(&priv->sta_lock, flags); + + return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); +} + +int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta, + int tid) +{ + unsigned long flags; + int sta_id; + struct iwl_addsta_cmd sta_cmd; + + lockdep_assert_held(&priv->mutex); + + sta_id = iwl_sta_id(sta); + if (sta_id == IWL_INVALID_STATION) { + IWL_ERR(priv, "Invalid station for AGG tid %d\n", tid); + return -ENXIO; + } + + spin_lock_irqsave(&priv->sta_lock, flags); + priv->stations[sta_id].sta.station_flags_msk = 0; + priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK; + priv->stations[sta_id].sta.remove_immediate_ba_tid = (u8)tid; + priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; + memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); + spin_unlock_irqrestore(&priv->sta_lock, flags); + + return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); +} + +void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id) +{ + unsigned long flags; + + spin_lock_irqsave(&priv->sta_lock, flags); + priv->stations[sta_id].sta.station_flags &= ~STA_FLG_PWR_SAVE_MSK; + priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK; + priv->stations[sta_id].sta.sta.modify_mask = 0; + priv->stations[sta_id].sta.sleep_tx_count = 0; + priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; + iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); + spin_unlock_irqrestore(&priv->sta_lock, flags); + +} + +void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt) +{ + unsigned long flags; + + spin_lock_irqsave(&priv->sta_lock, flags); + priv->stations[sta_id].sta.station_flags |= STA_FLG_PWR_SAVE_MSK; + priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK; + priv->stations[sta_id].sta.sta.modify_mask = + STA_MODIFY_SLEEP_TX_COUNT_MSK; + priv->stations[sta_id].sta.sleep_tx_count = cpu_to_le16(cnt); + priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; + iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); + spin_unlock_irqrestore(&priv->sta_lock, flags); + +} diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index b59ce92730c7..8233c6410411 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -3089,7 +3089,7 @@ static int __iwl_up(struct iwl_priv *priv) } for_each_context(priv, ctx) { - ret = iwl_alloc_bcast_station(priv, ctx, true); + ret = iwlagn_alloc_bcast_station(priv, ctx); if (ret) { iwl_dealloc_bcast_stations(priv); return ret; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 5d5cacb54eb7..632ea4ba82bb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -252,4 +252,35 @@ const char *iwl_get_agg_tx_fail_reason(u16 status); #else static inline const char *iwl_get_agg_tx_fail_reason(u16 status) { return ""; } #endif + +/* station management */ +int iwlagn_alloc_bcast_station(struct iwl_priv *priv, + struct iwl_rxon_context *ctx); +int iwlagn_add_bssid_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx, + const u8 *addr, u8 *sta_id_r); +int iwl_remove_default_wep_key(struct iwl_priv *priv, + struct iwl_rxon_context *ctx, + struct ieee80211_key_conf *key); +int iwl_set_default_wep_key(struct iwl_priv *priv, + struct iwl_rxon_context *ctx, + struct ieee80211_key_conf *key); +int iwl_restore_default_wep_keys(struct iwl_priv *priv, + struct iwl_rxon_context *ctx); +int iwl_set_dynamic_key(struct iwl_priv *priv, struct iwl_rxon_context *ctx, + struct ieee80211_key_conf *key, u8 sta_id); +int iwl_remove_dynamic_key(struct iwl_priv *priv, struct iwl_rxon_context *ctx, + struct ieee80211_key_conf *key, u8 sta_id); +void iwl_update_tkip_key(struct iwl_priv *priv, + struct iwl_rxon_context *ctx, + struct ieee80211_key_conf *keyconf, + struct ieee80211_sta *sta, u32 iv32, u16 *phase1key); +int iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid); +int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta, + int tid, u16 ssn); +int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta, + int tid); +void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id); +void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt); +int iwl_update_bcast_stations(struct iwl_priv *priv); + #endif /* __iwl_agn_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 50a3c26e1412..31ec9db58b26 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -750,8 +750,6 @@ static inline int iwl_is_ready_rf(struct iwl_priv *priv) extern void iwl_send_bt_config(struct iwl_priv *priv); extern int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear); -extern int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx, - struct iwl_link_quality_cmd *lq, u8 flags, bool init); void iwl_apm_stop(struct iwl_priv *priv); int iwl_apm_init(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 6edd0341dfe2..7c7f7dcb1b1e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -228,9 +228,8 @@ static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index, * * should be called with sta_lock held */ -static u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx, - const u8 *addr, bool is_ap, - struct ieee80211_sta *sta) +u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx, + const u8 *addr, bool is_ap, struct ieee80211_sta *sta) { struct iwl_station_entry *station; int i; @@ -317,6 +316,7 @@ static u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx, return sta_id; } +EXPORT_SYMBOL_GPL(iwl_prep_station); #define STA_WAIT_TIMEOUT (HZ/2) @@ -381,108 +381,6 @@ int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx, } EXPORT_SYMBOL(iwl_add_station_common); -static struct iwl_link_quality_cmd *iwl_sta_alloc_lq(struct iwl_priv *priv, - u8 sta_id) -{ - int i, r; - struct iwl_link_quality_cmd *link_cmd; - u32 rate_flags = 0; - __le32 rate_n_flags; - - link_cmd = kzalloc(sizeof(struct iwl_link_quality_cmd), GFP_KERNEL); - if (!link_cmd) { - IWL_ERR(priv, "Unable to allocate memory for LQ cmd.\n"); - return NULL; - } - /* Set up the rate scaling to start at selected rate, fall back - * all the way down to 1M in IEEE order, and then spin on 1M */ - if (priv->band == IEEE80211_BAND_5GHZ) - r = IWL_RATE_6M_INDEX; - else - r = IWL_RATE_1M_INDEX; - - if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE) - rate_flags |= RATE_MCS_CCK_MSK; - - rate_flags |= first_antenna(priv->hw_params.valid_tx_ant) << - RATE_MCS_ANT_POS; - rate_n_flags = iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags); - for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) - link_cmd->rs_table[i].rate_n_flags = rate_n_flags; - - link_cmd->general_params.single_stream_ant_msk = - first_antenna(priv->hw_params.valid_tx_ant); - - link_cmd->general_params.dual_stream_ant_msk = - priv->hw_params.valid_tx_ant & - ~first_antenna(priv->hw_params.valid_tx_ant); - if (!link_cmd->general_params.dual_stream_ant_msk) { - link_cmd->general_params.dual_stream_ant_msk = ANT_AB; - } else if (num_of_ant(priv->hw_params.valid_tx_ant) == 2) { - link_cmd->general_params.dual_stream_ant_msk = - priv->hw_params.valid_tx_ant; - } - - link_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF; - link_cmd->agg_params.agg_time_limit = - cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF); - - link_cmd->sta_id = sta_id; - - return link_cmd; -} - -/* - * iwl_add_bssid_station - Add the special IBSS BSSID station - * - * Function sleeps. - */ -int iwl_add_bssid_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx, - const u8 *addr, bool init_rs, u8 *sta_id_r) -{ - int ret; - u8 sta_id; - struct iwl_link_quality_cmd *link_cmd; - unsigned long flags; - - if (sta_id_r) - *sta_id_r = IWL_INVALID_STATION; - - ret = iwl_add_station_common(priv, ctx, addr, 0, NULL, &sta_id); - if (ret) { - IWL_ERR(priv, "Unable to add station %pM\n", addr); - return ret; - } - - if (sta_id_r) - *sta_id_r = sta_id; - - spin_lock_irqsave(&priv->sta_lock, flags); - priv->stations[sta_id].used |= IWL_STA_LOCAL; - spin_unlock_irqrestore(&priv->sta_lock, flags); - - if (init_rs) { - /* Set up default rate scaling table in device's station table */ - link_cmd = iwl_sta_alloc_lq(priv, sta_id); - if (!link_cmd) { - IWL_ERR(priv, "Unable to initialize rate scaling for station %pM.\n", - addr); - return -ENOMEM; - } - - ret = iwl_send_lq_cmd(priv, ctx, link_cmd, CMD_SYNC, true); - if (ret) - IWL_ERR(priv, "Link quality command failed (%d)\n", ret); - - spin_lock_irqsave(&priv->sta_lock, flags); - priv->stations[sta_id].lq = link_cmd; - spin_unlock_irqrestore(&priv->sta_lock, flags); - } - - return 0; -} -EXPORT_SYMBOL(iwl_add_bssid_station); - /** * iwl_sta_ucode_deactivate - deactivate ucode status for a station * @@ -738,405 +636,25 @@ int iwl_get_free_ucode_key_index(struct iwl_priv *priv) } EXPORT_SYMBOL(iwl_get_free_ucode_key_index); -static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, - struct iwl_rxon_context *ctx, - bool send_if_empty) +void iwl_dealloc_bcast_stations(struct iwl_priv *priv) { - 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 = ctx->wep_key_cmd, - .data = wep_cmd, - .flags = CMD_SYNC, - }; - - might_sleep(); - - 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 (ctx->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 = ctx->wep_keys[i].key_size; - memcpy(&wep_cmd->key[i].key[3], ctx->wep_keys[i].key, - ctx->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_restore_default_wep_keys(struct iwl_priv *priv, - struct iwl_rxon_context *ctx) -{ - lockdep_assert_held(&priv->mutex); - - return iwl_send_static_wepkey_cmd(priv, ctx, false); -} -EXPORT_SYMBOL(iwl_restore_default_wep_keys); - -int iwl_remove_default_wep_key(struct iwl_priv *priv, - struct iwl_rxon_context *ctx, - struct ieee80211_key_conf *keyconf) -{ - int ret; - - lockdep_assert_held(&priv->mutex); - - IWL_DEBUG_WEP(priv, "Removing default WEP key: idx=%d\n", - keyconf->keyidx); - - memset(&ctx->wep_keys[keyconf->keyidx], 0, sizeof(ctx->wep_keys[0])); - if (iwl_is_rfkill(priv)) { - IWL_DEBUG_WEP(priv, "Not sending REPLY_WEPKEY command due to RFKILL.\n"); - /* but keys in device are clear anyway so return success */ - return 0; - } - ret = iwl_send_static_wepkey_cmd(priv, ctx, 1); - IWL_DEBUG_WEP(priv, "Remove default WEP key: idx=%d ret=%d\n", - keyconf->keyidx, ret); - - return ret; -} -EXPORT_SYMBOL(iwl_remove_default_wep_key); - -int iwl_set_default_wep_key(struct iwl_priv *priv, - struct iwl_rxon_context *ctx, - struct ieee80211_key_conf *keyconf) -{ - int ret; - - lockdep_assert_held(&priv->mutex); - - if (keyconf->keylen != WEP_KEY_LEN_128 && - keyconf->keylen != WEP_KEY_LEN_64) { - IWL_DEBUG_WEP(priv, "Bad WEP key length %d\n", keyconf->keylen); - return -EINVAL; - } - - keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV; - keyconf->hw_key_idx = HW_KEY_DEFAULT; - priv->stations[ctx->ap_sta_id].keyinfo.cipher = keyconf->cipher; - - ctx->wep_keys[keyconf->keyidx].key_size = keyconf->keylen; - memcpy(&ctx->wep_keys[keyconf->keyidx].key, &keyconf->key, - keyconf->keylen); - - ret = iwl_send_static_wepkey_cmd(priv, ctx, false); - IWL_DEBUG_WEP(priv, "Set default WEP key: len=%d idx=%d ret=%d\n", - keyconf->keylen, keyconf->keyidx, ret); - - return ret; -} -EXPORT_SYMBOL(iwl_set_default_wep_key); - -static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv, - struct iwl_rxon_context *ctx, - struct ieee80211_key_conf *keyconf, - u8 sta_id) -{ - unsigned long flags; - __le16 key_flags = 0; - struct iwl_addsta_cmd sta_cmd; - - lockdep_assert_held(&priv->mutex); - - keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV; - - 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 == ctx->bcast_sta_id) - key_flags |= STA_KEY_MULTICAST_MSK; - - spin_lock_irqsave(&priv->sta_lock, flags); - - priv->stations[sta_id].keyinfo.cipher = keyconf->cipher; - 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); - - if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK) - == STA_KEY_FLG_NO_ENC) - priv->stations[sta_id].sta.key.key_offset = - iwl_get_free_ucode_key_index(priv); - /* else, we are overriding an existing key => no need to allocated room - * in uCode. */ - - WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET, - "no space for a new key"); - - 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; - - memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); - spin_unlock_irqrestore(&priv->sta_lock, flags); - - return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); -} - -static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv, - struct iwl_rxon_context *ctx, - struct ieee80211_key_conf *keyconf, - u8 sta_id) -{ - unsigned long flags; - __le16 key_flags = 0; - struct iwl_addsta_cmd sta_cmd; - - lockdep_assert_held(&priv->mutex); - - 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 == ctx->bcast_sta_id) - key_flags |= STA_KEY_MULTICAST_MSK; - - keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; - - spin_lock_irqsave(&priv->sta_lock, flags); - priv->stations[sta_id].keyinfo.cipher = keyconf->cipher; - 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); - - if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK) - == STA_KEY_FLG_NO_ENC) - priv->stations[sta_id].sta.key.key_offset = - iwl_get_free_ucode_key_index(priv); - /* else, we are overriding an existing key => no need to allocated room - * in uCode. */ - - WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET, - "no space for a new key"); - - 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; - - memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); - spin_unlock_irqrestore(&priv->sta_lock, flags); - - return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); -} - -static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv, - struct iwl_rxon_context *ctx, - struct ieee80211_key_conf *keyconf, - u8 sta_id) -{ - unsigned long flags; - int ret = 0; - __le16 key_flags = 0; - - 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 == ctx->bcast_sta_id) - key_flags |= STA_KEY_MULTICAST_MSK; - - keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; - keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; - - spin_lock_irqsave(&priv->sta_lock, flags); - - priv->stations[sta_id].keyinfo.cipher = keyconf->cipher; - priv->stations[sta_id].keyinfo.keylen = 16; - - if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK) - == STA_KEY_FLG_NO_ENC) - priv->stations[sta_id].sta.key.key_offset = - iwl_get_free_ucode_key_index(priv); - /* else, we are overriding an existing key => no need to allocated room - * in uCode. */ - - WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET, - "no space for a new key"); - - priv->stations[sta_id].sta.key.key_flags = key_flags; - - - /* 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; -} - -void iwl_update_tkip_key(struct iwl_priv *priv, - struct iwl_rxon_context *ctx, - struct ieee80211_key_conf *keyconf, - struct ieee80211_sta *sta, u32 iv32, u16 *phase1key) -{ - u8 sta_id; unsigned long flags; int i; - if (iwl_scan_cancel(priv)) { - /* cancel scan failed, just live w/ bad key and rely - briefly on SW decryption */ - return; - } - - sta_id = iwl_sta_id_or_broadcast(priv, ctx, sta); - if (sta_id == IWL_INVALID_STATION) - return; - spin_lock_irqsave(&priv->sta_lock, flags); + for (i = 0; i < priv->hw_params.max_stations; i++) { + if (!(priv->stations[i].used & IWL_STA_BCAST)) + continue; - 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; - - iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); - + priv->stations[i].used &= ~IWL_STA_UCODE_ACTIVE; + priv->num_stations--; + BUG_ON(priv->num_stations < 0); + kfree(priv->stations[i].lq); + priv->stations[i].lq = NULL; + } spin_unlock_irqrestore(&priv->sta_lock, flags); - } -EXPORT_SYMBOL(iwl_update_tkip_key); - -int iwl_remove_dynamic_key(struct iwl_priv *priv, - struct iwl_rxon_context *ctx, - struct ieee80211_key_conf *keyconf, - u8 sta_id) -{ - unsigned long flags; - u16 key_flags; - u8 keyidx; - struct iwl_addsta_cmd sta_cmd; - - lockdep_assert_held(&priv->mutex); - - ctx->key_mapping_keys--; - - spin_lock_irqsave(&priv->sta_lock, flags); - key_flags = le16_to_cpu(priv->stations[sta_id].sta.key.key_flags); - keyidx = (key_flags >> STA_KEY_FLG_KEYID_POS) & 0x3; - - IWL_DEBUG_WEP(priv, "Remove dynamic key: idx=%d sta=%d\n", - keyconf->keyidx, sta_id); - - if (keyconf->keyidx != keyidx) { - /* We need to remove a key with index different that the one - * in the uCode. This means that the key we need to remove has - * been replaced by another one with different index. - * Don't do anything and return ok - */ - spin_unlock_irqrestore(&priv->sta_lock, flags); - return 0; - } - - if (priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET) { - IWL_WARN(priv, "Removing wrong key %d 0x%x\n", - keyconf->keyidx, key_flags); - spin_unlock_irqrestore(&priv->sta_lock, flags); - return 0; - } - - if (!test_and_clear_bit(priv->stations[sta_id].sta.key.key_offset, - &priv->ucode_key_table)) - IWL_ERR(priv, "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 iwl_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 | STA_KEY_FLG_INVALID; - priv->stations[sta_id].sta.key.key_offset = WEP_INVALID_OFFSET; - priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; - priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; - - if (iwl_is_rfkill(priv)) { - IWL_DEBUG_WEP(priv, "Not sending REPLY_ADD_STA command because RFKILL enabled.\n"); - spin_unlock_irqrestore(&priv->sta_lock, flags); - return 0; - } - memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); - spin_unlock_irqrestore(&priv->sta_lock, flags); - - return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); -} -EXPORT_SYMBOL(iwl_remove_dynamic_key); - -int iwl_set_dynamic_key(struct iwl_priv *priv, struct iwl_rxon_context *ctx, - struct ieee80211_key_conf *keyconf, u8 sta_id) -{ - int ret; - - lockdep_assert_held(&priv->mutex); - - ctx->key_mapping_keys++; - keyconf->hw_key_idx = HW_KEY_DYNAMIC; - - switch (keyconf->cipher) { - case WLAN_CIPHER_SUITE_CCMP: - ret = iwl_set_ccmp_dynamic_key_info(priv, ctx, keyconf, sta_id); - break; - case WLAN_CIPHER_SUITE_TKIP: - ret = iwl_set_tkip_dynamic_key_info(priv, ctx, keyconf, sta_id); - break; - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - ret = iwl_set_wep_dynamic_key_info(priv, ctx, keyconf, sta_id); - break; - default: - IWL_ERR(priv, - "Unknown alg: %s cipher = %x\n", __func__, - keyconf->cipher); - ret = -EINVAL; - } - - IWL_DEBUG_WEP(priv, "Set dynamic key: cipher=%x len=%d idx=%d sta=%d ret=%d\n", - keyconf->cipher, keyconf->keylen, keyconf->keyidx, - sta_id, ret); - - return ret; -} -EXPORT_SYMBOL(iwl_set_dynamic_key); +EXPORT_SYMBOL_GPL(iwl_dealloc_bcast_stations); #ifdef CONFIG_IWLWIFI_DEBUG static void iwl_dump_lq_cmd(struct iwl_priv *priv, @@ -1240,223 +758,6 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx, } EXPORT_SYMBOL(iwl_send_lq_cmd); -/** - * iwl_alloc_bcast_station - add broadcast station into driver's station table. - * - * This adds the broadcast station into the driver's station table - * and marks it driver active, so that it will be restored to the - * device at the next best time. - */ -int iwl_alloc_bcast_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx, - bool init_lq) -{ - struct iwl_link_quality_cmd *link_cmd; - unsigned long flags; - u8 sta_id; - - spin_lock_irqsave(&priv->sta_lock, flags); - sta_id = iwl_prep_station(priv, ctx, iwl_bcast_addr, false, NULL); - if (sta_id == IWL_INVALID_STATION) { - IWL_ERR(priv, "Unable to prepare broadcast station\n"); - spin_unlock_irqrestore(&priv->sta_lock, flags); - - return -EINVAL; - } - - priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE; - priv->stations[sta_id].used |= IWL_STA_BCAST; - spin_unlock_irqrestore(&priv->sta_lock, flags); - - if (init_lq) { - link_cmd = iwl_sta_alloc_lq(priv, sta_id); - if (!link_cmd) { - IWL_ERR(priv, - "Unable to initialize rate scaling for bcast station.\n"); - return -ENOMEM; - } - - spin_lock_irqsave(&priv->sta_lock, flags); - priv->stations[sta_id].lq = link_cmd; - spin_unlock_irqrestore(&priv->sta_lock, flags); - } - - return 0; -} -EXPORT_SYMBOL_GPL(iwl_alloc_bcast_station); - -/** - * iwl_update_bcast_station - update broadcast station's LQ command - * - * Only used by iwlagn. Placed here to have all bcast station management - * code together. - */ -static int iwl_update_bcast_station(struct iwl_priv *priv, - struct iwl_rxon_context *ctx) -{ - unsigned long flags; - struct iwl_link_quality_cmd *link_cmd; - u8 sta_id = ctx->bcast_sta_id; - - link_cmd = iwl_sta_alloc_lq(priv, sta_id); - if (!link_cmd) { - IWL_ERR(priv, "Unable to initialize rate scaling for bcast station.\n"); - return -ENOMEM; - } - - spin_lock_irqsave(&priv->sta_lock, flags); - if (priv->stations[sta_id].lq) - kfree(priv->stations[sta_id].lq); - else - IWL_DEBUG_INFO(priv, "Bcast station rate scaling has not been initialized yet.\n"); - priv->stations[sta_id].lq = link_cmd; - spin_unlock_irqrestore(&priv->sta_lock, flags); - - return 0; -} - -int iwl_update_bcast_stations(struct iwl_priv *priv) -{ - struct iwl_rxon_context *ctx; - int ret = 0; - - for_each_context(priv, ctx) { - ret = iwl_update_bcast_station(priv, ctx); - if (ret) - break; - } - - return ret; -} -EXPORT_SYMBOL_GPL(iwl_update_bcast_stations); - -void iwl_dealloc_bcast_stations(struct iwl_priv *priv) -{ - unsigned long flags; - int i; - - spin_lock_irqsave(&priv->sta_lock, flags); - for (i = 0; i < priv->hw_params.max_stations; i++) { - if (!(priv->stations[i].used & IWL_STA_BCAST)) - continue; - - priv->stations[i].used &= ~IWL_STA_UCODE_ACTIVE; - priv->num_stations--; - BUG_ON(priv->num_stations < 0); - kfree(priv->stations[i].lq); - priv->stations[i].lq = NULL; - } - spin_unlock_irqrestore(&priv->sta_lock, flags); -} -EXPORT_SYMBOL_GPL(iwl_dealloc_bcast_stations); - -/** - * iwl_sta_tx_modify_enable_tid - Enable Tx for this TID in station table - */ -int iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid) -{ - unsigned long flags; - struct iwl_addsta_cmd sta_cmd; - - lockdep_assert_held(&priv->mutex); - - /* Remove "disable" flag, to enable Tx for this TID */ - spin_lock_irqsave(&priv->sta_lock, flags); - priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_TID_DISABLE_TX; - priv->stations[sta_id].sta.tid_disable_tx &= cpu_to_le16(~(1 << tid)); - priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; - memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); - spin_unlock_irqrestore(&priv->sta_lock, flags); - - return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); -} -EXPORT_SYMBOL(iwl_sta_tx_modify_enable_tid); - -int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta, - int tid, u16 ssn) -{ - unsigned long flags; - int sta_id; - struct iwl_addsta_cmd sta_cmd; - - lockdep_assert_held(&priv->mutex); - - sta_id = iwl_sta_id(sta); - if (sta_id == IWL_INVALID_STATION) - return -ENXIO; - - spin_lock_irqsave(&priv->sta_lock, flags); - priv->stations[sta_id].sta.station_flags_msk = 0; - priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_ADDBA_TID_MSK; - priv->stations[sta_id].sta.add_immediate_ba_tid = (u8)tid; - priv->stations[sta_id].sta.add_immediate_ba_ssn = cpu_to_le16(ssn); - priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; - memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); - spin_unlock_irqrestore(&priv->sta_lock, flags); - - return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); -} -EXPORT_SYMBOL(iwl_sta_rx_agg_start); - -int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta, - int tid) -{ - unsigned long flags; - int sta_id; - struct iwl_addsta_cmd sta_cmd; - - lockdep_assert_held(&priv->mutex); - - sta_id = iwl_sta_id(sta); - if (sta_id == IWL_INVALID_STATION) { - IWL_ERR(priv, "Invalid station for AGG tid %d\n", tid); - return -ENXIO; - } - - spin_lock_irqsave(&priv->sta_lock, flags); - priv->stations[sta_id].sta.station_flags_msk = 0; - priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK; - priv->stations[sta_id].sta.remove_immediate_ba_tid = (u8)tid; - priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; - memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd)); - spin_unlock_irqrestore(&priv->sta_lock, flags); - - return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC); -} -EXPORT_SYMBOL(iwl_sta_rx_agg_stop); - -void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id) -{ - unsigned long flags; - - spin_lock_irqsave(&priv->sta_lock, flags); - priv->stations[sta_id].sta.station_flags &= ~STA_FLG_PWR_SAVE_MSK; - priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK; - priv->stations[sta_id].sta.sta.modify_mask = 0; - priv->stations[sta_id].sta.sleep_tx_count = 0; - priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; - iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); - spin_unlock_irqrestore(&priv->sta_lock, flags); - -} -EXPORT_SYMBOL(iwl_sta_modify_ps_wake); - -void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt) -{ - unsigned long flags; - - spin_lock_irqsave(&priv->sta_lock, flags); - priv->stations[sta_id].sta.station_flags |= STA_FLG_PWR_SAVE_MSK; - priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK; - priv->stations[sta_id].sta.sta.modify_mask = - STA_MODIFY_SLEEP_TX_COUNT_MSK; - priv->stations[sta_id].sta.sleep_tx_count = cpu_to_le16(cnt); - priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; - iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); - spin_unlock_irqrestore(&priv->sta_lock, flags); - -} -EXPORT_SYMBOL(iwl_sta_modify_sleep_tx_count); - int iwl_mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta) diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index 56bad3f60d81..06475872eee4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h @@ -43,35 +43,13 @@ #define IWL_STA_BCAST BIT(4) /* this station is the special bcast station */ -int iwl_remove_default_wep_key(struct iwl_priv *priv, - struct iwl_rxon_context *ctx, - struct ieee80211_key_conf *key); -int iwl_set_default_wep_key(struct iwl_priv *priv, - struct iwl_rxon_context *ctx, - struct ieee80211_key_conf *key); -int iwl_restore_default_wep_keys(struct iwl_priv *priv, - struct iwl_rxon_context *ctx); -int iwl_set_dynamic_key(struct iwl_priv *priv, struct iwl_rxon_context *ctx, - struct ieee80211_key_conf *key, u8 sta_id); -int iwl_remove_dynamic_key(struct iwl_priv *priv, struct iwl_rxon_context *ctx, - struct ieee80211_key_conf *key, u8 sta_id); -void iwl_update_tkip_key(struct iwl_priv *priv, - struct iwl_rxon_context *ctx, - struct ieee80211_key_conf *keyconf, - struct ieee80211_sta *sta, u32 iv32, u16 *phase1key); - void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx); void iwl_clear_ucode_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx); -int iwl_alloc_bcast_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx, - bool init_lq); void iwl_dealloc_bcast_stations(struct iwl_priv *priv); -int iwl_update_bcast_stations(struct iwl_priv *priv); int iwl_get_free_ucode_key_index(struct iwl_priv *priv); int iwl_send_add_sta(struct iwl_priv *priv, struct iwl_addsta_cmd *sta, u8 flags); -int iwl_add_bssid_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx, - const u8 *addr, bool init_rs, u8 *sta_id_r); int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx, const u8 *addr, bool is_ap, struct ieee80211_sta *sta, u8 *sta_id_r); @@ -79,13 +57,12 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id, const u8 *addr); int iwl_mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta); -int iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid); -int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta, - int tid, u16 ssn); -int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta, - int tid); -void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id); -void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt); + +u8 iwl_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx, + const u8 *addr, bool is_ap, struct ieee80211_sta *sta); + +int iwl_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx, + struct iwl_link_quality_cmd *lq, u8 flags, bool init); /** * iwl_clear_driver_stations - clear knowledge of all stations from driver diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 64eb049140dc..c06b2189e09e 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2661,12 +2661,33 @@ static void iwl3945_down(struct iwl_priv *priv) #define MAX_HW_RESTARTS 5 +static int iwl3945_alloc_bcast_station(struct iwl_priv *priv) +{ + struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; + unsigned long flags; + u8 sta_id; + + spin_lock_irqsave(&priv->sta_lock, flags); + sta_id = iwl_prep_station(priv, ctx, iwl_bcast_addr, false, NULL); + if (sta_id == IWL_INVALID_STATION) { + IWL_ERR(priv, "Unable to prepare broadcast station\n"); + spin_unlock_irqrestore(&priv->sta_lock, flags); + + return -EINVAL; + } + + priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE; + priv->stations[sta_id].used |= IWL_STA_BCAST; + spin_unlock_irqrestore(&priv->sta_lock, flags); + + return 0; +} + static int __iwl3945_up(struct iwl_priv *priv) { int rc, i; - rc = iwl_alloc_bcast_station(priv, &priv->contexts[IWL_RXON_CTX_BSS], - false); + rc = iwl3945_alloc_bcast_station(priv); if (rc) return rc; From 69fdb710b29d096bc50123f7c97891e31ffe45f9 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 22 Sep 2010 18:02:02 +0200 Subject: [PATCH 008/127] iwlwifi: move tx fail code to agn The code to print out TX failure reasons is AGN specific, so it can be in the AGN module. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 40 +++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-agn.h | 2 ++ drivers/net/wireless/iwlwifi/iwl-dev.h | 3 -- drivers/net/wireless/iwlwifi/iwl-tx.c | 38 --------------------- 4 files changed, 42 insertions(+), 41 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 77753b72f236..db57aea629d9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -1391,3 +1391,43 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, spin_unlock_irqrestore(&priv->sta_lock, flags); } + +#ifdef CONFIG_IWLWIFI_DEBUG +const char *iwl_get_tx_fail_reason(u32 status) +{ +#define TX_STATUS_FAIL(x) case TX_STATUS_FAIL_ ## x: return #x +#define TX_STATUS_POSTPONE(x) case TX_STATUS_POSTPONE_ ## x: return #x + + switch (status & TX_STATUS_MSK) { + case TX_STATUS_SUCCESS: + return "SUCCESS"; + TX_STATUS_POSTPONE(DELAY); + TX_STATUS_POSTPONE(FEW_BYTES); + TX_STATUS_POSTPONE(BT_PRIO); + TX_STATUS_POSTPONE(QUIET_PERIOD); + TX_STATUS_POSTPONE(CALC_TTAK); + TX_STATUS_FAIL(INTERNAL_CROSSED_RETRY); + TX_STATUS_FAIL(SHORT_LIMIT); + TX_STATUS_FAIL(LONG_LIMIT); + TX_STATUS_FAIL(FIFO_UNDERRUN); + TX_STATUS_FAIL(DRAIN_FLOW); + TX_STATUS_FAIL(RFKILL_FLUSH); + TX_STATUS_FAIL(LIFE_EXPIRE); + TX_STATUS_FAIL(DEST_PS); + TX_STATUS_FAIL(HOST_ABORTED); + TX_STATUS_FAIL(BT_RETRY); + TX_STATUS_FAIL(STA_INVALID); + TX_STATUS_FAIL(FRAG_DROPPED); + TX_STATUS_FAIL(TID_DISABLE); + TX_STATUS_FAIL(FIFO_FLUSHED); + TX_STATUS_FAIL(INSUFFICIENT_CF_POLL); + TX_STATUS_FAIL(PASSIVE_NO_RX); + TX_STATUS_FAIL(NO_BEACON_ON_RADAR); + } + + return "UNKNOWN"; + +#undef TX_STATUS_FAIL +#undef TX_STATUS_POSTPONE +} +#endif /* CONFIG_IWLWIFI_DEBUG */ diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 632ea4ba82bb..d6645ec9ec5b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -248,8 +248,10 @@ void iwlagn_bt_setup_deferred_work(struct iwl_priv *priv); void iwlagn_bt_cancel_deferred_work(struct iwl_priv *priv); #ifdef CONFIG_IWLWIFI_DEBUG +const char *iwl_get_tx_fail_reason(u32 status); const char *iwl_get_agg_tx_fail_reason(u16 status); #else +static inline const char *iwl_get_tx_fail_reason(u32 status) { return ""; } static inline const char *iwl_get_agg_tx_fail_reason(u16 status) { return ""; } #endif diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 90a37a94c698..2b04714c3a9c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1566,7 +1566,6 @@ static inline void iwl_txq_ctx_deactivate(struct iwl_priv *priv, int txq_id) } #ifdef CONFIG_IWLWIFI_DEBUG -const char *iwl_get_tx_fail_reason(u32 status); /* * iwl_get_debug_level: Return active debug level for device * @@ -1582,8 +1581,6 @@ static inline u32 iwl_get_debug_level(struct iwl_priv *priv) return iwl_debug_level; } #else -static inline const char *iwl_get_tx_fail_reason(u32 status) { return ""; } - static inline u32 iwl_get_debug_level(struct iwl_priv *priv) { return iwl_debug_level; diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 3290b1552f5a..7261ee49f282 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -636,41 +636,3 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) meta->flags = 0; } EXPORT_SYMBOL(iwl_tx_cmd_complete); - -#ifdef CONFIG_IWLWIFI_DEBUG -#define TX_STATUS_FAIL(x) case TX_STATUS_FAIL_ ## x: return #x -#define TX_STATUS_POSTPONE(x) case TX_STATUS_POSTPONE_ ## x: return #x - -const char *iwl_get_tx_fail_reason(u32 status) -{ - switch (status & TX_STATUS_MSK) { - case TX_STATUS_SUCCESS: - return "SUCCESS"; - TX_STATUS_POSTPONE(DELAY); - TX_STATUS_POSTPONE(FEW_BYTES); - TX_STATUS_POSTPONE(BT_PRIO); - TX_STATUS_POSTPONE(QUIET_PERIOD); - TX_STATUS_POSTPONE(CALC_TTAK); - TX_STATUS_FAIL(INTERNAL_CROSSED_RETRY); - TX_STATUS_FAIL(SHORT_LIMIT); - TX_STATUS_FAIL(LONG_LIMIT); - TX_STATUS_FAIL(FIFO_UNDERRUN); - TX_STATUS_FAIL(DRAIN_FLOW); - TX_STATUS_FAIL(RFKILL_FLUSH); - TX_STATUS_FAIL(LIFE_EXPIRE); - TX_STATUS_FAIL(DEST_PS); - TX_STATUS_FAIL(HOST_ABORTED); - TX_STATUS_FAIL(BT_RETRY); - TX_STATUS_FAIL(STA_INVALID); - TX_STATUS_FAIL(FRAG_DROPPED); - TX_STATUS_FAIL(TID_DISABLE); - TX_STATUS_FAIL(FIFO_FLUSHED); - TX_STATUS_FAIL(INSUFFICIENT_CF_POLL); - TX_STATUS_FAIL(PASSIVE_NO_RX); - TX_STATUS_FAIL(NO_BEACON_ON_RADAR); - } - - return "UNKNOWN"; -} -EXPORT_SYMBOL(iwl_get_tx_fail_reason); -#endif /* CONFIG_IWLWIFI_DEBUG */ From 57934dc1fb7ef65a8a0f5d7a1578536b36043c0a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 22 Sep 2010 18:02:03 +0200 Subject: [PATCH 009/127] iwlwifi: remove spurious exports A number of exports, especially related to thermal throttling, are unnecessary because the code lives in the same module that it is used in, so remove them. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-tt.c | 5 ----- drivers/net/wireless/iwlwifi/iwl-core.c | 1 - drivers/net/wireless/iwlwifi/iwl-scan.c | 1 - 3 files changed, 7 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c index 0c6c4d969706..e3a8216a033c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c @@ -571,7 +571,6 @@ void iwl_tt_enter_ct_kill(struct iwl_priv *priv) IWL_DEBUG_POWER(priv, "Queueing critical temperature enter.\n"); queue_work(priv->workqueue, &priv->ct_enter); } -EXPORT_SYMBOL(iwl_tt_enter_ct_kill); void iwl_tt_exit_ct_kill(struct iwl_priv *priv) { @@ -581,7 +580,6 @@ void iwl_tt_exit_ct_kill(struct iwl_priv *priv) IWL_DEBUG_POWER(priv, "Queueing critical temperature exit.\n"); queue_work(priv->workqueue, &priv->ct_exit); } -EXPORT_SYMBOL(iwl_tt_exit_ct_kill); static void iwl_bg_tt_work(struct work_struct *work) { @@ -608,7 +606,6 @@ void iwl_tt_handler(struct iwl_priv *priv) IWL_DEBUG_POWER(priv, "Queueing thermal throttling work.\n"); queue_work(priv->workqueue, &priv->tt_work); } -EXPORT_SYMBOL(iwl_tt_handler); /* Thermal throttling initialization * For advance thermal throttling: @@ -678,7 +675,6 @@ void iwl_tt_initialize(struct iwl_priv *priv) priv->thermal_throttle.advanced_tt = false; } } -EXPORT_SYMBOL(iwl_tt_initialize); /* cleanup thermal throttling management related memory and timer */ void iwl_tt_exit(struct iwl_priv *priv) @@ -701,4 +697,3 @@ void iwl_tt_exit(struct iwl_priv *priv) tt->transaction = NULL; } } -EXPORT_SYMBOL(iwl_tt_exit); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 71f245f3f0f6..eefcb2d1a738 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2653,7 +2653,6 @@ int iwl_force_reset(struct iwl_priv *priv, int mode, bool external) } return 0; } -EXPORT_SYMBOL(iwl_force_reset); /** * iwl_bg_monitor_recover - Timer callback to check for stuck queue and recover diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index a7e8c7f969f4..67da31295781 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -121,7 +121,6 @@ void iwl_force_scan_end(struct iwl_priv *priv) clear_bit(STATUS_SCAN_ABORTING, &priv->status); iwl_complete_scan(priv, true); } -EXPORT_SYMBOL(iwl_force_scan_end); static void iwl_do_scan_abort(struct iwl_priv *priv) { From 635b85b42796a6ab4e6a31cde78f1d9660c9c4a0 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 22 Sep 2010 18:02:04 +0200 Subject: [PATCH 010/127] iwlwifi: remove agn rates info there Code and data related to agn bitrates can be part of the agn module rather than being in the core module. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-3945.c | 9 +++ drivers/net/wireless/iwlwifi/iwl-3945.h | 5 +- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 68 ++++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-agn-rs.h | 10 ---- drivers/net/wireless/iwlwifi/iwl-core.c | 70 ----------------------- drivers/net/wireless/iwlwifi/iwl-core.h | 2 - 6 files changed, 80 insertions(+), 84 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 4b3eb785dcb2..ba3ab04c1fba 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -87,6 +87,15 @@ const struct iwl3945_rate_info iwl3945_rates[IWL_RATE_COUNT_3945] = { IWL_DECLARE_RATE_INFO(54, 48, INV, 48, INV, 48, INV),/* 54mbps */ }; +static inline u8 iwl3945_get_prev_ieee_rate(u8 rate_index) +{ + u8 rate = iwl3945_rates[rate_index].prev_ieee; + + if (rate == IWL_RATE_INVALID) + rate = rate_index; + return rate; +} + /* 1 = enable the iwl3945_disable_events() function */ #define IWL_EVT_DISABLE (0) #define IWL_EVT_DISABLE_SIZE (1532/32) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 77e8e1970350..09391f0ee61f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -138,8 +138,6 @@ enum iwl3945_antenna { #define DEFAULT_SHORT_RETRY_LIMIT 7U #define DEFAULT_LONG_RETRY_LIMIT 4U -#include "iwl-agn-rs.h" - #define IWL_TX_FIFO_AC0 0 #define IWL_TX_FIFO_AC1 1 #define IWL_TX_FIFO_AC2 2 @@ -301,6 +299,9 @@ extern int iwl3945_rs_next_rate(struct iwl_priv *priv, int rate); int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif); void iwl3945_post_scan(struct iwl_priv *priv); +/* rates */ +extern const struct iwl3945_rate_info iwl3945_rates[IWL_RATE_COUNT_3945]; + /* Requires full declaration of iwl_priv before including */ #include "iwl-io.h" diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 7e5cf1a2b21e..5abe2e9ff0d2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -77,6 +77,74 @@ static const u8 ant_toggle_lookup[] = { /*ANT_ABC -> */ ANT_ABC, }; +#define IWL_DECLARE_RATE_INFO(r, s, ip, in, rp, rn, pp, np) \ + [IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP, \ + IWL_RATE_SISO_##s##M_PLCP, \ + IWL_RATE_MIMO2_##s##M_PLCP,\ + IWL_RATE_MIMO3_##s##M_PLCP,\ + IWL_RATE_##r##M_IEEE, \ + IWL_RATE_##ip##M_INDEX, \ + IWL_RATE_##in##M_INDEX, \ + IWL_RATE_##rp##M_INDEX, \ + IWL_RATE_##rn##M_INDEX, \ + IWL_RATE_##pp##M_INDEX, \ + IWL_RATE_##np##M_INDEX } + +/* + * Parameter order: + * rate, ht rate, prev rate, next rate, prev tgg rate, next tgg rate + * + * If there isn't a valid next or previous rate then INV is used which + * maps to IWL_RATE_INVALID + * + */ +const struct iwl_rate_info iwl_rates[IWL_RATE_COUNT] = { + IWL_DECLARE_RATE_INFO(1, INV, INV, 2, INV, 2, INV, 2), /* 1mbps */ + IWL_DECLARE_RATE_INFO(2, INV, 1, 5, 1, 5, 1, 5), /* 2mbps */ + IWL_DECLARE_RATE_INFO(5, INV, 2, 6, 2, 11, 2, 11), /*5.5mbps */ + IWL_DECLARE_RATE_INFO(11, INV, 9, 12, 9, 12, 5, 18), /* 11mbps */ + IWL_DECLARE_RATE_INFO(6, 6, 5, 9, 5, 11, 5, 11), /* 6mbps */ + IWL_DECLARE_RATE_INFO(9, 6, 6, 11, 6, 11, 5, 11), /* 9mbps */ + IWL_DECLARE_RATE_INFO(12, 12, 11, 18, 11, 18, 11, 18), /* 12mbps */ + IWL_DECLARE_RATE_INFO(18, 18, 12, 24, 12, 24, 11, 24), /* 18mbps */ + IWL_DECLARE_RATE_INFO(24, 24, 18, 36, 18, 36, 18, 36), /* 24mbps */ + IWL_DECLARE_RATE_INFO(36, 36, 24, 48, 24, 48, 24, 48), /* 36mbps */ + IWL_DECLARE_RATE_INFO(48, 48, 36, 54, 36, 54, 36, 54), /* 48mbps */ + IWL_DECLARE_RATE_INFO(54, 54, 48, INV, 48, INV, 48, INV),/* 54mbps */ + IWL_DECLARE_RATE_INFO(60, 60, 48, INV, 48, INV, 48, INV),/* 60mbps */ + /* FIXME:RS: ^^ should be INV (legacy) */ +}; + +static int iwl_hwrate_to_plcp_idx(u32 rate_n_flags) +{ + int idx = 0; + + /* HT rate format */ + if (rate_n_flags & RATE_MCS_HT_MSK) { + idx = (rate_n_flags & 0xff); + + if (idx >= IWL_RATE_MIMO3_6M_PLCP) + idx = idx - IWL_RATE_MIMO3_6M_PLCP; + else if (idx >= IWL_RATE_MIMO2_6M_PLCP) + idx = idx - IWL_RATE_MIMO2_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; + + /* legacy rate format, search for match in table */ + } else { + for (idx = 0; idx < ARRAY_SIZE(iwl_rates); idx++) + if (iwl_rates[idx].plcp == (rate_n_flags & 0xFF)) + return idx; + } + + return -1; +} + static void rs_rate_scale_perform(struct iwl_priv *priv, struct sk_buff *skb, struct ieee80211_sta *sta, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h index 357cdb26f16d..75e50d33ecb3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h @@ -299,7 +299,6 @@ enum { #define TIME_WRAP_AROUND(x, y) (((y) > (x)) ? (y) - (x) : (0-(x)) + (y)) extern const struct iwl_rate_info iwl_rates[IWL_RATE_COUNT]; -extern const struct iwl3945_rate_info iwl3945_rates[IWL_RATE_COUNT_3945]; enum iwl_table_type { LQ_NONE, @@ -453,15 +452,6 @@ static inline u8 first_antenna(u8 mask) } -static inline u8 iwl3945_get_prev_ieee_rate(u8 rate_index) -{ - u8 rate = iwl3945_rates[rate_index].prev_ieee; - - if (rate == IWL_RATE_INVALID) - rate = rate_index; - return rate; -} - /** * iwl3945_rate_scale_init - Initialize the rate scale table based on assoc info * diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index eefcb2d1a738..295038450a01 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -69,79 +69,9 @@ EXPORT_SYMBOL_GPL(bt_coex_active); module_param(bt_coex_active, bool, S_IRUGO); MODULE_PARM_DESC(bt_coex_active, "enable wifi/bluetooth co-exist"); -#define IWL_DECLARE_RATE_INFO(r, s, ip, in, rp, rn, pp, np) \ - [IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP, \ - IWL_RATE_SISO_##s##M_PLCP, \ - IWL_RATE_MIMO2_##s##M_PLCP,\ - IWL_RATE_MIMO3_##s##M_PLCP,\ - IWL_RATE_##r##M_IEEE, \ - IWL_RATE_##ip##M_INDEX, \ - IWL_RATE_##in##M_INDEX, \ - IWL_RATE_##rp##M_INDEX, \ - IWL_RATE_##rn##M_INDEX, \ - IWL_RATE_##pp##M_INDEX, \ - IWL_RATE_##np##M_INDEX } - u32 iwl_debug_level; EXPORT_SYMBOL(iwl_debug_level); -/* - * Parameter order: - * rate, ht rate, prev rate, next rate, prev tgg rate, next tgg rate - * - * If there isn't a valid next or previous rate then INV is used which - * maps to IWL_RATE_INVALID - * - */ -const struct iwl_rate_info iwl_rates[IWL_RATE_COUNT] = { - IWL_DECLARE_RATE_INFO(1, INV, INV, 2, INV, 2, INV, 2), /* 1mbps */ - IWL_DECLARE_RATE_INFO(2, INV, 1, 5, 1, 5, 1, 5), /* 2mbps */ - IWL_DECLARE_RATE_INFO(5, INV, 2, 6, 2, 11, 2, 11), /*5.5mbps */ - IWL_DECLARE_RATE_INFO(11, INV, 9, 12, 9, 12, 5, 18), /* 11mbps */ - IWL_DECLARE_RATE_INFO(6, 6, 5, 9, 5, 11, 5, 11), /* 6mbps */ - IWL_DECLARE_RATE_INFO(9, 6, 6, 11, 6, 11, 5, 11), /* 9mbps */ - IWL_DECLARE_RATE_INFO(12, 12, 11, 18, 11, 18, 11, 18), /* 12mbps */ - IWL_DECLARE_RATE_INFO(18, 18, 12, 24, 12, 24, 11, 24), /* 18mbps */ - IWL_DECLARE_RATE_INFO(24, 24, 18, 36, 18, 36, 18, 36), /* 24mbps */ - IWL_DECLARE_RATE_INFO(36, 36, 24, 48, 24, 48, 24, 48), /* 36mbps */ - IWL_DECLARE_RATE_INFO(48, 48, 36, 54, 36, 54, 36, 54), /* 48mbps */ - IWL_DECLARE_RATE_INFO(54, 54, 48, INV, 48, INV, 48, INV),/* 54mbps */ - IWL_DECLARE_RATE_INFO(60, 60, 48, INV, 48, INV, 48, INV),/* 60mbps */ - /* FIXME:RS: ^^ should be INV (legacy) */ -}; -EXPORT_SYMBOL(iwl_rates); - -int iwl_hwrate_to_plcp_idx(u32 rate_n_flags) -{ - int idx = 0; - - /* HT rate format */ - if (rate_n_flags & RATE_MCS_HT_MSK) { - idx = (rate_n_flags & 0xff); - - if (idx >= IWL_RATE_MIMO3_6M_PLCP) - idx = idx - IWL_RATE_MIMO3_6M_PLCP; - else if (idx >= IWL_RATE_MIMO2_6M_PLCP) - idx = idx - IWL_RATE_MIMO2_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; - - /* legacy rate format, search for match in table */ - } else { - for (idx = 0; idx < ARRAY_SIZE(iwl_rates); idx++) - if (iwl_rates[idx].plcp == (rate_n_flags & 0xFF)) - return idx; - } - - return -1; -} -EXPORT_SYMBOL(iwl_hwrate_to_plcp_idx); - u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant, u8 valid) { int i; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 31ec9db58b26..56251de85100 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -547,8 +547,6 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force); * Rate ******************************************************************************/ -int iwl_hwrate_to_plcp_idx(u32 rate_n_flags); - u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv, struct iwl_rxon_context *ctx); From facd982e8246ed25a049d270a71513fb11b901ec Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 22 Sep 2010 18:02:05 +0200 Subject: [PATCH 011/127] iwlwifi: move iwl_toggle_rx_ant to agn The iwl_toggle_tx_ant function is only used by agn code, so it can be moved into the agn module instead of being exported from the core. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 17 +++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-agn.h | 2 ++ drivers/net/wireless/iwlwifi/iwl-core.c | 18 ------------------ drivers/net/wireless/iwlwifi/iwl-core.h | 2 -- 4 files changed, 19 insertions(+), 20 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 3eeab0a99def..9f1c93bbb01c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -2205,3 +2205,20 @@ void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx) WARN_ON(active_rx_cnt == 0 || idle_rx_cnt == 0 || active_rx_cnt < idle_rx_cnt); } + +u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant, u8 valid) +{ + int i; + u8 ind = ant; + + if (priv->band == IEEE80211_BAND_2GHZ && + priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH) + return 0; + + for (i = 0; i < RATE_ANT_NUM - 1; i++) { + ind = (ind + 1) < RATE_ANT_NUM ? ind + 1 : 0; + if (valid & BIT(ind)) + return ind; + } + return ant; +} diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index d6645ec9ec5b..cc7a3b56cfe5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -216,6 +216,8 @@ static inline bool iwl_is_tx_success(u32 status) (status == TX_STATUS_DIRECT_DONE); } +u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx, u8 valid); + /* rx */ void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 295038450a01..88c1ed5b7dd7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -72,24 +72,6 @@ MODULE_PARM_DESC(bt_coex_active, "enable wifi/bluetooth co-exist"); u32 iwl_debug_level; EXPORT_SYMBOL(iwl_debug_level); -u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant, u8 valid) -{ - int i; - u8 ind = ant; - - if (priv->band == IEEE80211_BAND_2GHZ && - priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH) - return 0; - - for (i = 0; i < RATE_ANT_NUM - 1; i++) { - ind = (ind + 1) < RATE_ANT_NUM ? ind + 1 : 0; - if (valid & BIT(ind)) - return ind; - } - return ant; -} -EXPORT_SYMBOL(iwl_toggle_tx_ant); - const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; EXPORT_SYMBOL(iwl_bcast_addr); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 56251de85100..0bc7b7a28a30 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -550,8 +550,6 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force); u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv, struct iwl_rxon_context *ctx); -u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx, u8 valid); - static inline u32 iwl_ant_idx_to_flags(u8 ant_idx) { return BIT(ant_idx) << RATE_MCS_ANT_POS; From fed732920bf9d96a95804a499ca586ff745540cd Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 22 Sep 2010 18:02:06 +0200 Subject: [PATCH 012/127] iwlwifi: move iwl_dump_csr to agn The iwl_dump_csr function is only used within the agn module, so it can be moved there instead of being exported by the core. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 69 +++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-agn.h | 1 + drivers/net/wireless/iwlwifi/iwl-core.c | 71 ---------------------- drivers/net/wireless/iwlwifi/iwl-core.h | 1 - 4 files changed, 70 insertions(+), 72 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 9f1c93bbb01c..de91ff6dcd6c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -2222,3 +2222,72 @@ u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant, u8 valid) } return ant; } + +static const char *get_csr_string(int cmd) +{ + switch (cmd) { + IWL_CMD(CSR_HW_IF_CONFIG_REG); + IWL_CMD(CSR_INT_COALESCING); + IWL_CMD(CSR_INT); + IWL_CMD(CSR_INT_MASK); + IWL_CMD(CSR_FH_INT_STATUS); + IWL_CMD(CSR_GPIO_IN); + IWL_CMD(CSR_RESET); + IWL_CMD(CSR_GP_CNTRL); + IWL_CMD(CSR_HW_REV); + IWL_CMD(CSR_EEPROM_REG); + IWL_CMD(CSR_EEPROM_GP); + IWL_CMD(CSR_OTP_GP_REG); + IWL_CMD(CSR_GIO_REG); + IWL_CMD(CSR_GP_UCODE_REG); + IWL_CMD(CSR_GP_DRIVER_REG); + IWL_CMD(CSR_UCODE_DRV_GP1); + IWL_CMD(CSR_UCODE_DRV_GP2); + IWL_CMD(CSR_LED_REG); + IWL_CMD(CSR_DRAM_INT_TBL_REG); + IWL_CMD(CSR_GIO_CHICKEN_BITS); + IWL_CMD(CSR_ANA_PLL_CFG); + IWL_CMD(CSR_HW_REV_WA_REG); + IWL_CMD(CSR_DBG_HPET_MEM_REG); + default: + return "UNKNOWN"; + } +} + +void iwl_dump_csr(struct iwl_priv *priv) +{ + int i; + u32 csr_tbl[] = { + CSR_HW_IF_CONFIG_REG, + CSR_INT_COALESCING, + CSR_INT, + CSR_INT_MASK, + CSR_FH_INT_STATUS, + CSR_GPIO_IN, + CSR_RESET, + CSR_GP_CNTRL, + CSR_HW_REV, + CSR_EEPROM_REG, + CSR_EEPROM_GP, + CSR_OTP_GP_REG, + CSR_GIO_REG, + CSR_GP_UCODE_REG, + CSR_GP_DRIVER_REG, + CSR_UCODE_DRV_GP1, + CSR_UCODE_DRV_GP2, + CSR_LED_REG, + CSR_DRAM_INT_TBL_REG, + CSR_GIO_CHICKEN_BITS, + CSR_ANA_PLL_CFG, + CSR_HW_REV_WA_REG, + CSR_DBG_HPET_MEM_REG + }; + IWL_ERR(priv, "CSR values:\n"); + IWL_ERR(priv, "(2nd byte of CSR_INT_COALESCING is " + "CSR_INT_PERIODIC_REG)\n"); + for (i = 0; i < ARRAY_SIZE(csr_tbl); i++) { + IWL_ERR(priv, " %25s: 0X%08x\n", + get_csr_string(csr_tbl[i]), + iwl_read32(priv, csr_tbl[i])); + } +} diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index cc7a3b56cfe5..5458e63f803d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -162,6 +162,7 @@ int iwlagn_hw_nic_init(struct iwl_priv *priv); int iwlagn_wait_tx_queue_empty(struct iwl_priv *priv); int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control); void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control); +void iwl_dump_csr(struct iwl_priv *priv); /* rx */ void iwlagn_rx_queue_restock(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 88c1ed5b7dd7..c0d531c669bf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2351,77 +2351,6 @@ void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, u16 len) EXPORT_SYMBOL(iwl_update_stats); #endif -static const char *get_csr_string(int cmd) -{ - switch (cmd) { - IWL_CMD(CSR_HW_IF_CONFIG_REG); - IWL_CMD(CSR_INT_COALESCING); - IWL_CMD(CSR_INT); - IWL_CMD(CSR_INT_MASK); - IWL_CMD(CSR_FH_INT_STATUS); - IWL_CMD(CSR_GPIO_IN); - IWL_CMD(CSR_RESET); - IWL_CMD(CSR_GP_CNTRL); - IWL_CMD(CSR_HW_REV); - IWL_CMD(CSR_EEPROM_REG); - IWL_CMD(CSR_EEPROM_GP); - IWL_CMD(CSR_OTP_GP_REG); - IWL_CMD(CSR_GIO_REG); - IWL_CMD(CSR_GP_UCODE_REG); - IWL_CMD(CSR_GP_DRIVER_REG); - IWL_CMD(CSR_UCODE_DRV_GP1); - IWL_CMD(CSR_UCODE_DRV_GP2); - IWL_CMD(CSR_LED_REG); - IWL_CMD(CSR_DRAM_INT_TBL_REG); - IWL_CMD(CSR_GIO_CHICKEN_BITS); - IWL_CMD(CSR_ANA_PLL_CFG); - IWL_CMD(CSR_HW_REV_WA_REG); - IWL_CMD(CSR_DBG_HPET_MEM_REG); - default: - return "UNKNOWN"; - - } -} - -void iwl_dump_csr(struct iwl_priv *priv) -{ - int i; - u32 csr_tbl[] = { - CSR_HW_IF_CONFIG_REG, - CSR_INT_COALESCING, - CSR_INT, - CSR_INT_MASK, - CSR_FH_INT_STATUS, - CSR_GPIO_IN, - CSR_RESET, - CSR_GP_CNTRL, - CSR_HW_REV, - CSR_EEPROM_REG, - CSR_EEPROM_GP, - CSR_OTP_GP_REG, - CSR_GIO_REG, - CSR_GP_UCODE_REG, - CSR_GP_DRIVER_REG, - CSR_UCODE_DRV_GP1, - CSR_UCODE_DRV_GP2, - CSR_LED_REG, - CSR_DRAM_INT_TBL_REG, - CSR_GIO_CHICKEN_BITS, - CSR_ANA_PLL_CFG, - CSR_HW_REV_WA_REG, - CSR_DBG_HPET_MEM_REG - }; - IWL_ERR(priv, "CSR values:\n"); - IWL_ERR(priv, "(2nd byte of CSR_INT_COALESCING is " - "CSR_INT_PERIODIC_REG)\n"); - for (i = 0; i < ARRAY_SIZE(csr_tbl); i++) { - IWL_ERR(priv, " %25s: 0X%08x\n", - get_csr_string(csr_tbl[i]), - iwl_read32(priv, csr_tbl[i])); - } -} -EXPORT_SYMBOL(iwl_dump_csr); - static const char *get_fh_string(int cmd) { switch (cmd) { diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 0bc7b7a28a30..7e99b7dccb84 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -659,7 +659,6 @@ int iwl_pci_resume(struct pci_dev *pdev); void iwl_dump_nic_error_log(struct iwl_priv *priv); int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, char **buf, bool display); -void iwl_dump_csr(struct iwl_priv *priv); int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display); #ifdef CONFIG_IWLWIFI_DEBUG void iwl_print_rx_config_cmd(struct iwl_priv *priv, From 84fac3d9604147db37bd8c68897f79442d7ed714 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 22 Sep 2010 18:02:07 +0200 Subject: [PATCH 013/127] iwlwifi: move iwl_dump_fh to agn The iwl_dump_fh function is only used by the agn module, so it can be there instead of being exported by the core. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 61 +++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-agn.h | 1 + drivers/net/wireless/iwlwifi/iwl-core.c | 63 ---------------------- drivers/net/wireless/iwlwifi/iwl-core.h | 1 - 4 files changed, 62 insertions(+), 64 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index de91ff6dcd6c..ff5f2fc4d6d9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -2291,3 +2291,64 @@ void iwl_dump_csr(struct iwl_priv *priv) iwl_read32(priv, csr_tbl[i])); } } + +static const char *get_fh_string(int cmd) +{ + switch (cmd) { + IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG); + IWL_CMD(FH_RSCSR_CHNL0_RBDCB_BASE_REG); + IWL_CMD(FH_RSCSR_CHNL0_WPTR); + IWL_CMD(FH_MEM_RCSR_CHNL0_CONFIG_REG); + IWL_CMD(FH_MEM_RSSR_SHARED_CTRL_REG); + IWL_CMD(FH_MEM_RSSR_RX_STATUS_REG); + IWL_CMD(FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV); + IWL_CMD(FH_TSSR_TX_STATUS_REG); + IWL_CMD(FH_TSSR_TX_ERROR_REG); + default: + return "UNKNOWN"; + } +} + +int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display) +{ + int i; +#ifdef CONFIG_IWLWIFI_DEBUG + int pos = 0; + size_t bufsz = 0; +#endif + u32 fh_tbl[] = { + FH_RSCSR_CHNL0_STTS_WPTR_REG, + FH_RSCSR_CHNL0_RBDCB_BASE_REG, + FH_RSCSR_CHNL0_WPTR, + FH_MEM_RCSR_CHNL0_CONFIG_REG, + FH_MEM_RSSR_SHARED_CTRL_REG, + FH_MEM_RSSR_RX_STATUS_REG, + FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV, + FH_TSSR_TX_STATUS_REG, + FH_TSSR_TX_ERROR_REG + }; +#ifdef CONFIG_IWLWIFI_DEBUG + if (display) { + bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40; + *buf = kmalloc(bufsz, GFP_KERNEL); + if (!*buf) + return -ENOMEM; + pos += scnprintf(*buf + pos, bufsz - pos, + "FH register values:\n"); + for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) { + pos += scnprintf(*buf + pos, bufsz - pos, + " %34s: 0X%08x\n", + get_fh_string(fh_tbl[i]), + iwl_read_direct32(priv, fh_tbl[i])); + } + return pos; + } +#endif + IWL_ERR(priv, "FH register values:\n"); + for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) { + IWL_ERR(priv, " %34s: 0X%08x\n", + get_fh_string(fh_tbl[i]), + iwl_read_direct32(priv, fh_tbl[i])); + } + return 0; +} diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 5458e63f803d..1fca5af35771 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -163,6 +163,7 @@ int iwlagn_wait_tx_queue_empty(struct iwl_priv *priv); int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control); void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control); void iwl_dump_csr(struct iwl_priv *priv); +int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display); /* rx */ void iwlagn_rx_queue_restock(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index c0d531c669bf..5cd16a745bac 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2351,69 +2351,6 @@ void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, u16 len) EXPORT_SYMBOL(iwl_update_stats); #endif -static const char *get_fh_string(int cmd) -{ - switch (cmd) { - IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG); - IWL_CMD(FH_RSCSR_CHNL0_RBDCB_BASE_REG); - IWL_CMD(FH_RSCSR_CHNL0_WPTR); - IWL_CMD(FH_MEM_RCSR_CHNL0_CONFIG_REG); - IWL_CMD(FH_MEM_RSSR_SHARED_CTRL_REG); - IWL_CMD(FH_MEM_RSSR_RX_STATUS_REG); - IWL_CMD(FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV); - IWL_CMD(FH_TSSR_TX_STATUS_REG); - IWL_CMD(FH_TSSR_TX_ERROR_REG); - default: - return "UNKNOWN"; - - } -} - -int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display) -{ - int i; -#ifdef CONFIG_IWLWIFI_DEBUG - int pos = 0; - size_t bufsz = 0; -#endif - u32 fh_tbl[] = { - FH_RSCSR_CHNL0_STTS_WPTR_REG, - FH_RSCSR_CHNL0_RBDCB_BASE_REG, - FH_RSCSR_CHNL0_WPTR, - FH_MEM_RCSR_CHNL0_CONFIG_REG, - FH_MEM_RSSR_SHARED_CTRL_REG, - FH_MEM_RSSR_RX_STATUS_REG, - FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV, - FH_TSSR_TX_STATUS_REG, - FH_TSSR_TX_ERROR_REG - }; -#ifdef CONFIG_IWLWIFI_DEBUG - if (display) { - bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40; - *buf = kmalloc(bufsz, GFP_KERNEL); - if (!*buf) - return -ENOMEM; - pos += scnprintf(*buf + pos, bufsz - pos, - "FH register values:\n"); - for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) { - pos += scnprintf(*buf + pos, bufsz - pos, - " %34s: 0X%08x\n", - get_fh_string(fh_tbl[i]), - iwl_read_direct32(priv, fh_tbl[i])); - } - return pos; - } -#endif - IWL_ERR(priv, "FH register values:\n"); - for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) { - IWL_ERR(priv, " %34s: 0X%08x\n", - get_fh_string(fh_tbl[i]), - iwl_read_direct32(priv, fh_tbl[i])); - } - return 0; -} -EXPORT_SYMBOL(iwl_dump_fh); - static void iwl_force_rf_reset(struct iwl_priv *priv) { if (test_bit(STATUS_EXIT_PENDING, &priv->status)) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 7e99b7dccb84..b02db31d7d5b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -659,7 +659,6 @@ int iwl_pci_resume(struct pci_dev *pdev); void iwl_dump_nic_error_log(struct iwl_priv *priv); int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, char **buf, bool display); -int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display); #ifdef CONFIG_IWLWIFI_DEBUG void iwl_print_rx_config_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx); From 0453674c90be7b39c8925ba5e1d746447905f8ee Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 22 Sep 2010 18:02:08 +0200 Subject: [PATCH 014/127] iwlwifi: remove set_ct_kill operation This operation is only ever called from set_hw_params, which is also already based on the config/ops, so that there's no need to have a separate set_ct_kill op and we can just call the right ct_threshold function. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-1000.c | 4 +--- drivers/net/wireless/iwlwifi/iwl-4965.c | 5 ++--- drivers/net/wireless/iwlwifi/iwl-5000.c | 8 ++------ drivers/net/wireless/iwlwifi/iwl-6000.c | 5 +---- drivers/net/wireless/iwlwifi/iwl-core.h | 1 - 5 files changed, 6 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 8c2db55df426..8aed9ead3a75 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -151,8 +151,7 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv) priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant; priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant; - if (priv->cfg->ops->lib->temp_ops.set_ct_kill) - priv->cfg->ops->lib->temp_ops.set_ct_kill(priv); + iwl1000_set_ct_threshold(priv); /* Set initial sensitivity parameters */ /* Set initial calibration set */ @@ -219,7 +218,6 @@ static struct iwl_lib_ops iwl1000_lib = { .config_ap = iwl_config_ap, .temp_ops = { .temperature = iwlagn_temperature, - .set_ct_kill = iwl1000_set_ct_threshold, }, .manage_ibss_station = iwlagn_manage_ibss_station, .update_bcast_stations = iwl_update_bcast_stations, diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 08d2dbc4efb3..c192856bb644 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -669,8 +669,8 @@ static int iwl4965_hw_set_hw_params(struct iwl_priv *priv) priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant); priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant; priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant; - if (priv->cfg->ops->lib->temp_ops.set_ct_kill) - priv->cfg->ops->lib->temp_ops.set_ct_kill(priv); + + iwl4965_set_ct_threshold(priv); priv->hw_params.sens = &iwl4965_sensitivity; priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; @@ -2292,7 +2292,6 @@ static struct iwl_lib_ops iwl4965_lib = { .isr = iwl_isr_legacy, .temp_ops = { .temperature = iwl4965_temperature_calib, - .set_ct_kill = iwl4965_set_ct_threshold, }, .manage_ibss_station = iwlagn_manage_ibss_station, .update_bcast_stations = iwl_update_bcast_stations, diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index ddbbb9320aca..084271e5e468 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -195,8 +195,7 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant; priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant; - if (priv->cfg->ops->lib->temp_ops.set_ct_kill) - priv->cfg->ops->lib->temp_ops.set_ct_kill(priv); + iwl5000_set_ct_threshold(priv); /* Set initial sensitivity parameters */ /* Set initial calibration set */ @@ -242,8 +241,7 @@ static int iwl5150_hw_set_hw_params(struct iwl_priv *priv) priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant; priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant; - if (priv->cfg->ops->lib->temp_ops.set_ct_kill) - priv->cfg->ops->lib->temp_ops.set_ct_kill(priv); + iwl5150_set_ct_threshold(priv); /* Set initial sensitivity parameters */ /* Set initial calibration set */ @@ -394,7 +392,6 @@ static struct iwl_lib_ops iwl5000_lib = { .config_ap = iwl_config_ap, .temp_ops = { .temperature = iwlagn_temperature, - .set_ct_kill = iwl5000_set_ct_threshold, }, .manage_ibss_station = iwlagn_manage_ibss_station, .update_bcast_stations = iwl_update_bcast_stations, @@ -465,7 +462,6 @@ static struct iwl_lib_ops iwl5150_lib = { .config_ap = iwl_config_ap, .temp_ops = { .temperature = iwl5150_temperature, - .set_ct_kill = iwl5150_set_ct_threshold, }, .manage_ibss_station = iwlagn_manage_ibss_station, .update_bcast_stations = iwl_update_bcast_stations, diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 198cd8f40de3..84f181443f02 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -192,8 +192,7 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv) priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant; priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant; - if (priv->cfg->ops->lib->temp_ops.set_ct_kill) - priv->cfg->ops->lib->temp_ops.set_ct_kill(priv); + iwl6000_set_ct_threshold(priv); /* Set initial sensitivity parameters */ /* Set initial calibration set */ @@ -334,7 +333,6 @@ static struct iwl_lib_ops iwl6000_lib = { .config_ap = iwl_config_ap, .temp_ops = { .temperature = iwlagn_temperature, - .set_ct_kill = iwl6000_set_ct_threshold, }, .manage_ibss_station = iwlagn_manage_ibss_station, .update_bcast_stations = iwl_update_bcast_stations, @@ -408,7 +406,6 @@ static struct iwl_lib_ops iwl6000g2b_lib = { .config_ap = iwl_config_ap, .temp_ops = { .temperature = iwlagn_temperature, - .set_ct_kill = iwl6000_set_ct_threshold, }, .manage_ibss_station = iwlagn_manage_ibss_station, .update_bcast_stations = iwl_update_bcast_stations, diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index b02db31d7d5b..f3c3d8531505 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -137,7 +137,6 @@ struct iwl_debugfs_ops { struct iwl_temp_ops { void (*temperature)(struct iwl_priv *priv); - void (*set_ct_kill)(struct iwl_priv *priv); }; struct iwl_tt_ops { From 9597ebac91e5a88f558d236a51d776508d42a237 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 22 Sep 2010 18:02:09 +0200 Subject: [PATCH 015/127] iwlwifi: remove set_pwr_src operation The set_pwr_src operation is only ever used from within the same sub-driver that it is declared in, so it can just be called directly instead of being an operation. Also, it is never called to set the power source to V_aux, so change the two functions accordingly (but keep the V_aux code for documentation purposes in a comment). Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-1000.c | 1 - drivers/net/wireless/iwlwifi/iwl-3945.c | 26 ++++++++++------------ drivers/net/wireless/iwlwifi/iwl-4965.c | 1 - drivers/net/wireless/iwlwifi/iwl-5000.c | 2 -- drivers/net/wireless/iwlwifi/iwl-6000.c | 2 -- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 19 +++++++++++++++- drivers/net/wireless/iwlwifi/iwl-agn.c | 16 ------------- drivers/net/wireless/iwlwifi/iwl-core.h | 1 - drivers/net/wireless/iwlwifi/iwl-dev.h | 8 ------- 9 files changed, 30 insertions(+), 46 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 8aed9ead3a75..5bdfe9dcd070 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -196,7 +196,6 @@ static struct iwl_lib_ops iwl1000_lib = { .init = iwl_apm_init, .stop = iwl_apm_stop, .config = iwl1000_nic_config, - .set_pwr_src = iwl_set_pwr_src, }, .eeprom_ops = { .regulatory_bands = { diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index ba3ab04c1fba..824c9428efaa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -816,9 +816,12 @@ static u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, u16 tx_rate) return sta_id; } -static int iwl3945_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src) +static void iwl3945_set_pwr_vmain(struct iwl_priv *priv) { - if (src == IWL_PWR_SRC_VAUX) { +/* + * (for documentation purposes) + * to set power to V_AUX, do + if (pci_pme_capable(priv->pci_dev, PCI_D3cold)) { iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_PWR_SRC_VAUX, @@ -828,16 +831,14 @@ static int iwl3945_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src) CSR_GPIO_IN_VAL_VAUX_PWR_SRC, CSR_GPIO_IN_BIT_AUX_POWER, 5000); } - } else { - iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, - APMG_PS_CTRL_VAL_PWR_SRC_VMAIN, - ~APMG_PS_CTRL_MSK_PWR_SRC); + */ - iwl_poll_bit(priv, CSR_GPIO_IN, CSR_GPIO_IN_VAL_VMAIN_PWR_SRC, - CSR_GPIO_IN_BIT_AUX_POWER, 5000); /* uS */ - } + iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, + APMG_PS_CTRL_VAL_PWR_SRC_VMAIN, + ~APMG_PS_CTRL_MSK_PWR_SRC); - return 0; + iwl_poll_bit(priv, CSR_GPIO_IN, CSR_GPIO_IN_VAL_VMAIN_PWR_SRC, + CSR_GPIO_IN_BIT_AUX_POWER, 5000); /* uS */ } static int iwl3945_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) @@ -1031,9 +1032,7 @@ int iwl3945_hw_nic_init(struct iwl_priv *priv) priv->cfg->ops->lib->apm_ops.init(priv); spin_unlock_irqrestore(&priv->lock, flags); - rc = priv->cfg->ops->lib->apm_ops.set_pwr_src(priv, IWL_PWR_SRC_VMAIN); - if (rc) - return rc; + iwl3945_set_pwr_vmain(priv); priv->cfg->ops->lib->apm_ops.config(priv); @@ -2707,7 +2706,6 @@ static struct iwl_lib_ops iwl3945_lib = { .init = iwl3945_apm_init, .stop = iwl_apm_stop, .config = iwl3945_nic_config, - .set_pwr_src = iwl3945_set_pwr_src, }, .eeprom_ops = { .regulatory_bands = { diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index c192856bb644..cda4a319ed97 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2268,7 +2268,6 @@ static struct iwl_lib_ops iwl4965_lib = { .init = iwl_apm_init, .stop = iwl_apm_stop, .config = iwl4965_nic_config, - .set_pwr_src = iwl_set_pwr_src, }, .eeprom_ops = { .regulatory_bands = { diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 084271e5e468..c90a16cdfaff 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -370,7 +370,6 @@ static struct iwl_lib_ops iwl5000_lib = { .init = iwl_apm_init, .stop = iwl_apm_stop, .config = iwl5000_nic_config, - .set_pwr_src = iwl_set_pwr_src, }, .eeprom_ops = { .regulatory_bands = { @@ -440,7 +439,6 @@ static struct iwl_lib_ops iwl5150_lib = { .init = iwl_apm_init, .stop = iwl_apm_stop, .config = iwl5000_nic_config, - .set_pwr_src = iwl_set_pwr_src, }, .eeprom_ops = { .regulatory_bands = { diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 84f181443f02..02103a7ae1df 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -310,7 +310,6 @@ static struct iwl_lib_ops iwl6000_lib = { .init = iwl_apm_init, .stop = iwl_apm_stop, .config = iwl6000_nic_config, - .set_pwr_src = iwl_set_pwr_src, }, .eeprom_ops = { .regulatory_bands = { @@ -383,7 +382,6 @@ static struct iwl_lib_ops iwl6000g2b_lib = { .init = iwl_apm_init, .stop = iwl_apm_stop, .config = iwl6000_nic_config, - .set_pwr_src = iwl_set_pwr_src, }, .eeprom_ops = { .regulatory_bands = { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index ff5f2fc4d6d9..0ad0d44893ab 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -685,6 +685,23 @@ int iwlagn_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) return 0; } +static void iwlagn_set_pwr_vmain(struct iwl_priv *priv) +{ +/* + * (for documentation purposes) + * to set power to V_AUX, do: + + if (pci_pme_capable(priv->pci_dev, PCI_D3cold)) + iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, + APMG_PS_CTRL_VAL_PWR_SRC_VAUX, + ~APMG_PS_CTRL_MSK_PWR_SRC); + */ + + iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, + APMG_PS_CTRL_VAL_PWR_SRC_VMAIN, + ~APMG_PS_CTRL_MSK_PWR_SRC); +} + int iwlagn_hw_nic_init(struct iwl_priv *priv) { unsigned long flags; @@ -700,7 +717,7 @@ int iwlagn_hw_nic_init(struct iwl_priv *priv) spin_unlock_irqrestore(&priv->lock, flags); - ret = priv->cfg->ops->lib->apm_ops.set_pwr_src(priv, IWL_PWR_SRC_VMAIN); + iwlagn_set_pwr_vmain(priv); priv->cfg->ops->lib->apm_ops.config(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 8233c6410411..75472a3d87de 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -935,22 +935,6 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv, wake_up_interruptible(&priv->wait_command_queue); } -int iwl_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src) -{ - if (src == IWL_PWR_SRC_VAUX) { - if (pci_pme_capable(priv->pci_dev, PCI_D3cold)) - iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, - APMG_PS_CTRL_VAL_PWR_SRC_VAUX, - ~APMG_PS_CTRL_MSK_PWR_SRC); - } else { - iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, - APMG_PS_CTRL_VAL_PWR_SRC_VMAIN, - ~APMG_PS_CTRL_MSK_PWR_SRC); - } - - return 0; -} - static void iwl_bg_tx_flush(struct work_struct *work) { struct iwl_priv *priv = diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index f3c3d8531505..ae77279d3d98 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -119,7 +119,6 @@ struct iwl_apm_ops { int (*init)(struct iwl_priv *priv); void (*stop)(struct iwl_priv *priv); void (*config)(struct iwl_priv *priv); - int (*set_pwr_src)(struct iwl_priv *priv, enum iwl_pwr_src src); }; struct iwl_debugfs_ops { diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 2b04714c3a9c..2c57dbd2de19 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -282,13 +282,6 @@ struct iwl_channel_info { */ #define IWL_IPAN_MCAST_QUEUE 8 -/* Power management (not Tx power) structures */ - -enum iwl_pwr_src { - IWL_PWR_SRC_VMAIN, - IWL_PWR_SRC_VAUX, -}; - #define IEEE80211_DATA_LEN 2304 #define IEEE80211_4ADDR_LEN 30 #define IEEE80211_HLEN (IEEE80211_4ADDR_LEN) @@ -732,7 +725,6 @@ struct iwl_hw_params { * ****************************************************************************/ extern void iwl_update_chain_flags(struct iwl_priv *priv); -extern int iwl_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src); extern const u8 iwl_bcast_addr[ETH_ALEN]; extern int iwl_rxq_stop(struct iwl_priv *priv); extern void iwl_txq_ctx_stop(struct iwl_priv *priv); From 14e8e4afeb7e90f1f2d3f2d3b54da57c27f59f38 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 22 Sep 2010 18:02:10 +0200 Subject: [PATCH 016/127] iwlwifi: remove apm_ops.stop Since all devices share the same operation here, there's no need to call it indirectly. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-1000.c | 1 - drivers/net/wireless/iwlwifi/iwl-3945.c | 1 - drivers/net/wireless/iwlwifi/iwl-4965.c | 1 - drivers/net/wireless/iwlwifi/iwl-5000.c | 2 -- drivers/net/wireless/iwlwifi/iwl-6000.c | 2 -- drivers/net/wireless/iwlwifi/iwl-agn.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-core.c | 2 +- drivers/net/wireless/iwlwifi/iwl-core.h | 1 - drivers/net/wireless/iwlwifi/iwl-eeprom.c | 2 +- drivers/net/wireless/iwlwifi/iwl3945-base.c | 4 ++-- 10 files changed, 6 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 5bdfe9dcd070..db540910b110 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -194,7 +194,6 @@ static struct iwl_lib_ops iwl1000_lib = { .update_chain_flags = iwl_update_chain_flags, .apm_ops = { .init = iwl_apm_init, - .stop = iwl_apm_stop, .config = iwl1000_nic_config, }, .eeprom_ops = { diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 824c9428efaa..b06a7bd8b285 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -2704,7 +2704,6 @@ static struct iwl_lib_ops iwl3945_lib = { .dump_nic_error_log = iwl3945_dump_nic_error_log, .apm_ops = { .init = iwl3945_apm_init, - .stop = iwl_apm_stop, .config = iwl3945_nic_config, }, .eeprom_ops = { diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index cda4a319ed97..28ba563197cb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -2266,7 +2266,6 @@ static struct iwl_lib_ops iwl4965_lib = { .set_channel_switch = iwl4965_hw_channel_switch, .apm_ops = { .init = iwl_apm_init, - .stop = iwl_apm_stop, .config = iwl4965_nic_config, }, .eeprom_ops = { diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index c90a16cdfaff..fd9fbc93ea1b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -368,7 +368,6 @@ static struct iwl_lib_ops iwl5000_lib = { .set_channel_switch = iwl5000_hw_channel_switch, .apm_ops = { .init = iwl_apm_init, - .stop = iwl_apm_stop, .config = iwl5000_nic_config, }, .eeprom_ops = { @@ -437,7 +436,6 @@ static struct iwl_lib_ops iwl5150_lib = { .set_channel_switch = iwl5000_hw_channel_switch, .apm_ops = { .init = iwl_apm_init, - .stop = iwl_apm_stop, .config = iwl5000_nic_config, }, .eeprom_ops = { diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 02103a7ae1df..a45929ef22ec 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -308,7 +308,6 @@ static struct iwl_lib_ops iwl6000_lib = { .set_channel_switch = iwl6000_hw_channel_switch, .apm_ops = { .init = iwl_apm_init, - .stop = iwl_apm_stop, .config = iwl6000_nic_config, }, .eeprom_ops = { @@ -380,7 +379,6 @@ static struct iwl_lib_ops iwl6000g2b_lib = { .set_channel_switch = iwl6000_hw_channel_switch, .apm_ops = { .init = iwl_apm_init, - .stop = iwl_apm_stop, .config = iwl6000_nic_config, }, .eeprom_ops = { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 75472a3d87de..b1af79e7020a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2983,7 +2983,7 @@ static void __iwl_down(struct iwl_priv *priv) iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); /* Stop the device, and put it in low power state */ - priv->cfg->ops->lib->apm_ops.stop(priv); + iwl_apm_stop(priv); exit: memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp)); @@ -4597,7 +4597,7 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev) * paths to avoid running iwl_down() at all before leaving driver. * This (inexpensive) call *makes sure* device is reset. */ - priv->cfg->ops->lib->apm_ops.stop(priv); + iwl_apm_stop(priv); iwl_tt_exit(priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 5cd16a745bac..b3efbe02df67 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2599,7 +2599,7 @@ int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state) * it will not call apm_ops.stop() to stop the DMA operation. * Calling apm_ops.stop here to make sure we stop the DMA. */ - priv->cfg->ops->lib->apm_ops.stop(priv); + iwl_apm_stop(priv); pci_save_state(pdev); pci_disable_device(pdev); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index ae77279d3d98..c01262cf7249 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -117,7 +117,6 @@ struct iwl_hcmd_utils_ops { struct iwl_apm_ops { int (*init)(struct iwl_priv *priv); - void (*stop)(struct iwl_priv *priv); void (*config)(struct iwl_priv *priv); }; diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index bd51b06288eb..66eccb12159d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -603,7 +603,7 @@ err: if (ret) iwl_eeprom_free(priv); /* Reset chip to save power until we load uCode during "up". */ - priv->cfg->ops->lib->apm_ops.stop(priv); + iwl_apm_stop(priv); alloc_err: return ret; } diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index c06b2189e09e..980c6096620a 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2637,7 +2637,7 @@ static void __iwl3945_down(struct iwl_priv *priv) udelay(5); /* Stop the device, and put it in low power state */ - priv->cfg->ops->lib->apm_ops.stop(priv); + iwl_apm_stop(priv); exit: memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp)); @@ -4212,7 +4212,7 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) * paths to avoid running iwl_down() at all before leaving driver. * This (inexpensive) call *makes sure* device is reset. */ - priv->cfg->ops->lib->apm_ops.stop(priv); + iwl_apm_stop(priv); /* make sure we flush any pending irq or * tasklet for the driver From 0de76736552cff02cc6ee4bae41e5502d7673f8e Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 22 Sep 2010 18:02:11 +0200 Subject: [PATCH 017/127] iwlwifi: clean up declarations A number of declarations in iwl-core.h should be in agn specific files, and also rename the iwl-calib.h file to iwl-agn-calib.h to better reflect that it belongs to agn. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-4965.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-calib.c | 2 +- .../iwlwifi/{iwl-calib.h => iwl-agn-calib.h} | 4 +++ drivers/net/wireless/iwlwifi/iwl-agn-rx.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | 1 + drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn.h | 23 +++++++++++++ drivers/net/wireless/iwlwifi/iwl-core.h | 33 ------------------- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 1 - drivers/net/wireless/iwlwifi/iwl-rx.c | 1 - 10 files changed, 32 insertions(+), 39 deletions(-) rename drivers/net/wireless/iwlwifi/{iwl-calib.h => iwl-agn-calib.h} (95%) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 28ba563197cb..b207e3e9299f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -43,7 +43,7 @@ #include "iwl-core.h" #include "iwl-io.h" #include "iwl-helpers.h" -#include "iwl-calib.h" +#include "iwl-agn-calib.h" #include "iwl-sta.h" #include "iwl-agn-led.h" #include "iwl-agn.h" diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c index 4c5ab783737f..e2019e756936 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c @@ -65,7 +65,7 @@ #include "iwl-dev.h" #include "iwl-core.h" -#include "iwl-calib.h" +#include "iwl-agn-calib.h" /***************************************************************************** * INIT calibrations framework diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.h b/drivers/net/wireless/iwlwifi/iwl-agn-calib.h similarity index 95% rename from drivers/net/wireless/iwlwifi/iwl-calib.h rename to drivers/net/wireless/iwlwifi/iwl-agn-calib.h index ba9523fbb300..e37ae7261630 100644 --- a/drivers/net/wireless/iwlwifi/iwl-calib.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.h @@ -79,4 +79,8 @@ static inline void iwl_chain_noise_reset(struct iwl_priv *priv) priv->cfg->ops->utils->chain_noise_reset(priv); } +int iwl_send_calib_results(struct iwl_priv *priv); +int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len); +void iwl_calib_free_results(struct iwl_priv *priv); + #endif /* __iwl_calib_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c index 1e08eb455474..bbd40b7dd597 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c @@ -34,7 +34,7 @@ #include "iwl-dev.h" #include "iwl-core.h" -#include "iwl-calib.h" +#include "iwl-agn-calib.h" #include "iwl-sta.h" #include "iwl-io.h" #include "iwl-helpers.h" diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index e1dd76267dca..3a9537953875 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -38,6 +38,7 @@ #include "iwl-helpers.h" #include "iwl-agn-hw.h" #include "iwl-agn.h" +#include "iwl-agn-calib.h" static const s8 iwlagn_default_queue_to_tx_fifo[] = { IWL_TX_FIFO_VO, diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index b1af79e7020a..763a93d832f8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -57,7 +57,7 @@ #include "iwl-io.h" #include "iwl-helpers.h" #include "iwl-sta.h" -#include "iwl-calib.h" +#include "iwl-agn-calib.h" #include "iwl-agn.h" diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 1fca5af35771..b4deef4e91db 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -177,8 +177,15 @@ void iwlagn_rx_reply_rx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); void iwlagn_rx_reply_rx_phy(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); +void iwl_rx_handle(struct iwl_priv *priv); /* tx */ +void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq); +int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, + struct iwl_tx_queue *txq, + dma_addr_t addr, u16 len, u8 reset, u8 pad); +int iwl_hw_tx_queue_init(struct iwl_priv *priv, + struct iwl_tx_queue *txq); void iwlagn_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, struct ieee80211_tx_info *info); int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb); @@ -289,4 +296,20 @@ void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id); void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt); int iwl_update_bcast_stations(struct iwl_priv *priv); +/* rate */ +static inline u32 iwl_ant_idx_to_flags(u8 ant_idx) +{ + return BIT(ant_idx) << RATE_MCS_ANT_POS; +} + +static inline u8 iwl_hw_get_rate(__le32 rate_n_flags) +{ + return le32_to_cpu(rate_n_flags) & 0xFF; +} + +static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags) +{ + return cpu_to_le32(flags|(u32)rate); +} + #endif /* __iwl_agn_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index c01262cf7249..a5e12b70c594 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -396,7 +396,6 @@ struct iwl_cfg { struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg, struct ieee80211_ops *hw_ops); -void iwl_activate_qos(struct iwl_priv *priv); int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, const struct ieee80211_tx_queue_params *params); int iwl_mac_tx_last_beacon(struct ieee80211_hw *hw); @@ -505,7 +504,6 @@ void iwl_rx_reply_error(struct iwl_priv *priv, ******************************************************/ void iwl_cmd_queue_free(struct iwl_priv *priv); int iwl_rx_queue_alloc(struct iwl_priv *priv); -void iwl_rx_handle(struct iwl_priv *priv); void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q); int iwl_rx_queue_space(const struct iwl_rx_queue *q); @@ -523,12 +521,6 @@ void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); /***************************************************** * TX ******************************************************/ -void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq); -int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, - struct iwl_tx_queue *txq, - dma_addr_t addr, u16 len, u8 reset, u8 pad); -int iwl_hw_tx_queue_init(struct iwl_priv *priv, - struct iwl_tx_queue *txq); void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq); int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, int slots_num, u32 txq_id); @@ -547,24 +539,6 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force); u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv, struct iwl_rxon_context *ctx); -static inline u32 iwl_ant_idx_to_flags(u8 ant_idx) -{ - return BIT(ant_idx) << RATE_MCS_ANT_POS; -} - -static inline u8 iwl_hw_get_rate(__le32 rate_n_flags) -{ - return le32_to_cpu(rate_n_flags) & 0xFF; -} -static inline u32 iwl_hw_get_rate_n_flags(__le32 rate_n_flags) -{ - return le32_to_cpu(rate_n_flags) & 0x1FFFF; -} -static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags) -{ - return cpu_to_le32(flags|(u32)rate); -} - /******************************************************************************* * Scanning ******************************************************************************/ @@ -600,13 +574,6 @@ void iwl_cancel_scan_deferred_work(struct iwl_priv *priv); #define IWL_SCAN_CHECK_WATCHDOG (HZ * 7) -/******************************************************************************* - * Calibrations - implemented in iwl-calib.c - ******************************************************************************/ -int iwl_send_calib_results(struct iwl_priv *priv); -int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len); -void iwl_calib_free_results(struct iwl_priv *priv); - /***************************************************** * S e n d i n g H o s t C o m m a n d s * *****************************************************/ diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index fc340311ea0a..96d9085639e3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -39,7 +39,6 @@ #include "iwl-debug.h" #include "iwl-core.h" #include "iwl-io.h" -#include "iwl-calib.h" /* create and remove of files */ #define DEBUGFS_ADD_FILE(name, parent, mode) do { \ diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 10be197b0f22..f436270ca39a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c @@ -36,7 +36,6 @@ #include "iwl-core.h" #include "iwl-sta.h" #include "iwl-io.h" -#include "iwl-calib.h" #include "iwl-helpers.h" /************************** RX-FUNCTIONS ****************************/ /* From a313f3839eeeebb3cbbcf1fbd2aee92bde389032 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 22 Sep 2010 18:02:12 +0200 Subject: [PATCH 018/127] iwlwifi: remove iwl_check_bits The function is used exactly once, and the caller doesn't even need the special check, it can be simplified to a simple bit check. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-3945.c | 2 +- drivers/net/wireless/iwlwifi/iwl-helpers.h | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index b06a7bd8b285..7d74ae53950c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -348,7 +348,7 @@ static void iwl3945_rx_reply_tx(struct iwl_priv *priv, IWL_DEBUG_TX_REPLY(priv, "Tx queue reclaim %d\n", index); iwl3945_tx_queue_reclaim(priv, txq_id, index); - if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK)) + if (status & TX_ABORT_REQUIRED_MSK) IWL_ERR(priv, "TODO: Implement Tx ABORT REQUIRED!!!\n"); } diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h index 621abe3c5afc..1aaef70deaec 100644 --- a/drivers/net/wireless/iwlwifi/iwl-helpers.h +++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h @@ -44,11 +44,6 @@ static inline struct ieee80211_conf *ieee80211_get_hw_conf( return &hw->conf; } -static inline int iwl_check_bits(unsigned long field, unsigned long mask) -{ - return ((field & mask) == mask) ? 1 : 0; -} - static inline unsigned long elapsed_jiffies(unsigned long start, unsigned long end) { From 1cf263736092b3712103a5290a93dd0fff376f26 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 22 Sep 2010 07:32:13 -0700 Subject: [PATCH 019/127] iwlwifi: fix dual-mode scanning The recent scanning code shuffle accidentally moved the SCAN_HW bit setting _after_ the PAN parameters are modified, which means that they don't take the scan into account -- fix that. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 0ad0d44893ab..c1a389883af0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -1565,13 +1565,15 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) cmd.data = scan; scan->len = cpu_to_le16(cmd.len); + /* set scan bit here for PAN params */ + set_bit(STATUS_SCAN_HW, &priv->status); + if (priv->cfg->ops->hcmd->set_pan_params) { ret = priv->cfg->ops->hcmd->set_pan_params(priv); if (ret) return ret; } - set_bit(STATUS_SCAN_HW, &priv->status); ret = iwl_send_cmd_sync(priv, &cmd); if (ret) { clear_bit(STATUS_SCAN_HW, &priv->status); From 65cccfb03d0dc99fd213d57be5f60f8ca6a60824 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 21 Sep 2010 16:15:58 -0700 Subject: [PATCH 020/127] iwlagn: no version check for experimental uCode For experimental uCode, it should work with the driver if driver has experimental uCode support option enabled; remove the API version checking. Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn.c | 27 +++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 763a93d832f8..1b682ddcf4e8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2104,18 +2104,23 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) * firmware filename ... but we don't check for that and only rely * on the API version read from firmware header from here on forward */ - if (api_ver < api_min || api_ver > api_max) { - IWL_ERR(priv, "Driver unable to support your firmware API. " - "Driver supports v%u, firmware is v%u.\n", - api_max, api_ver); - goto try_again; - } + /* no api version check required for experimental uCode */ + if (priv->fw_index != UCODE_EXPERIMENTAL_INDEX) { + if (api_ver < api_min || api_ver > api_max) { + IWL_ERR(priv, + "Driver unable to support your firmware API. " + "Driver supports v%u, firmware is v%u.\n", + api_max, api_ver); + goto try_again; + } - if (api_ver != api_max) - IWL_ERR(priv, "Firmware has old API version. Expected v%u, " - "got v%u. New firmware can be obtained " - "from http://www.intellinuxwireless.org.\n", - api_max, api_ver); + if (api_ver != api_max) + IWL_ERR(priv, + "Firmware has old API version. Expected v%u, " + "got v%u. New firmware can be obtained " + "from http://www.intellinuxwireless.org.\n", + api_max, api_ver); + } if (build) sprintf(buildstr, " build %u%s", build, From 642454cc0774e0774bc1ccb4292d6dc0abd06d20 Mon Sep 17 00:00:00 2001 From: Shanyu Zhao Date: Tue, 21 Sep 2010 12:06:18 -0700 Subject: [PATCH 021/127] iwlagn: fix default calibration table size iwlagn driver uses the IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE as the chain noise reset calibration index and IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE+1 as the chain noise gain calibration index, if not specified by the TLV value in the new firmware format. However, this is broken if we need to add more calibrations like the temperature offset calibration because we increased IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE by 1. To fix this issue, define IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE and use it as the calibration index instead. We still keep the IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE as a sanity check for the TLV value given by ucode. Signed-off-by: Shanyu Zhao Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +- drivers/net/wireless/iwlwifi/iwl-commands.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 1b682ddcf4e8..c4fe3f94c366 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2062,7 +2062,7 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) struct iwlagn_ucode_capabilities ucode_capa = { .max_probe_length = 200, .standard_phy_calibration_size = - IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE, + IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE, }; memset(&pieces, 0, sizeof(pieces)); diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index fe652568fec7..74b78d858936 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -3784,7 +3784,8 @@ struct iwl_enhance_sensitivity_cmd { */ /* Phy calibration command for series */ - +/* The default calibrate table size if not specified by firmware */ +#define IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE 18 enum { IWL_PHY_CALIBRATE_DIFF_GAIN_CMD = 7, IWL_PHY_CALIBRATE_DC_CMD = 8, From bf53f939e02c0e818df93ab130fedc0e4ba95796 Mon Sep 17 00:00:00 2001 From: Shanyu Zhao Date: Tue, 21 Sep 2010 16:54:01 -0700 Subject: [PATCH 022/127] iwlagn: add temperature offset calib for 6000g2 6000g2 devices need to have temperature offset calibration. The runtime uCode needs to receive the calibration results just like BB and LO calibration. To do this, driver reads the offset value from NVM and send it to uCode after runtime uCode is alive. Signed-off-by: Shanyu Zhao Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-6000.c | 11 ++++++++ drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | 27 ++++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-commands.h | 10 +++++++- drivers/net/wireless/iwlwifi/iwl-core.h | 2 ++ drivers/net/wireless/iwlwifi/iwl-dev.h | 1 + 5 files changed, 50 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index a45929ef22ec..4810258aefd9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -204,6 +204,8 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv) BIT(IWL_CALIB_BASE_BAND); if (priv->cfg->need_dc_calib) priv->hw_params.calib_rt_cfg |= BIT(IWL_CALIB_CFG_DC_IDX); + if (priv->cfg->need_temp_offset_calib) + priv->hw_params.calib_init_cfg |= BIT(IWL_CALIB_TEMP_OFFSET); priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS; @@ -536,6 +538,7 @@ struct iwl_cfg iwl6000g2a_2agn_cfg = { .base_params = &iwl6000_base_params, .ht_params = &iwl6000_ht_params, .need_dc_calib = true, + .need_temp_offset_calib = true, }; struct iwl_cfg iwl6000g2a_2abg_cfg = { @@ -552,6 +555,7 @@ struct iwl_cfg iwl6000g2a_2abg_cfg = { .mod_params = &iwlagn_mod_params, .base_params = &iwl6000_base_params, .need_dc_calib = true, + .need_temp_offset_calib = true, }; struct iwl_cfg iwl6000g2a_2bg_cfg = { @@ -568,6 +572,7 @@ struct iwl_cfg iwl6000g2a_2bg_cfg = { .mod_params = &iwlagn_mod_params, .base_params = &iwl6000_base_params, .need_dc_calib = true, + .need_temp_offset_calib = true, }; struct iwl_cfg iwl6000g2b_2agn_cfg = { @@ -586,6 +591,7 @@ struct iwl_cfg iwl6000g2b_2agn_cfg = { .bt_params = &iwl6000_bt_params, .ht_params = &iwl6000_ht_params, .need_dc_calib = true, + .need_temp_offset_calib = true, /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, }; @@ -605,6 +611,7 @@ struct iwl_cfg iwl6000g2b_2abg_cfg = { .base_params = &iwl6000_base_params, .bt_params = &iwl6000_bt_params, .need_dc_calib = true, + .need_temp_offset_calib = true, /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, }; @@ -625,6 +632,7 @@ struct iwl_cfg iwl6000g2b_2bgn_cfg = { .bt_params = &iwl6000_bt_params, .ht_params = &iwl6000_ht_params, .need_dc_calib = true, + .need_temp_offset_calib = true, /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, }; @@ -644,6 +652,7 @@ struct iwl_cfg iwl6000g2b_2bg_cfg = { .base_params = &iwl6000_base_params, .bt_params = &iwl6000_bt_params, .need_dc_calib = true, + .need_temp_offset_calib = true, /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, }; @@ -664,6 +673,7 @@ struct iwl_cfg iwl6000g2b_bgn_cfg = { .bt_params = &iwl6000_bt_params, .ht_params = &iwl6000_ht_params, .need_dc_calib = true, + .need_temp_offset_calib = true, /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, }; @@ -683,6 +693,7 @@ struct iwl_cfg iwl6000g2b_bg_cfg = { .base_params = &iwl6000_base_params, .bt_params = &iwl6000_bt_params, .need_dc_calib = true, + .need_temp_offset_calib = true, /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index 3a9537953875..703621107dac 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c @@ -215,6 +215,25 @@ static int iwlagn_set_Xtal_calib(struct iwl_priv *priv) (u8 *)&cmd, sizeof(cmd)); } +static int iwlagn_set_temperature_offset_calib(struct iwl_priv *priv) +{ + struct iwl_calib_temperature_offset_cmd cmd; + __le16 *offset_calib = + (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_5000_TEMPERATURE); + cmd.hdr.op_code = IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD; + cmd.hdr.first_group = 0; + cmd.hdr.groups_num = 1; + cmd.hdr.data_valid = 1; + cmd.radio_sensor_offset = le16_to_cpu(offset_calib[1]); + if (!(cmd.radio_sensor_offset)) + cmd.radio_sensor_offset = DEFAULT_RADIO_SENSOR_OFFSET; + cmd.reserved = 0; + IWL_DEBUG_CALIB(priv, "Radio sensor offset: %d\n", + cmd.radio_sensor_offset); + return iwl_calib_set(&priv->calib_results[IWL_CALIB_TEMP_OFFSET], + (u8 *)&cmd, sizeof(cmd)); +} + static int iwlagn_send_calib_cfg(struct iwl_priv *priv) { struct iwl_calib_cfg_cmd calib_cfg_cmd; @@ -321,6 +340,14 @@ void iwlagn_init_alive_start(struct iwl_priv *priv) } iwlagn_send_calib_cfg(priv); + + /** + * temperature offset calibration is only needed for runtime ucode, + * so prepare the value now. + */ + if (priv->cfg->need_temp_offset_calib) + iwlagn_set_temperature_offset_calib(priv); + return; restart: diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 74b78d858936..424801abc80e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -3794,7 +3794,8 @@ enum { IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD = 15, IWL_PHY_CALIBRATE_BASE_BAND_CMD = 16, IWL_PHY_CALIBRATE_TX_IQ_PERD_CMD = 17, - IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE = 18, + IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD = 18, + IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE = 19, }; #define IWL_MAX_PHY_CALIBRATE_TBL_SIZE (253) @@ -3864,6 +3865,13 @@ struct iwl_calib_xtal_freq_cmd { u8 pad[2]; } __packed; +#define DEFAULT_RADIO_SENSOR_OFFSET 2700 +struct iwl_calib_temperature_offset_cmd { + struct iwl_calib_hdr hdr; + s16 radio_sensor_offset; + s16 reserved; +} __packed; + /* IWL_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD */ struct iwl_calib_chain_noise_reset_cmd { struct iwl_calib_hdr hdr; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index a5e12b70c594..64527def059f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -342,6 +342,7 @@ struct iwl_ht_params { * @ucode_api_min: Lowest version of uCode API supported by driver. * @pa_type: used by 6000 series only to identify the type of Power Amplifier * @need_dc_calib: need to perform init dc calibration + * @need_temp_offset_calib: need to perform temperature offset calibration * @scan_antennas: available antenna for scan operation * * We enable the driver to be backward compatible wrt API version. The @@ -386,6 +387,7 @@ struct iwl_cfg { struct iwl_bt_params *bt_params; enum iwl_pa_type pa_type; /* if used set to IWL_PA_SYSTEM */ const bool need_dc_calib; /* if used set to true */ + const bool need_temp_offset_calib; /* if used set to true */ u8 scan_rx_antennas[IEEE80211_NUM_BANDS]; u8 scan_tx_antennas[IEEE80211_NUM_BANDS]; }; diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 2c57dbd2de19..de43e1350ed1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -835,6 +835,7 @@ enum iwl_calib { IWL_CALIB_TX_IQ, IWL_CALIB_TX_IQ_PERD, IWL_CALIB_BASE_BAND, + IWL_CALIB_TEMP_OFFSET, IWL_CALIB_MAX }; From 00cbb3c5317d418c349c60876fe12fba7624f3e7 Mon Sep 17 00:00:00 2001 From: Ohad Ben-Cohen Date: Fri, 8 Oct 2010 16:16:16 +0300 Subject: [PATCH 023/127] wl1271: sdio: enable runtime PM Enable runtime PM for the wl1271 SDIO device. We request power whenever the WLAN interface is brought up, and release it after the WLAN interface is taken down. As a result, power is released immediately after probe returns, since at that point power has not been explicitly requested yet (i.e. the WLAN interface is still down). Signed-off-by: Ohad Ben-Cohen Acked-by: Luciano Coelho Tested-by: Luciano Coelho Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/wl1271_sdio.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/wl12xx/wl1271_sdio.c b/drivers/net/wireless/wl12xx/wl1271_sdio.c index 4c250d7dc3fa..f7bef32f04c9 100644 --- a/drivers/net/wireless/wl12xx/wl1271_sdio.c +++ b/drivers/net/wireless/wl12xx/wl1271_sdio.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "wl1271.h" #include "wl12xx_80211.h" @@ -160,12 +161,19 @@ static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf, static int wl1271_sdio_power_on(struct wl1271 *wl) { struct sdio_func *func = wl_to_func(wl); + int ret; + + /* Power up the card */ + ret = pm_runtime_get_sync(&func->dev); + if (ret < 0) + goto out; sdio_claim_host(func); sdio_enable_func(func); sdio_release_host(func); - return 0; +out: + return ret; } static int wl1271_sdio_power_off(struct wl1271 *wl) @@ -176,15 +184,12 @@ static int wl1271_sdio_power_off(struct wl1271 *wl) sdio_disable_func(func); sdio_release_host(func); - return 0; + /* Power down the card */ + return pm_runtime_put_sync(&func->dev); } static int wl1271_sdio_set_power(struct wl1271 *wl, bool enable) { - /* Let the SDIO stack handle wlan_enable control, so we - * keep host claimed while wlan is in use to keep wl1271 - * alive. - */ if (enable) return wl1271_sdio_power_on(wl); else @@ -256,6 +261,9 @@ static int __devinit wl1271_probe(struct sdio_func *func, sdio_set_drvdata(func, wl); + /* Tell PM core that we don't need the card to be powered now */ + pm_runtime_put_noidle(&func->dev); + wl1271_notice("initialized"); return 0; @@ -274,6 +282,9 @@ static void __devexit wl1271_remove(struct sdio_func *func) { struct wl1271 *wl = sdio_get_drvdata(func); + /* Undo decrement done above in wl1271_probe */ + pm_runtime_get_noresume(&func->dev); + wl1271_unregister_hw(wl); free_irq(wl->irq, wl); wl1271_free_hw(wl); From 674f3058c806ae2591b98f59194fa85b650aa667 Mon Sep 17 00:00:00 2001 From: Ohad Ben-Cohen Date: Fri, 8 Oct 2010 16:16:27 +0300 Subject: [PATCH 024/127] wl1271: sdio: add suspend/resume support Add required suspend/resume support to prevent the SDIO core from removing our card completely during system suspend. Signed-off-by: Ohad Ben-Cohen Tested-by: Luciano Coelho Signed-off-by: Luciano Coelho --- drivers/net/wireless/wl12xx/wl1271_sdio.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/drivers/net/wireless/wl12xx/wl1271_sdio.c b/drivers/net/wireless/wl12xx/wl1271_sdio.c index f7bef32f04c9..784ef3432641 100644 --- a/drivers/net/wireless/wl12xx/wl1271_sdio.c +++ b/drivers/net/wireless/wl12xx/wl1271_sdio.c @@ -290,11 +290,31 @@ static void __devexit wl1271_remove(struct sdio_func *func) wl1271_free_hw(wl); } +static int wl1271_suspend(struct device *dev) +{ + /* Tell MMC/SDIO core it's OK to power down the card + * (if it isn't already), but not to remove it completely */ + return 0; +} + +static int wl1271_resume(struct device *dev) +{ + return 0; +} + +static const struct dev_pm_ops wl1271_sdio_pm_ops = { + .suspend = wl1271_suspend, + .resume = wl1271_resume, +}; + static struct sdio_driver wl1271_sdio_driver = { .name = "wl1271_sdio", .id_table = wl1271_devices, .probe = wl1271_probe, .remove = __devexit_p(wl1271_remove), + .drv = { + .pm = &wl1271_sdio_pm_ops, + }, }; static int __init wl1271_init(void) From 7623225f905263424c7254dc6a07bff083a498dd Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 11 Oct 2010 14:46:52 -0400 Subject: [PATCH 025/127] Revert "wireless: Use first phyX name available when registering phy devices." This reverts commit 5a254ffe3ffdfa84fe076009bd8e88da412180d2. The commit failed to take into account that allocated wireless devices (wiphys) are not added into the device list upon allocation, but only when they are registered. Therefore, it opened up a race between allocating and registering a name, so that if two processes allocate and register concurrently ("alloc, alloc, register, register" rather than "alloc, register, alloc, register") the code will attempt to use the same name twice. Signed-off-by: Johannes Berg --- net/wireless/core.c | 54 ++++++++++++++++++++------------------------- 1 file changed, 24 insertions(+), 30 deletions(-) diff --git a/net/wireless/core.c b/net/wireless/core.c index 1684ad91763c..9c21ebf9780e 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -178,10 +178,26 @@ int cfg80211_dev_rename(struct cfg80211_registered_device *rdev, char *newname) { struct cfg80211_registered_device *rdev2; - int result; + int wiphy_idx, taken = -1, result, digits; assert_cfg80211_lock(); + /* prohibit calling the thing phy%d when %d is not its number */ + sscanf(newname, PHY_NAME "%d%n", &wiphy_idx, &taken); + if (taken == strlen(newname) && wiphy_idx != rdev->wiphy_idx) { + /* count number of places needed to print wiphy_idx */ + digits = 1; + while (wiphy_idx /= 10) + digits++; + /* + * deny the name if it is phy where is printed + * without leading zeroes. taken == strlen(newname) here + */ + if (taken == strlen(PHY_NAME) + digits) + return -EINVAL; + } + + /* Ignore nop renames */ if (strcmp(newname, dev_name(&rdev->wiphy.dev)) == 0) return 0; @@ -189,7 +205,7 @@ int cfg80211_dev_rename(struct cfg80211_registered_device *rdev, /* Ensure another device does not already have this name. */ list_for_each_entry(rdev2, &cfg80211_rdev_list, list) if (strcmp(newname, dev_name(&rdev2->wiphy.dev)) == 0) - return -EEXIST; + return -EINVAL; result = device_rename(&rdev->wiphy.dev, newname); if (result) @@ -304,11 +320,9 @@ static void cfg80211_event_work(struct work_struct *work) struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv) { static int wiphy_counter; - int i; - struct cfg80211_registered_device *rdev, *rdev2; + + struct cfg80211_registered_device *rdev; int alloc_size; - char nname[IFNAMSIZ + 1]; - bool found = false; WARN_ON(ops->add_key && (!ops->del_key || !ops->set_default_key)); WARN_ON(ops->auth && (!ops->assoc || !ops->deauth || !ops->disassoc)); @@ -332,37 +346,17 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv) if (unlikely(!wiphy_idx_valid(rdev->wiphy_idx))) { wiphy_counter--; - goto too_many_devs; - } - - /* 64k wiphy devices is enough for anyone! */ - for (i = 0; i < 0xFFFF; i++) { - found = false; - snprintf(nname, sizeof(nname)-1, PHY_NAME "%d", i); - nname[sizeof(nname)-1] = 0; - list_for_each_entry(rdev2, &cfg80211_rdev_list, list) - if (strcmp(nname, dev_name(&rdev2->wiphy.dev)) == 0) { - found = true; - break; - } - - if (!found) - break; - } - - if (unlikely(found)) { -too_many_devs: mutex_unlock(&cfg80211_mutex); - /* ugh, too many devices already! */ + /* ugh, wrapped! */ kfree(rdev); return NULL; } - /* give it a proper name */ - dev_set_name(&rdev->wiphy.dev, "%s", nname); - mutex_unlock(&cfg80211_mutex); + /* give it a proper name */ + dev_set_name(&rdev->wiphy.dev, PHY_NAME "%d", rdev->wiphy_idx); + mutex_init(&rdev->mtx); mutex_init(&rdev->devlist_mtx); INIT_LIST_HEAD(&rdev->netdev_list); From b38afa87698375179026224522c2e48dcbf17e65 Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Thu, 7 Oct 2010 16:12:06 -0700 Subject: [PATCH 026/127] mac80211: Improve mlme probe response log messages. Old messages didn't mention the device in question. Signed-off-by: Ben Greear Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 5695c94c49aa..a3a9421555af 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1864,10 +1864,12 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) else if (ifmgd->probe_send_count < IEEE80211_MAX_PROBE_TRIES) { #ifdef CONFIG_MAC80211_VERBOSE_DEBUG - printk(KERN_DEBUG "No probe response from AP %pM" - " after %dms, try %d\n", bssid, - (1000 * IEEE80211_PROBE_WAIT)/HZ, - ifmgd->probe_send_count); + wiphy_debug(local->hw.wiphy, + "%s: No probe response from AP %pM" + " after %dms, try %d\n", + sdata->name, + bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ, + ifmgd->probe_send_count); #endif ieee80211_mgd_probe_ap_send(sdata); } else { @@ -1877,9 +1879,11 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) */ ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL | IEEE80211_STA_BEACON_POLL); - printk(KERN_DEBUG "No probe response from AP %pM" - " after %dms, disconnecting.\n", - bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); + wiphy_debug(local->hw.wiphy, + "%s: No probe response from AP %pM" + " after %dms, disconnecting.\n", + sdata->name, + bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); ieee80211_set_disassoc(sdata, true, true); mutex_unlock(&ifmgd->mtx); mutex_lock(&local->mtx); From 5a5c731aa59cc2c44ca20f45b1a577cd4f5435e2 Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Thu, 7 Oct 2010 16:39:20 -0700 Subject: [PATCH 027/127] wireless: Set some stats used by /proc/net/wireless (wext) Some stats for /proc/net/wireless (and wext in general) are not being set. This patch addresses a few of those with values easily obtained from mac80211 core. Signed-off-by: Ben Greear Signed-off-by: John W. Linville --- include/net/cfg80211.h | 4 ++++ net/mac80211/cfg.c | 4 +++- net/wireless/wext-compat.c | 4 ++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 0778d04b3bbe..f920a06f363e 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -403,6 +403,7 @@ struct station_parameters { * @STATION_INFO_TX_PACKETS: @tx_packets filled * @STATION_INFO_TX_RETRIES: @tx_retries filled * @STATION_INFO_TX_FAILED: @tx_failed filled + * @STATION_INFO_RX_DROP_MISC: @rx_dropped_misc filled */ enum station_info_flags { STATION_INFO_INACTIVE_TIME = 1<<0, @@ -417,6 +418,7 @@ enum station_info_flags { STATION_INFO_TX_PACKETS = 1<<9, STATION_INFO_TX_RETRIES = 1<<10, STATION_INFO_TX_FAILED = 1<<11, + STATION_INFO_RX_DROP_MISC = 1<<12, }; /** @@ -468,6 +470,7 @@ struct rate_info { * @tx_packets: packets transmitted to this station * @tx_retries: cumulative retry counts * @tx_failed: number of failed transmissions (retries exceeded, no ACK) + * @rx_dropped_misc: Dropped for un-specified reason. * @generation: generation number for nl80211 dumps. * This number should increase every time the list of stations * changes, i.e. when a station is added or removed, so that @@ -487,6 +490,7 @@ struct station_info { u32 tx_packets; u32 tx_retries; u32 tx_failed; + u32 rx_dropped_misc; int generation; }; diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index ecf9b7166ed1..25fb351e00f8 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -329,7 +329,8 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) STATION_INFO_TX_PACKETS | STATION_INFO_TX_RETRIES | STATION_INFO_TX_FAILED | - STATION_INFO_TX_BITRATE; + STATION_INFO_TX_BITRATE | + STATION_INFO_RX_DROP_MISC; sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx); sinfo->rx_bytes = sta->rx_bytes; @@ -338,6 +339,7 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) sinfo->tx_packets = sta->tx_packets; sinfo->tx_retries = sta->tx_retry_count; sinfo->tx_failed = sta->tx_retry_failed; + sinfo->rx_dropped_misc = sta->rx_dropped; if ((sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) || (sta->local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)) { diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index 6002265289c6..12222ee6ebf2 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c @@ -1366,6 +1366,10 @@ struct iw_statistics *cfg80211_wireless_stats(struct net_device *dev) } wstats.qual.updated |= IW_QUAL_NOISE_INVALID; + if (sinfo.filled & STATION_INFO_RX_DROP_MISC) + wstats.discard.misc = sinfo.rx_dropped_misc; + if (sinfo.filled & STATION_INFO_TX_FAILED) + wstats.discard.retries = sinfo.tx_failed; return &wstats; } From 92c68a66a8f73c51f062ae8cae958c86a21fea78 Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Fri, 8 Oct 2010 09:43:29 -0700 Subject: [PATCH 028/127] ath5k: Print out opmode in debugfs. Helps debug multi-VIF scenarios. Signed-off-by: Ben Greear Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/debug.c | 10 +++++++++ drivers/net/wireless/ath/debug.c | 29 ++++++++++++++++++++++++++ drivers/net/wireless/ath/debug.h | 3 +++ 3 files changed, 42 insertions(+) diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c index c2d549f871f9..a342a9da1b3e 100644 --- a/drivers/net/wireless/ath/ath5k/debug.c +++ b/drivers/net/wireless/ath/ath5k/debug.c @@ -60,6 +60,7 @@ #include "base.h" #include "debug.h" +#include "../debug.h" static unsigned int ath5k_debug; module_param_named(debug, ath5k_debug, uint, 0); @@ -492,6 +493,7 @@ static ssize_t read_file_misc(struct file *file, char __user *user_buf, char buf[700]; unsigned int len = 0; u32 filt = ath5k_hw_get_rx_filter(sc->ah); + const char *tmp; len += snprintf(buf+len, sizeof(buf)-len, "bssid-mask: %pM\n", sc->bssidmask); @@ -524,6 +526,14 @@ static ssize_t read_file_misc(struct file *file, char __user *user_buf, else len += snprintf(buf+len, sizeof(buf)-len, "\n"); + tmp = ath_opmode_to_string(sc->opmode); + if (tmp) + len += snprintf(buf+len, sizeof(buf)-len, "opmode: %s\n", + tmp); + else + len += snprintf(buf+len, sizeof(buf)-len, + "opmode: UNKNOWN-%i\n", sc->opmode); + if (len > sizeof(buf)) len = sizeof(buf); diff --git a/drivers/net/wireless/ath/debug.c b/drivers/net/wireless/ath/debug.c index 53e77bd131b9..a9eb7876dbe1 100644 --- a/drivers/net/wireless/ath/debug.c +++ b/drivers/net/wireless/ath/debug.c @@ -30,3 +30,32 @@ void ath_print(struct ath_common *common, int dbg_mask, const char *fmt, ...) va_end(args); } EXPORT_SYMBOL(ath_print); + +const char *ath_opmode_to_string(enum nl80211_iftype opmode) +{ + switch (opmode) { + case NL80211_IFTYPE_UNSPECIFIED: + return "UNSPEC"; + case NL80211_IFTYPE_ADHOC: + return "ADHOC"; + case NL80211_IFTYPE_STATION: + return "STATION"; + case NL80211_IFTYPE_AP: + return "AP"; + case NL80211_IFTYPE_AP_VLAN: + return "AP-VLAN"; + case NL80211_IFTYPE_WDS: + return "WDS"; + case NL80211_IFTYPE_MONITOR: + return "MONITOR"; + case NL80211_IFTYPE_MESH_POINT: + return "MESH"; + case NL80211_IFTYPE_P2P_CLIENT: + return "P2P-CLIENT"; + case NL80211_IFTYPE_P2P_GO: + return "P2P-GO"; + default: + return NULL; + } +} +EXPORT_SYMBOL(ath_opmode_to_string); diff --git a/drivers/net/wireless/ath/debug.h b/drivers/net/wireless/ath/debug.h index fd3a020682dc..a3a5a628d24d 100644 --- a/drivers/net/wireless/ath/debug.h +++ b/drivers/net/wireless/ath/debug.h @@ -77,4 +77,7 @@ ath_print(struct ath_common *common, int dbg_mask, const char *fmt, ...) } #endif /* CONFIG_ATH_DEBUG */ +/** Returns string describing opmode, or NULL if unknown mode. */ +const char *ath_opmode_to_string(enum nl80211_iftype opmode); + #endif /* ATH_DEBUG_H */ From 62c58fb4316905cd9c1dbf01967935ed5610b45d Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Fri, 8 Oct 2010 12:01:15 -0700 Subject: [PATCH 029/127] ath5k: Adjust opmode when interfaces are removed. Otherwise, if there is an AP and a STATION, and AP is removed, the NIC will not revert back to STATION mode. Reported-by: Eliad Peller Signed-off-by: Ben Greear Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/base.c | 66 ++++++++++++++++----------- 1 file changed, 40 insertions(+), 26 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index dad726585637..c9732a6ce87f 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -62,6 +62,7 @@ #include "reg.h" #include "debug.h" #include "ani.h" +#include "../debug.h" static int modparam_nohwcrypt; module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); @@ -517,12 +518,14 @@ struct ath_vif_iter_data { bool need_set_hw_addr; bool found_active; bool any_assoc; + enum nl80211_iftype opmode; }; static void ath_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif) { struct ath_vif_iter_data *iter_data = data; int i; + struct ath5k_vif *avf = (void *)vif->drv_priv; if (iter_data->hw_macaddr) for (i = 0; i < ETH_ALEN; i++) @@ -539,13 +542,34 @@ static void ath_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif) iter_data->need_set_hw_addr = false; if (!iter_data->any_assoc) { - struct ath5k_vif *avf = (void *)vif->drv_priv; if (avf->assoc) iter_data->any_assoc = true; } + + /* Calculate combined mode - when APs are active, operate in AP mode. + * Otherwise use the mode of the new interface. This can currently + * only deal with combinations of APs and STAs. Only one ad-hoc + * interfaces is allowed above. + */ + if (avf->opmode == NL80211_IFTYPE_AP) + iter_data->opmode = NL80211_IFTYPE_AP; + else + if (iter_data->opmode == NL80211_IFTYPE_UNSPECIFIED) + iter_data->opmode = avf->opmode; } -void ath5k_update_bssid_mask(struct ath5k_softc *sc, struct ieee80211_vif *vif) +static void ath_do_set_opmode(struct ath5k_softc *sc) +{ + struct ath5k_hw *ah = sc->ah; + ath5k_hw_set_opmode(ah, sc->opmode); + ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "mode setup opmode %d (%s)\n", + sc->opmode, + ath_opmode_to_string(sc->opmode) ? + ath_opmode_to_string(sc->opmode) : "UKNOWN"); +} + +void ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc, + struct ieee80211_vif *vif) { struct ath_common *common = ath5k_hw_common(sc->ah); struct ath_vif_iter_data iter_data; @@ -558,6 +582,7 @@ void ath5k_update_bssid_mask(struct ath5k_softc *sc, struct ieee80211_vif *vif) memset(&iter_data.mask, 0xff, ETH_ALEN); iter_data.found_active = false; iter_data.need_set_hw_addr = true; + iter_data.opmode = NL80211_IFTYPE_UNSPECIFIED; if (vif) ath_vif_iter(&iter_data, vif->addr, vif); @@ -567,10 +592,18 @@ void ath5k_update_bssid_mask(struct ath5k_softc *sc, struct ieee80211_vif *vif) &iter_data); memcpy(sc->bssidmask, iter_data.mask, ETH_ALEN); + sc->opmode = iter_data.opmode; + if (sc->opmode == NL80211_IFTYPE_UNSPECIFIED) + /* Nothing active, default to station mode */ + sc->opmode = NL80211_IFTYPE_STATION; + + ath_do_set_opmode(sc); + if (iter_data.need_set_hw_addr && iter_data.found_active) ath5k_hw_set_lladdr(sc->ah, iter_data.active_mac); - ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask); + if (ath5k_hw_hasbssidmask(sc->ah)) + ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask); } static void @@ -582,15 +615,9 @@ ath5k_mode_setup(struct ath5k_softc *sc, struct ieee80211_vif *vif) /* configure rx filter */ rfilt = sc->filter_flags; ath5k_hw_set_rx_filter(ah, rfilt); - - if (ath5k_hw_hasbssidmask(ah)) - ath5k_update_bssid_mask(sc, vif); - - /* configure operational mode */ - ath5k_hw_set_opmode(ah, sc->opmode); - - ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "mode setup opmode %d\n", sc->opmode); ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "RX filter 0x%x\n", rfilt); + + ath5k_update_bssid_mask_and_opmode(sc, vif); } static inline int @@ -2688,7 +2715,7 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) SET_IEEE80211_PERM_ADDR(hw, mac); memcpy(&sc->lladdr, mac, ETH_ALEN); /* All MAC address bits matter for ACKs */ - ath5k_update_bssid_mask(sc, NULL); + ath5k_update_bssid_mask_and_opmode(sc, NULL); regulatory->current_rd = ah->ah_capabilities.cap_eeprom.ee_regdomain; ret = ath_regd_init(regulatory, hw->wiphy, ath5k_reg_notifier); @@ -2786,7 +2813,6 @@ static int ath5k_add_interface(struct ieee80211_hw *hw, { struct ath5k_softc *sc = hw->priv; int ret; - struct ath5k_hw *ah = sc->ah; struct ath5k_vif *avf = (void *)vif->drv_priv; mutex_lock(&sc->lock); @@ -2850,18 +2876,6 @@ static int ath5k_add_interface(struct ieee80211_hw *hw, sc->num_adhoc_vifs++; } - /* Set combined mode - when APs are configured, operate in AP mode. - * Otherwise use the mode of the new interface. This can currently - * only deal with combinations of APs and STAs. Only one ad-hoc - * interfaces is allowed above. - */ - if (sc->num_ap_vifs) - sc->opmode = NL80211_IFTYPE_AP; - else - sc->opmode = vif->type; - - ath5k_hw_set_opmode(ah, sc->opmode); - /* Any MAC address is fine, all others are included through the * filter. */ @@ -2905,7 +2919,7 @@ ath5k_remove_interface(struct ieee80211_hw *hw, else if (avf->opmode == NL80211_IFTYPE_ADHOC) sc->num_adhoc_vifs--; - ath5k_update_bssid_mask(sc, NULL); + ath5k_update_bssid_mask_and_opmode(sc, NULL); mutex_unlock(&sc->lock); } From dfdac8ac033c9ad048a5c68563bd41bda6c5e60b Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 8 Oct 2010 22:13:51 +0200 Subject: [PATCH 030/127] ath9k_hw: store the clock rate in common data on channel changes Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath.h | 2 ++ drivers/net/wireless/ath/ath9k/ani.c | 26 ++-------------------- drivers/net/wireless/ath/ath9k/hw.c | 32 +++++++++++++++++----------- 3 files changed, 23 insertions(+), 37 deletions(-) diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h index cee0191704f5..b36d9d770ff1 100644 --- a/drivers/net/wireless/ath/ath.h +++ b/drivers/net/wireless/ath/ath.h @@ -145,6 +145,8 @@ struct ath_common { DECLARE_BITMAP(tkip_keymap, ATH_KEYMAX); enum ath_crypt_caps crypt_caps; + unsigned int clockrate; + struct ath_regulatory regulatory; const struct ath_ops *ops; const struct ath_bus_ops *bus_ops; diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index f2a907b4acb8..f2aa68405d2f 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c @@ -465,35 +465,13 @@ static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah) ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel - 1); } -static u8 ath9k_hw_chan_2_clockrate_mhz(struct ath_hw *ah) -{ - struct ath9k_channel *chan = ah->curchan; - struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; - u8 clockrate; /* in MHz */ - - if (!ah->curchan) /* should really check for CCK instead */ - clockrate = ATH9K_CLOCK_RATE_CCK; - else if (conf->channel->band == IEEE80211_BAND_2GHZ) - clockrate = ATH9K_CLOCK_RATE_2GHZ_OFDM; - else if (IS_CHAN_A_FAST_CLOCK(ah, chan)) - clockrate = ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM; - else - clockrate = ATH9K_CLOCK_RATE_5GHZ_OFDM; - - if (conf_is_ht40(conf)) - return clockrate * 2; - - return clockrate; -} - static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw *ah) { + struct ath_common *common = ath9k_hw_common(ah); int32_t listen_time; - int32_t clock_rate; ath9k_hw_update_cycle_counters(ah); - clock_rate = ath9k_hw_chan_2_clockrate_mhz(ah) * 1000; - listen_time = ah->listen_time / clock_rate; + listen_time = ah->listen_time / (common->clockrate * 1000); ah->listen_time = 0; return listen_time; diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 05e9935ef160..f5d79177770c 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -88,29 +88,32 @@ static void ath9k_hw_ani_cache_ini_regs(struct ath_hw *ah) /* Helper Functions */ /********************/ -static u32 ath9k_hw_mac_clks(struct ath_hw *ah, u32 usecs) +static void ath9k_hw_set_clockrate(struct ath_hw *ah) { struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; + struct ath_common *common = ath9k_hw_common(ah); + unsigned int clockrate; if (!ah->curchan) /* should really check for CCK instead */ - return usecs *ATH9K_CLOCK_RATE_CCK; - if (conf->channel->band == IEEE80211_BAND_2GHZ) - return usecs *ATH9K_CLOCK_RATE_2GHZ_OFDM; - - if (ah->caps.hw_caps & ATH9K_HW_CAP_FASTCLOCK) - return usecs * ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM; + clockrate = ATH9K_CLOCK_RATE_CCK; + else if (conf->channel->band == IEEE80211_BAND_2GHZ) + clockrate = ATH9K_CLOCK_RATE_2GHZ_OFDM; + else if (ah->caps.hw_caps & ATH9K_HW_CAP_FASTCLOCK) + clockrate = ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM; else - return usecs * ATH9K_CLOCK_RATE_5GHZ_OFDM; + clockrate = ATH9K_CLOCK_RATE_5GHZ_OFDM; + + if (conf_is_ht40(conf)) + clockrate *= 2; + + common->clockrate = clockrate; } static u32 ath9k_hw_mac_to_clks(struct ath_hw *ah, u32 usecs) { - struct ieee80211_conf *conf = &ath9k_hw_common(ah)->hw->conf; + struct ath_common *common = ath9k_hw_common(ah); - if (conf_is_ht40(conf)) - return ath9k_hw_mac_clks(ah, usecs) * 2; - else - return ath9k_hw_mac_clks(ah, usecs); + return usecs * common->clockrate; } bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout) @@ -1156,6 +1159,7 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, "Failed to set channel\n"); return false; } + ath9k_hw_set_clockrate(ah); ah->eep_ops->set_txpower(ah, chan, ath9k_regd_get_ctl(regulatory, chan), @@ -1368,6 +1372,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, if (r) return r; + ath9k_hw_set_clockrate(ah); + ENABLE_REGWRITE_BUFFER(ah); for (i = 0; i < AR_NUM_DCU; i++) From 9d119f3ebd074bde0b801f476a44ca60d222efb2 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 8 Oct 2010 22:13:52 +0200 Subject: [PATCH 031/127] ath5k: store the clock rate in common data on channel changes Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/ath5k.h | 2 +- drivers/net/wireless/ath/ath5k/pcu.c | 13 ++++++++----- drivers/net/wireless/ath/ath5k/phy.c | 1 + 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 0cba2e315d9a..4a367cdb3eb9 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -1201,7 +1201,7 @@ void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high); /* Clock rate related functions */ unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec); unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock); -unsigned int ath5k_hw_get_clockrate(struct ath5k_hw *ah); +void ath5k_hw_set_clockrate(struct ath5k_hw *ah); /* Queue Control Unit, DFS Control Unit Functions */ int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index 095d30b50ec7..074b4c644399 100644 --- a/drivers/net/wireless/ath/ath5k/pcu.c +++ b/drivers/net/wireless/ath/ath5k/pcu.c @@ -207,7 +207,8 @@ static int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout) */ unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec) { - return usec * ath5k_hw_get_clockrate(ah); + struct ath_common *common = ath5k_hw_common(ah); + return usec * common->clockrate; } /** @@ -216,17 +217,19 @@ unsigned int ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec) */ unsigned int ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock) { - return clock / ath5k_hw_get_clockrate(ah); + struct ath_common *common = ath5k_hw_common(ah); + return clock / common->clockrate; } /** - * ath5k_hw_get_clockrate - Get the clock rate for current mode + * ath5k_hw_set_clockrate - Set common->clockrate for the current channel * * @ah: The &struct ath5k_hw */ -unsigned int ath5k_hw_get_clockrate(struct ath5k_hw *ah) +void ath5k_hw_set_clockrate(struct ath5k_hw *ah) { struct ieee80211_channel *channel = ah->ah_current_channel; + struct ath_common *common = ath5k_hw_common(ah); int clock; if (channel->hw_value & CHANNEL_5GHZ) @@ -240,7 +243,7 @@ unsigned int ath5k_hw_get_clockrate(struct ath5k_hw *ah) if (channel->hw_value & CHANNEL_TURBO) clock *= 2; - return clock; + common->clockrate = clock; } /** diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 61da913e7c8f..219367884e64 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -1093,6 +1093,7 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) ah->ah_current_channel = channel; ah->ah_turbo = channel->hw_value == CHANNEL_T ? true : false; + ath5k_hw_set_clockrate(ah); return 0; } From b5bfc5683db44a121ad47ec0a9f4efd4aac040e0 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 8 Oct 2010 22:13:53 +0200 Subject: [PATCH 032/127] ath9k_hw: move the cycle counter tracking to ath Instead of keeping track of wraparound, clear the counters on every access and keep separate deltas for ANI and later survey use. Also moves the function for calculating the 'listen time' for ANI Signed-off-by: Felix Fietkau Signed-off-by: Bruno Randolf Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath.h | 14 +++++ drivers/net/wireless/ath/ath9k/ani.c | 64 +-------------------- drivers/net/wireless/ath/ath9k/ani.h | 8 --- drivers/net/wireless/ath/ath9k/ar9003_phy.c | 7 +-- drivers/net/wireless/ath/ath9k/hw.h | 2 - drivers/net/wireless/ath/ath9k/main.c | 12 +++- drivers/net/wireless/ath/ath9k/reg.h | 11 ---- drivers/net/wireless/ath/hw.c | 59 +++++++++++++++++++ drivers/net/wireless/ath/reg.h | 11 ++++ 9 files changed, 101 insertions(+), 87 deletions(-) diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h index b36d9d770ff1..501050c0296f 100644 --- a/drivers/net/wireless/ath/ath.h +++ b/drivers/net/wireless/ath/ath.h @@ -19,6 +19,7 @@ #include #include +#include #include /* @@ -42,6 +43,13 @@ struct ath_ani { struct timer_list timer; }; +struct ath_cycle_counters { + u32 cycles; + u32 rx_busy; + u32 rx_frame; + u32 tx_frame; +}; + enum ath_device_state { ATH_HW_UNAVAILABLE, ATH_HW_INITIALIZED, @@ -147,6 +155,10 @@ struct ath_common { unsigned int clockrate; + spinlock_t cc_lock; + struct ath_cycle_counters cc_ani; + struct ath_cycle_counters cc_survey; + struct ath_regulatory regulatory; const struct ath_ops *ops; const struct ath_bus_ops *bus_ops; @@ -163,5 +175,7 @@ int ath_key_config(struct ath_common *common, struct ieee80211_sta *sta, struct ieee80211_key_conf *key); bool ath_hw_keyreset(struct ath_common *common, u16 entry); +void ath_hw_cycle_counters_update(struct ath_common *common); +int32_t ath_hw_get_listen_time(struct ath_common *common); #endif /* ATH_H */ diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index f2aa68405d2f..3aa8fb1ad77f 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c @@ -465,18 +465,6 @@ static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah) ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel - 1); } -static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw *ah) -{ - struct ath_common *common = ath9k_hw_common(ah); - int32_t listen_time; - - ath9k_hw_update_cycle_counters(ah); - listen_time = ah->listen_time / (common->clockrate * 1000); - ah->listen_time = 0; - - return listen_time; -} - static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning) { struct ar5416AniState *aniState; @@ -655,7 +643,9 @@ static void ath9k_hw_ani_read_counters(struct ath_hw *ah) u32 phyCnt1, phyCnt2; int32_t listenTime; - listenTime = ath9k_hw_ani_get_listen_time(ah); + ath_hw_cycle_counters_update(common); + listenTime = ath_hw_get_listen_time(common); + if (listenTime < 0) { ah->stats.ast_ani_lneg++; ath9k_ani_restart(ah); @@ -796,54 +786,6 @@ void ath9k_hw_disable_mib_counters(struct ath_hw *ah) } EXPORT_SYMBOL(ath9k_hw_disable_mib_counters); -void ath9k_hw_update_cycle_counters(struct ath_hw *ah) -{ - struct ath_cycle_counters cc; - bool clear; - - memcpy(&cc, &ah->cc, sizeof(cc)); - - /* freeze counters */ - REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC); - - ah->cc.cycles = REG_READ(ah, AR_CCCNT); - if (ah->cc.cycles < cc.cycles) { - clear = true; - goto skip; - } - - ah->cc.rx_clear = REG_READ(ah, AR_RCCNT); - ah->cc.rx_frame = REG_READ(ah, AR_RFCNT); - ah->cc.tx_frame = REG_READ(ah, AR_TFCNT); - - /* prevent wraparound */ - if (ah->cc.cycles & BIT(31)) - clear = true; - -#define CC_DELTA(_field, _reg) ah->cc_delta._field += ah->cc._field - cc._field - CC_DELTA(cycles, AR_CCCNT); - CC_DELTA(rx_frame, AR_RFCNT); - CC_DELTA(rx_clear, AR_RCCNT); - CC_DELTA(tx_frame, AR_TFCNT); -#undef CC_DELTA - - ah->listen_time += (ah->cc.cycles - cc.cycles) - - ((ah->cc.rx_frame - cc.rx_frame) + - (ah->cc.tx_frame - cc.tx_frame)); - -skip: - if (clear) { - REG_WRITE(ah, AR_CCCNT, 0); - REG_WRITE(ah, AR_RFCNT, 0); - REG_WRITE(ah, AR_RCCNT, 0); - REG_WRITE(ah, AR_TFCNT, 0); - memset(&ah->cc, 0, sizeof(ah->cc)); - } - - /* unfreeze counters */ - REG_WRITE(ah, AR_MIBC, 0); -} - /* * Process a MIB interrupt. We may potentially be invoked because * any of the MIB counters overflow/trigger so don't assume we're diff --git a/drivers/net/wireless/ath/ath9k/ani.h b/drivers/net/wireless/ath/ath9k/ani.h index 98cfd8154c71..0cd6783de883 100644 --- a/drivers/net/wireless/ath/ath9k/ani.h +++ b/drivers/net/wireless/ath/ath9k/ani.h @@ -93,13 +93,6 @@ struct ath9k_mib_stats { u32 beacons; }; -struct ath_cycle_counters { - u32 cycles; - u32 rx_frame; - u32 rx_clear; - u32 tx_frame; -}; - /* INI default values for ANI registers */ struct ath9k_ani_default { u16 m1ThreshLow; @@ -164,7 +157,6 @@ struct ar5416Stats { void ath9k_enable_mib_counters(struct ath_hw *ah); void ath9k_hw_disable_mib_counters(struct ath_hw *ah); -void ath9k_hw_update_cycle_counters(struct ath_hw *ah); void ath9k_hw_ani_setup(struct ath_hw *ah); void ath9k_hw_ani_init(struct ath_hw *ah); int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah, diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index efb05599b84c..669b777729b3 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -1254,13 +1254,12 @@ void ar9003_hw_bb_watchdog_dbg_info(struct ath_hw *ah) "** BB mode: BB_gen_controls=0x%08x **\n", REG_READ(ah, AR_PHY_GEN_CTRL)); - ath9k_hw_update_cycle_counters(ah); -#define PCT(_field) (ah->cc_delta._field * 100 / ah->cc_delta.cycles) - if (ah->cc_delta.cycles) +#define PCT(_field) (common->cc_survey._field * 100 / common->cc_survey.cycles) + if (common->cc_survey.cycles) ath_print(common, ATH_DBG_RESET, "** BB busy times: rx_clear=%d%%, " "rx_frame=%d%%, tx_frame=%d%% **\n", - PCT(rx_clear), PCT(rx_frame), PCT(tx_frame)); + PCT(rx_busy), PCT(rx_frame), PCT(tx_frame)); ath_print(common, ATH_DBG_RESET, "==== BB update: done ====\n\n"); diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 87627dd63463..7f696c82ca0a 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -740,8 +740,6 @@ struct ath_hw { int coarse_low[5]; int firpwr[5]; enum ath9k_ani_cmd ani_function; - struct ath_cycle_counters cc, cc_delta; - int32_t listen_time; /* Bluetooth coexistance */ struct ath_btcoex_hw btcoex_hw; diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 74c2dc8a8b8a..360c6f5e843a 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -399,6 +399,7 @@ void ath_ani_calibrate(unsigned long data) bool aniflag = false; unsigned int timestamp = jiffies_to_msecs(jiffies); u32 cal_interval, short_cal_interval, long_cal_interval; + unsigned long flags; if (ah->caldata && ah->caldata->nfcal_interference) long_cal_interval = ATH_LONG_CALINTERVAL_INT; @@ -449,8 +450,11 @@ void ath_ani_calibrate(unsigned long data) /* Skip all processing if there's nothing to do. */ if (longcal || shortcal || aniflag) { /* Call ANI routine if necessary */ - if (aniflag) + if (aniflag) { + spin_lock_irqsave(&common->cc_lock, flags); ath9k_hw_ani_monitor(ah, ah->curchan); + spin_unlock_irqrestore(&common->cc_lock, flags); + } /* Perform calibration if necessary */ if (longcal || shortcal) { @@ -635,6 +639,7 @@ irqreturn_t ath_isr(int irq, void *dev) struct ath_softc *sc = dev; struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(ah); enum ath9k_int status; bool sched = false; @@ -684,7 +689,12 @@ irqreturn_t ath_isr(int irq, void *dev) if ((ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) && (status & ATH9K_INT_BB_WATCHDOG)) { + + spin_lock(&common->cc_lock); + ath_hw_cycle_counters_update(common); ar9003_hw_bb_watchdog_dbg_info(ah); + spin_unlock(&common->cc_lock); + goto chip_reset; } diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 6d01e501b9b4..017617894533 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -107,12 +107,6 @@ #define AR_RXCFG_DMASZ_256B 6 #define AR_RXCFG_DMASZ_512B 7 -#define AR_MIBC 0x0040 -#define AR_MIBC_COW 0x00000001 -#define AR_MIBC_FMC 0x00000002 -#define AR_MIBC_CMC 0x00000004 -#define AR_MIBC_MCS 0x00000008 - #define AR_TOPS 0x0044 #define AR_TOPS_MASK 0x0000FFFF @@ -1524,11 +1518,6 @@ enum { #define AR_TPC_CHIRP 0x003f0000 #define AR_TPC_CHIRP_S 0x16 -#define AR_TFCNT 0x80ec -#define AR_RFCNT 0x80f0 -#define AR_RCCNT 0x80f4 -#define AR_CCCNT 0x80f8 - #define AR_QUIET1 0x80fc #define AR_QUIET1_NEXT_QUIET_S 0 #define AR_QUIET1_NEXT_QUIET_M 0x0000ffff diff --git a/drivers/net/wireless/ath/hw.c b/drivers/net/wireless/ath/hw.c index a8f81ea09f14..183c28281385 100644 --- a/drivers/net/wireless/ath/hw.c +++ b/drivers/net/wireless/ath/hw.c @@ -124,3 +124,62 @@ void ath_hw_setbssidmask(struct ath_common *common) REG_WRITE(ah, get_unaligned_le16(common->bssidmask + 4), AR_BSSMSKU); } EXPORT_SYMBOL(ath_hw_setbssidmask); + + +/** + * ath_hw_cycle_counters_update - common function to update cycle counters + * + * @common: the ath_common struct for the device. + * + * This function is used to update all cycle counters in one place. + * It has to be called while holding common->cc_lock! + */ +void ath_hw_cycle_counters_update(struct ath_common *common) +{ + u32 cycles, busy, rx, tx; + void *ah = common->ah; + + /* freeze */ + REG_WRITE(ah, AR_MIBC_FMC, AR_MIBC); + + /* read */ + cycles = REG_READ(ah, AR_CCCNT); + busy = REG_READ(ah, AR_RCCNT); + rx = REG_READ(ah, AR_RFCNT); + tx = REG_READ(ah, AR_TFCNT); + + /* clear */ + REG_WRITE(ah, 0, AR_CCCNT); + REG_WRITE(ah, 0, AR_RFCNT); + REG_WRITE(ah, 0, AR_RCCNT); + REG_WRITE(ah, 0, AR_TFCNT); + + /* unfreeze */ + REG_WRITE(ah, 0, AR_MIBC); + + /* update all cycle counters here */ + common->cc_ani.cycles += cycles; + common->cc_ani.rx_busy += busy; + common->cc_ani.rx_frame += rx; + common->cc_ani.tx_frame += tx; + + common->cc_survey.cycles += cycles; + common->cc_survey.rx_busy += busy; + common->cc_survey.rx_frame += rx; + common->cc_survey.tx_frame += tx; +} +EXPORT_SYMBOL(ath_hw_cycle_counters_update); + +int32_t ath_hw_get_listen_time(struct ath_common *common) +{ + struct ath_cycle_counters *cc = &common->cc_ani; + int32_t listen_time; + + listen_time = (cc->cycles - cc->rx_frame - cc->tx_frame) / + (common->clockrate * 1000); + + memset(cc, 0, sizeof(*cc)); + + return listen_time; +} +EXPORT_SYMBOL(ath_hw_get_listen_time); diff --git a/drivers/net/wireless/ath/reg.h b/drivers/net/wireless/ath/reg.h index e798ef476581..298e53f3fa48 100644 --- a/drivers/net/wireless/ath/reg.h +++ b/drivers/net/wireless/ath/reg.h @@ -17,6 +17,12 @@ #ifndef ATH_REGISTERS_H #define ATH_REGISTERS_H +#define AR_MIBC 0x0040 +#define AR_MIBC_COW 0x00000001 +#define AR_MIBC_FMC 0x00000002 +#define AR_MIBC_CMC 0x00000004 +#define AR_MIBC_MCS 0x00000008 + /* * BSSID mask registers. See ath_hw_set_bssid_mask() * for detailed documentation about these registers. @@ -24,6 +30,11 @@ #define AR_BSSMSKL 0x80e0 #define AR_BSSMSKU 0x80e4 +#define AR_TFCNT 0x80ec +#define AR_RFCNT 0x80f0 +#define AR_RCCNT 0x80f4 +#define AR_CCCNT 0x80f8 + #define AR_KEYTABLE_0 0x8800 #define AR_KEYTABLE(_n) (AR_KEYTABLE_0 + ((_n)*32)) #define AR_KEY_CACHE_SIZE 128 From 7109ca5c80a0bb94378ebd7f8bb6d00edb5e6fba Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Fri, 8 Oct 2010 22:13:54 +0200 Subject: [PATCH 033/127] ath5k: use the common cycle counter / listen time implementation Signed-off-by: Felix Fietkau Signed-off-by: Bruno Randolf Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/ani.c | 37 +++++++++----------------- drivers/net/wireless/ath/ath5k/ani.h | 5 +--- drivers/net/wireless/ath/ath5k/debug.c | 21 ++++++++------- 3 files changed, 24 insertions(+), 39 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/ani.c b/drivers/net/wireless/ath/ath5k/ani.c index e4a5f046bba4..f1419198a479 100644 --- a/drivers/net/wireless/ath/ath5k/ani.c +++ b/drivers/net/wireless/ath/ath5k/ani.c @@ -355,41 +355,28 @@ ath5k_ani_lower_immunity(struct ath5k_hw *ah, struct ath5k_ani_state *as) /** - * ath5k_hw_ani_get_listen_time() - Calculate time spent listening + * ath5k_hw_ani_get_listen_time() - Update counters and return listening time * * Return an approximation of the time spent "listening" in milliseconds (ms) - * since the last call of this function by deducting the cycles spent - * transmitting and receiving from the total cycle count. - * Save profile count values for debugging/statistics and because we might want - * to use them later. - * - * We assume no one else clears these registers! + * since the last call of this function. + * Save a snapshot of the counter values for debugging/statistics. */ static int ath5k_hw_ani_get_listen_time(struct ath5k_hw *ah, struct ath5k_ani_state *as) { + struct ath_common *common = ath5k_hw_common(ah); int listen; - /* freeze */ - ath5k_hw_reg_write(ah, AR5K_MIBC_FMC, AR5K_MIBC); - /* read */ - as->pfc_cycles = ath5k_hw_reg_read(ah, AR5K_PROFCNT_CYCLE); - as->pfc_busy = ath5k_hw_reg_read(ah, AR5K_PROFCNT_RXCLR); - as->pfc_tx = ath5k_hw_reg_read(ah, AR5K_PROFCNT_TX); - as->pfc_rx = ath5k_hw_reg_read(ah, AR5K_PROFCNT_RX); - /* clear */ - ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_TX); - ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RX); - ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RXCLR); - ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_CYCLE); - /* un-freeze */ - ath5k_hw_reg_write(ah, 0, AR5K_MIBC); + spin_lock_bh(&common->cc_lock); - /* TODO: where does 44000 come from? (11g clock rate?) */ - listen = (as->pfc_cycles - as->pfc_rx - as->pfc_tx) / 44000; + ath_hw_cycle_counters_update(common); + memcpy(&as->last_cc, &common->cc_ani, sizeof(as->last_cc)); + + /* clears common->cc_ani */ + listen = ath_hw_get_listen_time(common); + + spin_unlock_bh(&common->cc_lock); - if (as->pfc_cycles == 0 || listen < 0) - return 0; return listen; } diff --git a/drivers/net/wireless/ath/ath5k/ani.h b/drivers/net/wireless/ath/ath5k/ani.h index 55cf26d8522c..d0a664039c87 100644 --- a/drivers/net/wireless/ath/ath5k/ani.h +++ b/drivers/net/wireless/ath/ath5k/ani.h @@ -75,10 +75,7 @@ struct ath5k_ani_state { unsigned int cck_errors; /* debug/statistics only: numbers from last ANI calibration */ - unsigned int pfc_tx; - unsigned int pfc_rx; - unsigned int pfc_busy; - unsigned int pfc_cycles; + struct ath_cycle_counters last_cc; unsigned int last_listen; unsigned int last_ofdm_errors; unsigned int last_cck_errors; diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c index a342a9da1b3e..a3b217125331 100644 --- a/drivers/net/wireless/ath/ath5k/debug.c +++ b/drivers/net/wireless/ath/ath5k/debug.c @@ -725,20 +725,21 @@ static ssize_t read_file_ani(struct file *file, char __user *user_buf, len += snprintf(buf+len, sizeof(buf)-len, "beacon RSSI average:\t%d\n", sc->ah->ah_beacon_rssi_avg.avg); + +#define CC_PRINT(_struct, _field) \ + _struct._field, \ + _struct.cycles > 0 ? \ + _struct._field*100/_struct.cycles : 0 + len += snprintf(buf+len, sizeof(buf)-len, "profcnt tx\t\t%u\t(%d%%)\n", - as->pfc_tx, - as->pfc_cycles > 0 ? - as->pfc_tx*100/as->pfc_cycles : 0); + CC_PRINT(as->last_cc, tx_frame)); len += snprintf(buf+len, sizeof(buf)-len, "profcnt rx\t\t%u\t(%d%%)\n", - as->pfc_rx, - as->pfc_cycles > 0 ? - as->pfc_rx*100/as->pfc_cycles : 0); + CC_PRINT(as->last_cc, rx_frame)); len += snprintf(buf+len, sizeof(buf)-len, "profcnt busy\t\t%u\t(%d%%)\n", - as->pfc_busy, - as->pfc_cycles > 0 ? - as->pfc_busy*100/as->pfc_cycles : 0); + CC_PRINT(as->last_cc, rx_busy)); +#undef CC_PRINT len += snprintf(buf+len, sizeof(buf)-len, "profcnt cycles\t\t%u\n", - as->pfc_cycles); + as->last_cc.cycles); len += snprintf(buf+len, sizeof(buf)-len, "listen time\t\t%d\tlast: %d\n", as->listen_time, as->last_listen); From d12c74528e3065c90df70fbc06ec6ffd6e804738 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Fri, 8 Oct 2010 22:27:07 +0200 Subject: [PATCH 034/127] mac80211: fix possible null-pointer de-reference This patch not only fixes a null-pointer de-reference that would be triggered by a PLINK_OPEN frame with mis- matching/incompatible mesh configuration, but also responds correctly to non-compatible PLINK_OPEN frames by generating a PLINK_CLOSE with the right reason code. The original bug was detected by smatch. ( http://repo.or.cz/w/smatch.git ) net/mac80211/mesh_plink.c +574 mesh_rx_plink_frame(168) error: we previously assumed 'sta' could be null. Cc: Reviewed-and-Tested-by: Steve deRosier Reviewed-and-Tested-by: Javier Cardona Acked-by: Johannes Berg Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- net/mac80211/mesh_plink.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index ea13a80a476c..1c91f0f3c307 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c @@ -412,7 +412,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m enum plink_event event; enum plink_frame_type ftype; size_t baselen; - bool deactivated; + bool deactivated, matches_local = true; u8 ie_len; u8 *baseaddr; __le16 plid, llid, reason; @@ -487,6 +487,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m /* Now we will figure out the appropriate event... */ event = PLINK_UNDEFINED; if (ftype != PLINK_CLOSE && (!mesh_matches_local(&elems, sdata))) { + matches_local = false; switch (ftype) { case PLINK_OPEN: event = OPN_RJCT; @@ -498,7 +499,15 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m /* avoid warning */ break; } - spin_lock_bh(&sta->lock); + } + + if (!sta && !matches_local) { + rcu_read_unlock(); + reason = cpu_to_le16(MESH_CAPABILITY_POLICY_VIOLATION); + llid = 0; + mesh_plink_frame_tx(sdata, PLINK_CLOSE, mgmt->sa, llid, + plid, reason); + return; } else if (!sta) { /* ftype == PLINK_OPEN */ u32 rates; @@ -522,7 +531,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m } event = OPN_ACPT; spin_lock_bh(&sta->lock); - } else { + } else if (matches_local) { spin_lock_bh(&sta->lock); switch (ftype) { case PLINK_OPEN: @@ -564,6 +573,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m rcu_read_unlock(); return; } + } else { + spin_lock_bh(&sta->lock); } mpl_dbg("Mesh plink (peer, state, llid, plid, event): %pM %s %d %d %d\n", From 15943a72c7d2031c9150917ca9161a9f891d455a Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Fri, 8 Oct 2010 22:35:09 +0200 Subject: [PATCH 035/127] mac80211: temporarily disable reorder release timer Several serve threading problems in the current release reorder timer implementation have been discovered. A lengthy discussion - which lists some of the pitfalls and possible solutions - can be found at: http://marc.info/?t=128635927000001 But due to the complicated nature of the subject and the imminent advent of a new -rc cycle, it was decided to disable the feature for the time being. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- net/mac80211/rx.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index b67221def584..902b03ee8f60 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -622,6 +622,26 @@ static void ieee80211_sta_reorder_release(struct ieee80211_hw *hw, tid_agg_rx->buf_size; } + /* + * Disable the reorder release timer for now. + * + * The current implementation lacks a proper locking scheme + * which would protect vital statistic and debug counters + * from being updated by two different but concurrent BHs. + * + * More information about the topic is available from: + * - thread: http://marc.info/?t=128635927000001 + * + * What was wrong: + * => http://marc.info/?l=linux-wireless&m=128636170811964 + * "Basically the thing is that until your patch, the data + * in the struct didn't actually need locking because it + * was accessed by the RX path only which is not concurrent." + * + * List of what needs to be fixed: + * => http://marc.info/?l=linux-wireless&m=128656352920957 + * + if (tid_agg_rx->stored_mpdu_num) { j = index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % tid_agg_rx->buf_size; @@ -640,6 +660,10 @@ static void ieee80211_sta_reorder_release(struct ieee80211_hw *hw, } else { del_timer(&tid_agg_rx->reorder_timer); } + */ + +set_release_timer: + return; } /* From 8610c29a2c9f273886b1c31ae4d92c69d4326262 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 9 Oct 2010 02:39:29 +0200 Subject: [PATCH 036/127] cfg80211: add channel utilization stats to the survey command Using these, user space can calculate a relative channel utilization with arbitrary intervals by regularly taking snapshots of the survey results. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- include/linux/nl80211.h | 15 +++++++++++++++ include/net/cfg80211.h | 20 ++++++++++++++++++++ net/wireless/nl80211.c | 15 +++++++++++++++ 3 files changed, 50 insertions(+) diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index c08709fe36fc..0edb2566c14c 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -1413,6 +1413,16 @@ enum nl80211_reg_rule_flags { * @NL80211_SURVEY_INFO_FREQUENCY: center frequency of channel * @NL80211_SURVEY_INFO_NOISE: noise level of channel (u8, dBm) * @NL80211_SURVEY_INFO_IN_USE: channel is currently being used + * @NL80211_SURVEY_INFO_CHANNEL_TIME: amount of time (in ms) that the radio + * spent on this channel + * @NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY: amount of the time the primary + * channel was sensed busy (either due to activity or energy detect) + * @NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY: amount of time the extension + * channel was sensed busy + * @NL80211_SURVEY_INFO_CHANNEL_TIME_RX: amount of time the radio spent + * receiving data + * @NL80211_SURVEY_INFO_CHANNEL_TIME_TX: amount of time the radio spent + * transmitting data * @NL80211_SURVEY_INFO_MAX: highest survey info attribute number * currently defined * @__NL80211_SURVEY_INFO_AFTER_LAST: internal use @@ -1422,6 +1432,11 @@ enum nl80211_survey_info { NL80211_SURVEY_INFO_FREQUENCY, NL80211_SURVEY_INFO_NOISE, NL80211_SURVEY_INFO_IN_USE, + NL80211_SURVEY_INFO_CHANNEL_TIME, + NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY, + NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY, + NL80211_SURVEY_INFO_CHANNEL_TIME_RX, + NL80211_SURVEY_INFO_CHANNEL_TIME_TX, /* keep last */ __NL80211_SURVEY_INFO_AFTER_LAST, diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index f920a06f363e..24d5b5869272 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -294,6 +294,11 @@ struct key_params { * * @SURVEY_INFO_NOISE_DBM: noise (in dBm) was filled in * @SURVEY_INFO_IN_USE: channel is currently being used + * @SURVEY_INFO_CHANNEL_TIME: channel active time (in ms) was filled in + * @SURVEY_INFO_CHANNEL_TIME_BUSY: channel busy time was filled in + * @SURVEY_INFO_CHANNEL_TIME_EXT_BUSY: extension channel busy time was filled in + * @SURVEY_INFO_CHANNEL_TIME_RX: channel receive time was filled in + * @SURVEY_INFO_CHANNEL_TIME_TX: channel transmit time was filled in * * Used by the driver to indicate which info in &struct survey_info * it has filled in during the get_survey(). @@ -301,6 +306,11 @@ struct key_params { enum survey_info_flags { SURVEY_INFO_NOISE_DBM = 1<<0, SURVEY_INFO_IN_USE = 1<<1, + SURVEY_INFO_CHANNEL_TIME = 1<<2, + SURVEY_INFO_CHANNEL_TIME_BUSY = 1<<3, + SURVEY_INFO_CHANNEL_TIME_EXT_BUSY = 1<<4, + SURVEY_INFO_CHANNEL_TIME_RX = 1<<5, + SURVEY_INFO_CHANNEL_TIME_TX = 1<<6, }; /** @@ -310,6 +320,11 @@ enum survey_info_flags { * @filled: bitflag of flags from &enum survey_info_flags * @noise: channel noise in dBm. This and all following fields are * optional + * @channel_time: amount of time in ms the radio spent on the channel + * @channel_time_busy: amount of time the primary channel was sensed busy + * @channel_time_ext_busy: amount of time the extension channel was sensed busy + * @channel_time_rx: amount of time the radio spent receiving data + * @channel_time_tx: amount of time the radio spent transmitting data * * Used by dump_survey() to report back per-channel survey information. * @@ -318,6 +333,11 @@ enum survey_info_flags { */ struct survey_info { struct ieee80211_channel *channel; + u64 channel_time; + u64 channel_time_busy; + u64 channel_time_ext_busy; + u64 channel_time_rx; + u64 channel_time_tx; u32 filled; s8 noise; }; diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 882dc921103b..c506241f8637 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -3153,6 +3153,21 @@ static int nl80211_send_survey(struct sk_buff *msg, u32 pid, u32 seq, survey->noise); if (survey->filled & SURVEY_INFO_IN_USE) NLA_PUT_FLAG(msg, NL80211_SURVEY_INFO_IN_USE); + if (survey->filled & SURVEY_INFO_CHANNEL_TIME) + NLA_PUT_U64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME, + survey->channel_time); + if (survey->filled & SURVEY_INFO_CHANNEL_TIME_BUSY) + NLA_PUT_U64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY, + survey->channel_time_busy); + if (survey->filled & SURVEY_INFO_CHANNEL_TIME_EXT_BUSY) + NLA_PUT_U64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY, + survey->channel_time_ext_busy); + if (survey->filled & SURVEY_INFO_CHANNEL_TIME_RX) + NLA_PUT_U64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME_RX, + survey->channel_time_rx); + if (survey->filled & SURVEY_INFO_CHANNEL_TIME_TX) + NLA_PUT_U64(msg, NL80211_SURVEY_INFO_CHANNEL_TIME_TX, + survey->channel_time_tx); nla_nest_end(msg, infoattr); From cac4220b2e93e6344f987581d52d5bd71ff2cc0e Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sat, 9 Oct 2010 02:39:30 +0200 Subject: [PATCH 037/127] ath9k: add compile time checking for the size of the channel list This prevents random memory corruption if the number of channels ever gets changed without an update to the internal channel array size. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/hw.h | 4 +++- drivers/net/wireless/ath/ath9k/init.c | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 7f696c82ca0a..6b9233472fbf 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -61,6 +61,8 @@ #define ATH9K_RSSI_BAD -128 +#define ATH9K_NUM_CHANNELS 38 + /* Register read/write primitives */ #define REG_WRITE(_ah, _reg, _val) \ ath9k_hw_common(_ah)->ops->write((_ah), (_val), (_reg)) @@ -618,7 +620,7 @@ struct ath_hw { struct ath9k_hw_version hw_version; struct ath9k_ops_config config; struct ath9k_hw_capabilities caps; - struct ath9k_channel channels[38]; + struct ath9k_channel channels[ATH9K_NUM_CHANNELS]; struct ath9k_channel *curchan; union { diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index d76003c06fe4..a4c5ed41b176 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -481,6 +481,10 @@ static int ath9k_init_channels_rates(struct ath_softc *sc) { void *channels; + BUILD_BUG_ON(ARRAY_SIZE(ath9k_2ghz_chantable) + + ARRAY_SIZE(ath9k_5ghz_chantable) != + ATH9K_NUM_CHANNELS); + if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes)) { channels = kmemdup(ath9k_2ghz_chantable, sizeof(ath9k_2ghz_chantable), GFP_KERNEL); From 3430098ae463e31ab16926ac3eb295368a3ca5d9 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 10 Oct 2010 18:21:52 +0200 Subject: [PATCH 038/127] ath9k: implement channel utilization stats for survey Results for the active channel are updated whenever a new survey dump is requested, the old data is kept to allow multiple processes to make their own channel utilization averages. All other channels only contain the data for the last time that the hardware was on the channel, i.e. the last scan result or other off-channel activity. Running a background scan does not clear the data for the active channel. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 2 + drivers/net/wireless/ath/ath9k/main.c | 112 +++++++++++++++++++++---- 2 files changed, 98 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index de2b18ee7f77..4e81fe35aa3f 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -593,6 +593,8 @@ struct ath_softc { struct delayed_work wiphy_work; unsigned long wiphy_scheduler_int; int wiphy_scheduler_index; + struct survey_info *cur_survey; + struct survey_info survey[ATH9K_NUM_CHANNELS]; struct tasklet_struct intr_tq; struct tasklet_struct bcon_tasklet; diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 360c6f5e843a..865649120075 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -175,6 +175,44 @@ static void ath_start_ani(struct ath_common *common) msecs_to_jiffies((u32)ah->config.ani_poll_interval)); } +static void ath_update_survey_nf(struct ath_softc *sc, int channel) +{ + struct ath_hw *ah = sc->sc_ah; + struct ath9k_channel *chan = &ah->channels[channel]; + struct survey_info *survey = &sc->survey[channel]; + + if (chan->noisefloor) { + survey->filled |= SURVEY_INFO_NOISE_DBM; + survey->noise = chan->noisefloor; + } +} + +static void ath_update_survey_stats(struct ath_softc *sc) +{ + struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(ah); + int pos = ah->curchan - &ah->channels[0]; + struct survey_info *survey = &sc->survey[pos]; + struct ath_cycle_counters *cc = &common->cc_survey; + unsigned int div = common->clockrate * 1000; + + ath_hw_cycle_counters_update(common); + + if (cc->cycles > 0) { + survey->filled |= SURVEY_INFO_CHANNEL_TIME | + SURVEY_INFO_CHANNEL_TIME_BUSY | + SURVEY_INFO_CHANNEL_TIME_RX | + SURVEY_INFO_CHANNEL_TIME_TX; + survey->channel_time += cc->cycles / div; + survey->channel_time_busy += cc->rx_busy / div; + survey->channel_time_rx += cc->rx_frame / div; + survey->channel_time_tx += cc->tx_frame / div; + } + memset(cc, 0, sizeof(*cc)); + + ath_update_survey_nf(sc, pos); +} + /* * Set/change channels. If the channel is really being changed, it's done * by reseting the chip. To accomplish this we must first cleanup any pending @@ -453,6 +491,7 @@ void ath_ani_calibrate(unsigned long data) if (aniflag) { spin_lock_irqsave(&common->cc_lock, flags); ath9k_hw_ani_monitor(ah, ah->curchan); + ath_update_survey_stats(sc); spin_unlock_irqrestore(&common->cc_lock, flags); } @@ -1532,7 +1571,8 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) { struct ath_wiphy *aphy = hw->priv; struct ath_softc *sc = aphy->sc; - struct ath_common *common = ath9k_hw_common(sc->sc_ah); + struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(ah); struct ieee80211_conf *conf = &hw->conf; bool disable_radio; @@ -1598,6 +1638,11 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { struct ieee80211_channel *curchan = hw->conf.channel; int pos = curchan->hw_value; + int old_pos = -1; + unsigned long flags; + + if (ah->curchan) + old_pos = ah->curchan - &ah->channels[0]; aphy->chan_idx = pos; aphy->chan_is_ht = conf_is_ht(conf); @@ -1625,12 +1670,45 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) ath_update_chainmask(sc, conf_is_ht(conf)); + /* update survey stats for the old channel before switching */ + spin_lock_irqsave(&common->cc_lock, flags); + ath_update_survey_stats(sc); + spin_unlock_irqrestore(&common->cc_lock, flags); + + /* + * If the operating channel changes, change the survey in-use flags + * along with it. + * Reset the survey data for the new channel, unless we're switching + * back to the operating channel from an off-channel operation. + */ + if (!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) && + sc->cur_survey != &sc->survey[pos]) { + + if (sc->cur_survey) + sc->cur_survey->filled &= ~SURVEY_INFO_IN_USE; + + sc->cur_survey = &sc->survey[pos]; + + memset(sc->cur_survey, 0, sizeof(struct survey_info)); + sc->cur_survey->filled |= SURVEY_INFO_IN_USE; + } else if (!(sc->survey[pos].filled & SURVEY_INFO_IN_USE)) { + memset(&sc->survey[pos], 0, sizeof(struct survey_info)); + } + if (ath_set_channel(sc, hw, &sc->sc_ah->channels[pos]) < 0) { ath_print(common, ATH_DBG_FATAL, "Unable to set channel\n"); mutex_unlock(&sc->mutex); return -EINVAL; } + + /* + * The most recent snapshot of channel->noisefloor for the old + * channel is only available after the hardware reset. Copy it to + * the survey stats now. + */ + if (old_pos >= 0) + ath_update_survey_nf(sc, old_pos); } skip_chan_change: @@ -2000,9 +2078,15 @@ static int ath9k_get_survey(struct ieee80211_hw *hw, int idx, { struct ath_wiphy *aphy = hw->priv; struct ath_softc *sc = aphy->sc; - struct ath_hw *ah = sc->sc_ah; + struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ieee80211_supported_band *sband; - struct ath9k_channel *chan; + struct ieee80211_channel *chan; + unsigned long flags; + int pos; + + spin_lock_irqsave(&common->cc_lock, flags); + if (idx == 0) + ath_update_survey_stats(sc); sband = hw->wiphy->bands[IEEE80211_BAND_2GHZ]; if (sband && idx >= sband->n_channels) { @@ -2013,21 +2097,17 @@ static int ath9k_get_survey(struct ieee80211_hw *hw, int idx, if (!sband) sband = hw->wiphy->bands[IEEE80211_BAND_5GHZ]; - if (!sband || idx >= sband->n_channels) - return -ENOENT; - - survey->channel = &sband->channels[idx]; - chan = &ah->channels[survey->channel->hw_value]; - survey->filled = 0; - - if (chan == ah->curchan) - survey->filled |= SURVEY_INFO_IN_USE; - - if (chan->noisefloor) { - survey->filled |= SURVEY_INFO_NOISE_DBM; - survey->noise = chan->noisefloor; + if (!sband || idx >= sband->n_channels) { + spin_unlock_irqrestore(&common->cc_lock, flags); + return -ENOENT; } + chan = &sband->channels[idx]; + pos = chan->hw_value; + memcpy(survey, &sc->survey[pos], sizeof(*survey)); + survey->channel = chan; + spin_unlock_irqrestore(&common->cc_lock, flags); + return 0; } From cfdfa4d3a0c7aa1287c61326a7714f262466157a Mon Sep 17 00:00:00 2001 From: Steve deRosier Date: Sat, 9 Oct 2010 17:23:28 -0700 Subject: [PATCH 039/127] mac80211: Update mesh constants to approved IEEE ANA values This patch updates IEEE802.11 mesh constants to be consistent with newly approved values. It modifies some values, as well as adds many new constants in preparation for updating mesh code to the current 802.11s drafts. ANA numbers were taken from: https://mentor.ieee.org/802.11/dcn/09/11-09-0031-12-0000-ana-database-assigned-number-authority.xls A few notes are in order: 1. This will break backwards compatibility with existing Linux kernels as over-the-air constants have changed. 2. Some old and obsolete constants have been retained for now as the mesh code itself hasn't been updated yet to the new 802.11s draft. This was desired to keep the existing mesh scheme working until it can be updated. Adding the approved values is the first step in updating the mesh code. 3. Obsolete constants have been clearly marked. 4. All ANA approved 802.11s constants have been added. Signed-off-by: Steve deRosier Signed-off-by: John W. Linville --- include/linux/ieee80211.h | 71 ++++++++++++++++++++++++++++++--------- 1 file changed, 56 insertions(+), 15 deletions(-) diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 97b2eae6a22c..ed5a03cbe184 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -986,6 +986,7 @@ struct ieee80211_ht_info { #define WLAN_AUTH_OPEN 0 #define WLAN_AUTH_SHARED_KEY 1 #define WLAN_AUTH_FT 2 +#define WLAN_AUTH_SAE 3 #define WLAN_AUTH_LEAP 128 #define WLAN_AUTH_CHALLENGE_LEN 128 @@ -1072,6 +1073,10 @@ enum ieee80211_statuscode { WLAN_STATUS_NO_DIRECT_LINK = 48, WLAN_STATUS_STA_NOT_PRESENT = 49, WLAN_STATUS_STA_NOT_QSTA = 50, + /* 802.11s */ + WLAN_STATUS_ANTI_CLOG_REQUIRED = 76, + WLAN_STATUS_FCG_NOT_SUPP = 78, + WLAN_STATUS_STA_NO_TBTT = 78, }; @@ -1112,6 +1117,22 @@ enum ieee80211_reasoncode { WLAN_REASON_QSTA_REQUIRE_SETUP = 38, WLAN_REASON_QSTA_TIMEOUT = 39, WLAN_REASON_QSTA_CIPHER_NOT_SUPP = 45, + /* 802.11s */ + WLAN_REASON_MESH_PEER_CANCELED = 52, + WLAN_REASON_MESH_MAX_PEERS = 53, + WLAN_REASON_MESH_CONFIG = 54, + WLAN_REASON_MESH_CLOSE = 55, + WLAN_REASON_MESH_MAX_RETRIES = 56, + WLAN_REASON_MESH_CONFIRM_TIMEOUT = 57, + WLAN_REASON_MESH_INVALID_GTK = 58, + WLAN_REASON_MESH_INCONSISTENT_PARAM = 59, + WLAN_REASON_MESH_INVALID_SECURITY = 60, + WLAN_REASON_MESH_PATH_ERROR = 61, + WLAN_REASON_MESH_PATH_NOFORWARD = 62, + WLAN_REASON_MESH_PATH_DEST_UNREACHABLE = 63, + WLAN_REASON_MAC_EXISTS_IN_MBSS = 64, + WLAN_REASON_MESH_CHAN_REGULATORY = 65, + WLAN_REASON_MESH_CHAN = 66, }; @@ -1139,20 +1160,33 @@ enum ieee80211_eid { WLAN_EID_TS_DELAY = 43, WLAN_EID_TCLAS_PROCESSING = 44, WLAN_EID_QOS_CAPA = 46, - /* 802.11s - * - * All mesh EID numbers are pending IEEE 802.11 ANA approval. - * The numbers have been incremented from those suggested in - * 802.11s/D2.0 so that MESH_CONFIG does not conflict with - * EXT_SUPP_RATES. + /* 802.11s */ + WLAN_EID_MESH_CONFIG = 113, + WLAN_EID_MESH_ID = 114, + WLAN_EID_LINK_METRIC_REPORT = 115, + WLAN_EID_CONGESTION_NOTIFICATION = 116, + /* Note that the Peer Link IE has been replaced with the similar + * Peer Management IE. We will keep the former definition until mesh + * code is changed to comply with latest 802.11s drafts. */ - WLAN_EID_MESH_CONFIG = 51, - WLAN_EID_MESH_ID = 52, - WLAN_EID_PEER_LINK = 55, - WLAN_EID_PREQ = 68, - WLAN_EID_PREP = 69, - WLAN_EID_PERR = 70, - WLAN_EID_RANN = 49, /* compatible with FreeBSD */ + WLAN_EID_PEER_LINK = 55, /* no longer in 802.11s drafts */ + WLAN_EID_PEER_MGMT = 117, + WLAN_EID_CHAN_SWITCH_PARAM = 118, + WLAN_EID_MESH_AWAKE_WINDOW = 119, + WLAN_EID_BEACON_TIMING = 120, + WLAN_EID_MCCAOP_SETUP_REQ = 121, + WLAN_EID_MCCAOP_SETUP_RESP = 122, + WLAN_EID_MCCAOP_ADVERT = 123, + WLAN_EID_MCCAOP_TEARDOWN = 124, + WLAN_EID_GANN = 125, + WLAN_EID_RANN = 126, + WLAN_EID_PREQ = 130, + WLAN_EID_PREP = 131, + WLAN_EID_PERR = 132, + WLAN_EID_PXU = 137, + WLAN_EID_PXUC = 138, + WLAN_EID_AUTH_MESH_PEER_EXCH = 139, + WLAN_EID_MIC = 140, WLAN_EID_PWR_CONSTRAINT = 32, WLAN_EID_PWR_CAPABILITY = 33, @@ -1211,9 +1245,14 @@ enum ieee80211_category { WLAN_CATEGORY_HT = 7, WLAN_CATEGORY_SA_QUERY = 8, WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION = 9, + WLAN_CATEGORY_MESH_ACTION = 13, + WLAN_CATEGORY_MULTIHOP_ACTION = 14, + WLAN_CATEGORY_SELF_PROTECTED = 15, WLAN_CATEGORY_WMM = 17, - WLAN_CATEGORY_MESH_PLINK = 30, /* Pending ANA approval */ - WLAN_CATEGORY_MESH_PATH_SEL = 32, /* Pending ANA approval */ + /* TODO: remove MESH_PLINK and MESH_PATH_SEL after */ + /* mesh is updated to current 802.11s draft */ + WLAN_CATEGORY_MESH_PLINK = 30, + WLAN_CATEGORY_MESH_PATH_SEL = 32, WLAN_CATEGORY_VENDOR_SPECIFIC_PROTECTED = 126, WLAN_CATEGORY_VENDOR_SPECIFIC = 127, }; @@ -1351,6 +1390,8 @@ enum ieee80211_sa_query_action { /* AKM suite selectors */ #define WLAN_AKM_SUITE_8021X 0x000FAC01 #define WLAN_AKM_SUITE_PSK 0x000FAC02 +#define WLAN_AKM_SUITE_SAE 0x000FAC08 +#define WLAN_AKM_SUITE_FT_OVER_SAE 0x000FAC09 #define WLAN_MAX_KEY_LEN 32 From a23c22080345f1748a933f32736986ff11f44d60 Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Sat, 9 Oct 2010 13:33:16 +0200 Subject: [PATCH 040/127] rt2x00: Shortcut link state updates when not operating as STA Signed-off-by: Helmut Schaa Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00link.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c index 4d534e9dc628..46836f801b35 100644 --- a/drivers/net/wireless/rt2x00/rt2x00link.c +++ b/drivers/net/wireless/rt2x00/rt2x00link.c @@ -235,6 +235,12 @@ void rt2x00link_update_stats(struct rt2x00_dev *rt2x00dev, struct link_ant *ant = &rt2x00dev->link.ant; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + /* + * No need to update the stats for !=STA interfaces + */ + if (!rt2x00dev->intf_sta_count) + return; + /* * Frame was received successfully since non-succesfull * frames would have been dropped by the hardware. From 546adf294e85ca0dcd9c052294ef35b83a6ab2f4 Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Sat, 9 Oct 2010 13:33:43 +0200 Subject: [PATCH 041/127] rt2x00: Optimize unmapping of skbs Since no skb will be mapped for RX and TX at the same time we can simply shortcut the check for SKBDESC_DMA_MAPPED_TX. Signed-off-by: Helmut Schaa Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00queue.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 6d41599a090c..4436ff72c864 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -115,9 +115,7 @@ void rt2x00queue_unmap_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb) dma_unmap_single(rt2x00dev->dev, skbdesc->skb_dma, skb->len, DMA_FROM_DEVICE); skbdesc->flags &= ~SKBDESC_DMA_MAPPED_RX; - } - - if (skbdesc->flags & SKBDESC_DMA_MAPPED_TX) { + } else if (skbdesc->flags & SKBDESC_DMA_MAPPED_TX) { dma_unmap_single(rt2x00dev->dev, skbdesc->skb_dma, skb->len, DMA_TO_DEVICE); skbdesc->flags &= ~SKBDESC_DMA_MAPPED_TX; From ff6133becae9ae1657fcff339a160a21448fa11c Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Sat, 9 Oct 2010 13:34:11 +0200 Subject: [PATCH 042/127] rt2x00: Use proper type for rxwi_w2 in rt2800_agc_to_rssi Signed-off-by: Helmut Schaa Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 7f040b0eac36..b9433fe2855a 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -499,7 +499,7 @@ void rt2800_write_tx_data(struct queue_entry *entry, } EXPORT_SYMBOL_GPL(rt2800_write_tx_data); -static int rt2800_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxwi_w2) +static int rt2800_agc_to_rssi(struct rt2x00_dev *rt2x00dev, u32 rxwi_w2) { int rssi0 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI0); int rssi1 = rt2x00_get_field32(rxwi_w2, RXWI_W2_RSSI1); From c6084d5fa2e70a436ab944066146de01819f5493 Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Sat, 9 Oct 2010 13:34:43 +0200 Subject: [PATCH 043/127] rt2x00: Use unlikely for error case in rt2x00queue_write_tx_frame This is an error condition that is not supposed to happen. Hence, it is safe to add unlikely to this check. Signed-off-by: Helmut Schaa 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(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 4436ff72c864..83630f16dc64 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -489,7 +489,8 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb, if (unlikely(rt2x00queue_full(queue))) return -ENOBUFS; - if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) { + if (unlikely(test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, + &entry->flags))) { ERROR(queue->rt2x00dev, "Arrived at non-free entry in the non-full queue %d.\n" "Please file bug report to %s.\n", From 74374725cdf466629fd401a81b3a04e4cdb0815f Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Sat, 9 Oct 2010 13:35:13 +0200 Subject: [PATCH 044/127] rt2x00: Remove superfluous initialization of qidx There is no need to initialize qidx to zero as it will ever be overwritten by the correct value. Signed-off-by: Helmut Schaa Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 85a134cd62bf..cc4e17c437d1 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -573,7 +573,7 @@ static void rt2800pci_kick_tx_queue(struct data_queue *queue) { struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX); - unsigned int qidx = 0; + unsigned int qidx; if (queue->qid == QID_MGMT) qidx = 5; From 12eec2cc0d5eacd8287646585dc88ab558d4866d Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Sat, 9 Oct 2010 13:35:48 +0200 Subject: [PATCH 045/127] rt2x00: Fix tx status handling in rt2800pci The patches "rt2x00: Improve TX status entry validation" and "rt2x00: rework tx status handling in rt2800pci" together were causing problems with tx status processing in rt2800pci: phy1 -> rt2800pci_txdone: Warning - Got TX status for an empty queue 3, dropping phy1 -> rt2800pci_txdone: Warning - Got TX status for an unavailable queue 7, dropping Fix this by using the correct field definition for getting the QID out of the tx status report. Reported-by: Luis Correia Signed-off-by: Helmut Schaa Tested-by: Luis Correia Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2800pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index cc4e17c437d1..b26739535986 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -676,7 +676,7 @@ static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) break; } - qid = rt2x00_get_field32(status, TX_STA_FIFO_PID_TYPE) - 1; + qid = rt2x00_get_field32(status, TX_STA_FIFO_PID_QUEUE); if (qid >= QID_RX) { /* * Unknown queue, this shouldn't happen. Just drop From c8a16c68ef4eb7817e41759c7105678ebc155377 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sat, 9 Oct 2010 21:37:11 +0200 Subject: [PATCH 046/127] carl9170: common error path for bad frames This patch replaces several identical frame drop paths with a single shared rx frame error handler. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/ath/carl9170/rx.c | 48 +++++++++++--------------- 1 file changed, 20 insertions(+), 28 deletions(-) diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c index 671dbc429547..31287e0d362f 100644 --- a/drivers/net/wireless/ath/carl9170/rx.c +++ b/drivers/net/wireless/ath/carl9170/rx.c @@ -598,18 +598,14 @@ static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len) if (!IS_STARTED(ar)) return; - if (unlikely(len < sizeof(*mac))) { - ar->rx_dropped++; - return; - } + if (unlikely(len < sizeof(*mac))) + goto drop; mpdu_len = len - sizeof(*mac); mac = (void *)(buf + mpdu_len); - if (unlikely(mac->error & AR9170_RX_ERROR_FATAL)) { - ar->rx_dropped++; - return; - } + if (unlikely(mac->error & AR9170_RX_ERROR_FATAL)) + goto drop; switch (mac->status & AR9170_RX_STATUS_MPDU) { case AR9170_RX_STATUS_MPDU_FIRST: @@ -638,8 +634,7 @@ static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len) "is clipped.\n"); } - ar->rx_dropped++; - return; + goto drop; } break; @@ -659,8 +654,7 @@ static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len) "is clipped.\n"); } - ar->rx_dropped++; - return; + goto drop; } case AR9170_RX_STATUS_MPDU_MIDDLE: @@ -672,8 +666,7 @@ static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len) wiphy_err(ar->hw->wiphy, "rx stream does not start " "with a first_mpdu frame tag.\n"); - ar->rx_dropped++; - return; + goto drop; } head = &ar->rx_plcp; @@ -696,16 +689,12 @@ static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len) } /* FC + DU + RA + FCS */ - if (unlikely(mpdu_len < (2 + 2 + 6 + FCS_LEN))) { - ar->rx_dropped++; - return; - } + if (unlikely(mpdu_len < (2 + 2 + ETH_ALEN + FCS_LEN))) + goto drop; memset(&status, 0, sizeof(status)); - if (unlikely(carl9170_rx_mac_status(ar, head, mac, &status))) { - ar->rx_dropped++; - return; - } + if (unlikely(carl9170_rx_mac_status(ar, head, mac, &status))) + goto drop; if (phy) carl9170_rx_phy_status(ar, phy, &status); @@ -713,12 +702,15 @@ static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len) carl9170_ps_beacon(ar, buf, mpdu_len); skb = carl9170_rx_copy_data(buf, mpdu_len); - if (likely(skb)) { - memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); - ieee80211_rx(ar->hw, skb); - } else { - ar->rx_dropped++; - } + if (!skb) + goto drop; + + memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); + ieee80211_rx(ar->hw, skb); + return; + +drop: + ar->rx_dropped++; } static void carl9170_rx_untie_cmds(struct ar9170 *ar, const u8 *respbuf, From 9f59f3c694c184c69e0be7d0fd0829bcb61b0429 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sat, 9 Oct 2010 22:23:37 +0200 Subject: [PATCH 047/127] carl9170: remove stale rx error path The total/fatal error bit was erroneously prefixed with AR9170_RX_ERROR instead of AR9170_RX_STATUS. Luckily, the hardware specification confirmed that the 0x80 flag will never be set for mac->error. So, it was always just a dead branch. This patch also imports the latest version of shared wlan.h header from the firmware git. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/ath/carl9170/rx.c | 3 --- drivers/net/wireless/ath/carl9170/wlan.h | 14 +++++++++++--- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c index 31287e0d362f..256dd42bb4ab 100644 --- a/drivers/net/wireless/ath/carl9170/rx.c +++ b/drivers/net/wireless/ath/carl9170/rx.c @@ -604,9 +604,6 @@ static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len) mpdu_len = len - sizeof(*mac); mac = (void *)(buf + mpdu_len); - if (unlikely(mac->error & AR9170_RX_ERROR_FATAL)) - goto drop; - switch (mac->status & AR9170_RX_STATUS_MPDU) { case AR9170_RX_STATUS_MPDU_FIRST: /* Aggregated MPDUs start with an PLCP header */ diff --git a/drivers/net/wireless/ath/carl9170/wlan.h b/drivers/net/wireless/ath/carl9170/wlan.h index 48ead2268f50..24d63b583b6b 100644 --- a/drivers/net/wireless/ath/carl9170/wlan.h +++ b/drivers/net/wireless/ath/carl9170/wlan.h @@ -74,6 +74,9 @@ #define AR9170_RX_STATUS_MPDU_MIDDLE 0x30 #define AR9170_RX_STATUS_MPDU_LAST 0x10 +#define AR9170_RX_STATUS_CONT_AGGR 0x40 +#define AR9170_RX_STATUS_TOTAL_ERROR 0x80 + #define AR9170_RX_ERROR_RXTO 0x01 #define AR9170_RX_ERROR_OVERRUN 0x02 #define AR9170_RX_ERROR_DECRYPT 0x04 @@ -81,7 +84,6 @@ #define AR9170_RX_ERROR_WRONG_RA 0x10 #define AR9170_RX_ERROR_PLCP 0x20 #define AR9170_RX_ERROR_MMIC 0x40 -#define AR9170_RX_ERROR_FATAL 0x80 /* these are either-or */ #define AR9170_TX_MAC_PROT_RTS 0x0001 @@ -329,13 +331,15 @@ struct _carl9170_tx_superframe { #define CARL9170_TX_SUPERDESC_LEN 24 #define AR9170_TX_HWDESC_LEN 8 -#define AR9170_TX_SUPERFRAME_LEN (CARL9170_TX_HWDESC_LEN + \ - AR9170_TX_SUPERDESC_LEN) +#define CARL9170_TX_SUPERFRAME_LEN (CARL9170_TX_SUPERDESC_LEN + \ + AR9170_TX_HWDESC_LEN) struct ar9170_rx_head { u8 plcp[12]; } __packed; +#define AR9170_RX_HEAD_LEN 12 + struct ar9170_rx_phystatus { union { struct { @@ -350,12 +354,16 @@ struct ar9170_rx_phystatus { u8 phy_err; } __packed; +#define AR9170_RX_PHYSTATUS_LEN 20 + struct ar9170_rx_macstatus { u8 SAidx, DAidx; u8 error; u8 status; } __packed; +#define AR9170_RX_MACSTATUS_LEN 4 + struct ar9170_rx_frame_single { struct ar9170_rx_head phy_head; struct ieee80211_hdr i3e; From 8f236d1bef659ca69c912536a69b3031e5ba3269 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sun, 10 Oct 2010 01:15:07 +0200 Subject: [PATCH 048/127] carl9170: A-MPDU frame type filter In the past, carl9170 has been plagued by mysterious ghosts. e.g.: wlan4: deauthenticated from 02:04:d8:3c:ac:c1 (Reason: 0) Apparently, the AP sent us a bogus deauthentication notification. But upon closer inspection the "management frame" turned out to be a corrupted scrap of an unsuccessful A-MPDU. Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/ath/carl9170/rx.c | 42 +++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c index 256dd42bb4ab..939a0e96ed1f 100644 --- a/drivers/net/wireless/ath/carl9170/rx.c +++ b/drivers/net/wireless/ath/carl9170/rx.c @@ -576,6 +576,41 @@ static void carl9170_ps_beacon(struct ar9170 *ar, void *data, unsigned int len) } } +static bool carl9170_ampdu_check(struct ar9170 *ar, u8 *buf, u8 ms) +{ + __le16 fc; + + if ((ms & AR9170_RX_STATUS_MPDU) == AR9170_RX_STATUS_MPDU_SINGLE) { + /* + * This frame is not part of an aMPDU. + * Therefore it is not subjected to any + * of the following content restrictions. + */ + return true; + } + + /* + * "802.11n - 7.4a.3 A-MPDU contents" describes in which contexts + * certain frame types can be part of an aMPDU. + * + * In order to keep the processing cost down, I opted for a + * stateless filter solely based on the frame control field. + */ + + fc = ((struct ieee80211_hdr *)buf)->frame_control; + if (ieee80211_is_data_qos(fc) && ieee80211_is_data_present(fc)) + return true; + + if (ieee80211_is_ack(fc) || ieee80211_is_back(fc) || + ieee80211_is_back_req(fc)) + return true; + + if (ieee80211_is_action(fc)) + return true; + + return false; +} + /* * If the frame alignment is right (or the kernel has * CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS), and there @@ -594,6 +629,7 @@ static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len) struct ieee80211_rx_status status; struct sk_buff *skb; int mpdu_len; + u8 mac_status; if (!IS_STARTED(ar)) return; @@ -604,7 +640,8 @@ static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len) mpdu_len = len - sizeof(*mac); mac = (void *)(buf + mpdu_len); - switch (mac->status & AR9170_RX_STATUS_MPDU) { + mac_status = mac->status; + switch (mac_status & AR9170_RX_STATUS_MPDU) { case AR9170_RX_STATUS_MPDU_FIRST: /* Aggregated MPDUs start with an PLCP header */ if (likely(mpdu_len >= sizeof(struct ar9170_rx_head))) { @@ -693,6 +730,9 @@ static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len) if (unlikely(carl9170_rx_mac_status(ar, head, mac, &status))) goto drop; + if (!carl9170_ampdu_check(ar, buf, mac_status)) + goto drop; + if (phy) carl9170_rx_phy_status(ar, phy, &status); From f03ee1ec73d8cad07b0ef5ba6106a9fc4d179ecb Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Sun, 10 Oct 2010 11:28:31 +0300 Subject: [PATCH 049/127] wl1251: create a copy of wl12xx_80211.h for wl1251 In preparation of moving wl1251 out from drivers/net/wireless/wl12xx create a separate copy of wl12xx_80211.h. This file should not even exist, we should instead use generic ieee80211 definitions. This will be fixed in the future so that the file can be removed. Signed-off-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/wl1251/wl12xx_80211.h | 156 +++++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 drivers/net/wireless/wl1251/wl12xx_80211.h diff --git a/drivers/net/wireless/wl1251/wl12xx_80211.h b/drivers/net/wireless/wl1251/wl12xx_80211.h new file mode 100644 index 000000000000..184628027213 --- /dev/null +++ b/drivers/net/wireless/wl1251/wl12xx_80211.h @@ -0,0 +1,156 @@ +#ifndef __WL12XX_80211_H__ +#define __WL12XX_80211_H__ + +#include /* ETH_ALEN */ + +/* RATES */ +#define IEEE80211_CCK_RATE_1MB 0x02 +#define IEEE80211_CCK_RATE_2MB 0x04 +#define IEEE80211_CCK_RATE_5MB 0x0B +#define IEEE80211_CCK_RATE_11MB 0x16 +#define IEEE80211_OFDM_RATE_6MB 0x0C +#define IEEE80211_OFDM_RATE_9MB 0x12 +#define IEEE80211_OFDM_RATE_12MB 0x18 +#define IEEE80211_OFDM_RATE_18MB 0x24 +#define IEEE80211_OFDM_RATE_24MB 0x30 +#define IEEE80211_OFDM_RATE_36MB 0x48 +#define IEEE80211_OFDM_RATE_48MB 0x60 +#define IEEE80211_OFDM_RATE_54MB 0x6C +#define IEEE80211_BASIC_RATE_MASK 0x80 + +#define IEEE80211_CCK_RATE_1MB_MASK (1<<0) +#define IEEE80211_CCK_RATE_2MB_MASK (1<<1) +#define IEEE80211_CCK_RATE_5MB_MASK (1<<2) +#define IEEE80211_CCK_RATE_11MB_MASK (1<<3) +#define IEEE80211_OFDM_RATE_6MB_MASK (1<<4) +#define IEEE80211_OFDM_RATE_9MB_MASK (1<<5) +#define IEEE80211_OFDM_RATE_12MB_MASK (1<<6) +#define IEEE80211_OFDM_RATE_18MB_MASK (1<<7) +#define IEEE80211_OFDM_RATE_24MB_MASK (1<<8) +#define IEEE80211_OFDM_RATE_36MB_MASK (1<<9) +#define IEEE80211_OFDM_RATE_48MB_MASK (1<<10) +#define IEEE80211_OFDM_RATE_54MB_MASK (1<<11) + +#define IEEE80211_CCK_RATES_MASK 0x0000000F +#define IEEE80211_CCK_BASIC_RATES_MASK (IEEE80211_CCK_RATE_1MB_MASK | \ + IEEE80211_CCK_RATE_2MB_MASK) +#define IEEE80211_CCK_DEFAULT_RATES_MASK (IEEE80211_CCK_BASIC_RATES_MASK | \ + IEEE80211_CCK_RATE_5MB_MASK | \ + IEEE80211_CCK_RATE_11MB_MASK) + +#define IEEE80211_OFDM_RATES_MASK 0x00000FF0 +#define IEEE80211_OFDM_BASIC_RATES_MASK (IEEE80211_OFDM_RATE_6MB_MASK | \ + IEEE80211_OFDM_RATE_12MB_MASK | \ + IEEE80211_OFDM_RATE_24MB_MASK) +#define IEEE80211_OFDM_DEFAULT_RATES_MASK (IEEE80211_OFDM_BASIC_RATES_MASK | \ + IEEE80211_OFDM_RATE_9MB_MASK | \ + IEEE80211_OFDM_RATE_18MB_MASK | \ + IEEE80211_OFDM_RATE_36MB_MASK | \ + IEEE80211_OFDM_RATE_48MB_MASK | \ + IEEE80211_OFDM_RATE_54MB_MASK) +#define IEEE80211_DEFAULT_RATES_MASK (IEEE80211_OFDM_DEFAULT_RATES_MASK | \ + IEEE80211_CCK_DEFAULT_RATES_MASK) + + +/* This really should be 8, but not for our firmware */ +#define MAX_SUPPORTED_RATES 32 +#define COUNTRY_STRING_LEN 3 +#define MAX_COUNTRY_TRIPLETS 32 + +/* Headers */ +struct ieee80211_header { + __le16 frame_ctl; + __le16 duration_id; + u8 da[ETH_ALEN]; + u8 sa[ETH_ALEN]; + u8 bssid[ETH_ALEN]; + __le16 seq_ctl; + u8 payload[0]; +} __packed; + +struct wl12xx_ie_header { + u8 id; + u8 len; +} __packed; + +/* IEs */ + +struct wl12xx_ie_ssid { + struct wl12xx_ie_header header; + char ssid[IW_ESSID_MAX_SIZE]; +} __packed; + +struct wl12xx_ie_rates { + struct wl12xx_ie_header header; + u8 rates[MAX_SUPPORTED_RATES]; +} __packed; + +struct wl12xx_ie_ds_params { + struct wl12xx_ie_header header; + u8 channel; +} __packed; + +struct country_triplet { + u8 channel; + u8 num_channels; + u8 max_tx_power; +} __packed; + +struct wl12xx_ie_country { + struct wl12xx_ie_header header; + u8 country_string[COUNTRY_STRING_LEN]; + struct country_triplet triplets[MAX_COUNTRY_TRIPLETS]; +} __packed; + + +/* Templates */ + +struct wl12xx_beacon_template { + struct ieee80211_header header; + __le32 time_stamp[2]; + __le16 beacon_interval; + __le16 capability; + struct wl12xx_ie_ssid ssid; + struct wl12xx_ie_rates rates; + struct wl12xx_ie_rates ext_rates; + struct wl12xx_ie_ds_params ds_params; + struct wl12xx_ie_country country; +} __packed; + +struct wl12xx_null_data_template { + struct ieee80211_header header; +} __packed; + +struct wl12xx_ps_poll_template { + __le16 fc; + __le16 aid; + u8 bssid[ETH_ALEN]; + u8 ta[ETH_ALEN]; +} __packed; + +struct wl12xx_qos_null_data_template { + struct ieee80211_header header; + __le16 qos_ctl; +} __packed; + +struct wl12xx_probe_req_template { + struct ieee80211_header header; + struct wl12xx_ie_ssid ssid; + struct wl12xx_ie_rates rates; + struct wl12xx_ie_rates ext_rates; +} __packed; + + +struct wl12xx_probe_resp_template { + struct ieee80211_header header; + __le32 time_stamp[2]; + __le16 beacon_interval; + __le16 capability; + struct wl12xx_ie_ssid ssid; + struct wl12xx_ie_rates rates; + struct wl12xx_ie_rates ext_rates; + struct wl12xx_ie_ds_params ds_params; + struct wl12xx_ie_country country; +} __packed; + +#endif From 9bc6772e15d25f58c1be638031280e04514287d4 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Sun, 10 Oct 2010 11:28:32 +0300 Subject: [PATCH 050/127] wl1251: move to it's own directory wl1271 driver is under heavy development but on the other hand the older wl1251 driver is currently considered more as a legacy driver. To make it easier to develop wl1271 features move wl1251 to it's own directory, drivers/net/wireless/wl1251. There are no functional changes, only moving of files. One regression is that Kconfig won't be updated automatically and user needs to enable wl1251 manually with an older config file. Signed-off-by: Kalle Valo Signed-off-by: John W. Linville --- drivers/net/wireless/Kconfig | 1 + drivers/net/wireless/Makefile | 1 + drivers/net/wireless/wl1251/Kconfig | 33 ++++++++++++++++++ drivers/net/wireless/wl1251/Makefile | 6 ++++ .../{wl12xx/wl1251_acx.c => wl1251/acx.c} | 8 ++--- .../{wl12xx/wl1251_acx.h => wl1251/acx.h} | 2 +- .../{wl12xx/wl1251_boot.c => wl1251/boot.c} | 12 +++---- .../{wl12xx/wl1251_boot.h => wl1251/boot.h} | 0 .../{wl12xx/wl1251_cmd.c => wl1251/cmd.c} | 10 +++--- .../{wl12xx/wl1251_cmd.h => wl1251/cmd.h} | 0 .../wl1251_debugfs.c => wl1251/debugfs.c} | 6 ++-- .../wl1251_debugfs.h => wl1251/debugfs.h} | 0 .../{wl12xx/wl1251_event.c => wl1251/event.c} | 8 ++--- .../{wl12xx/wl1251_event.h => wl1251/event.h} | 0 .../{wl12xx/wl1251_init.c => wl1251/init.c} | 8 ++--- .../{wl12xx/wl1251_init.h => wl1251/init.h} | 0 .../{wl12xx/wl1251_io.c => wl1251/io.c} | 4 +-- .../{wl12xx/wl1251_io.h => wl1251/io.h} | 0 .../{wl12xx/wl1251_main.c => wl1251/main.c} | 20 +++++------ .../{wl12xx/wl1251_ps.c => wl1251/ps.c} | 8 ++--- .../{wl12xx/wl1251_ps.h => wl1251/ps.h} | 2 +- .../{wl12xx/wl1251_reg.h => wl1251/reg.h} | 0 .../{wl12xx/wl1251_rx.c => wl1251/rx.c} | 10 +++--- .../{wl12xx/wl1251_rx.h => wl1251/rx.h} | 0 .../{wl12xx/wl1251_sdio.c => wl1251/sdio.c} | 0 .../{wl12xx/wl1251_spi.c => wl1251/spi.c} | 4 +-- .../{wl12xx/wl1251_spi.h => wl1251/spi.h} | 6 ++-- .../{wl12xx/wl1251_tx.c => wl1251/tx.c} | 8 ++--- .../{wl12xx/wl1251_tx.h => wl1251/tx.h} | 2 +- .../net/wireless/{wl12xx => wl1251}/wl1251.h | 0 drivers/net/wireless/wl12xx/Kconfig | 34 ------------------- drivers/net/wireless/wl12xx/Makefile | 9 ----- 32 files changed, 100 insertions(+), 102 deletions(-) create mode 100644 drivers/net/wireless/wl1251/Kconfig create mode 100644 drivers/net/wireless/wl1251/Makefile rename drivers/net/wireless/{wl12xx/wl1251_acx.c => wl1251/acx.c} (99%) rename drivers/net/wireless/{wl12xx/wl1251_acx.h => wl1251/acx.h} (99%) rename drivers/net/wireless/{wl12xx/wl1251_boot.c => wl1251/boot.c} (99%) rename drivers/net/wireless/{wl12xx/wl1251_boot.h => wl1251/boot.h} (100%) rename drivers/net/wireless/{wl12xx/wl1251_cmd.c => wl1251/cmd.c} (98%) rename drivers/net/wireless/{wl12xx/wl1251_cmd.h => wl1251/cmd.h} (100%) rename drivers/net/wireless/{wl12xx/wl1251_debugfs.c => wl1251/debugfs.c} (99%) rename drivers/net/wireless/{wl12xx/wl1251_debugfs.h => wl1251/debugfs.h} (100%) rename drivers/net/wireless/{wl12xx/wl1251_event.c => wl1251/event.c} (97%) rename drivers/net/wireless/{wl12xx/wl1251_event.h => wl1251/event.h} (100%) rename drivers/net/wireless/{wl12xx/wl1251_init.c => wl1251/init.c} (98%) rename drivers/net/wireless/{wl12xx/wl1251_init.h => wl1251/init.h} (100%) rename drivers/net/wireless/{wl12xx/wl1251_io.c => wl1251/io.c} (99%) rename drivers/net/wireless/{wl12xx/wl1251_io.h => wl1251/io.h} (100%) rename drivers/net/wireless/{wl12xx/wl1251_main.c => wl1251/main.c} (99%) rename drivers/net/wireless/{wl12xx/wl1251_ps.c => wl1251/ps.c} (97%) rename drivers/net/wireless/{wl12xx/wl1251_ps.h => wl1251/ps.h} (97%) rename drivers/net/wireless/{wl12xx/wl1251_reg.h => wl1251/reg.h} (100%) rename drivers/net/wireless/{wl12xx/wl1251_rx.c => wl1251/rx.c} (97%) rename drivers/net/wireless/{wl12xx/wl1251_rx.h => wl1251/rx.h} (100%) rename drivers/net/wireless/{wl12xx/wl1251_sdio.c => wl1251/sdio.c} (100%) rename drivers/net/wireless/{wl12xx/wl1251_spi.c => wl1251/spi.c} (99%) rename drivers/net/wireless/{wl12xx/wl1251_spi.h => wl1251/spi.h} (96%) rename drivers/net/wireless/{wl12xx/wl1251_tx.c => wl1251/tx.c} (99%) rename drivers/net/wireless/{wl12xx/wl1251_tx.h => wl1251/tx.h} (99%) rename drivers/net/wireless/{wl12xx => wl1251}/wl1251.h (100%) diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 174e3442d519..4de4410cd38e 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -279,6 +279,7 @@ source "drivers/net/wireless/libertas/Kconfig" source "drivers/net/wireless/orinoco/Kconfig" source "drivers/net/wireless/p54/Kconfig" source "drivers/net/wireless/rt2x00/Kconfig" +source "drivers/net/wireless/wl1251/Kconfig" source "drivers/net/wireless/wl12xx/Kconfig" source "drivers/net/wireless/zd1211rw/Kconfig" diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile index a13a602edb13..06f8ca26c5c1 100644 --- a/drivers/net/wireless/Makefile +++ b/drivers/net/wireless/Makefile @@ -49,6 +49,7 @@ obj-$(CONFIG_ATH_COMMON) += ath/ obj-$(CONFIG_MAC80211_HWSIM) += mac80211_hwsim.o +obj-$(CONFIG_WL1251) += wl1251/ obj-$(CONFIG_WL12XX) += wl12xx/ obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wl12xx/ diff --git a/drivers/net/wireless/wl1251/Kconfig b/drivers/net/wireless/wl1251/Kconfig new file mode 100644 index 000000000000..1fb65849414f --- /dev/null +++ b/drivers/net/wireless/wl1251/Kconfig @@ -0,0 +1,33 @@ +menuconfig WL1251 + tristate "TI wl1251 driver support" + depends on MAC80211 && EXPERIMENTAL && GENERIC_HARDIRQS + select FW_LOADER + select CRC7 + ---help--- + This will enable TI wl1251 driver support. The drivers make + use of the mac80211 stack. + + If you choose to build a module, it'll be called wl1251. Say + N if unsure. + +config WL1251_SPI + tristate "TI wl1251 SPI support" + depends on WL1251 && SPI_MASTER + ---help--- + This module adds support for the SPI interface of adapters using + TI wl1251 chipset. Select this if your platform is using + the SPI bus. + + If you choose to build a module, it'll be called wl1251_spi. + Say N if unsure. + +config WL1251_SDIO + tristate "TI wl1251 SDIO support" + depends on WL1251 && MMC + ---help--- + This module adds support for the SDIO interface of adapters using + TI wl1251 chipset. Select this if your platform is using + the SDIO bus. + + If you choose to build a module, it'll be called + wl1251_sdio. Say N if unsure. diff --git a/drivers/net/wireless/wl1251/Makefile b/drivers/net/wireless/wl1251/Makefile new file mode 100644 index 000000000000..4fe246824db3 --- /dev/null +++ b/drivers/net/wireless/wl1251/Makefile @@ -0,0 +1,6 @@ +wl1251-objs = main.o event.o tx.o rx.o ps.o cmd.o \ + acx.o boot.o init.o debugfs.o io.o + +obj-$(CONFIG_WL1251) += wl1251.o +obj-$(CONFIG_WL1251_SPI) += spi.o +obj-$(CONFIG_WL1251_SDIO) += sdio.o diff --git a/drivers/net/wireless/wl12xx/wl1251_acx.c b/drivers/net/wireless/wl1251/acx.c similarity index 99% rename from drivers/net/wireless/wl12xx/wl1251_acx.c rename to drivers/net/wireless/wl1251/acx.c index 2f8a2ba744dc..64a0214cfb29 100644 --- a/drivers/net/wireless/wl12xx/wl1251_acx.c +++ b/drivers/net/wireless/wl1251/acx.c @@ -1,13 +1,13 @@ -#include "wl1251_acx.h" +#include "acx.h" #include #include #include #include "wl1251.h" -#include "wl1251_reg.h" -#include "wl1251_cmd.h" -#include "wl1251_ps.h" +#include "reg.h" +#include "cmd.h" +#include "ps.h" int wl1251_acx_frame_rates(struct wl1251 *wl, u8 ctrl_rate, u8 ctrl_mod, u8 mgt_rate, u8 mgt_mod) diff --git a/drivers/net/wireless/wl12xx/wl1251_acx.h b/drivers/net/wireless/wl1251/acx.h similarity index 99% rename from drivers/net/wireless/wl12xx/wl1251_acx.h rename to drivers/net/wireless/wl1251/acx.h index c7cc5c1e8a75..e54b21a4f8b1 100644 --- a/drivers/net/wireless/wl12xx/wl1251_acx.h +++ b/drivers/net/wireless/wl1251/acx.h @@ -24,7 +24,7 @@ #define __WL1251_ACX_H__ #include "wl1251.h" -#include "wl1251_cmd.h" +#include "cmd.h" /* Target's information element */ struct acx_header { diff --git a/drivers/net/wireless/wl12xx/wl1251_boot.c b/drivers/net/wireless/wl1251/boot.c similarity index 99% rename from drivers/net/wireless/wl12xx/wl1251_boot.c rename to drivers/net/wireless/wl1251/boot.c index 468b47b0328a..61572dfa1f60 100644 --- a/drivers/net/wireless/wl12xx/wl1251_boot.c +++ b/drivers/net/wireless/wl1251/boot.c @@ -22,12 +22,12 @@ #include #include -#include "wl1251_reg.h" -#include "wl1251_boot.h" -#include "wl1251_io.h" -#include "wl1251_spi.h" -#include "wl1251_event.h" -#include "wl1251_acx.h" +#include "reg.h" +#include "boot.h" +#include "io.h" +#include "spi.h" +#include "event.h" +#include "acx.h" void wl1251_boot_target_enable_interrupts(struct wl1251 *wl) { diff --git a/drivers/net/wireless/wl12xx/wl1251_boot.h b/drivers/net/wireless/wl1251/boot.h similarity index 100% rename from drivers/net/wireless/wl12xx/wl1251_boot.h rename to drivers/net/wireless/wl1251/boot.h diff --git a/drivers/net/wireless/wl12xx/wl1251_cmd.c b/drivers/net/wireless/wl1251/cmd.c similarity index 98% rename from drivers/net/wireless/wl12xx/wl1251_cmd.c rename to drivers/net/wireless/wl1251/cmd.c index 15fb68c6b542..0ade4bd617c0 100644 --- a/drivers/net/wireless/wl12xx/wl1251_cmd.c +++ b/drivers/net/wireless/wl1251/cmd.c @@ -1,14 +1,14 @@ -#include "wl1251_cmd.h" +#include "cmd.h" #include #include #include #include "wl1251.h" -#include "wl1251_reg.h" -#include "wl1251_io.h" -#include "wl1251_ps.h" -#include "wl1251_acx.h" +#include "reg.h" +#include "io.h" +#include "ps.h" +#include "acx.h" /** * send command to firmware diff --git a/drivers/net/wireless/wl12xx/wl1251_cmd.h b/drivers/net/wireless/wl1251/cmd.h similarity index 100% rename from drivers/net/wireless/wl12xx/wl1251_cmd.h rename to drivers/net/wireless/wl1251/cmd.h diff --git a/drivers/net/wireless/wl12xx/wl1251_debugfs.c b/drivers/net/wireless/wl1251/debugfs.c similarity index 99% rename from drivers/net/wireless/wl12xx/wl1251_debugfs.c rename to drivers/net/wireless/wl1251/debugfs.c index 6ffe4cd58561..6e5caaa9f613 100644 --- a/drivers/net/wireless/wl12xx/wl1251_debugfs.c +++ b/drivers/net/wireless/wl1251/debugfs.c @@ -19,14 +19,14 @@ * */ -#include "wl1251_debugfs.h" +#include "debugfs.h" #include #include #include "wl1251.h" -#include "wl1251_acx.h" -#include "wl1251_ps.h" +#include "acx.h" +#include "ps.h" /* ms */ #define WL1251_DEBUGFS_STATS_LIFETIME 1000 diff --git a/drivers/net/wireless/wl12xx/wl1251_debugfs.h b/drivers/net/wireless/wl1251/debugfs.h similarity index 100% rename from drivers/net/wireless/wl12xx/wl1251_debugfs.h rename to drivers/net/wireless/wl1251/debugfs.h diff --git a/drivers/net/wireless/wl12xx/wl1251_event.c b/drivers/net/wireless/wl1251/event.c similarity index 97% rename from drivers/net/wireless/wl12xx/wl1251_event.c rename to drivers/net/wireless/wl1251/event.c index 54223556b308..712372e50a87 100644 --- a/drivers/net/wireless/wl12xx/wl1251_event.c +++ b/drivers/net/wireless/wl1251/event.c @@ -21,10 +21,10 @@ */ #include "wl1251.h" -#include "wl1251_reg.h" -#include "wl1251_io.h" -#include "wl1251_event.h" -#include "wl1251_ps.h" +#include "reg.h" +#include "io.h" +#include "event.h" +#include "ps.h" static int wl1251_event_scan_complete(struct wl1251 *wl, struct event_mailbox *mbox) diff --git a/drivers/net/wireless/wl12xx/wl1251_event.h b/drivers/net/wireless/wl1251/event.h similarity index 100% rename from drivers/net/wireless/wl12xx/wl1251_event.h rename to drivers/net/wireless/wl1251/event.h diff --git a/drivers/net/wireless/wl12xx/wl1251_init.c b/drivers/net/wireless/wl1251/init.c similarity index 98% rename from drivers/net/wireless/wl12xx/wl1251_init.c rename to drivers/net/wireless/wl1251/init.c index c5daec05d9ee..89b43d35473c 100644 --- a/drivers/net/wireless/wl12xx/wl1251_init.c +++ b/drivers/net/wireless/wl1251/init.c @@ -23,11 +23,11 @@ #include #include -#include "wl1251_init.h" +#include "init.h" #include "wl12xx_80211.h" -#include "wl1251_acx.h" -#include "wl1251_cmd.h" -#include "wl1251_reg.h" +#include "acx.h" +#include "cmd.h" +#include "reg.h" int wl1251_hw_init_hwenc_config(struct wl1251 *wl) { diff --git a/drivers/net/wireless/wl12xx/wl1251_init.h b/drivers/net/wireless/wl1251/init.h similarity index 100% rename from drivers/net/wireless/wl12xx/wl1251_init.h rename to drivers/net/wireless/wl1251/init.h diff --git a/drivers/net/wireless/wl12xx/wl1251_io.c b/drivers/net/wireless/wl1251/io.c similarity index 99% rename from drivers/net/wireless/wl12xx/wl1251_io.c rename to drivers/net/wireless/wl1251/io.c index ad6ca68b303f..cdcadbf6ac2c 100644 --- a/drivers/net/wireless/wl12xx/wl1251_io.c +++ b/drivers/net/wireless/wl1251/io.c @@ -20,8 +20,8 @@ */ #include "wl1251.h" -#include "wl1251_reg.h" -#include "wl1251_io.h" +#include "reg.h" +#include "io.h" /* FIXME: this is static data nowadays and the table can be removed */ static enum wl12xx_acx_int_reg wl1251_io_reg_table[ACX_REG_TABLE_LEN] = { diff --git a/drivers/net/wireless/wl12xx/wl1251_io.h b/drivers/net/wireless/wl1251/io.h similarity index 100% rename from drivers/net/wireless/wl12xx/wl1251_io.h rename to drivers/net/wireless/wl1251/io.h diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl1251/main.c similarity index 99% rename from drivers/net/wireless/wl12xx/wl1251_main.c rename to drivers/net/wireless/wl1251/main.c index faf221ca3f41..7a8762553cdc 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl1251/main.c @@ -31,16 +31,16 @@ #include "wl1251.h" #include "wl12xx_80211.h" -#include "wl1251_reg.h" -#include "wl1251_io.h" -#include "wl1251_cmd.h" -#include "wl1251_event.h" -#include "wl1251_tx.h" -#include "wl1251_rx.h" -#include "wl1251_ps.h" -#include "wl1251_init.h" -#include "wl1251_debugfs.h" -#include "wl1251_boot.h" +#include "reg.h" +#include "io.h" +#include "cmd.h" +#include "event.h" +#include "tx.h" +#include "rx.h" +#include "ps.h" +#include "init.h" +#include "debugfs.h" +#include "boot.h" void wl1251_enable_interrupts(struct wl1251 *wl) { diff --git a/drivers/net/wireless/wl12xx/wl1251_ps.c b/drivers/net/wireless/wl1251/ps.c similarity index 97% rename from drivers/net/wireless/wl12xx/wl1251_ps.c rename to drivers/net/wireless/wl1251/ps.c index 0b997bdfec09..5ed47c8373d2 100644 --- a/drivers/net/wireless/wl12xx/wl1251_ps.c +++ b/drivers/net/wireless/wl1251/ps.c @@ -19,10 +19,10 @@ * */ -#include "wl1251_reg.h" -#include "wl1251_ps.h" -#include "wl1251_cmd.h" -#include "wl1251_io.h" +#include "reg.h" +#include "ps.h" +#include "cmd.h" +#include "io.h" /* in ms */ #define WL1251_WAKEUP_TIMEOUT 100 diff --git a/drivers/net/wireless/wl12xx/wl1251_ps.h b/drivers/net/wireless/wl1251/ps.h similarity index 97% rename from drivers/net/wireless/wl12xx/wl1251_ps.h rename to drivers/net/wireless/wl1251/ps.h index e5db81fc1dfc..55c3dda75e69 100644 --- a/drivers/net/wireless/wl12xx/wl1251_ps.h +++ b/drivers/net/wireless/wl1251/ps.h @@ -24,7 +24,7 @@ #define __WL1251_PS_H__ #include "wl1251.h" -#include "wl1251_acx.h" +#include "acx.h" int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_cmd_ps_mode mode); void wl1251_ps_elp_sleep(struct wl1251 *wl); diff --git a/drivers/net/wireless/wl12xx/wl1251_reg.h b/drivers/net/wireless/wl1251/reg.h similarity index 100% rename from drivers/net/wireless/wl12xx/wl1251_reg.h rename to drivers/net/wireless/wl1251/reg.h diff --git a/drivers/net/wireless/wl12xx/wl1251_rx.c b/drivers/net/wireless/wl1251/rx.c similarity index 97% rename from drivers/net/wireless/wl12xx/wl1251_rx.c rename to drivers/net/wireless/wl1251/rx.c index 25764592a596..efa53607d5c9 100644 --- a/drivers/net/wireless/wl12xx/wl1251_rx.c +++ b/drivers/net/wireless/wl1251/rx.c @@ -25,11 +25,11 @@ #include #include "wl1251.h" -#include "wl1251_reg.h" -#include "wl1251_io.h" -#include "wl1251_rx.h" -#include "wl1251_cmd.h" -#include "wl1251_acx.h" +#include "reg.h" +#include "io.h" +#include "rx.h" +#include "cmd.h" +#include "acx.h" static void wl1251_rx_header(struct wl1251 *wl, struct wl1251_rx_descriptor *desc) diff --git a/drivers/net/wireless/wl12xx/wl1251_rx.h b/drivers/net/wireless/wl1251/rx.h similarity index 100% rename from drivers/net/wireless/wl12xx/wl1251_rx.h rename to drivers/net/wireless/wl1251/rx.h diff --git a/drivers/net/wireless/wl12xx/wl1251_sdio.c b/drivers/net/wireless/wl1251/sdio.c similarity index 100% rename from drivers/net/wireless/wl12xx/wl1251_sdio.c rename to drivers/net/wireless/wl1251/sdio.c diff --git a/drivers/net/wireless/wl12xx/wl1251_spi.c b/drivers/net/wireless/wl1251/spi.c similarity index 99% rename from drivers/net/wireless/wl12xx/wl1251_spi.c rename to drivers/net/wireless/wl1251/spi.c index 320de79667a6..88fa8e69d0d1 100644 --- a/drivers/net/wireless/wl12xx/wl1251_spi.c +++ b/drivers/net/wireless/wl1251/spi.c @@ -27,8 +27,8 @@ #include #include "wl1251.h" -#include "wl1251_reg.h" -#include "wl1251_spi.h" +#include "reg.h" +#include "spi.h" static irqreturn_t wl1251_irq(int irq, void *cookie) { diff --git a/drivers/net/wireless/wl12xx/wl1251_spi.h b/drivers/net/wireless/wl1251/spi.h similarity index 96% rename from drivers/net/wireless/wl12xx/wl1251_spi.h rename to drivers/net/wireless/wl1251/spi.h index 7dcf3cf7ae40..16d506955cc0 100644 --- a/drivers/net/wireless/wl12xx/wl1251_spi.h +++ b/drivers/net/wireless/wl1251/spi.h @@ -23,9 +23,9 @@ #ifndef __WL1251_SPI_H__ #define __WL1251_SPI_H__ -#include "wl1251_cmd.h" -#include "wl1251_acx.h" -#include "wl1251_reg.h" +#include "cmd.h" +#include "acx.h" +#include "reg.h" #define WSPI_CMD_READ 0x40000000 #define WSPI_CMD_WRITE 0x00000000 diff --git a/drivers/net/wireless/wl12xx/wl1251_tx.c b/drivers/net/wireless/wl1251/tx.c similarity index 99% rename from drivers/net/wireless/wl12xx/wl1251_tx.c rename to drivers/net/wireless/wl1251/tx.c index 388492a7f41f..554b4f9a3d3e 100644 --- a/drivers/net/wireless/wl12xx/wl1251_tx.c +++ b/drivers/net/wireless/wl1251/tx.c @@ -24,10 +24,10 @@ #include #include "wl1251.h" -#include "wl1251_reg.h" -#include "wl1251_tx.h" -#include "wl1251_ps.h" -#include "wl1251_io.h" +#include "reg.h" +#include "tx.h" +#include "ps.h" +#include "io.h" static bool wl1251_tx_double_buffer_busy(struct wl1251 *wl, u32 data_out_count) { diff --git a/drivers/net/wireless/wl12xx/wl1251_tx.h b/drivers/net/wireless/wl1251/tx.h similarity index 99% rename from drivers/net/wireless/wl12xx/wl1251_tx.h rename to drivers/net/wireless/wl1251/tx.h index 96011e78cd5a..81338d39b43e 100644 --- a/drivers/net/wireless/wl12xx/wl1251_tx.h +++ b/drivers/net/wireless/wl1251/tx.h @@ -24,7 +24,7 @@ #define __WL1251_TX_H__ #include -#include "wl1251_acx.h" +#include "acx.h" /* * diff --git a/drivers/net/wireless/wl12xx/wl1251.h b/drivers/net/wireless/wl1251/wl1251.h similarity index 100% rename from drivers/net/wireless/wl12xx/wl1251.h rename to drivers/net/wireless/wl1251/wl1251.h diff --git a/drivers/net/wireless/wl12xx/Kconfig b/drivers/net/wireless/wl12xx/Kconfig index 4a8bb25c1739..b447559f1db5 100644 --- a/drivers/net/wireless/wl12xx/Kconfig +++ b/drivers/net/wireless/wl12xx/Kconfig @@ -5,40 +5,6 @@ menuconfig WL12XX This will enable TI wl12xx driver support. The drivers make use of the mac80211 stack. -config WL1251 - tristate "TI wl1251 support" - depends on WL12XX && GENERIC_HARDIRQS - select FW_LOADER - select CRC7 - ---help--- - This module adds support for wireless adapters based on - TI wl1251 chipset. - - If you choose to build a module, it'll be called wl1251. Say - N if unsure. - -config WL1251_SPI - tristate "TI wl1251 SPI support" - depends on WL1251 && SPI_MASTER - ---help--- - This module adds support for the SPI interface of adapters using - TI wl1251 chipset. Select this if your platform is using - the SPI bus. - - If you choose to build a module, it'll be called wl1251_spi. - Say N if unsure. - -config WL1251_SDIO - tristate "TI wl1251 SDIO support" - depends on WL1251 && MMC - ---help--- - This module adds support for the SDIO interface of adapters using - TI wl1251 chipset. Select this if your platform is using - the SDIO bus. - - If you choose to build a module, it'll be called - wl1251_sdio. Say N if unsure. - config WL1271 tristate "TI wl1271 support" depends on WL12XX && GENERIC_HARDIRQS diff --git a/drivers/net/wireless/wl12xx/Makefile b/drivers/net/wireless/wl12xx/Makefile index 0d334d6f86f4..3a807444b2af 100644 --- a/drivers/net/wireless/wl12xx/Makefile +++ b/drivers/net/wireless/wl12xx/Makefile @@ -1,12 +1,3 @@ -wl1251-objs = wl1251_main.o wl1251_event.o \ - wl1251_tx.o wl1251_rx.o wl1251_ps.o wl1251_cmd.o \ - wl1251_acx.o wl1251_boot.o wl1251_init.o \ - wl1251_debugfs.o wl1251_io.o - -obj-$(CONFIG_WL1251) += wl1251.o -obj-$(CONFIG_WL1251_SPI) += wl1251_spi.o -obj-$(CONFIG_WL1251_SDIO) += wl1251_sdio.o - wl1271-objs = wl1271_main.o wl1271_cmd.o wl1271_io.o \ wl1271_event.o wl1271_tx.o wl1271_rx.o \ wl1271_ps.o wl1271_acx.o wl1271_boot.o \ From cc2858c987f41286e059ee777c3bc09f7b7c19f6 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Sun, 10 Oct 2010 11:28:33 +0300 Subject: [PATCH 051/127] wl1251: update the new location to the maintainers file wl1251 is grown up now and can have its own room^H^H^H^Hdirectory. Signed-off-by: Kalle Valo Signed-off-by: John W. Linville --- MAINTAINERS | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 529bfee8c4b2..339606e0a781 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6314,8 +6314,7 @@ L: linux-wireless@vger.kernel.org W: http://wireless.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git S: Maintained -F: drivers/net/wireless/wl12xx/* -X: drivers/net/wireless/wl12xx/wl1271* +F: drivers/net/wireless/wl1251/* WL1271 WIRELESS DRIVER M: Luciano Coelho From 730bd83b036e72b0134352ca27e76ea08475fbf1 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sun, 10 Oct 2010 18:52:10 +0200 Subject: [PATCH 052/127] mac80211: don't kmalloc 16 bytes Since this small buffer isn't used for DMA, we can simply allocate it on the stack, it just needs to be 16 bytes of which only 8 will be used for WEP40 keys. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/wep.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c index f27484c22b9f..2ff6d1e3ed21 100644 --- a/net/mac80211/wep.c +++ b/net/mac80211/wep.c @@ -222,7 +222,7 @@ static int ieee80211_wep_decrypt(struct ieee80211_local *local, struct ieee80211_key *key) { u32 klen; - u8 *rc4key; + u8 rc4key[3 + WLAN_KEY_LEN_WEP104]; u8 keyidx; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; unsigned int hdrlen; @@ -245,10 +245,6 @@ static int ieee80211_wep_decrypt(struct ieee80211_local *local, klen = 3 + key->conf.keylen; - rc4key = kmalloc(klen, GFP_ATOMIC); - if (!rc4key) - return -1; - /* Prepend 24-bit IV to RC4 key */ memcpy(rc4key, skb->data + hdrlen, 3); @@ -260,8 +256,6 @@ static int ieee80211_wep_decrypt(struct ieee80211_local *local, len)) ret = -1; - kfree(rc4key); - /* Trim ICV */ skb_trim(skb, skb->len - WEP_ICV_LEN); From 15d46f38df87f89242e470f5797120fa384c1fc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Smedman?= Date: Sun, 10 Oct 2010 22:14:25 +0200 Subject: [PATCH 053/127] mac80211: minstrel_ht A-MPDU fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch fixes two problems with the minstrel_ht rate control algorithms handling of A-MPDU frames: 1. The ampdu_len field of the tx status is not always initialized for non-HT frames (and it would probably be unreasonable to require all drivers to do so). This could cause rate control statistics to be corrupted. We now trust the ampdu_len and ampdu_ack_len fields only when the frame is marked with the IEEE80211_TX_STAT_AMPDU flag. 2. Successful transmission attempts where only recognized when the A-MPDU subframe carrying the rate control status information was marked with the IEEE80211_TX_STAT_ACK flag. If this information happed to be carried on a frame that failed to be ACKed then the other subframes (which may have succeeded) where not correctly registered. We now update rate control statistics regardless of whether the subframe carrying the information was ACKed or not. Cc: Signed-off-by: Björn Smedman Acked-by: Felix Fietkau Signed-off-by: John W. Linville --- net/mac80211/rc80211_minstrel_ht.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index c5b465904e3b..2a18d6602d4a 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c @@ -397,8 +397,9 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband, !(info->flags & IEEE80211_TX_STAT_AMPDU)) return; - if (!info->status.ampdu_len) { - info->status.ampdu_ack_len = 1; + if (!(info->flags & IEEE80211_TX_STAT_AMPDU)) { + info->status.ampdu_ack_len = + (info->flags & IEEE80211_TX_STAT_ACK ? 1 : 0); info->status.ampdu_len = 1; } @@ -426,7 +427,7 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband, group = minstrel_ht_get_group_idx(&ar[i]); rate = &mi->groups[group].rates[ar[i].idx % 8]; - if (last && (info->flags & IEEE80211_TX_STAT_ACK)) + if (last) rate->success += info->status.ampdu_ack_len; rate->attempts += ar[i].count * info->status.ampdu_len; From ebd022873aa61937603d2c4dfea19ce63ea1a3c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Smedman?= Date: Sun, 10 Oct 2010 22:44:39 +0200 Subject: [PATCH 054/127] ath9k: A-MPDU rate control info fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch fixes the following problems with the rate control feedback generated by ath9k for A-MPDU frames: 1. Rate control feedback is carried on the first frame of an aggregate that is either ACKed, or has execeeded the software retry count and is considered failed. However, ath9k would incorrectly assume the aggregate had the length 1 if one of these conditions did not apply to the first frame of the aggregate, but instead a later frame. This fix therefor copies the bf_nframes field of the buffer in the same manner as the rates field of the tx status. 2. Sometimes the ampdu_len and ampdu_ack_len fields of the tx status was left uninitialized eventhough the IEEE80211_TX_STAT_AMPDU flag was set. This is now avoid by setting flag and fields in the same place. 3. Even if a frame has been selected for aggregation by mac80211 and marked with the IEEE80211_TX_CTL_AMPDU flag it can sometimes happen that ath9k transmits the frame without aggregation. In these cases the ampdu_ack_len field could be incorrectly computed because the nbad parameter to ath_tx_rc_status was incorrect. Cc: Signed-off-by: Björn Smedman Acked-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/xmit.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index aa447770eb2b..9a11099dd86a 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -317,6 +317,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0; bool rc_update = true; struct ieee80211_tx_rate rates[4]; + int nframes; skb = bf->bf_mpdu; hdr = (struct ieee80211_hdr *)skb->data; @@ -325,6 +326,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, hw = bf->aphy->hw; memcpy(rates, tx_info->control.rates, sizeof(rates)); + nframes = bf->bf_nframes; rcu_read_lock(); @@ -341,7 +343,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, !bf->bf_stale || bf_next != NULL) list_move_tail(&bf->list, &bf_head); - ath_tx_rc_status(bf, ts, 0, 0, false); + ath_tx_rc_status(bf, ts, 1, 0, false); ath_tx_complete_buf(sc, bf, txq, &bf_head, ts, 0, 0); @@ -446,6 +448,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) { memcpy(tx_info->control.rates, rates, sizeof(rates)); + bf->bf_nframes = nframes; ath_tx_rc_status(bf, ts, nbad, txok, true); rc_update = false; } else { @@ -1979,9 +1982,15 @@ static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts, if (ts->ts_status & ATH9K_TXERR_FILT) tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED; - if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && update_rc) + if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && update_rc) { tx_info->flags |= IEEE80211_TX_STAT_AMPDU; + BUG_ON(nbad > bf->bf_nframes); + + tx_info->status.ampdu_len = bf->bf_nframes; + tx_info->status.ampdu_ack_len = bf->bf_nframes - nbad; + } + if ((ts->ts_status & ATH9K_TXERR_FILT) == 0 && (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0 && update_rc) { if (ieee80211_is_data(hdr->frame_control)) { @@ -1991,8 +2000,6 @@ static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts, if ((ts->ts_status & ATH9K_TXERR_XRETRY) || (ts->ts_status & ATH9K_TXERR_FIFO)) tx_info->pad[0] |= ATH_TX_INFO_XRETRY; - tx_info->status.ampdu_len = bf->bf_nframes; - tx_info->status.ampdu_ack_len = bf->bf_nframes - nbad; } } @@ -2102,7 +2109,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) */ if (ts.ts_status & ATH9K_TXERR_XRETRY) bf->bf_state.bf_type |= BUF_XRETRY; - ath_tx_rc_status(bf, &ts, 0, txok, true); + ath_tx_rc_status(bf, &ts, txok ? 0 : 1, txok, true); } if (bf_isampdu(bf)) @@ -2220,7 +2227,7 @@ void ath_tx_edma_tasklet(struct ath_softc *sc) if (!bf_isampdu(bf)) { if (txs.ts_status & ATH9K_TXERR_XRETRY) bf->bf_state.bf_type |= BUF_XRETRY; - ath_tx_rc_status(bf, &txs, 0, txok, true); + ath_tx_rc_status(bf, &txs, txok ? 0 : 1, txok, true); } if (bf_isampdu(bf)) From a8909cfb1832ac623142898df2a9374722cfe68f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Smedman?= Date: Sun, 10 Oct 2010 22:51:54 +0200 Subject: [PATCH 055/127] ath9k: built-in rate control A-MPDU fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch attempts to ensure that ath9k's built-in rate control algorithm does not rely on the value of the ampdu_len and ampdu_ack_len tx status fields unless the IEEE80211_TX_STAT_AMPDU flag is set. This patch has not been tested. Cc: Signed-off-by: Björn Smedman Acked-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/rc.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index ce1cd6d85847..13f9e88e1187 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -1375,6 +1375,12 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, if (tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED) return; + if (!(tx_info->flags & IEEE80211_TX_STAT_AMPDU)) { + tx_info->status.ampdu_ack_len = + (tx_info->flags & IEEE80211_TX_STAT_ACK ? 1 : 0); + tx_info->status.ampdu_len = 1; + } + /* * If an underrun error is seen assume it as an excessive retry only * if max frame trigger level has been reached (2 KB for singel stream, From a656b6a9665dce09a8f273091f1b4aa3d5cec721 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Mon, 11 Oct 2010 03:11:01 +0200 Subject: [PATCH 056/127] b43: N-PHY: grab more info about new channel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 61 +++++++++++++++----------------- 1 file changed, 29 insertions(+), 32 deletions(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 52ce4383a056..6ca41a09fec4 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -3323,9 +3323,9 @@ int b43_phy_initn(struct b43_wldev *dev) } /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ChanspecSetup */ -static void b43_nphy_chanspec_setup(struct b43_wldev *dev, +static void b43_nphy_channel_setup(struct b43_wldev *dev, const struct b43_phy_n_sfo_cfg *e, - struct b43_chanspec chanspec) + struct ieee80211_channel *new_channel) { struct b43_phy *phy = &dev->phy; struct b43_phy_n *nphy = dev->phy.n; @@ -3334,13 +3334,13 @@ static void b43_nphy_chanspec_setup(struct b43_wldev *dev, u32 tmp32; tmp = b43_phy_read(dev, B43_NPHY_BANDCTL) & B43_NPHY_BANDCTL_5GHZ; - if (chanspec.b_freq == 1 && tmp == 0) { + if (new_channel->band == IEEE80211_BAND_5GHZ && tmp == 0) { tmp32 = b43_read32(dev, B43_MMIO_PSM_PHY_HDR); b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32 | 4); b43_phy_set(dev, B43_PHY_B_BBCFG, 0xC000); b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32); b43_phy_set(dev, B43_NPHY_BANDCTL, B43_NPHY_BANDCTL_5GHZ); - } else if (chanspec.b_freq == 1) { + } else if (new_channel->band == IEEE80211_BAND_5GHZ) { b43_phy_mask(dev, B43_NPHY_BANDCTL, ~B43_NPHY_BANDCTL_5GHZ); tmp32 = b43_read32(dev, B43_MMIO_PSM_PHY_HDR); b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32 | 4); @@ -3350,13 +3350,12 @@ static void b43_nphy_chanspec_setup(struct b43_wldev *dev, b43_chantab_phy_upload(dev, e); - - if (nphy->radio_chanspec.channel == 14) { + if (new_channel->hw_value == 14) { b43_nphy_classifier(dev, 2, 0); b43_phy_set(dev, B43_PHY_B_TEST, 0x0800); } else { b43_nphy_classifier(dev, 2, 2); - if (chanspec.b_freq == 2) + if (new_channel->band == IEEE80211_BAND_2GHZ) b43_phy_mask(dev, B43_PHY_B_TEST, ~0x840); } @@ -3379,16 +3378,17 @@ static void b43_nphy_chanspec_setup(struct b43_wldev *dev, } /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetChanspec */ -static int b43_nphy_set_chanspec(struct b43_wldev *dev, - struct b43_chanspec chanspec) +static int b43_nphy_set_channel(struct b43_wldev *dev, + struct ieee80211_channel *channel, + enum nl80211_channel_type channel_type) { + struct b43_phy *phy = &dev->phy; struct b43_phy_n *nphy = dev->phy.n; const struct b43_nphy_channeltab_entry_rev2 *tabent_r2; const struct b43_nphy_channeltab_entry_rev3 *tabent_r3; u8 tmp; - u8 channel = chanspec.channel; if (dev->phy.rev >= 3) { /* TODO */ @@ -3396,36 +3396,36 @@ static int b43_nphy_set_chanspec(struct b43_wldev *dev, if (!tabent_r3) return -ESRCH; } else { - tabent_r2 = b43_nphy_get_chantabent_rev2(dev, channel); + tabent_r2 = b43_nphy_get_chantabent_rev2(dev, + channel->hw_value); if (!tabent_r2) return -ESRCH; } - nphy->radio_chanspec = chanspec; + nphy->radio_chanspec.channel = channel->hw_value; + /* if (chanspec.b_width != nphy->b_width) - ; /* TODO: BMAC BW Set (chanspec.b_width) */ + ; TODO: BMAC BW Set (chanspec.b_width) + */ - /* TODO: use defines */ - if (chanspec.b_width == 3) { - if (chanspec.sideband == 2) - b43_phy_set(dev, B43_NPHY_RXCTL, - B43_NPHY_RXCTL_BSELU20); - else - b43_phy_mask(dev, B43_NPHY_RXCTL, - ~B43_NPHY_RXCTL_BSELU20); - } + if (channel_type == NL80211_CHAN_HT40PLUS) + b43_phy_set(dev, B43_NPHY_RXCTL, + B43_NPHY_RXCTL_BSELU20); + else if (channel_type == NL80211_CHAN_HT40MINUS) + b43_phy_mask(dev, B43_NPHY_RXCTL, + ~B43_NPHY_RXCTL_BSELU20); if (dev->phy.rev >= 3) { - tmp = (chanspec.b_freq == 1) ? 4 : 0; + tmp = (channel->band == IEEE80211_BAND_5GHZ) ? 4 : 0; b43_radio_maskset(dev, 0x08, 0xFFFB, tmp); /* TODO: PHY Radio2056 Setup (dev, tabent_r3); */ - b43_nphy_chanspec_setup(dev, &(tabent_r3->phy_regs), chanspec); + b43_nphy_channel_setup(dev, &(tabent_r3->phy_regs), channel); } else { - tmp = (chanspec.b_freq == 1) ? 0x0020 : 0x0050; + tmp = (channel->band == IEEE80211_BAND_5GHZ) ? 0x0020 : 0x0050; b43_radio_maskset(dev, B2055_MASTER1, 0xFF8F, tmp); b43_radio_2055_setup(dev, tabent_r2); - b43_nphy_chanspec_setup(dev, &(tabent_r2->phy_regs), chanspec); + b43_nphy_channel_setup(dev, &(tabent_r2->phy_regs), channel); } return 0; @@ -3567,8 +3567,8 @@ static void b43_nphy_op_switch_analog(struct b43_wldev *dev, bool on) static int b43_nphy_op_switch_channel(struct b43_wldev *dev, unsigned int new_channel) { - struct b43_phy_n *nphy = dev->phy.n; - struct b43_chanspec chanspec; + struct ieee80211_channel *channel = dev->wl->hw->conf.channel; + enum nl80211_channel_type channel_type = dev->wl->hw->conf.channel_type; if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { if ((new_channel < 1) || (new_channel > 14)) @@ -3578,10 +3578,7 @@ static int b43_nphy_op_switch_channel(struct b43_wldev *dev, return -EINVAL; } - chanspec = nphy->radio_chanspec; - chanspec.channel = new_channel; - - return b43_nphy_set_chanspec(dev, chanspec); + return b43_nphy_set_channel(dev, channel, channel_type); } static unsigned int b43_nphy_op_get_default_chan(struct b43_wldev *dev) From e5c407f970ea2977600eb54cf4cc8a67a44fefeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Mon, 11 Oct 2010 03:11:02 +0200 Subject: [PATCH 057/127] b43: N-PHY: store info about current channel's type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_common.h | 4 +++- drivers/net/wireless/b43/phy_n.c | 14 ++++++++++---- drivers/net/wireless/b43/phy_n.h | 1 - 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/b43/phy_common.h b/drivers/net/wireless/b43/phy_common.h index bd480b481bfc..6dcd0334ed02 100644 --- a/drivers/net/wireless/b43/phy_common.h +++ b/drivers/net/wireless/b43/phy_common.h @@ -2,6 +2,7 @@ #define LINUX_B43_PHY_COMMON_H_ #include +#include struct b43_wldev; @@ -250,8 +251,9 @@ struct b43_phy { * check is needed. */ unsigned long next_txpwr_check_time; - /* current channel */ + /* Current channel */ unsigned int channel; + enum nl80211_channel_type channel_type; /* PHY TX errors counter. */ atomic_t txerr_cnt; diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 6ca41a09fec4..789d21c54139 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -74,6 +74,13 @@ static void b43_nphy_rf_control_override(struct b43_wldev *dev, u16 field, static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field, u16 value, u8 core); +static inline bool b43_channel_type_is_40mhz( + enum nl80211_channel_type channel_type) +{ + return (channel_type == NL80211_CHAN_HT40MINUS || + channel_type == NL80211_CHAN_HT40PLUS); +} + static inline bool b43_empty_chanspec(struct b43_chanspec *chanspec) { return !chanspec->channel && !chanspec->sideband && @@ -3404,10 +3411,9 @@ static int b43_nphy_set_channel(struct b43_wldev *dev, nphy->radio_chanspec.channel = channel->hw_value; - /* - if (chanspec.b_width != nphy->b_width) - ; TODO: BMAC BW Set (chanspec.b_width) - */ + if (b43_channel_type_is_40mhz(phy->channel_type) != + b43_channel_type_is_40mhz(channel_type)) + ; /* TODO: BMAC BW Set (channel_type) */ if (channel_type == NL80211_CHAN_HT40PLUS) b43_phy_set(dev, B43_NPHY_RXCTL, diff --git a/drivers/net/wireless/b43/phy_n.h b/drivers/net/wireless/b43/phy_n.h index 8b6d570dd0aa..e7acae278be0 100644 --- a/drivers/net/wireless/b43/phy_n.h +++ b/drivers/net/wireless/b43/phy_n.h @@ -984,7 +984,6 @@ struct b43_phy_n { u16 papd_epsilon_offset[2]; s32 preamble_override; u32 bb_mult_save; - u8 b_width; struct b43_chanspec radio_chanspec; bool gain_boost; From 087de74ae512fe31894c1556d5f8d5a126322de7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Mon, 11 Oct 2010 03:11:03 +0200 Subject: [PATCH 058/127] b43: N-PHY: fix logic in band switching MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 789d21c54139..19582ba20598 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -3337,17 +3337,18 @@ static void b43_nphy_channel_setup(struct b43_wldev *dev, struct b43_phy *phy = &dev->phy; struct b43_phy_n *nphy = dev->phy.n; - u16 tmp; + u16 old_band_5ghz; u32 tmp32; - tmp = b43_phy_read(dev, B43_NPHY_BANDCTL) & B43_NPHY_BANDCTL_5GHZ; - if (new_channel->band == IEEE80211_BAND_5GHZ && tmp == 0) { + old_band_5ghz = + b43_phy_read(dev, B43_NPHY_BANDCTL) & B43_NPHY_BANDCTL_5GHZ; + if (new_channel->band == IEEE80211_BAND_5GHZ && !old_band_5ghz) { tmp32 = b43_read32(dev, B43_MMIO_PSM_PHY_HDR); b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32 | 4); b43_phy_set(dev, B43_PHY_B_BBCFG, 0xC000); b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32); b43_phy_set(dev, B43_NPHY_BANDCTL, B43_NPHY_BANDCTL_5GHZ); - } else if (new_channel->band == IEEE80211_BAND_5GHZ) { + } else if (new_channel->band == IEEE80211_BAND_2GHZ && old_band_5ghz) { b43_phy_mask(dev, B43_NPHY_BANDCTL, ~B43_NPHY_BANDCTL_5GHZ); tmp32 = b43_read32(dev, B43_MMIO_PSM_PHY_HDR); b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32 | 4); From f2a6d6a08cf13f621661dd57f32bf0a5100ba26b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Mon, 11 Oct 2010 03:19:22 +0200 Subject: [PATCH 059/127] b43: N-PHY: prepare for rev3+ channel tables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 3 ++- drivers/net/wireless/b43/tables_nphy.c | 24 +++++++++++++++++++++--- drivers/net/wireless/b43/tables_nphy.h | 4 +++- 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 19582ba20598..e532901246b6 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -3399,7 +3399,8 @@ static int b43_nphy_set_channel(struct b43_wldev *dev, u8 tmp; if (dev->phy.rev >= 3) { - /* TODO */ + tabent_r3 = b43_nphy_get_chantabent_rev3(dev, + channel->center_freq); tabent_r3 = NULL; if (!tabent_r3) return -ESRCH; diff --git a/drivers/net/wireless/b43/tables_nphy.c b/drivers/net/wireless/b43/tables_nphy.c index d96e870ab8fe..e74b8eb5795c 100644 --- a/drivers/net/wireless/b43/tables_nphy.c +++ b/drivers/net/wireless/b43/tables_nphy.c @@ -325,7 +325,7 @@ void b2055_upload_inittab(struct b43_wldev *dev, .phy_regs.phy_bw5 = r4, \ .phy_regs.phy_bw6 = r5 -static const struct b43_nphy_channeltab_entry_rev2 b43_nphy_channeltab[] = { +static const struct b43_nphy_channeltab_entry_rev2 b43_nphy_channeltab_rev2[] = { { .channel = 184, .freq = 4920, /* MHz */ .unk2 = 3280, @@ -1326,8 +1326,8 @@ b43_nphy_get_chantabent_rev2(struct b43_wldev *dev, u8 channel) const struct b43_nphy_channeltab_entry_rev2 *e; unsigned int i; - for (i = 0; i < ARRAY_SIZE(b43_nphy_channeltab); i++) { - e = &(b43_nphy_channeltab[i]); + for (i = 0; i < ARRAY_SIZE(b43_nphy_channeltab_rev2); i++) { + e = &(b43_nphy_channeltab_rev2[i]); if (e->channel == channel) return e; } @@ -1335,6 +1335,24 @@ b43_nphy_get_chantabent_rev2(struct b43_wldev *dev, u8 channel) return NULL; } +static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_rev3[] = { +}; + +const struct b43_nphy_channeltab_entry_rev3 * +b43_nphy_get_chantabent_rev3(struct b43_wldev *dev, u16 freq) +{ + const struct b43_nphy_channeltab_entry_rev3 *e; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(b43_nphy_channeltab_rev3); i++) { + e = &(b43_nphy_channeltab_rev3[i]); + if (e->freq == freq) + return e; + } + + return NULL; +} + static const u8 b43_ntab_adjustpower0[] = { 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, diff --git a/drivers/net/wireless/b43/tables_nphy.h b/drivers/net/wireless/b43/tables_nphy.h index 8fc1da9f8fe5..3eedb869f492 100644 --- a/drivers/net/wireless/b43/tables_nphy.h +++ b/drivers/net/wireless/b43/tables_nphy.h @@ -90,10 +90,12 @@ void b2055_upload_inittab(struct b43_wldev *dev, bool ghz5, bool ignore_uploadflag); -/* Get the NPHY Channel Switch Table entry for a channel number. +/* Get the NPHY Channel Switch Table entry for a channel. * Returns NULL on failure to find an entry. */ const struct b43_nphy_channeltab_entry_rev2 * b43_nphy_get_chantabent_rev2(struct b43_wldev *dev, u8 channel); +const struct b43_nphy_channeltab_entry_rev3 * +b43_nphy_get_chantabent_rev3(struct b43_wldev *dev, u16 freq); /* The N-PHY tables. */ From a9325199edb093a5c7311a25d15da20ee984e80b Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 11 Oct 2010 11:27:32 +0200 Subject: [PATCH 060/127] WIRELESS: at76c50x, remove unneeded NULL check Stanse found that urb cannot be NULL in at76_rx_tasklet because it is dereferenced earlier, so remove the unneeded check. Signed-off-by: Jiri Slaby Signed-off-by: John W. Linville --- drivers/net/wireless/at76c50x-usb.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c index 91c5f73b5ba3..1476314afa8a 100644 --- a/drivers/net/wireless/at76c50x-usb.c +++ b/drivers/net/wireless/at76c50x-usb.c @@ -1525,8 +1525,7 @@ static void at76_rx_tasklet(unsigned long param) if (priv->device_unplugged) { at76_dbg(DBG_DEVSTART, "device unplugged"); - if (urb) - at76_dbg(DBG_DEVSTART, "urb status %d", urb->status); + at76_dbg(DBG_DEVSTART, "urb status %d", urb->status); return; } From fa69560f317d961c56e29dea788b346d2b34fb87 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 11 Oct 2010 15:37:25 +0200 Subject: [PATCH 061/127] rt2x00: Simplify Queue function arguments A lot of functions accept a struct rt2x00_dev combined with either a struct queue_entry or struct data_queue argument. This can be simplified by only passing on the queue/entry argument. In cases where rt2x00_dev and a sk_buff are send together, we can send the queue_entry instead. rt2x00usb_alloc_urb and rt2x00usb_free_urb have a bit of vague naming. Instead they allocate all the data which belongs to a rt2x00 data queue entry. Signed-off-by: Ivo van Doorn Acked-by: Helmut Schaa Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2400pci.c | 2 +- drivers/net/wireless/rt2x00/rt2500pci.c | 2 +- drivers/net/wireless/rt2x00/rt2x00.h | 13 +++--- drivers/net/wireless/rt2x00/rt2x00dev.c | 10 ++--- drivers/net/wireless/rt2x00/rt2x00lib.h | 11 ++--- drivers/net/wireless/rt2x00/rt2x00pci.c | 2 +- drivers/net/wireless/rt2x00/rt2x00queue.c | 49 +++++++++++------------ drivers/net/wireless/rt2x00/rt2x00usb.c | 18 ++++----- 8 files changed, 50 insertions(+), 57 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 4b88909275a1..095cb6982d7a 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1104,7 +1104,7 @@ static void rt2400pci_write_beacon(struct queue_entry *entry, rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); rt2x00pci_register_write(rt2x00dev, CSR14, reg); - rt2x00queue_map_txskb(rt2x00dev, entry->skb); + rt2x00queue_map_txskb(entry); /* * Write the TX descriptor for the beacon. diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 46ef692e404d..7d85bf9bd253 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1258,7 +1258,7 @@ static void rt2500pci_write_beacon(struct queue_entry *entry, rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); rt2x00pci_register_write(rt2x00dev, CSR14, reg); - rt2x00queue_map_txskb(rt2x00dev, entry->skb); + rt2x00queue_map_txskb(entry); /* * Write the TX descriptor for the beacon. diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 75ac6624bf9e..2322c84adc1c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -1036,17 +1036,15 @@ static inline bool rt2x00_is_soc(struct rt2x00_dev *rt2x00dev) /** * rt2x00queue_map_txskb - Map a skb into DMA for TX purposes. - * @rt2x00dev: Pointer to &struct rt2x00_dev. - * @skb: The skb to map. + * @entry: Pointer to &struct queue_entry */ -void rt2x00queue_map_txskb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb); +void rt2x00queue_map_txskb(struct queue_entry *entry); /** * rt2x00queue_unmap_skb - Unmap a skb from DMA. - * @rt2x00dev: Pointer to &struct rt2x00_dev. - * @skb: The skb to unmap. + * @entry: Pointer to &struct queue_entry */ -void rt2x00queue_unmap_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb); +void rt2x00queue_unmap_skb(struct queue_entry *entry); /** * rt2x00queue_get_queue - Convert queue index to queue pointer @@ -1093,8 +1091,7 @@ void rt2x00lib_dmadone(struct queue_entry *entry); void rt2x00lib_txdone(struct queue_entry *entry, struct txdone_entry_desc *txdesc); void rt2x00lib_txdone_noinfo(struct queue_entry *entry, u32 status); -void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, - struct queue_entry *entry); +void rt2x00lib_rxdone(struct queue_entry *entry); /* * mac80211 handlers. diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 6f442b02b83e..9b745faef0ed 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -273,7 +273,7 @@ void rt2x00lib_txdone(struct queue_entry *entry, /* * Unmap the skb. */ - rt2x00queue_unmap_skb(rt2x00dev, entry->skb); + rt2x00queue_unmap_skb(entry); /* * Remove the extra tx headroom from the skb. @@ -465,9 +465,9 @@ static int rt2x00lib_rxdone_read_signal(struct rt2x00_dev *rt2x00dev, return 0; } -void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, - struct queue_entry *entry) +void rt2x00lib_rxdone(struct queue_entry *entry) { + struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct rxdone_entry_desc rxdesc; struct sk_buff *skb; struct ieee80211_rx_status *rx_status; @@ -481,14 +481,14 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, * Allocate a new sk_buffer. If no new buffer available, drop the * received frame and reuse the existing buffer. */ - skb = rt2x00queue_alloc_rxskb(rt2x00dev, entry); + skb = rt2x00queue_alloc_rxskb(entry); if (!skb) return; /* * Unmap the skb. */ - rt2x00queue_unmap_skb(rt2x00dev, entry->skb); + rt2x00queue_unmap_skb(entry); /* * Extract the RXD details. diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index 70c85ac2e53e..619da23b7b56 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h @@ -100,18 +100,15 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, /** * rt2x00queue_alloc_rxskb - allocate a skb for RX purposes. - * @rt2x00dev: Pointer to &struct rt2x00_dev. - * @queue: The queue for which the skb will be applicable. + * @entry: The entry for which the skb will be applicable. */ -struct sk_buff *rt2x00queue_alloc_rxskb(struct rt2x00_dev *rt2x00dev, - struct queue_entry *entry); +struct sk_buff *rt2x00queue_alloc_rxskb(struct queue_entry *entry); /** * rt2x00queue_free_skb - free a skb - * @rt2x00dev: Pointer to &struct rt2x00_dev. - * @skb: The skb to free. + * @entry: The entry for which the skb will be applicable. */ -void rt2x00queue_free_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb); +void rt2x00queue_free_skb(struct queue_entry *entry); /** * rt2x00queue_align_frame - Align 802.11 frame to 4-byte boundary diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index 63c2cc408e15..2449d785cf8d 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c @@ -84,7 +84,7 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) /* * Send the frame to rt2x00lib for further processing. */ - rt2x00lib_rxdone(rt2x00dev, entry); + rt2x00lib_rxdone(entry); } } EXPORT_SYMBOL_GPL(rt2x00pci_rxdone); diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 83630f16dc64..7e30144c5cfa 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -33,9 +33,9 @@ #include "rt2x00.h" #include "rt2x00lib.h" -struct sk_buff *rt2x00queue_alloc_rxskb(struct rt2x00_dev *rt2x00dev, - struct queue_entry *entry) +struct sk_buff *rt2x00queue_alloc_rxskb(struct queue_entry *entry) { + struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; struct sk_buff *skb; struct skb_frame_desc *skbdesc; unsigned int frame_size; @@ -97,39 +97,42 @@ struct sk_buff *rt2x00queue_alloc_rxskb(struct rt2x00_dev *rt2x00dev, return skb; } -void rt2x00queue_map_txskb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb) +void rt2x00queue_map_txskb(struct queue_entry *entry) { - struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); + struct device *dev = entry->queue->rt2x00dev->dev; + struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); skbdesc->skb_dma = - dma_map_single(rt2x00dev->dev, skb->data, skb->len, DMA_TO_DEVICE); + dma_map_single(dev, entry->skb->data, entry->skb->len, DMA_TO_DEVICE); skbdesc->flags |= SKBDESC_DMA_MAPPED_TX; } EXPORT_SYMBOL_GPL(rt2x00queue_map_txskb); -void rt2x00queue_unmap_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb) +void rt2x00queue_unmap_skb(struct queue_entry *entry) { - struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); + struct device *dev = entry->queue->rt2x00dev->dev; + struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); if (skbdesc->flags & SKBDESC_DMA_MAPPED_RX) { - dma_unmap_single(rt2x00dev->dev, skbdesc->skb_dma, skb->len, + dma_unmap_single(dev, skbdesc->skb_dma, entry->skb->len, DMA_FROM_DEVICE); skbdesc->flags &= ~SKBDESC_DMA_MAPPED_RX; } else if (skbdesc->flags & SKBDESC_DMA_MAPPED_TX) { - dma_unmap_single(rt2x00dev->dev, skbdesc->skb_dma, skb->len, + dma_unmap_single(dev, skbdesc->skb_dma, entry->skb->len, DMA_TO_DEVICE); skbdesc->flags &= ~SKBDESC_DMA_MAPPED_TX; } } EXPORT_SYMBOL_GPL(rt2x00queue_unmap_skb); -void rt2x00queue_free_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb) +void rt2x00queue_free_skb(struct queue_entry *entry) { - if (!skb) + if (!entry->skb) return; - rt2x00queue_unmap_skb(rt2x00dev, skb); - dev_kfree_skb_any(skb); + rt2x00queue_unmap_skb(entry); + dev_kfree_skb_any(entry->skb); + entry->skb = NULL; } void rt2x00queue_align_frame(struct sk_buff *skb) @@ -438,7 +441,7 @@ static int rt2x00queue_write_tx_data(struct queue_entry *entry, * Map the skb to DMA. */ if (test_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags)) - rt2x00queue_map_txskb(rt2x00dev, entry->skb); + rt2x00queue_map_txskb(entry); return 0; } @@ -585,8 +588,7 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, /* * Clean up the beacon skb. */ - rt2x00queue_free_skb(rt2x00dev, intf->beacon->skb); - intf->beacon->skb = NULL; + rt2x00queue_free_skb(intf->beacon); if (!enable_beacon) { rt2x00dev->ops->lib->kill_tx_queue(intf->beacon->queue); @@ -827,8 +829,7 @@ static int rt2x00queue_alloc_entries(struct data_queue *queue, return 0; } -static void rt2x00queue_free_skbs(struct rt2x00_dev *rt2x00dev, - struct data_queue *queue) +static void rt2x00queue_free_skbs(struct data_queue *queue) { unsigned int i; @@ -836,19 +837,17 @@ static void rt2x00queue_free_skbs(struct rt2x00_dev *rt2x00dev, return; for (i = 0; i < queue->limit; i++) { - if (queue->entries[i].skb) - rt2x00queue_free_skb(rt2x00dev, queue->entries[i].skb); + rt2x00queue_free_skb(&queue->entries[i]); } } -static int rt2x00queue_alloc_rxskbs(struct rt2x00_dev *rt2x00dev, - struct data_queue *queue) +static int rt2x00queue_alloc_rxskbs(struct data_queue *queue) { unsigned int i; struct sk_buff *skb; for (i = 0; i < queue->limit; i++) { - skb = rt2x00queue_alloc_rxskb(rt2x00dev, &queue->entries[i]); + skb = rt2x00queue_alloc_rxskb(&queue->entries[i]); if (!skb) return -ENOMEM; queue->entries[i].skb = skb; @@ -883,7 +882,7 @@ int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev) goto exit; } - status = rt2x00queue_alloc_rxskbs(rt2x00dev, rt2x00dev->rx); + status = rt2x00queue_alloc_rxskbs(rt2x00dev->rx); if (status) goto exit; @@ -901,7 +900,7 @@ void rt2x00queue_uninitialize(struct rt2x00_dev *rt2x00dev) { struct data_queue *queue; - rt2x00queue_free_skbs(rt2x00dev, rt2x00dev->rx); + rt2x00queue_free_skbs(rt2x00dev->rx); queue_for_each(rt2x00dev, queue) { kfree(queue->entries); diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 4c5ae3d45625..451d637377a2 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -398,7 +398,7 @@ static void rt2x00usb_work_rxdone(struct work_struct *work) /* * Send the frame to rt2x00lib for further processing. */ - rt2x00lib_rxdone(rt2x00dev, entry); + rt2x00lib_rxdone(entry); } } @@ -542,9 +542,9 @@ static int rt2x00usb_find_endpoints(struct rt2x00_dev *rt2x00dev) return 0; } -static int rt2x00usb_alloc_urb(struct rt2x00_dev *rt2x00dev, - struct data_queue *queue) +static int rt2x00usb_alloc_entries(struct data_queue *queue) { + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; struct queue_entry_priv_usb *entry_priv; struct queue_entry_priv_usb_bcn *bcn_priv; unsigned int i; @@ -561,7 +561,7 @@ static int rt2x00usb_alloc_urb(struct rt2x00_dev *rt2x00dev, * no guardian byte was required for the beacon, * then we are done. */ - if (rt2x00dev->bcn != queue || + if (queue->qid != QID_BEACON || !test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags)) return 0; @@ -575,9 +575,9 @@ static int rt2x00usb_alloc_urb(struct rt2x00_dev *rt2x00dev, return 0; } -static void rt2x00usb_free_urb(struct rt2x00_dev *rt2x00dev, - struct data_queue *queue) +static void rt2x00usb_free_entries(struct data_queue *queue) { + struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; struct queue_entry_priv_usb *entry_priv; struct queue_entry_priv_usb_bcn *bcn_priv; unsigned int i; @@ -596,7 +596,7 @@ static void rt2x00usb_free_urb(struct rt2x00_dev *rt2x00dev, * no guardian byte was required for the beacon, * then we are done. */ - if (rt2x00dev->bcn != queue || + if (queue->qid != QID_BEACON || !test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags)) return; @@ -623,7 +623,7 @@ int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev) * Allocate DMA */ queue_for_each(rt2x00dev, queue) { - status = rt2x00usb_alloc_urb(rt2x00dev, queue); + status = rt2x00usb_alloc_entries(queue); if (status) goto exit; } @@ -642,7 +642,7 @@ void rt2x00usb_uninitialize(struct rt2x00_dev *rt2x00dev) struct data_queue *queue; queue_for_each(rt2x00dev, queue) - rt2x00usb_free_urb(rt2x00dev, queue); + rt2x00usb_free_entries(queue); } EXPORT_SYMBOL_GPL(rt2x00usb_uninitialize); From cdfd2c5cffac2e744c855f9998212867387bb2de Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 11 Oct 2010 15:37:47 +0200 Subject: [PATCH 062/127] rt2x00: Move watchdog work to kernel work_queue The watchdog function must run on a work_queue which is independent of any other work inside rt2x00. The main reasons, being that a broken work on the mac80211 work_queue can otherwise prevent the watchdog to run (while in fact the watchdog could fix the issue). And on the other hand because the watchdog relies on the completion of the completion handlers for RX/TX which for the USB case, occur on the mac80211 workqueue. This fixes some "Queue %d failed to flush" errors, which were caused by the watchdog function waiting on the completion handler which was scheduled to run right after the watchdog. Signed-off-by: Ivo van Doorn Acked-by: Helmut Schaa Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00.h | 5 +++++ drivers/net/wireless/rt2x00/rt2x00link.c | 6 ++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 2322c84adc1c..94fe589acfaa 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -338,6 +338,11 @@ struct link { /* * Work structure for scheduling periodic watchdog monitoring. + * This work must be scheduled on the kernel workqueue, while + * all other work structures must be queued on the mac80211 + * workqueue. This guarantees that the watchdog can schedule + * other work structures and wait for their completion in order + * to bring the device/driver back into the desired state. */ struct delayed_work watchdog_work; }; diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c index 46836f801b35..b971d8798ebf 100644 --- a/drivers/net/wireless/rt2x00/rt2x00link.c +++ b/drivers/net/wireless/rt2x00/rt2x00link.c @@ -417,8 +417,7 @@ void rt2x00link_start_watchdog(struct rt2x00_dev *rt2x00dev) !test_bit(DRIVER_SUPPORT_WATCHDOG, &rt2x00dev->flags)) return; - ieee80211_queue_delayed_work(rt2x00dev->hw, - &link->watchdog_work, WATCHDOG_INTERVAL); + schedule_delayed_work(&link->watchdog_work, WATCHDOG_INTERVAL); } void rt2x00link_stop_watchdog(struct rt2x00_dev *rt2x00dev) @@ -442,8 +441,7 @@ static void rt2x00link_watchdog(struct work_struct *work) rt2x00dev->ops->lib->watchdog(rt2x00dev); if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) - ieee80211_queue_delayed_work(rt2x00dev->hw, - &link->watchdog_work, WATCHDOG_INTERVAL); + schedule_delayed_work(&link->watchdog_work, WATCHDOG_INTERVAL); } void rt2x00link_register(struct rt2x00_dev *rt2x00dev) From 3590eea41815679e268c90d30795a13a732b8413 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 11 Oct 2010 15:38:07 +0200 Subject: [PATCH 063/127] rt2x00: Validate MCS on RX path Similar to the PLCP signal and bitrates values, we should validate the MCS value from the RX descriptor before sending it to mac80211. Signed-off-by: Ivo van Doorn Acked-by: Helmut Schaa Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00dev.c | 70 +++++++++++++------------ 1 file changed, 36 insertions(+), 34 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 9b745faef0ed..db25209688fb 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -432,36 +432,44 @@ static int rt2x00lib_rxdone_read_signal(struct rt2x00_dev *rt2x00dev, struct ieee80211_supported_band *sband; const struct rt2x00_rate *rate; unsigned int i; - int signal; - int type; + int signal = rxdesc->signal; + int type = (rxdesc->dev_flags & RXDONE_SIGNAL_MASK); - /* - * For non-HT rates the MCS value needs to contain the - * actually used rate modulation (CCK or OFDM). - */ - if (rxdesc->dev_flags & RXDONE_SIGNAL_MCS) - signal = RATE_MCS(rxdesc->rate_mode, rxdesc->signal); - else - signal = rxdesc->signal; + switch (rxdesc->rate_mode) { + case RATE_MODE_CCK: + case RATE_MODE_OFDM: + /* + * For non-HT rates the MCS value needs to contain the + * actually used rate modulation (CCK or OFDM). + */ + if (rxdesc->dev_flags & RXDONE_SIGNAL_MCS) + signal = RATE_MCS(rxdesc->rate_mode, signal); - type = (rxdesc->dev_flags & RXDONE_SIGNAL_MASK); - - sband = &rt2x00dev->bands[rt2x00dev->curr_band]; - for (i = 0; i < sband->n_bitrates; i++) { - rate = rt2x00_get_rate(sband->bitrates[i].hw_value); - - if (((type == RXDONE_SIGNAL_PLCP) && - (rate->plcp == signal)) || - ((type == RXDONE_SIGNAL_BITRATE) && - (rate->bitrate == signal)) || - ((type == RXDONE_SIGNAL_MCS) && - (rate->mcs == signal))) { - return i; + sband = &rt2x00dev->bands[rt2x00dev->curr_band]; + for (i = 0; i < sband->n_bitrates; i++) { + rate = rt2x00_get_rate(sband->bitrates[i].hw_value); + if (((type == RXDONE_SIGNAL_PLCP) && + (rate->plcp == signal)) || + ((type == RXDONE_SIGNAL_BITRATE) && + (rate->bitrate == signal)) || + ((type == RXDONE_SIGNAL_MCS) && + (rate->mcs == signal))) { + return i; + } } + break; + case RATE_MODE_HT_MIX: + case RATE_MODE_HT_GREENFIELD: + if (signal >= 0 && signal <= 76) + return signal; + break; + default: + break; } WARNING(rt2x00dev, "Frame received with unrecognized signal, " - "signal=0x%.4x, type=%d.\n", signal, type); + "mode=0x%.4x, signal=0x%.4x, type=%d.\n", + rxdesc->rate_mode, signal, type); return 0; } @@ -523,18 +531,12 @@ void rt2x00lib_rxdone(struct queue_entry *entry) skb_trim(entry->skb, rxdesc.size); /* - * Check if the frame was received using HT. In that case, - * the rate is the MCS index and should be passed to mac80211 - * directly. Otherwise we need to translate the signal to - * the correct bitrate index. + * Translate the signal to the correct bitrate index. */ - if (rxdesc.rate_mode == RATE_MODE_CCK || - rxdesc.rate_mode == RATE_MODE_OFDM) { - rate_idx = rt2x00lib_rxdone_read_signal(rt2x00dev, &rxdesc); - } else { + rate_idx = rt2x00lib_rxdone_read_signal(rt2x00dev, &rxdesc); + if (rxdesc.rate_mode == RATE_MODE_HT_MIX || + rxdesc.rate_mode == RATE_MODE_HT_GREENFIELD) rxdesc.flags |= RX_FLAG_HT; - rate_idx = rxdesc.signal; - } /* * Update extra components From 1550c8ef835af17df322045e92541561afa0f017 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 11 Oct 2010 15:38:26 +0200 Subject: [PATCH 064/127] rt2x00: Fix dead queue when skb allocation failed When the RX skb allocation failed, we should recycle the previously allocated skbuffer. By calling return we would kill the RX queue completely since the entry would be invalidated. Signed-off-by: Ivo van Doorn Acked-by: Helmut Schaa Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index db25209688fb..e5e8ba3bf228 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -491,7 +491,7 @@ void rt2x00lib_rxdone(struct queue_entry *entry) */ skb = rt2x00queue_alloc_rxskb(entry); if (!skb) - return; + goto submit_entry; /* * Unmap the skb. From a1d1eabc8c42ddf5fd3ea4184094561b3edd127b Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 11 Oct 2010 15:38:45 +0200 Subject: [PATCH 065/127] rt2x00: Make queue_entry flags access atomic All access to the queue_entry->flags can be done concurrently, so all flags must use the atomic operators. On most locations this was already done, so just fix the last few non-atomic versions. Signed-off-by: Ivo van Doorn Acked-by: Helmut Schaa Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00usb.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 451d637377a2..769c53451b21 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -208,7 +208,7 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb) struct queue_entry *entry = (struct queue_entry *)urb->context; struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; - if (!__test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) + if (!test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) return; /* @@ -220,7 +220,7 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb) * Check if the frame was correctly uploaded */ if (urb->status) - __set_bit(ENTRY_DATA_IO_FAILED, &entry->flags); + set_bit(ENTRY_DATA_IO_FAILED, &entry->flags); /* * Schedule the delayed work for reading the TX status @@ -407,7 +407,7 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) struct queue_entry *entry = (struct queue_entry *)urb->context; struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; - if (!__test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) + if (!test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) return; /* @@ -421,7 +421,7 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) * a problem. */ if (urb->actual_length < entry->queue->desc_size || urb->status) - __set_bit(ENTRY_DATA_IO_FAILED, &entry->flags); + set_bit(ENTRY_DATA_IO_FAILED, &entry->flags); /* * Schedule the delayed work for reading the RX status From 1a397696536e896e7d763c0c38f3ae3e588b5d52 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 11 Oct 2010 15:39:04 +0200 Subject: [PATCH 066/127] rt2x00: Don't perform watchdog checks on empty queue The currently used watchdog functions cannot be applied to empty queues. Signed-off-by: Ivo van Doorn Acked-by: Helmut Schaa Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00usb.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 769c53451b21..89d77f55d76c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -363,10 +363,12 @@ void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev) struct data_queue *queue; tx_queue_for_each(rt2x00dev, queue) { - if (rt2x00queue_dma_timeout(queue)) - rt2x00usb_watchdog_tx_dma(queue); - if (rt2x00queue_timeout(queue)) - rt2x00usb_watchdog_tx_status(queue); + if (!rt2x00queue_empty(queue)) { + if (rt2x00queue_dma_timeout(queue)) + rt2x00usb_watchdog_tx_dma(queue); + if (rt2x00queue_timeout(queue)) + rt2x00usb_watchdog_tx_status(queue); + } } } EXPORT_SYMBOL_GPL(rt2x00usb_watchdog); From a13c8f3133b250e732c383b1c390d625e755db03 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 11 Oct 2010 15:39:48 +0200 Subject: [PATCH 067/127] rt2x00: Fix URB error handling kill_urb guarentees that when the function returns, the URB has been fully killed. This means we don't need the extra sleeping after the call to kill_urb. kill_urb can however also guarentee the submit_urb to fail, as a result, we must catch the return value from submit_urb an correctly mark the entry as owned by the driver, and the status as broken. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00dev.c | 1 + drivers/net/wireless/rt2x00/rt2x00usb.c | 18 ++++++++---------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index e5e8ba3bf228..5ba79b935f09 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -253,6 +253,7 @@ EXPORT_SYMBOL_GPL(rt2x00lib_pretbtt); void rt2x00lib_dmadone(struct queue_entry *entry) { + clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); rt2x00queue_index_inc(entry->queue, Q_INDEX_DMA_DONE); } EXPORT_SYMBOL_GPL(rt2x00lib_dmadone); diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 89d77f55d76c..b3317df7a7d4 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -253,7 +253,10 @@ static void rt2x00usb_kick_tx_entry(struct queue_entry *entry) entry->skb->data, length, rt2x00usb_interrupt_txdone, entry); - usb_submit_urb(entry_priv->urb, GFP_ATOMIC); + if (usb_submit_urb(entry_priv->urb, GFP_ATOMIC)) { + set_bit(ENTRY_DATA_IO_FAILED, &entry->flags); + rt2x00lib_dmadone(entry); + } } void rt2x00usb_kick_tx_queue(struct data_queue *queue) @@ -280,14 +283,6 @@ static void rt2x00usb_kill_tx_entry(struct queue_entry *entry) if ((entry->queue->qid == QID_BEACON) && (test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags))) usb_kill_urb(bcn_priv->guardian_urb); - - /* - * We need a short delay here to wait for - * the URB to be canceled - */ - do { - udelay(100); - } while (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)); } void rt2x00usb_kill_tx_queue(struct data_queue *queue) @@ -469,7 +464,10 @@ void rt2x00usb_clear_entry(struct queue_entry *entry) rt2x00usb_interrupt_rxdone, entry); set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); - usb_submit_urb(entry_priv->urb, GFP_ATOMIC); + if (usb_submit_urb(entry_priv->urb, GFP_ATOMIC)) { + set_bit(ENTRY_DATA_IO_FAILED, &entry->flags); + rt2x00lib_dmadone(entry); + } } } EXPORT_SYMBOL_GPL(rt2x00usb_clear_entry); From a5901cbb5783b25fa71536503bfa4617d8ee41bd Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Thu, 23 Sep 2010 09:56:51 -0700 Subject: [PATCH 068/127] iiwlagn: always download priority table For advance BT/WiFi co-exist, always download bt priority table before sending bt_config command Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index c4fe3f94c366..4470e8c80e9f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2835,8 +2835,7 @@ static void iwl_alive_start(struct iwl_priv *priv) priv->kill_cts_mask = IWLAGN_BT_KILL_CTS_MASK_DEFAULT; priv->cfg->ops->hcmd->send_bt_config(priv); priv->bt_valid = IWLAGN_BT_VALID_ENABLE_FLAGS; - if (bt_coex_active && priv->iw_mode != NL80211_IFTYPE_ADHOC) - iwlagn_send_prio_tbl(priv); + iwlagn_send_prio_tbl(priv); /* FIXME: w/a to force change uCode BT state machine */ iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN, From bc795df1d225415c2ec6ff2a81c07a753681d945 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Mon, 11 Oct 2010 14:24:05 -0700 Subject: [PATCH 069/127] iwlagn: prio_tbl need to download before calibration For WiFi/BT combo devices, priority table always need to download before perform any calibration operation. Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 4470e8c80e9f..6771c404fa73 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2809,9 +2809,6 @@ static void iwl_alive_start(struct iwl_priv *priv) goto restart; } - if (priv->hw_params.calib_rt_cfg) - iwlagn_send_calib_cfg_rt(priv, priv->hw_params.calib_rt_cfg); - /* After the ALIVE response, we can send host commands to the uCode */ set_bit(STATUS_ALIVE, &priv->status); @@ -2827,6 +2824,7 @@ static void iwl_alive_start(struct iwl_priv *priv) if (iwl_is_rfkill(priv)) return; + /* download priority table before any calibration request */ if (priv->cfg->bt_params && priv->cfg->bt_params->advanced_bt_coexist) { /* Configure Bluetooth device coexistence support */ @@ -2843,6 +2841,9 @@ static void iwl_alive_start(struct iwl_priv *priv) iwlagn_send_bt_env(priv, IWL_BT_COEX_ENV_CLOSE, BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); } + if (priv->hw_params.calib_rt_cfg) + iwlagn_send_calib_cfg_rt(priv, priv->hw_params.calib_rt_cfg); + ieee80211_wake_queues(priv->hw); priv->active_rate = IWL_RATES_MASK; From fd74d065f43f88eedc7492886d84f0accb683653 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 12 Oct 2010 02:26:13 -0700 Subject: [PATCH 070/127] iwl3945: fix queue allocation commit 6f98613258b966ffe0e6def18129b386514d10e0 Author: Jay Sternberg Date: Sat Sep 18 09:07:04 2010 -0700 iwlagn: reduce redundant parameter definitions broke 3945 because Jay accidentally removed the num_of_queues parameter for 3945, so that we now attempt to allocate a zero-sized queue array, which leads to SLUB returning ZERO_SIZE_PTR (0x10) which we then try to dereference thus crashing the system. Restore the necessary num_of_queues param. This fixes http://bugzilla.intellinuxwireless.org/show_bug.cgi?id=2254 Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-3945.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 7d74ae53950c..176e52577673 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -2753,6 +2753,7 @@ static const struct iwl_ops iwl3945_ops = { static struct iwl_base_params iwl3945_base_params = { .eeprom_size = IWL3945_EEPROM_IMG_SIZE, + .num_of_queues = IWL39_NUM_QUEUES, .pll_cfg_val = CSR39_ANA_PLL_CFG_VAL, .set_l0s = false, .use_bsm = true, From 8f1e1742233cd1c3444dfc6c945a2efb2814e157 Mon Sep 17 00:00:00 2001 From: David Vrabel Date: Mon, 9 Aug 2010 17:38:10 -0400 Subject: [PATCH 071/127] Bluetooth: HCI devices are either BR/EDR or AMP radios HCI transport drivers may not know what type of radio an AMP device has so only say whether they're BR/EDR or AMP devices. Signed-off-by: David Vrabel Signed-off-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- drivers/bluetooth/btmrvl_main.c | 4 ++-- include/net/bluetooth/hci.h | 2 +- net/bluetooth/hci_sysfs.c | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c index 0d32ec82e9bf..548d1d9e4dda 100644 --- a/drivers/bluetooth/btmrvl_main.c +++ b/drivers/bluetooth/btmrvl_main.c @@ -117,8 +117,8 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb) (event->data[2] == MODULE_ALREADY_UP)) ? "Bring-up succeed" : "Bring-up failed"); - if (event->length > 3) - priv->btmrvl_dev.dev_type = event->data[3]; + if (event->length > 3 && event->data[3]) + priv->btmrvl_dev.dev_type = HCI_AMP; else priv->btmrvl_dev.dev_type = HCI_BREDR; diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index bcbdd6d4e6dd..e30e00834340 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -54,7 +54,7 @@ /* HCI controller types */ #define HCI_BREDR 0x00 -#define HCI_80211 0x01 +#define HCI_AMP 0x01 /* HCI device quirks */ enum { diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index 8fb967beee80..1a9f0db027da 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c @@ -196,8 +196,8 @@ static inline char *host_typetostr(int type) switch (type) { case HCI_BREDR: return "BR/EDR"; - case HCI_80211: - return "802.11"; + case HCI_AMP: + return "AMP"; default: return "UNKNOWN"; } From fb3d8eb47ce377d6d7a8fc58b8046ea9eb376a28 Mon Sep 17 00:00:00 2001 From: David Vrabel Date: Mon, 9 Aug 2010 17:42:21 -0400 Subject: [PATCH 072/127] Bluetooth: Support SDIO devices that are AMP controllers Signed-off-by: David Vrabel Signed-off-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- drivers/bluetooth/btsdio.c | 8 ++++++++ include/linux/mmc/sdio_ids.h | 1 + 2 files changed, 9 insertions(+) diff --git a/drivers/bluetooth/btsdio.c b/drivers/bluetooth/btsdio.c index 76e5127884f0..792e32d29a1d 100644 --- a/drivers/bluetooth/btsdio.c +++ b/drivers/bluetooth/btsdio.c @@ -46,6 +46,9 @@ static const struct sdio_device_id btsdio_table[] = { /* Generic Bluetooth Type-B SDIO device */ { SDIO_DEVICE_CLASS(SDIO_CLASS_BT_B) }, + /* Generic Bluetooth AMP controller */ + { SDIO_DEVICE_CLASS(SDIO_CLASS_BT_AMP) }, + { } /* Terminating entry */ }; @@ -329,6 +332,11 @@ static int btsdio_probe(struct sdio_func *func, hdev->bus = HCI_SDIO; hdev->driver_data = data; + if (id->class == SDIO_CLASS_BT_AMP) + hdev->dev_type = HCI_AMP; + else + hdev->dev_type = HCI_BREDR; + data->hdev = hdev; SET_HCIDEV_DEV(hdev, &func->dev); diff --git a/include/linux/mmc/sdio_ids.h b/include/linux/mmc/sdio_ids.h index 33b2ea09a4ad..a36ab3bc7b03 100644 --- a/include/linux/mmc/sdio_ids.h +++ b/include/linux/mmc/sdio_ids.h @@ -18,6 +18,7 @@ #define SDIO_CLASS_PHS 0x06 /* PHS standard interface */ #define SDIO_CLASS_WLAN 0x07 /* WLAN interface */ #define SDIO_CLASS_ATA 0x08 /* Embedded SDIO-ATA std interface */ +#define SDIO_CLASS_BT_AMP 0x09 /* Type-A Bluetooth AMP interface */ /* * Vendors and devices. Sort key: vendor first, device next. From 08601469a5aac8b3453d8aca0b8f9bd8dfdae12c Mon Sep 17 00:00:00 2001 From: Yuri Kululin Date: Fri, 23 Jul 2010 13:57:12 +0400 Subject: [PATCH 073/127] Bluetooth: Fix RFCOMM RPN negotiation According to the ETSI 3GPP TS 07.10 the default bit rate value for RFCOMM is 9600 bit/s. Return this bit rate in case of RPN request and accept other sane bit rates proposed by the sender in RPM command. Signed-off-by: Yuri Kululin Signed-off-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- net/bluetooth/rfcomm/core.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 15ea84ba344e..b464843ed79e 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -1415,8 +1415,8 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_ return 0; if (len == 1) { - /* This is a request, return default settings */ - bit_rate = RFCOMM_RPN_BR_115200; + /* This is a request, return default (according to ETSI TS 07.10) settings */ + bit_rate = RFCOMM_RPN_BR_9600; data_bits = RFCOMM_RPN_DATA_8; stop_bits = RFCOMM_RPN_STOP_1; parity = RFCOMM_RPN_PARITY_NONE; @@ -1431,9 +1431,9 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_ if (rpn->param_mask & cpu_to_le16(RFCOMM_RPN_PM_BITRATE)) { bit_rate = rpn->bit_rate; - if (bit_rate != RFCOMM_RPN_BR_115200) { + if (bit_rate > RFCOMM_RPN_BR_230400) { BT_DBG("RPN bit rate mismatch 0x%x", bit_rate); - bit_rate = RFCOMM_RPN_BR_115200; + bit_rate = RFCOMM_RPN_BR_9600; rpn_mask ^= RFCOMM_RPN_PM_BITRATE; } } From 0fba2558cbb3fae3a09147b7d6e18a6204204e0e Mon Sep 17 00:00:00 2001 From: Mat Martineau Date: Wed, 8 Sep 2010 10:05:26 -0700 Subject: [PATCH 074/127] Bluetooth: Validate PSM values in calls to connect() and bind() Valid L2CAP PSMs are odd numbers, and the least significant bit of the most significant byte must be 0. Signed-off-by: Mat Martineau Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- net/bluetooth/l2cap.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 0b54b7dd8401..2f625b87a89e 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -1008,10 +1008,20 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) goto done; } - if (la.l2_psm && __le16_to_cpu(la.l2_psm) < 0x1001 && - !capable(CAP_NET_BIND_SERVICE)) { - err = -EACCES; - goto done; + if (la.l2_psm) { + __u16 psm = __le16_to_cpu(la.l2_psm); + + /* PSM must be odd and lsb of upper byte must be 0 */ + if ((psm & 0x0101) != 0x0001) { + err = -EINVAL; + goto done; + } + + /* Restrict usage of well-known PSMs */ + if (psm < 0x1001 && !capable(CAP_NET_BIND_SERVICE)) { + err = -EACCES; + goto done; + } } write_lock_bh(&l2cap_sk_list.lock); @@ -1190,6 +1200,13 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al goto done; } + /* PSM must be odd and lsb of upper byte must be 0 */ + if ((__le16_to_cpu(la.l2_psm) & 0x0101) != 0x0001 && + sk->sk_type != SOCK_RAW) { + err = -EINVAL; + goto done; + } + /* Set destination address and psm */ bacpy(&bt_sk(sk)->dst, &la.l2_bdaddr); l2cap_pi(sk)->psm = la.l2_psm; From 796c86eec84ddfd02281c5071838ed1fefda6b90 Mon Sep 17 00:00:00 2001 From: Mat Martineau Date: Wed, 8 Sep 2010 10:05:27 -0700 Subject: [PATCH 075/127] Bluetooth: Add common code for stream-oriented recvmsg() This commit adds a bt_sock_stream_recvmsg() function for use by any Bluetooth code that uses SOCK_STREAM sockets. This code is copied from rfcomm_sock_recvmsg() with minimal modifications to remove RFCOMM-specific functionality and improve readability. L2CAP (with the SOCK_STREAM socket type) and RFCOMM have common needs when it comes to reading data. Proper stream read semantics require that applications can read from a stream one byte at a time and not lose any data. The RFCOMM code already operated on and pulled data from the underlying L2CAP socket, so very few changes were required to make the code more generic for use with non-RFCOMM data over L2CAP. Applications that need more awareness of L2CAP frame boundaries are still free to use SOCK_SEQPACKET sockets, and may verify that they connection did not fall back to basic mode by calling getsockopt(). Signed-off-by: Mat Martineau Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/bluetooth.h | 2 + net/bluetooth/af_bluetooth.c | 109 ++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+) diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index 30fce0128dd7..d81ea7997701 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h @@ -126,6 +126,8 @@ int bt_sock_unregister(int proto); void bt_sock_link(struct bt_sock_list *l, struct sock *s); void bt_sock_unlink(struct bt_sock_list *l, struct sock *s); int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len, int flags); +int bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock, + struct msghdr *msg, size_t len, int flags); uint bt_sock_poll(struct file * file, struct socket *sock, poll_table *wait); int bt_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg); int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo); diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index ed0f22f57668..c4cf3f595004 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c @@ -265,6 +265,115 @@ int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, } EXPORT_SYMBOL(bt_sock_recvmsg); +static long bt_sock_data_wait(struct sock *sk, long timeo) +{ + DECLARE_WAITQUEUE(wait, current); + + add_wait_queue(sk_sleep(sk), &wait); + for (;;) { + set_current_state(TASK_INTERRUPTIBLE); + + if (!skb_queue_empty(&sk->sk_receive_queue)) + break; + + if (sk->sk_err || (sk->sk_shutdown & RCV_SHUTDOWN)) + break; + + if (signal_pending(current) || !timeo) + break; + + set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); + release_sock(sk); + timeo = schedule_timeout(timeo); + lock_sock(sk); + clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); + } + + __set_current_state(TASK_RUNNING); + remove_wait_queue(sk_sleep(sk), &wait); + return timeo; +} + +int bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock, + struct msghdr *msg, size_t size, int flags) +{ + struct sock *sk = sock->sk; + int err = 0; + size_t target, copied = 0; + long timeo; + + if (flags & MSG_OOB) + return -EOPNOTSUPP; + + msg->msg_namelen = 0; + + BT_DBG("sk %p size %zu", sk, size); + + lock_sock(sk); + + target = sock_rcvlowat(sk, flags & MSG_WAITALL, size); + timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); + + do { + struct sk_buff *skb; + int chunk; + + skb = skb_dequeue(&sk->sk_receive_queue); + if (!skb) { + if (copied >= target) + break; + + if ((err = sock_error(sk)) != 0) + break; + if (sk->sk_shutdown & RCV_SHUTDOWN) + break; + + err = -EAGAIN; + if (!timeo) + break; + + timeo = bt_sock_data_wait(sk, timeo); + + if (signal_pending(current)) { + err = sock_intr_errno(timeo); + goto out; + } + continue; + } + + chunk = min_t(unsigned int, skb->len, size); + if (memcpy_toiovec(msg->msg_iov, skb->data, chunk)) { + skb_queue_head(&sk->sk_receive_queue, skb); + if (!copied) + copied = -EFAULT; + break; + } + copied += chunk; + size -= chunk; + + sock_recv_ts_and_drops(msg, sk, skb); + + if (!(flags & MSG_PEEK)) { + skb_pull(skb, chunk); + if (skb->len) { + skb_queue_head(&sk->sk_receive_queue, skb); + break; + } + kfree_skb(skb); + + } else { + /* put message back and return */ + skb_queue_head(&sk->sk_receive_queue, skb); + break; + } + } while (size); + +out: + release_sock(sk); + return copied ? : err; +} +EXPORT_SYMBOL(bt_sock_stream_recvmsg); + static inline unsigned int bt_accept_poll(struct sock *parent) { struct list_head *p, *n; From 3d7d01dffec4a6757ed1e3182f01c7ef5caa2539 Mon Sep 17 00:00:00 2001 From: Mat Martineau Date: Wed, 8 Sep 2010 10:05:28 -0700 Subject: [PATCH 076/127] Bluetooth: Use common SOCK_STREAM receive code in RFCOMM To reduce code duplication, have rfcomm_sock_recvmsg() call bt_sock_stream_recvmsg(). The common bt_sock_stream_recvmsg() code is nearly identical, with the RFCOMM-specific functionality for deferred setup and connection unthrottling left in rfcomm_sock_recvmsg(). Signed-off-by: Mat Martineau Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- net/bluetooth/rfcomm/sock.c | 104 +++--------------------------------- 1 file changed, 6 insertions(+), 98 deletions(-) diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 194b3a04cfd3..aec505f934df 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c @@ -621,121 +621,29 @@ static int rfcomm_sock_sendmsg(struct kiocb *iocb, struct socket *sock, return sent; } -static long rfcomm_sock_data_wait(struct sock *sk, long timeo) -{ - DECLARE_WAITQUEUE(wait, current); - - add_wait_queue(sk_sleep(sk), &wait); - for (;;) { - set_current_state(TASK_INTERRUPTIBLE); - - if (!skb_queue_empty(&sk->sk_receive_queue) || - sk->sk_err || - (sk->sk_shutdown & RCV_SHUTDOWN) || - signal_pending(current) || - !timeo) - break; - - set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); - release_sock(sk); - timeo = schedule_timeout(timeo); - lock_sock(sk); - clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); - } - - __set_current_state(TASK_RUNNING); - remove_wait_queue(sk_sleep(sk), &wait); - return timeo; -} - static int rfcomm_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t size, int flags) { struct sock *sk = sock->sk; struct rfcomm_dlc *d = rfcomm_pi(sk)->dlc; - int err = 0; - size_t target, copied = 0; - long timeo; + int len; if (test_and_clear_bit(RFCOMM_DEFER_SETUP, &d->flags)) { rfcomm_dlc_accept(d); return 0; } - if (flags & MSG_OOB) - return -EOPNOTSUPP; - - msg->msg_namelen = 0; - - BT_DBG("sk %p size %zu", sk, size); + len = bt_sock_stream_recvmsg(iocb, sock, msg, size, flags); lock_sock(sk); + if (!(flags & MSG_PEEK) && len > 0) + atomic_sub(len, &sk->sk_rmem_alloc); - target = sock_rcvlowat(sk, flags & MSG_WAITALL, size); - timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); - - do { - struct sk_buff *skb; - int chunk; - - skb = skb_dequeue(&sk->sk_receive_queue); - if (!skb) { - if (copied >= target) - break; - - if ((err = sock_error(sk)) != 0) - break; - if (sk->sk_shutdown & RCV_SHUTDOWN) - break; - - err = -EAGAIN; - if (!timeo) - break; - - timeo = rfcomm_sock_data_wait(sk, timeo); - - if (signal_pending(current)) { - err = sock_intr_errno(timeo); - goto out; - } - continue; - } - - chunk = min_t(unsigned int, skb->len, size); - if (memcpy_toiovec(msg->msg_iov, skb->data, chunk)) { - skb_queue_head(&sk->sk_receive_queue, skb); - if (!copied) - copied = -EFAULT; - break; - } - copied += chunk; - size -= chunk; - - sock_recv_ts_and_drops(msg, sk, skb); - - if (!(flags & MSG_PEEK)) { - atomic_sub(chunk, &sk->sk_rmem_alloc); - - skb_pull(skb, chunk); - if (skb->len) { - skb_queue_head(&sk->sk_receive_queue, skb); - break; - } - kfree_skb(skb); - - } else { - /* put message back and return */ - skb_queue_head(&sk->sk_receive_queue, skb); - break; - } - } while (size); - -out: if (atomic_read(&sk->sk_rmem_alloc) <= (sk->sk_rcvbuf >> 2)) rfcomm_dlc_unthrottle(rfcomm_pi(sk)->dlc); - release_sock(sk); - return copied ? : err; + + return len; } static int rfcomm_sock_setsockopt_old(struct socket *sock, int optname, char __user *optval, unsigned int optlen) From 6fdf482bb3298267816be59d9a3dce29632382d3 Mon Sep 17 00:00:00 2001 From: Mat Martineau Date: Wed, 8 Sep 2010 10:05:29 -0700 Subject: [PATCH 077/127] Bluetooth: Use a stream-oriented recvmsg with SOCK_STREAM L2CAP sockets. L2CAP ERTM sockets can be opened with the SOCK_STREAM socket type, which is a mandatory request for ERTM mode. However, these sockets still have SOCK_SEQPACKET read semantics when bt_sock_recvmsg() is used to pull data from the receive queue. If the application is only reading part of a frame, then the unread portion of the frame is discarded. If the application requests more bytes than are in the current frame, only the current frame's data is returned. This patch utilizes common code derived from RFCOMM's recvmsg() function to make L2CAP SOCK_STREAM reads behave like RFCOMM reads (and other SOCK_STREAM sockets in general). The application may read one byte at a time from the input stream and not lose any data, and may also read across L2CAP frame boundaries. Signed-off-by: Mat Martineau Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- net/bluetooth/l2cap.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 2f625b87a89e..a9e7470d3cea 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -1951,6 +1951,9 @@ static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct ms release_sock(sk); + if (sock->type == SOCK_STREAM) + return bt_sock_stream_recvmsg(iocb, sock, msg, len, flags); + return bt_sock_recvmsg(iocb, sock, msg, len, flags); } From 5017d8dde13313cab1e607379536a7930ed682b0 Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Wed, 8 Sep 2010 16:26:53 +0300 Subject: [PATCH 078/127] Bluetooth: remove extra newline from debug output Signed-off-by: Andrei Emeltchenko Acked-by: Ville Tervo Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- net/bluetooth/rfcomm/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index b464843ed79e..4a22b14a2c60 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -1698,7 +1698,7 @@ static int rfcomm_recv_frame(struct rfcomm_session *s, struct sk_buff *skb) break; default: - BT_ERR("Unknown packet type 0x%02x\n", type); + BT_ERR("Unknown packet type 0x%02x", type); break; } kfree_skb(skb); From 80e2c88803c72747cb19febe2ad708bf0ad557bf Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 9 Sep 2010 10:32:39 +0300 Subject: [PATCH 079/127] Bluetooth: Don't clear the blacklist when closing the HCI device Clearing the blacklist in hci_dev_do_close() would mean that user space needs to do extra work to re-block devices after a DEVDOWN-DEVUP cycle. This patch removes the clearing of the blacklist in this case and thereby saves user space from the extra work. Signed-off-by: Johan Hedberg Acked-by: Ville Tervo Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- net/bluetooth/hci_core.c | 1 - 1 file changed, 1 deletion(-) diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index c52f091ee6de..bc2a052e518b 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -562,7 +562,6 @@ static int hci_dev_do_close(struct hci_dev *hdev) hci_dev_lock_bh(hdev); inquiry_cache_flush(hdev); hci_conn_hash_flush(hdev); - hci_blacklist_clear(hdev); hci_dev_unlock_bh(hdev); hci_notify(hdev, HCI_DEV_DOWN); From 9c047157a20521cd525527947b13b950d168d2e6 Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Fri, 20 Aug 2010 16:24:06 +0900 Subject: [PATCH 080/127] Bluetooth: Add support Bluetooth controller of MacbookPro 6,2 Bluetooth controller of MacbookPro 6,2 does not work. Because Device Class of these controllers was set 255 (Vendor Sepecific Class). T: Bus=01 Lev=03 Prnt=03 Port=02 Cnt=03 Dev#= 8 Spd=12 MxCh= 0 D: Ver= 2.00 Cls=ff(vend.) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 P: Vendor=05ac ProdID=8218 Rev=00.22 S: Manufacturer=Apple Inc. S: Product=Bluetooth USB Host Controller C: #Ifs= 4 Cfg#= 1 Atr=e0 MxPwr=0mA I: If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=01 Prot=01 Driver=(none) I: If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=(none) I: If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) I: If#= 3 Alt= 0 #EPs= 0 Cls=fe(app. ) Sub=01 Prot=01 Driver=(none) Signed-off-by: Nobuhiro Iwamatsu Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- drivers/bluetooth/btusb.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index d22ce3cc611e..d1bb809512fa 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -62,6 +62,9 @@ static struct usb_device_id btusb_table[] = { /* Apple iMac11,1 */ { USB_DEVICE(0x05ac, 0x8215) }, + /* Apple MacBookPro6,2 */ + { USB_DEVICE(0x05ac, 0x8218) }, + /* AVM BlueFRITZ! USB v2.0 */ { USB_DEVICE(0x057c, 0x3800) }, From 3cd01976e702ccaffb907727caff4f8789353599 Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Fri, 20 Aug 2010 16:24:07 +0900 Subject: [PATCH 081/127] Bluetooth: Add support Bluetooth controller of MacbookPro 7,1 Bluetooth controller of MacbookPro 7,1 does not work. Because Device Class of these controllers was set 255 (Vendor Sepecific Class). T: Bus=04 Lev=02 Prnt=04 Port=00 Cnt=01 Dev#= 5 Spd=12 MxCh= 0 D: Ver= 2.00 Cls=ff(vend.) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 P: Vendor=05ac ProdID=8213 Rev=01.86 S: Manufacturer=Apple Inc. S: Product=Bluetooth USB Host Controller S: SerialNumber=5C5948C81B99 C: #Ifs= 4 Cfg#= 1 Atr=e0 MxPwr=0mA I: If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=01 Prot=01 Driver=btusb I: If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb I: If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) I: If#= 3 Alt= 0 #EPs= 0 Cls=fe(app. ) Sub=01 Prot=00 Driver=(none) Signed-off-by: Nobuhiro Iwamatsu Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- drivers/bluetooth/btusb.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index d1bb809512fa..d120a5c1c093 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -59,6 +59,9 @@ static struct usb_device_id btusb_table[] = { /* Generic Bluetooth USB device */ { USB_DEVICE_INFO(0xe0, 0x01, 0x01) }, + /* Apple MacBookPro 7,1 */ + { USB_DEVICE(0x05ac, 0x8213) }, + /* Apple iMac11,1 */ { USB_DEVICE(0x05ac, 0x8215) }, From 8979481328dc2e14cea9f99b3562ffcf8655998e Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Wed, 15 Sep 2010 14:28:44 +0300 Subject: [PATCH 082/127] Bluetooth: check L2CAP length in first ACL fragment Current Bluetooth code assembles fragments of big L2CAP packets in l2cap_recv_acldata and then checks allowed L2CAP size in assemled L2CAP packet (pi->imtu < skb->len). The patch moves allowed L2CAP size check to the early stage when we receive the first fragment of L2CAP packet. We do not need to reserve and keep L2CAP fragments for bad packets. Updated version after comments from Mat Martineau and Gustavo Padovan . Trace below is received when using stress tools sending big fragmented L2CAP packets. ... [ 1712.798492] swapper: page allocation failure. order:4, mode:0x4020 [ 1712.804809] [] (unwind_backtrace+0x0/0xdc) from [] (__alloc_pages_nodemask+0x4) [ 1712.814666] [] (__alloc_pages_nodemask+0x47c/0x4d4) from [] (__get_free_pages+) [ 1712.824645] [] (__get_free_pages+0x10/0x3c) from [] (__alloc_skb+0x4c/0xfc) [ 1712.833465] [] (__alloc_skb+0x4c/0xfc) from [] (l2cap_recv_acldata+0xf0/0x1f8 ) [ 1712.843322] [] (l2cap_recv_acldata+0xf0/0x1f8 [l2cap]) from [] (hci_rx_task+0x) ... Signed-off-by: Andrei Emeltchenko Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- net/bluetooth/l2cap.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index a9e7470d3cea..5441083ff1ca 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -4663,6 +4663,8 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl if (flags & ACL_START) { struct l2cap_hdr *hdr; + struct sock *sk; + u16 cid; int len; if (conn->rx_len) { @@ -4681,6 +4683,7 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl hdr = (struct l2cap_hdr *) skb->data; len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE; + cid = __le16_to_cpu(hdr->cid); if (len == skb->len) { /* Complete frame received */ @@ -4697,6 +4700,19 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl goto drop; } + sk = l2cap_get_chan_by_scid(&conn->chan_list, cid); + + if (sk && l2cap_pi(sk)->imtu < len - L2CAP_HDR_SIZE) { + BT_ERR("Frame exceeding recv MTU (len %d, MTU %d)", + len, l2cap_pi(sk)->imtu); + bh_unlock_sock(sk); + l2cap_conn_unreliable(conn, ECOMM); + goto drop; + } + + if (sk) + bh_unlock_sock(sk); + /* Allocate skb for the complete frame (with header) */ conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC); if (!conn->rx_skb) From aae7fe22a875a84e328469e228cba033ebbf20cb Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Wed, 15 Sep 2010 14:28:43 +0300 Subject: [PATCH 083/127] Bluetooth: check for l2cap header in start fragment BLUETOOTH SPECIFICATION Version 4.0 [Vol 3] page 36 mentioned "Note: Start Fragments always begin with the Basic L2CAP header of a PDU." Signed-off-by: Andrei Emeltchenko Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- net/bluetooth/l2cap.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 5441083ff1ca..7da6432f6799 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -4675,7 +4675,8 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl l2cap_conn_unreliable(conn, ECOMM); } - if (skb->len < 2) { + /* Start fragment always begin with Basic L2CAP header */ + if (skb->len < L2CAP_HDR_SIZE) { BT_ERR("Frame is too short (len %d)", skb->len); l2cap_conn_unreliable(conn, ECOMM); goto drop; From cb810a189da312d4074cb3fc8b0267b7115e7be1 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Fri, 3 Sep 2010 17:51:57 -0300 Subject: [PATCH 084/127] Bluetooth: remove unused variable from cmtp A value was attributed to 'src', but no one was using. Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- net/bluetooth/cmtp/core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/bluetooth/cmtp/core.c b/net/bluetooth/cmtp/core.c index d4c6af082d48..d4616060a196 100644 --- a/net/bluetooth/cmtp/core.c +++ b/net/bluetooth/cmtp/core.c @@ -321,12 +321,11 @@ static int cmtp_session(void *arg) int cmtp_add_connection(struct cmtp_connadd_req *req, struct socket *sock) { struct cmtp_session *session, *s; - bdaddr_t src, dst; + bdaddr_t dst; int i, err; BT_DBG(""); - baswap(&src, &bt_sk(sock->sk)->src); baswap(&dst, &bt_sk(sock->sk)->dst); session = kzalloc(sizeof(struct cmtp_session), GFP_KERNEL); From d6b2eb2f893547d7488d31a7088d78dd77ab5995 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Fri, 3 Sep 2010 18:29:46 -0300 Subject: [PATCH 085/127] Bluetooth: make batostr() print in the right order The Bluetooth core uses the the BD_ADDR in the opposite order from the human readable order. So we are changing batostr() to print in the correct order and then removing some baswap(), as they are not needed anymore. Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- net/bluetooth/cmtp/core.c | 5 +---- net/bluetooth/hci_sysfs.c | 17 ++++------------- net/bluetooth/hidp/core.c | 8 ++------ net/bluetooth/lib.c | 4 ++-- net/bluetooth/rfcomm/tty.c | 4 +--- 5 files changed, 10 insertions(+), 28 deletions(-) diff --git a/net/bluetooth/cmtp/core.c b/net/bluetooth/cmtp/core.c index d4616060a196..ec0a1347f933 100644 --- a/net/bluetooth/cmtp/core.c +++ b/net/bluetooth/cmtp/core.c @@ -321,13 +321,10 @@ static int cmtp_session(void *arg) int cmtp_add_connection(struct cmtp_connadd_req *req, struct socket *sock) { struct cmtp_session *session, *s; - bdaddr_t dst; int i, err; BT_DBG(""); - baswap(&dst, &bt_sk(sock->sk)->dst); - session = kzalloc(sizeof(struct cmtp_session), GFP_KERNEL); if (!session) return -ENOMEM; @@ -346,7 +343,7 @@ int cmtp_add_connection(struct cmtp_connadd_req *req, struct socket *sock) BT_DBG("mtu %d", session->mtu); - sprintf(session->name, "%s", batostr(&dst)); + sprintf(session->name, "%s", batostr(&bt_sk(sock->sk)->dst)); session->sock = sock; session->state = BT_CONFIG; diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index 1a9f0db027da..5fce3d6d07b4 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c @@ -37,9 +37,7 @@ static ssize_t show_link_type(struct device *dev, struct device_attribute *attr, static ssize_t show_link_address(struct device *dev, struct device_attribute *attr, char *buf) { struct hci_conn *conn = dev_get_drvdata(dev); - bdaddr_t bdaddr; - baswap(&bdaddr, &conn->dst); - return sprintf(buf, "%s\n", batostr(&bdaddr)); + return sprintf(buf, "%s\n", batostr(&conn->dst)); } static ssize_t show_link_features(struct device *dev, struct device_attribute *attr, char *buf) @@ -238,9 +236,7 @@ static ssize_t show_class(struct device *dev, struct device_attribute *attr, cha static ssize_t show_address(struct device *dev, struct device_attribute *attr, char *buf) { struct hci_dev *hdev = dev_get_drvdata(dev); - bdaddr_t bdaddr; - baswap(&bdaddr, &hdev->bdaddr); - return sprintf(buf, "%s\n", batostr(&bdaddr)); + return sprintf(buf, "%s\n", batostr(&hdev->bdaddr)); } static ssize_t show_features(struct device *dev, struct device_attribute *attr, char *buf) @@ -408,10 +404,8 @@ static int inquiry_cache_show(struct seq_file *f, void *p) for (e = cache->list; e; e = e->next) { struct inquiry_data *data = &e->data; - bdaddr_t bdaddr; - baswap(&bdaddr, &data->bdaddr); seq_printf(f, "%s %d %d %d 0x%.2x%.2x%.2x 0x%.4x %d %d %u\n", - batostr(&bdaddr), + batostr(&data->bdaddr), data->pscan_rep_mode, data->pscan_period_mode, data->pscan_mode, data->dev_class[2], data->dev_class[1], data->dev_class[0], @@ -445,13 +439,10 @@ static int blacklist_show(struct seq_file *f, void *p) list_for_each(l, &hdev->blacklist) { struct bdaddr_list *b; - bdaddr_t bdaddr; b = list_entry(l, struct bdaddr_list, list); - baswap(&bdaddr, &b->bdaddr); - - seq_printf(f, "%s\n", batostr(&bdaddr)); + seq_printf(f, "%s\n", batostr(&b->bdaddr)); } hci_dev_unlock_bh(hdev); diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index bfe641b7dfaf..c0ee8b3928ed 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c @@ -758,7 +758,6 @@ static int hidp_setup_hid(struct hidp_session *session, struct hidp_connadd_req *req) { struct hid_device *hid; - bdaddr_t src, dst; int err; session->rd_data = kzalloc(req->rd_size, GFP_KERNEL); @@ -781,9 +780,6 @@ static int hidp_setup_hid(struct hidp_session *session, hid->driver_data = session; - baswap(&src, &bt_sk(session->ctrl_sock->sk)->src); - baswap(&dst, &bt_sk(session->ctrl_sock->sk)->dst); - hid->bus = BUS_BLUETOOTH; hid->vendor = req->vendor; hid->product = req->product; @@ -791,8 +787,8 @@ static int hidp_setup_hid(struct hidp_session *session, hid->country = req->country; strncpy(hid->name, req->name, 128); - strncpy(hid->phys, batostr(&src), 64); - strncpy(hid->uniq, batostr(&dst), 64); + strncpy(hid->phys, batostr(&bt_sk(session->ctrl_sock->sk)->src), 64); + strncpy(hid->uniq, batostr(&bt_sk(session->ctrl_sock->sk)->dst), 64); hid->dev.parent = hidp_get_device(session); hid->ll_driver = &hidp_hid_driver; diff --git a/net/bluetooth/lib.c b/net/bluetooth/lib.c index ad2af5814e40..b826d1bf10df 100644 --- a/net/bluetooth/lib.c +++ b/net/bluetooth/lib.c @@ -51,8 +51,8 @@ char *batostr(bdaddr_t *ba) i ^= 1; sprintf(str[i], "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X", - ba->b[0], ba->b[1], ba->b[2], - ba->b[3], ba->b[4], ba->b[5]); + ba->b[5], ba->b[4], ba->b[3], + ba->b[2], ba->b[1], ba->b[0]); return str[i]; } diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index befc3a52aa04..26461639f133 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c @@ -183,9 +183,7 @@ static struct device *rfcomm_get_device(struct rfcomm_dev *dev) static ssize_t show_address(struct device *tty_dev, struct device_attribute *attr, char *buf) { struct rfcomm_dev *dev = dev_get_drvdata(tty_dev); - bdaddr_t bdaddr; - baswap(&bdaddr, &dev->dst); - return sprintf(buf, "%s\n", batostr(&bdaddr)); + return sprintf(buf, "%s\n", batostr(&dev->dst)); } static ssize_t show_channel(struct device *tty_dev, struct device_attribute *attr, char *buf) From 0175d629e096a5a59dde6cc91b32ac3160a44b9e Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Fri, 24 Sep 2010 20:30:57 -0300 Subject: [PATCH 086/127] Bluetooth: Use the proper error value from bt_skb_send_alloc() &err points to the proper error set by bt_skb_send_alloc() when it fails. Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- net/bluetooth/l2cap.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 7da6432f6799..01c476239dd6 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -1652,7 +1652,7 @@ static inline int l2cap_skbuff_fromiovec(struct sock *sk, struct msghdr *msg, in *frag = bt_skb_send_alloc(sk, count, msg->msg_flags & MSG_DONTWAIT, &err); if (!*frag) - return -EFAULT; + return err; if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count)) return -EFAULT; @@ -1678,7 +1678,7 @@ static struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr skb = bt_skb_send_alloc(sk, count + hlen, msg->msg_flags & MSG_DONTWAIT, &err); if (!skb) - return ERR_PTR(-ENOMEM); + return ERR_PTR(err); /* Create L2CAP header */ lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); @@ -1707,7 +1707,7 @@ static struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *ms skb = bt_skb_send_alloc(sk, count + hlen, msg->msg_flags & MSG_DONTWAIT, &err); if (!skb) - return ERR_PTR(-ENOMEM); + return ERR_PTR(err); /* Create L2CAP header */ lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); @@ -1744,7 +1744,7 @@ static struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *m skb = bt_skb_send_alloc(sk, count + hlen, msg->msg_flags & MSG_DONTWAIT, &err); if (!skb) - return ERR_PTR(-ENOMEM); + return ERR_PTR(err); /* Create L2CAP header */ lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); From ab3e571564a5d8fa4923e2e858e574c931a014c7 Mon Sep 17 00:00:00 2001 From: Haijun Liu Date: Thu, 30 Sep 2010 16:52:40 +0800 Subject: [PATCH 087/127] Bluetooth: Update conf_state before send config_req out Update conf_state with L2CAP_CONF_REQ_SENT before send config_req out in l2cap_config_req(). Signed-off-by: Haijun Liu Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- net/bluetooth/l2cap.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 01c476239dd6..16049de49896 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -3171,6 +3171,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)) { u8 buf[64]; + l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT; l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, l2cap_build_conf_req(sk, buf), buf); l2cap_pi(sk)->num_conf_req++; From 534c92fde74c8d2143fc15b5f1d957f42cb43570 Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Fri, 1 Oct 2010 12:05:11 +0300 Subject: [PATCH 088/127] Bluetooth: clean up rfcomm code Remove dead code and unused rfcomm thread events Signed-off-by: Andrei Emeltchenko Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/rfcomm.h | 5 ----- net/bluetooth/rfcomm/core.c | 29 ++++++++++++++--------------- 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/include/net/bluetooth/rfcomm.h b/include/net/bluetooth/rfcomm.h index a140847d622c..71047bc0af84 100644 --- a/include/net/bluetooth/rfcomm.h +++ b/include/net/bluetooth/rfcomm.h @@ -213,11 +213,6 @@ struct rfcomm_dlc { #define RFCOMM_DEFER_SETUP 8 /* Scheduling flags and events */ -#define RFCOMM_SCHED_STATE 0 -#define RFCOMM_SCHED_RX 1 -#define RFCOMM_SCHED_TX 2 -#define RFCOMM_SCHED_TIMEO 3 -#define RFCOMM_SCHED_AUTH 4 #define RFCOMM_SCHED_WAKEUP 31 /* MSC exchange flags */ diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 4a22b14a2c60..39a5d87e33b4 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -113,11 +113,10 @@ static void rfcomm_session_del(struct rfcomm_session *s); #define __get_rpn_stop_bits(line) (((line) >> 2) & 0x1) #define __get_rpn_parity(line) (((line) >> 3) & 0x7) -static inline void rfcomm_schedule(uint event) +static inline void rfcomm_schedule(void) { if (!rfcomm_thread) return; - //set_bit(event, &rfcomm_event); set_bit(RFCOMM_SCHED_WAKEUP, &rfcomm_event); wake_up_process(rfcomm_thread); } @@ -203,13 +202,13 @@ static inline int __check_fcs(u8 *data, int type, u8 fcs) static void rfcomm_l2state_change(struct sock *sk) { BT_DBG("%p state %d", sk, sk->sk_state); - rfcomm_schedule(RFCOMM_SCHED_STATE); + rfcomm_schedule(); } static void rfcomm_l2data_ready(struct sock *sk, int bytes) { BT_DBG("%p bytes %d", sk, bytes); - rfcomm_schedule(RFCOMM_SCHED_RX); + rfcomm_schedule(); } static int rfcomm_l2sock_create(struct socket **sock) @@ -255,7 +254,7 @@ static void rfcomm_session_timeout(unsigned long arg) BT_DBG("session %p state %ld", s, s->state); set_bit(RFCOMM_TIMED_OUT, &s->flags); - rfcomm_schedule(RFCOMM_SCHED_TIMEO); + rfcomm_schedule(); } static void rfcomm_session_set_timer(struct rfcomm_session *s, long timeout) @@ -283,7 +282,7 @@ static void rfcomm_dlc_timeout(unsigned long arg) set_bit(RFCOMM_TIMED_OUT, &d->flags); rfcomm_dlc_put(d); - rfcomm_schedule(RFCOMM_SCHED_TIMEO); + rfcomm_schedule(); } static void rfcomm_dlc_set_timer(struct rfcomm_dlc *d, long timeout) @@ -465,7 +464,7 @@ static int __rfcomm_dlc_close(struct rfcomm_dlc *d, int err) case BT_CONFIG: if (test_and_clear_bit(RFCOMM_DEFER_SETUP, &d->flags)) { set_bit(RFCOMM_AUTH_REJECT, &d->flags); - rfcomm_schedule(RFCOMM_SCHED_AUTH); + rfcomm_schedule(); break; } /* Fall through */ @@ -485,7 +484,7 @@ static int __rfcomm_dlc_close(struct rfcomm_dlc *d, int err) case BT_CONNECT2: if (test_and_clear_bit(RFCOMM_DEFER_SETUP, &d->flags)) { set_bit(RFCOMM_AUTH_REJECT, &d->flags); - rfcomm_schedule(RFCOMM_SCHED_AUTH); + rfcomm_schedule(); break; } /* Fall through */ @@ -533,7 +532,7 @@ int rfcomm_dlc_send(struct rfcomm_dlc *d, struct sk_buff *skb) skb_queue_tail(&d->tx_queue, skb); if (!test_bit(RFCOMM_TX_THROTTLED, &d->flags)) - rfcomm_schedule(RFCOMM_SCHED_TX); + rfcomm_schedule(); return len; } @@ -545,7 +544,7 @@ void __rfcomm_dlc_throttle(struct rfcomm_dlc *d) d->v24_sig |= RFCOMM_V24_FC; set_bit(RFCOMM_MSC_PENDING, &d->flags); } - rfcomm_schedule(RFCOMM_SCHED_TX); + rfcomm_schedule(); } void __rfcomm_dlc_unthrottle(struct rfcomm_dlc *d) @@ -556,7 +555,7 @@ void __rfcomm_dlc_unthrottle(struct rfcomm_dlc *d) d->v24_sig &= ~RFCOMM_V24_FC; set_bit(RFCOMM_MSC_PENDING, &d->flags); } - rfcomm_schedule(RFCOMM_SCHED_TX); + rfcomm_schedule(); } /* @@ -577,7 +576,7 @@ int rfcomm_dlc_set_modem_status(struct rfcomm_dlc *d, u8 v24_sig) d->v24_sig = v24_sig; if (!test_and_set_bit(RFCOMM_MSC_PENDING, &d->flags)) - rfcomm_schedule(RFCOMM_SCHED_TX); + rfcomm_schedule(); return 0; } @@ -816,7 +815,7 @@ static int rfcomm_queue_disc(struct rfcomm_dlc *d) cmd->fcs = __fcs2((u8 *) cmd); skb_queue_tail(&d->tx_queue, skb); - rfcomm_schedule(RFCOMM_SCHED_TX); + rfcomm_schedule(); return 0; } @@ -1884,7 +1883,7 @@ static inline void rfcomm_accept_connection(struct rfcomm_session *s) * L2CAP MTU minus UIH header and FCS. */ s->mtu = min(l2cap_pi(nsock->sk)->omtu, l2cap_pi(nsock->sk)->imtu) - 5; - rfcomm_schedule(RFCOMM_SCHED_RX); + rfcomm_schedule(); } else sock_release(nsock); } @@ -2093,7 +2092,7 @@ static void rfcomm_security_cfm(struct hci_conn *conn, u8 status, u8 encrypt) rfcomm_session_put(s); - rfcomm_schedule(RFCOMM_SCHED_AUTH); + rfcomm_schedule(); } static struct hci_cb rfcomm_cb = { From 7f8f2729ce6380a2735ddf45c04d5bb09eaca8a5 Mon Sep 17 00:00:00 2001 From: Karl Beldan Date: Thu, 7 Oct 2010 21:57:10 +0200 Subject: [PATCH 089/127] Bluetooth: hci_uart: Fix typo in stats for sco tx s/stat.cmd_tx++/stat.sco_tx++ for HCI_SCODATA_PKT Signed-off-by: Karl Beldan Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- drivers/bluetooth/hci_ldisc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index 998833d93c13..74cb6f3e86c5 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c @@ -101,7 +101,7 @@ static inline void hci_uart_tx_complete(struct hci_uart *hu, int pkt_type) break; case HCI_SCODATA_PKT: - hdev->stat.cmd_tx++; + hdev->stat.sco_tx++; break; } } From b3c0598952e02f1f1f6d003574549d940ecbf31a Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Fri, 8 Oct 2010 09:13:28 -0300 Subject: [PATCH 090/127] Bluetooth: update MAINTAINERS for Bluetooth subsys Add myself to MAINTAINERS and update the git trees. Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- MAINTAINERS | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index ba8603ce4441..c539910b1f76 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1358,16 +1358,19 @@ F: drivers/mtd/devices/block2mtd.c BLUETOOTH DRIVERS M: Marcel Holtmann +M: Gustavo F. Padovan L: linux-bluetooth@vger.kernel.org W: http://www.bluez.org/ +T: git git://git.kernel.org/pub/scm/linux/kernel/git/padovan/bluetooth-2.6.git S: Maintained F: drivers/bluetooth/ BLUETOOTH SUBSYSTEM M: Marcel Holtmann +M: Gustavo F. Padovan L: linux-bluetooth@vger.kernel.org W: http://www.bluez.org/ -T: git git://git.kernel.org/pub/scm/linux/kernel/git/holtmann/bluetooth-2.6.git +T: git git://git.kernel.org/pub/scm/linux/kernel/git/padovan/bluetooth-2.6.git S: Maintained F: net/bluetooth/ F: include/net/bluetooth/ From cfd8e12f42746df396ecbdf7a1d8e92e8e4dbb97 Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Mon, 11 Oct 2010 10:28:59 -0700 Subject: [PATCH 091/127] wireless: Print wiphy name in sysfs. The index cannot be used to reliably reconstruct a phy name, so explicitly add the phy name to sysfs so that scripts can figure out the parent phy device for a particular wireless interface. Signed-off-by: Ben Greear Signed-off-by: John W. Linville --- net/wireless/sysfs.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/net/wireless/sysfs.c b/net/wireless/sysfs.c index 74a9e3cce452..4294fa22bb2d 100644 --- a/net/wireless/sysfs.c +++ b/net/wireless/sysfs.c @@ -35,6 +35,14 @@ SHOW_FMT(index, "%d", wiphy_idx); SHOW_FMT(macaddress, "%pM", wiphy.perm_addr); SHOW_FMT(address_mask, "%pM", wiphy.addr_mask); +static ssize_t name_show(struct device *dev, + struct device_attribute *attr, + char *buf) { + struct wiphy *wiphy = &dev_to_rdev(dev)->wiphy; + return sprintf(buf, "%s\n", dev_name(&wiphy->dev)); +} + + static ssize_t addresses_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -57,6 +65,7 @@ static struct device_attribute ieee80211_dev_attrs[] = { __ATTR_RO(macaddress), __ATTR_RO(address_mask), __ATTR_RO(addresses), + __ATTR_RO(name), {} }; From 908ebfb95d16bdf7f5f37ad911ccd9b7350ba780 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 12 Oct 2010 11:07:44 -0700 Subject: [PATCH 092/127] ath5k: fix build break from "ath5k: Print out opmode in debugfs" Also improve ath_opmode_to_string usage by having it return UNKNOWN rather than NULL in the event of failure to map the opmode value to a representative string. Signed-off-by: Joe Perches Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/base.c | 4 +--- drivers/net/wireless/ath/ath5k/debug.c | 14 +++----------- drivers/net/wireless/ath/debug.c | 2 +- drivers/net/wireless/ath/debug.h | 7 +++++++ 4 files changed, 12 insertions(+), 15 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index c9732a6ce87f..7baaf04f092d 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -563,9 +563,7 @@ static void ath_do_set_opmode(struct ath5k_softc *sc) struct ath5k_hw *ah = sc->ah; ath5k_hw_set_opmode(ah, sc->opmode); ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "mode setup opmode %d (%s)\n", - sc->opmode, - ath_opmode_to_string(sc->opmode) ? - ath_opmode_to_string(sc->opmode) : "UKNOWN"); + sc->opmode, ath_opmode_to_string(sc->opmode)); } void ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc, diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c index a3b217125331..7c77e5b7c9af 100644 --- a/drivers/net/wireless/ath/ath5k/debug.c +++ b/drivers/net/wireless/ath/ath5k/debug.c @@ -493,7 +493,6 @@ static ssize_t read_file_misc(struct file *file, char __user *user_buf, char buf[700]; unsigned int len = 0; u32 filt = ath5k_hw_get_rx_filter(sc->ah); - const char *tmp; len += snprintf(buf+len, sizeof(buf)-len, "bssid-mask: %pM\n", sc->bssidmask); @@ -522,17 +521,10 @@ static ssize_t read_file_misc(struct file *file, char __user *user_buf, if (filt & AR5K_RX_FILTER_PHYERR_5211) snprintf(buf+len, sizeof(buf)-len, " PHYERR-5211"); if (filt & AR5K_RX_FILTER_RADARERR_5211) - len += snprintf(buf+len, sizeof(buf)-len, " RADARERR-5211\n"); - else - len += snprintf(buf+len, sizeof(buf)-len, "\n"); + len += snprintf(buf+len, sizeof(buf)-len, " RADARERR-5211"); - tmp = ath_opmode_to_string(sc->opmode); - if (tmp) - len += snprintf(buf+len, sizeof(buf)-len, "opmode: %s\n", - tmp); - else - len += snprintf(buf+len, sizeof(buf)-len, - "opmode: UNKNOWN-%i\n", sc->opmode); + len += snprintf(buf+len, sizeof(buf)-len, "\nopmode: %s (%d)\n", + ath_opmode_to_string(sc->opmode), sc->opmode); if (len > sizeof(buf)) len = sizeof(buf); diff --git a/drivers/net/wireless/ath/debug.c b/drivers/net/wireless/ath/debug.c index a9eb7876dbe1..dacfb234f491 100644 --- a/drivers/net/wireless/ath/debug.c +++ b/drivers/net/wireless/ath/debug.c @@ -55,7 +55,7 @@ const char *ath_opmode_to_string(enum nl80211_iftype opmode) case NL80211_IFTYPE_P2P_GO: return "P2P-GO"; default: - return NULL; + return "UNKNOWN"; } } EXPORT_SYMBOL(ath_opmode_to_string); diff --git a/drivers/net/wireless/ath/debug.h b/drivers/net/wireless/ath/debug.h index a3a5a628d24d..64e4af2c2887 100644 --- a/drivers/net/wireless/ath/debug.h +++ b/drivers/net/wireless/ath/debug.h @@ -78,6 +78,13 @@ ath_print(struct ath_common *common, int dbg_mask, const char *fmt, ...) #endif /* CONFIG_ATH_DEBUG */ /** Returns string describing opmode, or NULL if unknown mode. */ +#ifdef CONFIG_ATH_DEBUG const char *ath_opmode_to_string(enum nl80211_iftype opmode); +#else +static inline const char *ath_opmode_to_string(enum nl80211_iftype opmode) +{ + return "UNKNOWN"; +} +#endif #endif /* ATH_DEBUG_H */ From 10d8dad8453f8648a448960d7a2d3d983dfe0ed3 Mon Sep 17 00:00:00 2001 From: Gerrit Renker Date: Tue, 12 Oct 2010 07:07:42 +0200 Subject: [PATCH 093/127] wext: fix alignment problem in serializing 'struct iw_point' wext: fix alignment problem in serializing 'struct iw_point' This fixes a typo in the definition of the serialized length of struct iw_point: a) wireless.h is exported to userspace, the typo causes IW_EV_POINT_PK_LEN to be 12 on 64-bit, and 8 on 32-bit systems (causing misalignment); b) in compat-64 mode iwe_stream_add_point() memcpys overlap (see below). The second case in in compat-64 mode looks like (variable names are as in include/net/iw_handler.h:iwe_stream_add_point()): point_len = IW_EV_COMPAT_POINT_LEN = 8 lcp_len = IW_EV_COMPAT_LCP_LEN = 4 2nd memcpy: IW_EV_POINT_PK_LEN - IW_EV_LCP_PK_LEN = 12 - 4 = 8 IW_EV_LCP_PK_LEN <--------------> *---> 'extra' data area +-------+-------+-------+-------+---------------+------- ...-+ | len | cmd |length | flags | (empty) -> extra ... | +-------+-------+-------+-------+---------------+------- ...-+ 2 2 2 2 4 lcp_len <--------------> <-!! OVERLAP !!> <--1st memcpy--><------- 2nd memcpy -----------> <---- 3rd memcpy ------- ... > <--------- point_len ----------> This case could cause overrun whenever iw_point.length < 4. The other two cases are - * 32-bit systems: IW_EV_POINT_PK_LEN - IW_EV_LCP_PK_LEN = 8 - 4 = 4, the second memcpy copies exactly the 4 required bytes; * 64-bit systems: IW_EV_POINT_PK_LEN - IW_EV_LCP_PK_LEN = 12 - 4 = 8, the second memcpy copies a superfluous (but non overlapping) 4 bytes. The patch changes IW_EV_POINT_PK_LEN to be 8, so that in all 3 cases always only the requested iw_point.{length,flags} (both __u16) are copied, avoiding overrrun (compat-64) and superfluous copy (64-bit). In addition, the userspace header is sanitized (in agreement with version 30 of the wireless tools). Many thanks to Johannes Berg for help and review with this patch. Signed-off-by: Gerrit Renker Signed-off-by: John W. Linville --- include/linux/wireless.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/wireless.h b/include/linux/wireless.h index e6827eedf18b..4395b28bb86c 100644 --- a/include/linux/wireless.h +++ b/include/linux/wireless.h @@ -1157,6 +1157,6 @@ struct __compat_iw_event { #define IW_EV_PARAM_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(struct iw_param)) #define IW_EV_ADDR_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(struct sockaddr)) #define IW_EV_QUAL_PK_LEN (IW_EV_LCP_PK_LEN + sizeof(struct iw_quality)) -#define IW_EV_POINT_PK_LEN (IW_EV_LCP_LEN + 4) +#define IW_EV_POINT_PK_LEN (IW_EV_LCP_PK_LEN + 4) #endif /* _LINUX_WIRELESS_H */ From d84a35d1323bc62f9b26a707072767a60da75015 Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Tue, 12 Oct 2010 10:55:38 -0700 Subject: [PATCH 094/127] ath5k: Move debugfs under ieee80211/[wiphy-name] This automatically keeps things proper when wiphy is renamed. Based on patch by Johannes Berg Signed-off-by: Ben Greear Acked-by: Bruno Randolf Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath5k/base.c | 7 +------ drivers/net/wireless/ath/ath5k/debug.c | 20 ++------------------ drivers/net/wireless/ath/ath5k/debug.h | 12 ------------ 3 files changed, 3 insertions(+), 36 deletions(-) diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 7baaf04f092d..f1ae75d35d5d 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -3541,8 +3541,6 @@ ath5k_pci_probe(struct pci_dev *pdev, sc->hw = hw; sc->pdev = pdev; - ath5k_debug_init_device(sc); - /* * Mark the device as detached to avoid processing * interrupts until setup is complete. @@ -3650,6 +3648,7 @@ ath5k_pci_probe(struct pci_dev *pdev, } } + ath5k_debug_init_device(sc); /* ready to process interrupts */ __clear_bit(ATH_STAT_INVALID, sc->status); @@ -3736,8 +3735,6 @@ init_ath5k_pci(void) { int ret; - ath5k_debug_init(); - ret = pci_register_driver(&ath5k_pci_driver); if (ret) { printk(KERN_ERR "ath5k_pci: can't register pci driver\n"); @@ -3751,8 +3748,6 @@ static void __exit exit_ath5k_pci(void) { pci_unregister_driver(&ath5k_pci_driver); - - ath5k_debug_finish(); } module_init(init_ath5k_pci); diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c index 7c77e5b7c9af..42ea5b1bdb12 100644 --- a/drivers/net/wireless/ath/ath5k/debug.c +++ b/drivers/net/wireless/ath/ath5k/debug.c @@ -72,8 +72,6 @@ module_param_named(debug, ath5k_debug, uint, 0); #include "reg.h" #include "ani.h" -static struct dentry *ath5k_global_debugfs; - static int ath5k_debugfs_open(struct inode *inode, struct file *file) { file->private_data = inode->i_private; @@ -882,21 +880,13 @@ static const struct file_operations fops_queue = { }; -/* init */ - -void -ath5k_debug_init(void) -{ - ath5k_global_debugfs = debugfs_create_dir("ath5k", NULL); -} - void ath5k_debug_init_device(struct ath5k_softc *sc) { sc->debug.level = ath5k_debug; - sc->debug.debugfs_phydir = debugfs_create_dir(wiphy_name(sc->hw->wiphy), - ath5k_global_debugfs); + sc->debug.debugfs_phydir = debugfs_create_dir("ath5k", + sc->hw->wiphy->debugfsdir); sc->debug.debugfs_debug = debugfs_create_file("debug", S_IWUSR | S_IRUSR, @@ -936,12 +926,6 @@ ath5k_debug_init_device(struct ath5k_softc *sc) &fops_queue); } -void -ath5k_debug_finish(void) -{ - debugfs_remove(ath5k_global_debugfs); -} - void ath5k_debug_finish_device(struct ath5k_softc *sc) { diff --git a/drivers/net/wireless/ath/ath5k/debug.h b/drivers/net/wireless/ath/ath5k/debug.h index 4f078b134015..236edbd2507d 100644 --- a/drivers/net/wireless/ath/ath5k/debug.h +++ b/drivers/net/wireless/ath/ath5k/debug.h @@ -137,15 +137,9 @@ enum ath5k_debug_level { __func__, __LINE__, ##__VA_ARGS__); \ } while (0) -void -ath5k_debug_init(void); - void ath5k_debug_init_device(struct ath5k_softc *sc); -void -ath5k_debug_finish(void); - void ath5k_debug_finish_device(struct ath5k_softc *sc); @@ -173,15 +167,9 @@ static inline void __attribute__ ((format (printf, 3, 4))) ATH5K_DBG_UNLIMIT(struct ath5k_softc *sc, unsigned int m, const char *fmt, ...) {} -static inline void -ath5k_debug_init(void) {} - static inline void ath5k_debug_init_device(struct ath5k_softc *sc) {} -static inline void -ath5k_debug_finish(void) {} - static inline void ath5k_debug_finish_device(struct ath5k_softc *sc) {} From 7a8266524af7ec70d1b3d10f964ce911d922d466 Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Wed, 13 Oct 2010 11:47:09 +0530 Subject: [PATCH 095/127] ath9k: Fix documentation in rate control This fix updates the documenation in Rate Control Table structure Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/rc.c | 2 +- drivers/net/wireless/ath/ath9k/rc.h | 15 ++++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 13f9e88e1187..abebf2466a13 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -302,7 +302,7 @@ static const struct ath_rate_table ar5416_11ng_ratetable = { [64] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS, 243000, 205100, 20, 20, 8, 64, 65, 65 }, /* 243 Mb */ [65] = { RC_INVALID, WLAN_RC_PHY_HT_40_TS_HGI, 270000, - 224700, 20, 20, 8, 64, 65, 65 }, /* 170 Mb */ + 224700, 20, 20, 8, 64, 65, 65 }, /* 270 Mb */ [66] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 324000, 263100, 21, 21, 8, 66, 67, 67 }, /* 324 Mb */ [67] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 360000, diff --git a/drivers/net/wireless/ath/ath9k/rc.h b/drivers/net/wireless/ath/ath9k/rc.h index 268072fd3c1c..fbb1d33ee4b7 100644 --- a/drivers/net/wireless/ath/ath9k/rc.h +++ b/drivers/net/wireless/ath/ath9k/rc.h @@ -135,20 +135,21 @@ enum { /** * struct ath_rate_table - Rate Control table - * @valid: valid for use in rate control - * @valid_single_stream: valid for use in rate control for - * single stream operation - * @phy: CCK/OFDM + * @rate_cnt: total number of rates for the given wireless mode + * @mcs_start: MCS rate index offset + * @rate_flags: Rate Control flags + * @phy: CCK/OFDM/HT20/HT40 * @ratekbps: rate in Kbits per second * @user_ratekbps: user rate in Kbits per second * @ratecode: rate that goes into HW descriptors - * @short_preamble: Mask for enabling short preamble in ratecode for CCK * @dot11rate: value that goes into supported * rates info element of MLME * @ctrl_rate: Index of next lower basic rate, used for duration computation - * @max_4ms_framelen: maximum frame length(bytes) for tx duration + * @cw40index: Index of rates having 40MHz channel width + * @sgi_index: Index of rates having Short Guard Interval + * @ht_index: high throughput rates having 40MHz channel width and + * Short Guard Interval * @probe_interval: interval for rate control to probe for other rates - * @rssi_reduce_interval: interval for rate control to reduce rssi * @initial_ratemax: initial ratemax value */ struct ath_rate_table { From 271733cf844a2f5f186ef3b40c26d6397b71039a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 13 Oct 2010 12:06:23 +0200 Subject: [PATCH 096/127] cfg80211: notify drivers about frame registrations Drivers may need to adjust their filters according to frame registrations, so notify them about them. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/cfg80211.h | 7 +++++++ net/wireless/mlme.c | 23 ++++++++++++++++++++--- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 24d5b5869272..2a7936d7851d 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1147,6 +1147,9 @@ struct cfg80211_pmksa { * allows the driver to adjust the dynamic ps timeout value. * @set_cqm_rssi_config: Configure connection quality monitor RSSI threshold. * + * @mgmt_frame_register: Notify driver that a management frame type was + * registered. Note that this callback may not sleep, and cannot run + * concurrently with itself. */ struct cfg80211_ops { int (*suspend)(struct wiphy *wiphy); @@ -1297,6 +1300,10 @@ struct cfg80211_ops { int (*set_cqm_rssi_config)(struct wiphy *wiphy, struct net_device *dev, s32 rssi_thold, u32 rssi_hyst); + + void (*mgmt_frame_register)(struct wiphy *wiphy, + struct net_device *dev, + u16 frame_type, bool reg); }; /* diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index caf11a427507..26838d903b9a 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c @@ -764,6 +764,8 @@ int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_pid, u16 frame_type, const u8 *match_data, int match_len) { + struct wiphy *wiphy = wdev->wiphy; + struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); struct cfg80211_mgmt_registration *reg, *nreg; int err = 0; u16 mgmt_type; @@ -810,22 +812,37 @@ int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_pid, nreg->frame_type = cpu_to_le16(frame_type); list_add(&nreg->list, &wdev->mgmt_registrations); + if (rdev->ops->mgmt_frame_register) + rdev->ops->mgmt_frame_register(wiphy, wdev->netdev, + frame_type, true); + out: spin_unlock_bh(&wdev->mgmt_registrations_lock); + return err; } void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlpid) { + struct wiphy *wiphy = wdev->wiphy; + struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); struct cfg80211_mgmt_registration *reg, *tmp; spin_lock_bh(&wdev->mgmt_registrations_lock); list_for_each_entry_safe(reg, tmp, &wdev->mgmt_registrations, list) { - if (reg->nlpid == nlpid) { - list_del(®->list); - kfree(reg); + if (reg->nlpid != nlpid) + continue; + + if (rdev->ops->mgmt_frame_register) { + u16 frame_type = le16_to_cpu(reg->frame_type); + + rdev->ops->mgmt_frame_register(wiphy, wdev->netdev, + frame_type, false); } + + list_del(®->list); + kfree(reg); } spin_unlock_bh(&wdev->mgmt_registrations_lock); From 7be5086d4cb7cceb71d724a9524d5e927785d04f Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 13 Oct 2010 12:06:24 +0200 Subject: [PATCH 097/127] mac80211: add probe request filter flag Using the frame registration notification, we can see when probe requests are requested and notify the low-level driver via filtering. The flag is also set in AP and IBSS modes. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- include/net/mac80211.h | 9 ++++++--- net/mac80211/cfg.c | 18 ++++++++++++++++++ net/mac80211/ieee80211_i.h | 4 +++- net/mac80211/iface.c | 9 ++++++++- net/mac80211/main.c | 3 +++ 5 files changed, 38 insertions(+), 5 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 33aa2e39147b..9fdf982d1286 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1478,12 +1478,14 @@ ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw, * honour this flag if possible. * * @FIF_CONTROL: pass control frames (except for PS Poll), if PROMISC_IN_BSS - * is not set then only those addressed to this station. + * is not set then only those addressed to this station. * * @FIF_OTHER_BSS: pass frames destined to other BSSes * - * @FIF_PSPOLL: pass PS Poll frames, if PROMISC_IN_BSS is not set then only - * those addressed to this station. + * @FIF_PSPOLL: pass PS Poll frames, if PROMISC_IN_BSS is not set then only + * those addressed to this station. + * + * @FIF_PROBE_REQ: pass probe request frames */ enum ieee80211_filter_flags { FIF_PROMISC_IN_BSS = 1<<0, @@ -1494,6 +1496,7 @@ enum ieee80211_filter_flags { FIF_CONTROL = 1<<5, FIF_OTHER_BSS = 1<<6, FIF_PSPOLL = 1<<7, + FIF_PROBE_REQ = 1<<8, }; /** diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 25fb351e00f8..18bd0e550600 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1604,6 +1604,23 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, return 0; } +static void ieee80211_mgmt_frame_register(struct wiphy *wiphy, + struct net_device *dev, + u16 frame_type, bool reg) +{ + struct ieee80211_local *local = wiphy_priv(wiphy); + + if (frame_type != (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ)) + return; + + if (reg) + local->probe_req_reg++; + else + local->probe_req_reg--; + + ieee80211_queue_work(&local->hw, &local->reconfig_filter); +} + struct cfg80211_ops mac80211_config_ops = { .add_virtual_intf = ieee80211_add_iface, .del_virtual_intf = ieee80211_del_iface, @@ -1655,4 +1672,5 @@ struct cfg80211_ops mac80211_config_ops = { .cancel_remain_on_channel = ieee80211_cancel_remain_on_channel, .mgmt_tx = ieee80211_mgmt_tx, .set_cqm_rssi_config = ieee80211_set_cqm_rssi_config, + .mgmt_frame_register = ieee80211_mgmt_frame_register, }; diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index f0610fa4fbe0..b80c38689927 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -707,7 +707,9 @@ struct ieee80211_local { int open_count; int monitors, cooked_mntrs; /* number of interfaces with corresponding FIF_ flags */ - int fif_fcsfail, fif_plcpfail, fif_control, fif_other_bss, fif_pspoll; + int fif_fcsfail, fif_plcpfail, fif_control, fif_other_bss, fif_pspoll, + fif_probe_req; + int probe_req_reg; unsigned int filter_flags; /* FIF_* */ bool wiphy_ciphers_allocated; diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index e99d1b60557c..f9163b12c7f1 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -280,8 +280,11 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) ieee80211_start_mesh(sdata); } else if (sdata->vif.type == NL80211_IFTYPE_AP) { local->fif_pspoll++; + local->fif_probe_req++; ieee80211_configure_filter(local); + } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { + local->fif_probe_req++; } changed |= ieee80211_reset_erp_info(sdata); @@ -428,8 +431,12 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, if (sdata->flags & IEEE80211_SDATA_PROMISC) atomic_dec(&local->iff_promiscs); - if (sdata->vif.type == NL80211_IFTYPE_AP) + if (sdata->vif.type == NL80211_IFTYPE_AP) { local->fif_pspoll--; + local->fif_probe_req--; + } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { + local->fif_probe_req--; + } netif_addr_lock_bh(sdata->dev); spin_lock_bh(&local->filter_lock); diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 915ecf87e4ac..5162303a8b4a 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -54,6 +54,9 @@ void ieee80211_configure_filter(struct ieee80211_local *local) if (local->monitors || local->scanning) new_flags |= FIF_BCN_PRBRESP_PROMISC; + if (local->fif_probe_req || local->probe_req_reg) + new_flags |= FIF_PROBE_REQ; + if (local->fif_fcsfail) new_flags |= FIF_FCSFAIL; From 9c1d8e4affe6748d884a677cf5db19ae0c20ef07 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 13 Oct 2010 17:29:31 +0300 Subject: [PATCH 098/127] ath9k: Set RX filter for Probe Request based on filter flag This allows mac80211 to enable receiving of Probe Request frames in station mode which is needed for P2P. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/main.c | 1 + drivers/net/wireless/ath/ath9k/recv.c | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 865649120075..bcd3892dca8d 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1739,6 +1739,7 @@ skip_chan_change: FIF_PSPOLL | \ FIF_OTHER_BSS | \ FIF_BCN_PRBRESP_PROMISC | \ + FIF_PROBE_REQ | \ FIF_FCSFAIL) /* FIXME: sc->sc_full_reset ? */ diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 9c166f3804ab..7c90eaf9ec55 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -430,8 +430,7 @@ u32 ath_calcrxfilter(struct ath_softc *sc) | ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST | ATH9K_RX_FILTER_MCAST; - /* If not a STA, enable processing of Probe Requests */ - if (sc->sc_ah->opmode != NL80211_IFTYPE_STATION) + if (sc->rx.rxfilter & FIF_PROBE_REQ) rfilt |= ATH9K_RX_FILTER_PROBEREQ; /* From e4b55957eb695b43055b6badec026628b24fe80a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 13 Oct 2010 19:23:21 +0200 Subject: [PATCH 099/127] mac80211: fix SMPS request It looks like I submitted a different patch than I tested, because clearly the code in mac80211 is missing actually propagating the requested SMPS mode. Fix that! Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/ht.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index 4214bb6e12fc..75d679d75e63 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c @@ -291,6 +291,8 @@ void ieee80211_request_smps(struct ieee80211_vif *vif, if (WARN_ON(smps_mode == IEEE80211_SMPS_OFF)) smps_mode = IEEE80211_SMPS_AUTOMATIC; + sdata->u.mgd.driver_smps_mode = smps_mode; + ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.request_smps_work); } From c23cc81a5e5c1d4486b662cedd0afcdf9145f154 Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Wed, 13 Oct 2010 12:01:23 -0700 Subject: [PATCH 100/127] ath9k: Fix potential use-after-free. The ath_debug_stat_tx references bf->bf_mpdu, which is the skb consumed by ath_tx_complete. So, call the ath_debug_stat_tx method first. Signed-off-by: Ben Greear Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/xmit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 9a11099dd86a..9b17108adc7c 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -1924,8 +1924,8 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, else complete(&sc->paprd_complete); } else { - ath_tx_complete(sc, skb, bf->aphy, tx_flags); ath_debug_stat_tx(sc, txq, bf, ts); + ath_tx_complete(sc, skb, bf->aphy, tx_flags); } /* From de05ead8f8649788603afc470eb1c2ea2b8b1655 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Thu, 23 Sep 2010 15:24:22 -0700 Subject: [PATCH 101/127] iwlgn: need longer tx queue stuck timer for coex devices For BT/WiFi combo devices, need longer tx stuck queue timer, so those devices won't reload firmware too often. Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-6000.c | 38 +++++++++++++++++++------ drivers/net/wireless/iwlwifi/iwl-core.c | 11 +++---- 2 files changed, 34 insertions(+), 15 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 4810258aefd9..3eaea6fcdaa7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -509,6 +509,28 @@ static struct iwl_base_params iwl6050_base_params = { .sensitivity_calib_by_driver = true, .chain_noise_calib_by_driver = true, }; +static struct iwl_base_params iwl6000_coex_base_params = { + .eeprom_size = OTP_LOW_IMAGE_SIZE, + .num_of_queues = IWLAGN_NUM_QUEUES, + .num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES, + .pll_cfg_val = 0, + .set_l0s = true, + .use_bsm = false, + .max_ll_items = OTP_MAX_LL_ITEMS_6x00, + .shadow_ram_support = true, + .led_compensation = 51, + .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, + .supports_idle = true, + .adv_thermal_throttle = true, + .support_ct_kill_exit = true, + .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, + .chain_noise_scale = 1000, + .monitor_recover_period = IWL_LONG_MONITORING_PERIOD, + .max_event_log_size = 512, + .ucode_tracing = true, + .sensitivity_calib_by_driver = true, + .chain_noise_calib_by_driver = true, +}; static struct iwl_ht_params iwl6000_ht_params = { .ht_greenfield_support = true, @@ -587,7 +609,7 @@ struct iwl_cfg iwl6000g2b_2agn_cfg = { .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, .ops = &iwl6000g2b_ops, .mod_params = &iwlagn_mod_params, - .base_params = &iwl6000_base_params, + .base_params = &iwl6000_coex_base_params, .bt_params = &iwl6000_bt_params, .ht_params = &iwl6000_ht_params, .need_dc_calib = true, @@ -608,7 +630,7 @@ struct iwl_cfg iwl6000g2b_2abg_cfg = { .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, .ops = &iwl6000g2b_ops, .mod_params = &iwlagn_mod_params, - .base_params = &iwl6000_base_params, + .base_params = &iwl6000_coex_base_params, .bt_params = &iwl6000_bt_params, .need_dc_calib = true, .need_temp_offset_calib = true, @@ -628,7 +650,7 @@ struct iwl_cfg iwl6000g2b_2bgn_cfg = { .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, .ops = &iwl6000g2b_ops, .mod_params = &iwlagn_mod_params, - .base_params = &iwl6000_base_params, + .base_params = &iwl6000_coex_base_params, .bt_params = &iwl6000_bt_params, .ht_params = &iwl6000_ht_params, .need_dc_calib = true, @@ -649,7 +671,7 @@ struct iwl_cfg iwl6000g2b_2bg_cfg = { .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, .ops = &iwl6000g2b_ops, .mod_params = &iwlagn_mod_params, - .base_params = &iwl6000_base_params, + .base_params = &iwl6000_coex_base_params, .bt_params = &iwl6000_bt_params, .need_dc_calib = true, .need_temp_offset_calib = true, @@ -669,7 +691,7 @@ struct iwl_cfg iwl6000g2b_bgn_cfg = { .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, .ops = &iwl6000g2b_ops, .mod_params = &iwlagn_mod_params, - .base_params = &iwl6000_base_params, + .base_params = &iwl6000_coex_base_params, .bt_params = &iwl6000_bt_params, .ht_params = &iwl6000_ht_params, .need_dc_calib = true, @@ -690,7 +712,7 @@ struct iwl_cfg iwl6000g2b_bg_cfg = { .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, .ops = &iwl6000g2b_ops, .mod_params = &iwlagn_mod_params, - .base_params = &iwl6000_base_params, + .base_params = &iwl6000_coex_base_params, .bt_params = &iwl6000_bt_params, .need_dc_calib = true, .need_temp_offset_calib = true, @@ -829,7 +851,7 @@ struct iwl_cfg iwl130_bgn_cfg = { .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, .ops = &iwl6000g2b_ops, .mod_params = &iwlagn_mod_params, - .base_params = &iwl6000_base_params, + .base_params = &iwl6000_coex_base_params, .bt_params = &iwl6000_bt_params, .ht_params = &iwl6000_ht_params, .need_dc_calib = true, @@ -849,7 +871,7 @@ struct iwl_cfg iwl130_bg_cfg = { .eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, .ops = &iwl6000g2b_ops, .mod_params = &iwlagn_mod_params, - .base_params = &iwl6000_base_params, + .base_params = &iwl6000_coex_base_params, .bt_params = &iwl6000_bt_params, .need_dc_calib = true, /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index b3efbe02df67..89b1827054e5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2483,13 +2483,10 @@ static int iwl_check_stuck_queue(struct iwl_priv *priv, int cnt) "queue %d, not read %d time\n", q->id, q->repeat_same_read_ptr); - if (priv->cfg->bt_params && - !priv->cfg->bt_params->advanced_bt_coexist) { - mod_timer(&priv->monitor_recover, - jiffies + msecs_to_jiffies( - IWL_ONE_HUNDRED_MSECS)); - return 1; - } + mod_timer(&priv->monitor_recover, + jiffies + msecs_to_jiffies( + IWL_ONE_HUNDRED_MSECS)); + return 1; } } else { q->last_read_ptr = q->read_ptr; From 085fbca29d7b4574c4e42189ee5789004e4beff7 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 4 Oct 2010 05:47:23 -0700 Subject: [PATCH 102/127] iwlwifi: allow probe-after-rx on 2.4 GHz There are two passive 2.4 GHz channels: 12 and 13. If you have a hidden SSID on those, you will not be able to connect to it because we don't send out probe requests there. We can allow this by using the firmware's probe-after-rx functionality on those channels as well. This fixes https://bugzilla.kernel.org/show_bug.cgi?id=16462 Reported-by: Daniel J Blueman Tested-by: Daniel J Blueman Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 40 ++++++++++----------- drivers/net/wireless/iwlwifi/iwl3945-base.c | 16 ++++----- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index c1a389883af0..b555edd53354 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -1447,35 +1447,35 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) if (priv->cfg->bt_params && priv->cfg->bt_params->advanced_bt_coexist) scan->tx_cmd.tx_flags |= TX_CMD_FLG_IGNORE_BT; - scan->good_CRC_th = IWL_GOOD_CRC_TH_DISABLED; break; case IEEE80211_BAND_5GHZ: rate = IWL_RATE_6M_PLCP; - /* - * If active scanning is requested but a certain channel is - * marked passive, we can do active scanning if we detect - * transmissions. - * - * There is an issue with some firmware versions that triggers - * a sysassert on a "good CRC threshold" of zero (== disabled), - * on a radar channel even though this means that we should NOT - * send probes. - * - * The "good CRC threshold" is the number of frames that we - * need to receive during our dwell time on a channel before - * sending out probes -- setting this to a huge value will - * mean we never reach it, but at the same time work around - * the aforementioned issue. Thus use IWL_GOOD_CRC_TH_NEVER - * here instead of IWL_GOOD_CRC_TH_DISABLED. - */ - scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT : - IWL_GOOD_CRC_TH_NEVER; break; default: IWL_WARN(priv, "Invalid scan band\n"); return -EIO; } + /* + * If active scanning is requested but a certain channel is + * marked passive, we can do active scanning if we detect + * transmissions. + * + * There is an issue with some firmware versions that triggers + * a sysassert on a "good CRC threshold" of zero (== disabled), + * on a radar channel even though this means that we should NOT + * send probes. + * + * The "good CRC threshold" is the number of frames that we + * need to receive during our dwell time on a channel before + * sending out probes -- setting this to a huge value will + * mean we never reach it, but at the same time work around + * the aforementioned issue. Thus use IWL_GOOD_CRC_TH_NEVER + * here instead of IWL_GOOD_CRC_TH_DISABLED. + */ + scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT : + IWL_GOOD_CRC_TH_NEVER; + band = priv->scan_band; if (priv->cfg->scan_rx_antennas[band]) diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 980c6096620a..3ee3e55fa546 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -2938,18 +2938,10 @@ int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) case IEEE80211_BAND_2GHZ: 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; band = IEEE80211_BAND_2GHZ; break; case IEEE80211_BAND_5GHZ: scan->tx_cmd.rate = IWL_RATE_6M_PLCP; - /* - * If active scaning is requested but a certain channel - * is marked passive, we can do active scanning if we - * detect transmissions. - */ - scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT : - IWL_GOOD_CRC_TH_DISABLED; band = IEEE80211_BAND_5GHZ; break; default: @@ -2957,6 +2949,14 @@ int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) return -EIO; } + /* + * If active scaning is requested but a certain channel + * is marked passive, we can do active scanning if we + * detect transmissions. + */ + scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT : + IWL_GOOD_CRC_TH_DISABLED; + if (!priv->is_internal_short_scan) { scan->tx_cmd.len = cpu_to_le16( iwl_fill_probe_req(priv, From 12e934dc602fafba946b33587c38077ebceb3698 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 4 Oct 2010 05:50:06 -0700 Subject: [PATCH 103/127] iwlwifi: rename ibss_beacon variable Since we're also going to support AP (GO) mode, the variable isn't used for just IBSS beacons any more -- rename it to not mislead readers. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn.c | 26 ++++++++++----------- drivers/net/wireless/iwlwifi/iwl-core.c | 16 ++++++------- drivers/net/wireless/iwlwifi/iwl-dev.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl3945-base.c | 26 ++++++++++----------- 4 files changed, 36 insertions(+), 36 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 6771c404fa73..0cc090b485a9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -317,15 +317,15 @@ static u32 iwl_fill_beacon_frame(struct iwl_priv *priv, struct ieee80211_hdr *hdr, int left) { - if (!priv->ibss_beacon) + if (!priv->beacon_skb) return 0; - if (priv->ibss_beacon->len > left) + if (priv->beacon_skb->len > left) return 0; - memcpy(hdr, priv->ibss_beacon->data, priv->ibss_beacon->len); + memcpy(hdr, priv->beacon_skb->data, priv->beacon_skb->len); - return priv->ibss_beacon->len; + return priv->beacon_skb->len; } /* Parse the beacon frame to find the TIM element and set tim_idx & tim_size */ @@ -653,10 +653,10 @@ static void iwl_bg_beacon_update(struct work_struct *work) } /* new beacon skb is allocated every time; dispose previous.*/ - if (priv->ibss_beacon) - dev_kfree_skb(priv->ibss_beacon); + if (priv->beacon_skb) + dev_kfree_skb(priv->beacon_skb); - priv->ibss_beacon = beacon; + priv->beacon_skb = beacon; iwl_send_beacon_cmd(priv); out: @@ -2993,9 +2993,9 @@ static void __iwl_down(struct iwl_priv *priv) exit: memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp)); - if (priv->ibss_beacon) - dev_kfree_skb(priv->ibss_beacon); - priv->ibss_beacon = NULL; + if (priv->beacon_skb) + dev_kfree_skb(priv->beacon_skb); + priv->beacon_skb = NULL; /* clear out any free frames */ iwl_clear_free_frames(priv); @@ -4131,7 +4131,7 @@ static int iwl_init_drv(struct iwl_priv *priv) { int ret; - priv->ibss_beacon = NULL; + priv->beacon_skb = NULL; spin_lock_init(&priv->sta_lock); spin_lock_init(&priv->hcmd_lock); @@ -4645,8 +4645,8 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev) iwl_free_isr_ict(priv); - if (priv->ibss_beacon) - dev_kfree_skb(priv->ibss_beacon); + if (priv->beacon_skb) + dev_kfree_skb(priv->beacon_skb); ieee80211_free_hw(priv->hw); } diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 89b1827054e5..09a4d1700952 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1552,10 +1552,10 @@ static void iwlcore_beacon_update(struct ieee80211_hw *hw, spin_lock_irqsave(&priv->lock, flags); - if (priv->ibss_beacon) - dev_kfree_skb(priv->ibss_beacon); + if (priv->beacon_skb) + dev_kfree_skb(priv->beacon_skb); - priv->ibss_beacon = skb; + priv->beacon_skb = skb; timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp; priv->timestamp = le64_to_cpu(timestamp); @@ -1610,8 +1610,8 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, } if (changes & BSS_CHANGED_BEACON && vif->type == NL80211_IFTYPE_AP) { - dev_kfree_skb(priv->ibss_beacon); - priv->ibss_beacon = ieee80211_beacon_get(hw, vif); + dev_kfree_skb(priv->beacon_skb); + priv->beacon_skb = ieee80211_beacon_get(hw, vif); } if (changes & BSS_CHANGED_BEACON_INT && vif->type == NL80211_IFTYPE_AP) @@ -2060,10 +2060,10 @@ void iwl_mac_reset_tsf(struct ieee80211_hw *hw) spin_lock_irqsave(&priv->lock, flags); /* new association get rid of ibss beacon skb */ - if (priv->ibss_beacon) - dev_kfree_skb(priv->ibss_beacon); + if (priv->beacon_skb) + dev_kfree_skb(priv->beacon_skb); - priv->ibss_beacon = NULL; + priv->beacon_skb = NULL; priv->timestamp = 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index de43e1350ed1..70e07fa48405 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1383,8 +1383,6 @@ struct iwl_priv { enum nl80211_iftype iw_mode; - struct sk_buff *ibss_beacon; - /* Last Rx'd beacon timestamp */ u64 timestamp; @@ -1496,8 +1494,10 @@ struct iwl_priv { struct work_struct scan_completed; struct work_struct rx_replenish; struct work_struct abort_scan; + struct work_struct beacon_update; struct iwl_rxon_context *beacon_ctx; + struct sk_buff *beacon_skb; struct work_struct tt_work; struct work_struct ct_enter; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 3ee3e55fa546..8f8c4b73f8b9 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -317,15 +317,15 @@ unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv, int left) { - if (!iwl_is_associated(priv, IWL_RXON_CTX_BSS) || !priv->ibss_beacon) + if (!iwl_is_associated(priv, IWL_RXON_CTX_BSS) || !priv->beacon_skb) return 0; - if (priv->ibss_beacon->len > left) + if (priv->beacon_skb->len > left) return 0; - memcpy(hdr, priv->ibss_beacon->data, priv->ibss_beacon->len); + memcpy(hdr, priv->beacon_skb->data, priv->beacon_skb->len); - return priv->ibss_beacon->len; + return priv->beacon_skb->len; } static int iwl3945_send_beacon_cmd(struct iwl_priv *priv) @@ -813,10 +813,10 @@ static void iwl3945_bg_beacon_update(struct work_struct *work) mutex_lock(&priv->mutex); /* new beacon skb is allocated every time; dispose previous.*/ - if (priv->ibss_beacon) - dev_kfree_skb(priv->ibss_beacon); + if (priv->beacon_skb) + dev_kfree_skb(priv->beacon_skb); - priv->ibss_beacon = beacon; + priv->beacon_skb = beacon; mutex_unlock(&priv->mutex); iwl3945_send_beacon_cmd(priv); @@ -2642,9 +2642,9 @@ static void __iwl3945_down(struct iwl_priv *priv) exit: memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp)); - if (priv->ibss_beacon) - dev_kfree_skb(priv->ibss_beacon); - priv->ibss_beacon = NULL; + if (priv->beacon_skb) + dev_kfree_skb(priv->beacon_skb); + priv->beacon_skb = NULL; /* clear out any free frames */ iwl3945_clear_free_frames(priv); @@ -3848,7 +3848,7 @@ static int iwl3945_init_drv(struct iwl_priv *priv) struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom; priv->retry_rate = 1; - priv->ibss_beacon = NULL; + priv->beacon_skb = NULL; spin_lock_init(&priv->sta_lock); spin_lock_init(&priv->hcmd_lock); @@ -4256,8 +4256,8 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) iwl_free_channel_map(priv); iwlcore_free_geos(priv); kfree(priv->scan_cmd); - if (priv->ibss_beacon) - dev_kfree_skb(priv->ibss_beacon); + if (priv->beacon_skb) + dev_kfree_skb(priv->beacon_skb); ieee80211_free_hw(priv->hw); } From 77834543a5278b55df6c2784cd5ed59970be3c44 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 4 Oct 2010 05:50:36 -0700 Subject: [PATCH 104/127] iwlwifi: clean up some beacon handling There's no need to check for NULL before calling dev_kfree_skb() since it is valid to call it on NULL -- it becomes a no-op. There's also no need to initialise the beacon_skb variable to NULL just after the memory it is in has been kzalloc'ed. Some minor whitespace cleanups, and a lock assertion in a function that needs the mutex (to access the beacon_skb var) complete the patch. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 0cc090b485a9..7079efbe34eb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -314,9 +314,11 @@ static void iwl_free_frame(struct iwl_priv *priv, struct iwl_frame *frame) } static u32 iwl_fill_beacon_frame(struct iwl_priv *priv, - struct ieee80211_hdr *hdr, - int left) + struct ieee80211_hdr *hdr, + int left) { + lockdep_assert_held(&priv->mutex); + if (!priv->beacon_skb) return 0; @@ -330,8 +332,8 @@ static u32 iwl_fill_beacon_frame(struct iwl_priv *priv, /* Parse the beacon frame to find the TIM element and set tim_idx & tim_size */ static void iwl_set_beacon_tim(struct iwl_priv *priv, - struct iwl_tx_beacon_cmd *tx_beacon_cmd, - u8 *beacon, u32 frame_size) + struct iwl_tx_beacon_cmd *tx_beacon_cmd, + u8 *beacon, u32 frame_size) { u16 tim_idx; struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)beacon; @@ -393,7 +395,7 @@ static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv, /* Set up TX beacon command fields */ iwl_set_beacon_tim(priv, tx_beacon_cmd, (u8 *)tx_beacon_cmd->frame, - frame_size); + frame_size); /* Set up packet rate and flags */ rate = iwl_rate_get_lowest_plcp(priv, priv->beacon_ctx); @@ -648,13 +650,12 @@ static void iwl_bg_beacon_update(struct work_struct *work) /* Pull updated AP beacon from mac80211. will fail if not in AP mode */ beacon = ieee80211_beacon_get(priv->hw, priv->beacon_ctx->vif); if (!beacon) { - IWL_ERR(priv, "update beacon failed\n"); + IWL_ERR(priv, "update beacon failed -- keeping old\n"); goto out; } /* new beacon skb is allocated every time; dispose previous.*/ - if (priv->beacon_skb) - dev_kfree_skb(priv->beacon_skb); + dev_kfree_skb(priv->beacon_skb); priv->beacon_skb = beacon; @@ -2993,8 +2994,7 @@ static void __iwl_down(struct iwl_priv *priv) exit: memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp)); - if (priv->beacon_skb) - dev_kfree_skb(priv->beacon_skb); + dev_kfree_skb(priv->beacon_skb); priv->beacon_skb = NULL; /* clear out any free frames */ @@ -4131,8 +4131,6 @@ static int iwl_init_drv(struct iwl_priv *priv) { int ret; - priv->beacon_skb = NULL; - spin_lock_init(&priv->sta_lock); spin_lock_init(&priv->hcmd_lock); @@ -4645,8 +4643,7 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev) iwl_free_isr_ict(priv); - if (priv->beacon_skb) - dev_kfree_skb(priv->beacon_skb); + dev_kfree_skb(priv->beacon_skb); ieee80211_free_hw(priv->hw); } From 34f5a70c08530bb0b4724991a712a0ef6bbec39a Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Wed, 6 Oct 2010 13:46:11 -0700 Subject: [PATCH 105/127] iwlagn: 6050 ops should be used; For 6050 series of devices, 6050 ops should be used; One of the 6050 config still use 6000 ops, fix it. Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-6000.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 3eaea6fcdaa7..11e6532fc573 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -780,7 +780,7 @@ struct iwl_cfg iwl6050_2agn_cfg = { .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, .valid_tx_ant = ANT_AB, .valid_rx_ant = ANT_AB, - .ops = &iwl6000_ops, + .ops = &iwl6050_ops, .eeprom_ver = EEPROM_6050_EEPROM_VERSION, .eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION, .mod_params = &iwlagn_mod_params, From dacefedb34e538e9934556ffe5eaad177e7a9718 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 7 Oct 2010 04:02:03 -0700 Subject: [PATCH 106/127] iwlwifi: rewrite RXON checks The RXON checking is a bit magical, and prints out too much information if something goes wrong. Make it less magical and print out only the items that were actually wrong. Also remove the comment about removing it -- the driver is constantly changing so these checks are useful. Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/iwl-core.c | 100 ++++++++++++------------ 1 file changed, 49 insertions(+), 51 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 09a4d1700952..ecf5c9b90089 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -510,76 +510,74 @@ void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, struct iwl_rxon_context *ctx, } EXPORT_SYMBOL(iwl_set_rxon_hwcrypto); -/** - * iwl_check_rxon_cmd - validate RXON structure is valid - * - * NOTE: This is really only useful during development and can eventually - * be #ifdef'd out once the driver is stable and folks aren't actively - * making changes - */ +/* validate RXON structure is valid */ int iwl_check_rxon_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx) { - int error = 0; - int counter = 1; struct iwl_rxon_cmd *rxon = &ctx->staging; + bool error = false; if (rxon->flags & RXON_FLG_BAND_24G_MSK) { - error |= le32_to_cpu(rxon->flags & - (RXON_FLG_TGJ_NARROW_BAND_MSK | - RXON_FLG_RADAR_DETECT_MSK)); - if (error) - IWL_WARN(priv, "check 24G fields %d | %d\n", - counter++, error); + if (rxon->flags & RXON_FLG_TGJ_NARROW_BAND_MSK) { + IWL_WARN(priv, "check 2.4G: wrong narrow\n"); + error = true; + } + if (rxon->flags & RXON_FLG_RADAR_DETECT_MSK) { + IWL_WARN(priv, "check 2.4G: wrong radar\n"); + error = true; + } } else { - error |= (rxon->flags & RXON_FLG_SHORT_SLOT_MSK) ? - 0 : le32_to_cpu(RXON_FLG_SHORT_SLOT_MSK); - if (error) - IWL_WARN(priv, "check 52 fields %d | %d\n", - counter++, error); - error |= le32_to_cpu(rxon->flags & RXON_FLG_CCK_MSK); - if (error) - IWL_WARN(priv, "check 52 CCK %d | %d\n", - counter++, error); + if (!(rxon->flags & RXON_FLG_SHORT_SLOT_MSK)) { + IWL_WARN(priv, "check 5.2G: not short slot!\n"); + error = true; + } + if (rxon->flags & RXON_FLG_CCK_MSK) { + IWL_WARN(priv, "check 5.2G: CCK!\n"); + error = true; + } + } + if ((rxon->node_addr[0] | rxon->bssid_addr[0]) & 0x1) { + IWL_WARN(priv, "mac/bssid mcast!\n"); + error = true; } - error |= (rxon->node_addr[0] | rxon->bssid_addr[0]) & 0x1; - if (error) - IWL_WARN(priv, "check mac addr %d | %d\n", counter++, error); /* make sure basic rates 6Mbps and 1Mbps are supported */ - error |= (((rxon->ofdm_basic_rates & IWL_RATE_6M_MASK) == 0) && - ((rxon->cck_basic_rates & IWL_RATE_1M_MASK) == 0)); - if (error) - IWL_WARN(priv, "check basic rate %d | %d\n", counter++, error); + if ((rxon->ofdm_basic_rates & IWL_RATE_6M_MASK) == 0 && + (rxon->cck_basic_rates & IWL_RATE_1M_MASK) == 0) { + IWL_WARN(priv, "neither 1 nor 6 are basic\n"); + error = true; + } - error |= (le16_to_cpu(rxon->assoc_id) > 2007); - if (error) - IWL_WARN(priv, "check assoc id %d | %d\n", counter++, error); + if (le16_to_cpu(rxon->assoc_id) > 2007) { + IWL_WARN(priv, "aid > 2007\n"); + error = true; + } - error |= ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK)) - == (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK)); - if (error) - IWL_WARN(priv, "check CCK and short slot %d | %d\n", - counter++, error); + if ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK)) + == (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK)) { + IWL_WARN(priv, "CCK and short slot\n"); + error = true; + } - error |= ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK)) - == (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK)); - if (error) - IWL_WARN(priv, "check CCK & auto detect %d | %d\n", - counter++, error); + if ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK)) + == (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK)) { + IWL_WARN(priv, "CCK and auto detect"); + error = true; + } - error |= ((rxon->flags & (RXON_FLG_AUTO_DETECT_MSK | - RXON_FLG_TGG_PROTECT_MSK)) == RXON_FLG_TGG_PROTECT_MSK); - if (error) - IWL_WARN(priv, "check TGG and auto detect %d | %d\n", - counter++, error); + if ((rxon->flags & (RXON_FLG_AUTO_DETECT_MSK | + RXON_FLG_TGG_PROTECT_MSK)) == + RXON_FLG_TGG_PROTECT_MSK) { + IWL_WARN(priv, "TGg but no auto-detect\n"); + error = true; + } if (error) IWL_WARN(priv, "Tuning to channel %d\n", le16_to_cpu(rxon->channel)); if (error) { - IWL_ERR(priv, "Not a valid iwl_rxon_assoc_cmd field values\n"); - return -1; + IWL_ERR(priv, "Invalid RXON\n"); + return -EINVAL; } return 0; } From 657e11a47dede79cae1d2f72084f6f7303aec725 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 7 Oct 2010 03:52:35 -0700 Subject: [PATCH 107/127] iwlwifi: blink LED in IBSS mode We recently found that contrary to expectations, the LED is not blinking in IBSS mode. Fix this. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index ecf5c9b90089..25fb3912342c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -1727,6 +1727,7 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, memcpy(ctx->staging.bssid_addr, bss_conf->bssid, ETH_ALEN); memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN); + iwl_led_associate(priv); iwlcore_config_ap(priv, vif); } else iwl_set_no_assoc(priv, vif); From 40bbfd4c1b336b8841bef9933b6e09252ace56b8 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 7 Oct 2010 04:00:33 -0700 Subject: [PATCH 108/127] iwlagn: check beacon frame size When the beacon_skb is NULL, we might still attempt to use it in this code path (if we ever get here) -- make the code a bit more defensive and check the return value of iwl_fill_beacon_frame() against zero. Signed-off-by: Johannes Berg Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 7079efbe34eb..c2636a7ab9ee 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -385,6 +385,8 @@ static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv, sizeof(frame->u) - sizeof(*tx_beacon_cmd)); if (WARN_ON_ONCE(frame_size > MAX_MPDU_SIZE)) return 0; + if (!frame_size) + return 0; /* Set up TX command fields */ tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size); From 3be63ff0ae196b371728ba8fc8aca12eafcae218 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 8 Oct 2010 16:05:19 -0700 Subject: [PATCH 109/127] iwlwifi: move agn only eeprom functions to separate file Some of the functions in iwl-eeprom.c file are for agn devices only, Those functions do not have to be part of iwlcore.ko, so move those to iwl-agn-eeprom.c file. Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/Makefile | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c | 454 ++++++++++++++++++ drivers/net/wireless/iwlwifi/iwl-agn.h | 6 + drivers/net/wireless/iwlwifi/iwl-eeprom.c | 374 +-------------- drivers/net/wireless/iwlwifi/iwl-eeprom.h | 7 +- 5 files changed, 476 insertions(+), 367 deletions(-) create mode 100644 drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index b4b24b67892c..63edbe2e557f 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile @@ -12,7 +12,7 @@ obj-$(CONFIG_IWLAGN) += iwlagn.o iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o iwl-agn-ict.o iwlagn-objs += iwl-agn-ucode.o iwl-agn-hcmd.o iwl-agn-tx.o iwlagn-objs += iwl-agn-lib.o iwl-agn-rx.o iwl-agn-calib.o -iwlagn-objs += iwl-agn-tt.o iwl-agn-sta.o +iwlagn-objs += iwl-agn-tt.o iwl-agn-sta.o iwl-agn-eeprom.o iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-agn-debugfs.o iwlagn-$(CONFIG_IWL4965) += iwl-4965.o diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c new file mode 100644 index 000000000000..a650baba0809 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c @@ -0,0 +1,454 @@ +/****************************************************************************** + * + * 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 - 2010 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: + * Intel Linux Wireless + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + * BSD LICENSE + * + * Copyright(c) 2005 - 2010 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-commands.h" +#include "iwl-dev.h" +#include "iwl-core.h" +#include "iwl-debug.h" +#include "iwl-agn.h" +#include "iwl-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. + * + *********************************************************************/ + +/** + * struct iwl_txpwr_section: eeprom section information + * @offset: indirect address into eeprom image + * @count: number of "struct iwl_eeprom_enhanced_txpwr" in this section + * @band: band type for the section + * @is_common - true: common section, false: channel section + * @is_cck - true: cck section, false: not cck section + * @is_ht_40 - true: all channel in the section are HT40 channel, + * false: legacy or HT 20 MHz + * ignore if it is common section + * @iwl_eeprom_section_channel: channel array in the section, + * ignore if common section + */ +struct iwl_txpwr_section { + u32 offset; + u8 count; + enum ieee80211_band band; + bool is_common; + bool is_cck; + bool is_ht40; + u8 iwl_eeprom_section_channel[EEPROM_MAX_TXPOWER_SECTION_ELEMENTS]; +}; + +/** + * section 1 - 3 are regulatory tx power apply to all channels based on + * modulation: CCK, OFDM + * Band: 2.4GHz, 5.2GHz + * section 4 - 10 are regulatory tx power apply to specified channels + * For example: + * 1L - Channel 1 Legacy + * 1HT - Channel 1 HT + * (1,+1) - Channel 1 HT40 "_above_" + * + * Section 1: all CCK channels + * Section 2: all 2.4 GHz OFDM (Legacy, HT and HT40) channels + * Section 3: all 5.2 GHz OFDM (Legacy, HT and HT40) channels + * Section 4: 2.4 GHz 20MHz channels: 1L, 1HT, 2L, 2HT, 10L, 10HT, 11L, 11HT + * Section 5: 2.4 GHz 40MHz channels: (1,+1) (2,+1) (6,+1) (7,+1) (9,+1) + * Section 6: 5.2 GHz 20MHz channels: 36L, 64L, 100L, 36HT, 64HT, 100HT + * Section 7: 5.2 GHz 40MHz channels: (36,+1) (60,+1) (100,+1) + * Section 8: 2.4 GHz channel: 13L, 13HT + * Section 9: 2.4 GHz channel: 140L, 140HT + * Section 10: 2.4 GHz 40MHz channels: (132,+1) (44,+1) + * + */ +static const struct iwl_txpwr_section enhinfo[] = { + { EEPROM_LB_CCK_20_COMMON, 1, IEEE80211_BAND_2GHZ, true, true, false }, + { EEPROM_LB_OFDM_COMMON, 3, IEEE80211_BAND_2GHZ, true, false, false }, + { EEPROM_HB_OFDM_COMMON, 3, IEEE80211_BAND_5GHZ, true, false, false }, + { EEPROM_LB_OFDM_20_BAND, 8, IEEE80211_BAND_2GHZ, + false, false, false, + {1, 1, 2, 2, 10, 10, 11, 11 } }, + { EEPROM_LB_OFDM_HT40_BAND, 5, IEEE80211_BAND_2GHZ, + false, false, true, + { 1, 2, 6, 7, 9 } }, + { EEPROM_HB_OFDM_20_BAND, 6, IEEE80211_BAND_5GHZ, + false, false, false, + { 36, 64, 100, 36, 64, 100 } }, + { EEPROM_HB_OFDM_HT40_BAND, 3, IEEE80211_BAND_5GHZ, + false, false, true, + { 36, 60, 100 } }, + { EEPROM_LB_OFDM_20_CHANNEL_13, 2, IEEE80211_BAND_2GHZ, + false, false, false, + { 13, 13 } }, + { EEPROM_HB_OFDM_20_CHANNEL_140, 2, IEEE80211_BAND_5GHZ, + false, false, false, + { 140, 140 } }, + { EEPROM_HB_OFDM_HT40_BAND_1, 2, IEEE80211_BAND_5GHZ, + false, false, true, + { 132, 44 } }, +}; + +/****************************************************************************** + * + * EEPROM related functions + * +******************************************************************************/ + +/* + * 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 iwl_priv *priv) +{ + u16 count; + int ret; + + for (count = 0; count < EEPROM_SEM_RETRY_LIMIT; count++) { + /* Request semaphore */ + iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, + CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); + + /* See if we got it */ + 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(priv, + "Acquired semaphore after %d tries.\n", + count+1); + return ret; + } + } + + return ret; +} + +void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv) +{ + iwl_clear_bit(priv, CSR_HW_IF_CONFIG_REG, + CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); + +} + +int iwl_eeprom_check_version(struct iwl_priv *priv) +{ + u16 eeprom_ver; + u16 calib_ver; + + eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION); + calib_ver = priv->cfg->ops->lib->eeprom_ops.calib_version(priv); + + if (eeprom_ver < priv->cfg->eeprom_ver || + calib_ver < priv->cfg->eeprom_calib_ver) + goto err; + + IWL_INFO(priv, "device EEPROM VER=0x%x, CALIB=0x%x\n", + eeprom_ver, calib_ver); + + return 0; +err: + IWL_ERR(priv, "Unsupported (too old) EEPROM VER=0x%x < 0x%x " + "CALIB=0x%x < 0x%x\n", + eeprom_ver, priv->cfg->eeprom_ver, + calib_ver, priv->cfg->eeprom_calib_ver); + return -EINVAL; + +} + +void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac) +{ + const u8 *addr = priv->cfg->ops->lib->eeprom_ops.query_addr(priv, + EEPROM_MAC_ADDRESS); + memcpy(mac, addr, ETH_ALEN); +} + +/** + * iwl_get_max_txpower_avg - get the highest tx power from all chains. + * find the highest tx power from all chains for the channel + */ +static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv, + struct iwl_eeprom_enhanced_txpwr *enhanced_txpower, + int element, s8 *max_txpower_in_half_dbm) +{ + s8 max_txpower_avg = 0; /* (dBm) */ + + IWL_DEBUG_INFO(priv, "%d - " + "chain_a: %d dB chain_b: %d dB " + "chain_c: %d dB mimo2: %d dB mimo3: %d dB\n", + element, + enhanced_txpower[element].chain_a_max >> 1, + enhanced_txpower[element].chain_b_max >> 1, + enhanced_txpower[element].chain_c_max >> 1, + enhanced_txpower[element].mimo2_max >> 1, + enhanced_txpower[element].mimo3_max >> 1); + /* Take the highest tx power from any valid chains */ + if ((priv->cfg->valid_tx_ant & ANT_A) && + (enhanced_txpower[element].chain_a_max > max_txpower_avg)) + max_txpower_avg = enhanced_txpower[element].chain_a_max; + if ((priv->cfg->valid_tx_ant & ANT_B) && + (enhanced_txpower[element].chain_b_max > max_txpower_avg)) + max_txpower_avg = enhanced_txpower[element].chain_b_max; + if ((priv->cfg->valid_tx_ant & ANT_C) && + (enhanced_txpower[element].chain_c_max > max_txpower_avg)) + max_txpower_avg = enhanced_txpower[element].chain_c_max; + if (((priv->cfg->valid_tx_ant == ANT_AB) | + (priv->cfg->valid_tx_ant == ANT_BC) | + (priv->cfg->valid_tx_ant == ANT_AC)) && + (enhanced_txpower[element].mimo2_max > max_txpower_avg)) + max_txpower_avg = enhanced_txpower[element].mimo2_max; + if ((priv->cfg->valid_tx_ant == ANT_ABC) && + (enhanced_txpower[element].mimo3_max > max_txpower_avg)) + max_txpower_avg = enhanced_txpower[element].mimo3_max; + + /* + * max. tx power in EEPROM is in 1/2 dBm format + * convert from 1/2 dBm to dBm (round-up convert) + * but we also do not want to loss 1/2 dBm resolution which + * will impact performance + */ + *max_txpower_in_half_dbm = max_txpower_avg; + return (max_txpower_avg & 0x01) + (max_txpower_avg >> 1); +} + +/** + * iwl_update_common_txpower: update channel tx power + * update tx power per band based on EEPROM enhanced tx power info. + */ +static s8 iwl_update_common_txpower(struct iwl_priv *priv, + struct iwl_eeprom_enhanced_txpwr *enhanced_txpower, + int section, int element, s8 *max_txpower_in_half_dbm) +{ + struct iwl_channel_info *ch_info; + int ch; + bool is_ht40 = false; + s8 max_txpower_avg; /* (dBm) */ + + /* it is common section, contain all type (Legacy, HT and HT40) + * based on the element in the section to determine + * is it HT 40 or not + */ + if (element == EEPROM_TXPOWER_COMMON_HT40_INDEX) + is_ht40 = true; + max_txpower_avg = + iwl_get_max_txpower_avg(priv, enhanced_txpower, + element, max_txpower_in_half_dbm); + + ch_info = priv->channel_info; + + for (ch = 0; ch < priv->channel_count; ch++) { + /* find matching band and update tx power if needed */ + if ((ch_info->band == enhinfo[section].band) && + (ch_info->max_power_avg < max_txpower_avg) && + (!is_ht40)) { + /* Update regulatory-based run-time data */ + ch_info->max_power_avg = ch_info->curr_txpow = + max_txpower_avg; + ch_info->scan_power = max_txpower_avg; + } + if ((ch_info->band == enhinfo[section].band) && is_ht40 && + (ch_info->ht40_max_power_avg < max_txpower_avg)) { + /* Update regulatory-based run-time data */ + ch_info->ht40_max_power_avg = max_txpower_avg; + } + ch_info++; + } + return max_txpower_avg; +} + +/** + * iwl_update_channel_txpower: update channel tx power + * update channel tx power based on EEPROM enhanced tx power info. + */ +static s8 iwl_update_channel_txpower(struct iwl_priv *priv, + struct iwl_eeprom_enhanced_txpwr *enhanced_txpower, + int section, int element, s8 *max_txpower_in_half_dbm) +{ + struct iwl_channel_info *ch_info; + int ch; + u8 channel; + s8 max_txpower_avg; /* (dBm) */ + + channel = enhinfo[section].iwl_eeprom_section_channel[element]; + max_txpower_avg = + iwl_get_max_txpower_avg(priv, enhanced_txpower, + element, max_txpower_in_half_dbm); + + ch_info = priv->channel_info; + for (ch = 0; ch < priv->channel_count; ch++) { + /* find matching channel and update tx power if needed */ + if (ch_info->channel == channel) { + if ((ch_info->max_power_avg < max_txpower_avg) && + (!enhinfo[section].is_ht40)) { + /* Update regulatory-based run-time data */ + ch_info->max_power_avg = max_txpower_avg; + ch_info->curr_txpow = max_txpower_avg; + ch_info->scan_power = max_txpower_avg; + } + if ((enhinfo[section].is_ht40) && + (ch_info->ht40_max_power_avg < max_txpower_avg)) { + /* Update regulatory-based run-time data */ + ch_info->ht40_max_power_avg = max_txpower_avg; + } + break; + } + ch_info++; + } + return max_txpower_avg; +} + +/** + * iwlcore_eeprom_enhanced_txpower: process enhanced tx power info + */ +void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv) +{ + int eeprom_section_count = 0; + int section, element; + struct iwl_eeprom_enhanced_txpwr *enhanced_txpower; + u32 offset; + s8 max_txpower_avg; /* (dBm) */ + s8 max_txpower_in_half_dbm; /* (half-dBm) */ + + /* Loop through all the sections + * adjust bands and channel's max tx power + * Set the tx_power_user_lmt to the highest power + * supported by any channels and chains + */ + for (section = 0; section < ARRAY_SIZE(enhinfo); section++) { + eeprom_section_count = enhinfo[section].count; + offset = enhinfo[section].offset; + enhanced_txpower = (struct iwl_eeprom_enhanced_txpwr *) + iwl_eeprom_query_addr(priv, offset); + + /* + * check for valid entry - + * different version of EEPROM might contain different set + * of enhanced tx power table + * always check for valid entry before process + * the information + */ + if (!enhanced_txpower->common || enhanced_txpower->reserved) + continue; + + for (element = 0; element < eeprom_section_count; element++) { + if (enhinfo[section].is_common) + max_txpower_avg = + iwl_update_common_txpower(priv, + enhanced_txpower, section, + element, + &max_txpower_in_half_dbm); + else + max_txpower_avg = + iwl_update_channel_txpower(priv, + enhanced_txpower, section, + element, + &max_txpower_in_half_dbm); + + /* Update the tx_power_user_lmt to the highest power + * supported by any channel */ + if (max_txpower_avg > priv->tx_power_user_lmt) + priv->tx_power_user_lmt = max_txpower_avg; + + /* + * Update the tx_power_lmt_in_half_dbm to + * the highest power supported by any channel + */ + if (max_txpower_in_half_dbm > + priv->tx_power_lmt_in_half_dbm) + priv->tx_power_lmt_in_half_dbm = + max_txpower_in_half_dbm; + } + } +} diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index b4deef4e91db..f525d55f2c0f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -312,4 +312,10 @@ static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags) return cpu_to_le32(flags|(u32)rate); } +/* eeprom */ +void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv); +void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac); +int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv); +void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv); + #endif /* __iwl_agn_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index 66eccb12159d..87cd10ff285d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -136,78 +136,6 @@ static const u8 iwl_eeprom_band_7[] = { /* 5.2 ht40 channel */ 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157 }; -/** - * struct iwl_txpwr_section: eeprom section information - * @offset: indirect address into eeprom image - * @count: number of "struct iwl_eeprom_enhanced_txpwr" in this section - * @band: band type for the section - * @is_common - true: common section, false: channel section - * @is_cck - true: cck section, false: not cck section - * @is_ht_40 - true: all channel in the section are HT40 channel, - * false: legacy or HT 20 MHz - * ignore if it is common section - * @iwl_eeprom_section_channel: channel array in the section, - * ignore if common section - */ -struct iwl_txpwr_section { - u32 offset; - u8 count; - enum ieee80211_band band; - bool is_common; - bool is_cck; - bool is_ht40; - u8 iwl_eeprom_section_channel[EEPROM_MAX_TXPOWER_SECTION_ELEMENTS]; -}; - -/** - * section 1 - 3 are regulatory tx power apply to all channels based on - * modulation: CCK, OFDM - * Band: 2.4GHz, 5.2GHz - * section 4 - 10 are regulatory tx power apply to specified channels - * For example: - * 1L - Channel 1 Legacy - * 1HT - Channel 1 HT - * (1,+1) - Channel 1 HT40 "_above_" - * - * Section 1: all CCK channels - * Section 2: all 2.4 GHz OFDM (Legacy, HT and HT40) channels - * Section 3: all 5.2 GHz OFDM (Legacy, HT and HT40) channels - * Section 4: 2.4 GHz 20MHz channels: 1L, 1HT, 2L, 2HT, 10L, 10HT, 11L, 11HT - * Section 5: 2.4 GHz 40MHz channels: (1,+1) (2,+1) (6,+1) (7,+1) (9,+1) - * Section 6: 5.2 GHz 20MHz channels: 36L, 64L, 100L, 36HT, 64HT, 100HT - * Section 7: 5.2 GHz 40MHz channels: (36,+1) (60,+1) (100,+1) - * Section 8: 2.4 GHz channel: 13L, 13HT - * Section 9: 2.4 GHz channel: 140L, 140HT - * Section 10: 2.4 GHz 40MHz channels: (132,+1) (44,+1) - * - */ -static const struct iwl_txpwr_section enhinfo[] = { - { EEPROM_LB_CCK_20_COMMON, 1, IEEE80211_BAND_2GHZ, true, true, false }, - { EEPROM_LB_OFDM_COMMON, 3, IEEE80211_BAND_2GHZ, true, false, false }, - { EEPROM_HB_OFDM_COMMON, 3, IEEE80211_BAND_5GHZ, true, false, false }, - { EEPROM_LB_OFDM_20_BAND, 8, IEEE80211_BAND_2GHZ, - false, false, false, - {1, 1, 2, 2, 10, 10, 11, 11 } }, - { EEPROM_LB_OFDM_HT40_BAND, 5, IEEE80211_BAND_2GHZ, - false, false, true, - { 1, 2, 6, 7, 9 } }, - { EEPROM_HB_OFDM_20_BAND, 6, IEEE80211_BAND_5GHZ, - false, false, false, - { 36, 64, 100, 36, 64, 100 } }, - { EEPROM_HB_OFDM_HT40_BAND, 3, IEEE80211_BAND_5GHZ, - false, false, true, - { 36, 60, 100 } }, - { EEPROM_LB_OFDM_20_CHANNEL_13, 2, IEEE80211_BAND_2GHZ, - false, false, false, - { 13, 13 } }, - { EEPROM_HB_OFDM_20_CHANNEL_140, 2, IEEE80211_BAND_5GHZ, - false, false, false, - { 140, 140 } }, - { EEPROM_HB_OFDM_HT40_BAND_1, 2, IEEE80211_BAND_5GHZ, - false, false, true, - { 132, 44 } }, -}; - /****************************************************************************** * * EEPROM related functions @@ -289,46 +217,6 @@ static int iwlcore_get_nvm_type(struct iwl_priv *priv) return nvm_type; } -/* - * 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 iwl_priv *priv) -{ - u16 count; - int ret; - - for (count = 0; count < EEPROM_SEM_RETRY_LIMIT; count++) { - /* Request semaphore */ - iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, - CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); - - /* See if we got it */ - 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(priv, "Acquired semaphore after %d tries.\n", - count+1); - return ret; - } - } - - return ret; -} -EXPORT_SYMBOL(iwlcore_eeprom_acquire_semaphore); - -void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv) -{ - iwl_clear_bit(priv, CSR_HW_IF_CONFIG_REG, - CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); - -} -EXPORT_SYMBOL(iwlcore_eeprom_release_semaphore); - const u8 *iwlcore_eeprom_query_addr(const struct iwl_priv *priv, size_t offset) { BUG_ON(offset >= priv->cfg->base_params->eeprom_size); @@ -490,6 +378,20 @@ static int iwl_find_otp_image(struct iwl_priv *priv, return -EINVAL; } +const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset) +{ + return priv->cfg->ops->lib->eeprom_ops.query_addr(priv, offset); +} +EXPORT_SYMBOL(iwl_eeprom_query_addr); + +u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset) +{ + if (!priv->eeprom) + return 0; + return (u16)priv->eeprom[offset] | ((u16)priv->eeprom[offset + 1] << 8); +} +EXPORT_SYMBOL(iwl_eeprom_query16); + /** * iwl_eeprom_init - read EEPROM contents * @@ -616,53 +518,6 @@ void iwl_eeprom_free(struct iwl_priv *priv) } EXPORT_SYMBOL(iwl_eeprom_free); -int iwl_eeprom_check_version(struct iwl_priv *priv) -{ - u16 eeprom_ver; - u16 calib_ver; - - eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION); - calib_ver = priv->cfg->ops->lib->eeprom_ops.calib_version(priv); - - if (eeprom_ver < priv->cfg->eeprom_ver || - calib_ver < priv->cfg->eeprom_calib_ver) - goto err; - - IWL_INFO(priv, "device EEPROM VER=0x%x, CALIB=0x%x\n", - eeprom_ver, calib_ver); - - return 0; -err: - IWL_ERR(priv, "Unsupported (too old) EEPROM VER=0x%x < 0x%x CALIB=0x%x < 0x%x\n", - eeprom_ver, priv->cfg->eeprom_ver, - calib_ver, priv->cfg->eeprom_calib_ver); - return -EINVAL; - -} -EXPORT_SYMBOL(iwl_eeprom_check_version); - -const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset) -{ - return priv->cfg->ops->lib->eeprom_ops.query_addr(priv, offset); -} -EXPORT_SYMBOL(iwl_eeprom_query_addr); - -u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset) -{ - if (!priv->eeprom) - return 0; - return (u16)priv->eeprom[offset] | ((u16)priv->eeprom[offset + 1] << 8); -} -EXPORT_SYMBOL(iwl_eeprom_query16); - -void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac) -{ - const u8 *addr = priv->cfg->ops->lib->eeprom_ops.query_addr(priv, - EEPROM_MAC_ADDRESS); - memcpy(mac, addr, ETH_ALEN); -} -EXPORT_SYMBOL(iwl_eeprom_get_mac); - static void iwl_init_band_reference(const struct iwl_priv *priv, int eep_band, int *eeprom_ch_count, const struct iwl_eeprom_channel **eeprom_ch_info, @@ -721,7 +576,6 @@ static void iwl_init_band_reference(const struct iwl_priv *priv, #define CHECK_AND_PRINT(x) ((eeprom_ch->flags & EEPROM_CHANNEL_##x) \ ? # x " " : "") - /** * iwl_mod_ht40_chan_info - Copy ht40 channel info into driver's priv. * @@ -765,205 +619,6 @@ static int iwl_mod_ht40_chan_info(struct iwl_priv *priv, return 0; } -/** - * iwl_get_max_txpower_avg - get the highest tx power from all chains. - * find the highest tx power from all chains for the channel - */ -static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv, - struct iwl_eeprom_enhanced_txpwr *enhanced_txpower, - int element, s8 *max_txpower_in_half_dbm) -{ - s8 max_txpower_avg = 0; /* (dBm) */ - - IWL_DEBUG_INFO(priv, "%d - " - "chain_a: %d dB chain_b: %d dB " - "chain_c: %d dB mimo2: %d dB mimo3: %d dB\n", - element, - enhanced_txpower[element].chain_a_max >> 1, - enhanced_txpower[element].chain_b_max >> 1, - enhanced_txpower[element].chain_c_max >> 1, - enhanced_txpower[element].mimo2_max >> 1, - enhanced_txpower[element].mimo3_max >> 1); - /* Take the highest tx power from any valid chains */ - if ((priv->cfg->valid_tx_ant & ANT_A) && - (enhanced_txpower[element].chain_a_max > max_txpower_avg)) - max_txpower_avg = enhanced_txpower[element].chain_a_max; - if ((priv->cfg->valid_tx_ant & ANT_B) && - (enhanced_txpower[element].chain_b_max > max_txpower_avg)) - max_txpower_avg = enhanced_txpower[element].chain_b_max; - if ((priv->cfg->valid_tx_ant & ANT_C) && - (enhanced_txpower[element].chain_c_max > max_txpower_avg)) - max_txpower_avg = enhanced_txpower[element].chain_c_max; - if (((priv->cfg->valid_tx_ant == ANT_AB) | - (priv->cfg->valid_tx_ant == ANT_BC) | - (priv->cfg->valid_tx_ant == ANT_AC)) && - (enhanced_txpower[element].mimo2_max > max_txpower_avg)) - max_txpower_avg = enhanced_txpower[element].mimo2_max; - if ((priv->cfg->valid_tx_ant == ANT_ABC) && - (enhanced_txpower[element].mimo3_max > max_txpower_avg)) - max_txpower_avg = enhanced_txpower[element].mimo3_max; - - /* - * max. tx power in EEPROM is in 1/2 dBm format - * convert from 1/2 dBm to dBm (round-up convert) - * but we also do not want to loss 1/2 dBm resolution which - * will impact performance - */ - *max_txpower_in_half_dbm = max_txpower_avg; - return (max_txpower_avg & 0x01) + (max_txpower_avg >> 1); -} - -/** - * iwl_update_common_txpower: update channel tx power - * update tx power per band based on EEPROM enhanced tx power info. - */ -static s8 iwl_update_common_txpower(struct iwl_priv *priv, - struct iwl_eeprom_enhanced_txpwr *enhanced_txpower, - int section, int element, s8 *max_txpower_in_half_dbm) -{ - struct iwl_channel_info *ch_info; - int ch; - bool is_ht40 = false; - s8 max_txpower_avg; /* (dBm) */ - - /* it is common section, contain all type (Legacy, HT and HT40) - * based on the element in the section to determine - * is it HT 40 or not - */ - if (element == EEPROM_TXPOWER_COMMON_HT40_INDEX) - is_ht40 = true; - max_txpower_avg = - iwl_get_max_txpower_avg(priv, enhanced_txpower, - element, max_txpower_in_half_dbm); - - ch_info = priv->channel_info; - - for (ch = 0; ch < priv->channel_count; ch++) { - /* find matching band and update tx power if needed */ - if ((ch_info->band == enhinfo[section].band) && - (ch_info->max_power_avg < max_txpower_avg) && - (!is_ht40)) { - /* Update regulatory-based run-time data */ - ch_info->max_power_avg = ch_info->curr_txpow = - max_txpower_avg; - ch_info->scan_power = max_txpower_avg; - } - if ((ch_info->band == enhinfo[section].band) && is_ht40 && - (ch_info->ht40_max_power_avg < max_txpower_avg)) { - /* Update regulatory-based run-time data */ - ch_info->ht40_max_power_avg = max_txpower_avg; - } - ch_info++; - } - return max_txpower_avg; -} - -/** - * iwl_update_channel_txpower: update channel tx power - * update channel tx power based on EEPROM enhanced tx power info. - */ -static s8 iwl_update_channel_txpower(struct iwl_priv *priv, - struct iwl_eeprom_enhanced_txpwr *enhanced_txpower, - int section, int element, s8 *max_txpower_in_half_dbm) -{ - struct iwl_channel_info *ch_info; - int ch; - u8 channel; - s8 max_txpower_avg; /* (dBm) */ - - channel = enhinfo[section].iwl_eeprom_section_channel[element]; - max_txpower_avg = - iwl_get_max_txpower_avg(priv, enhanced_txpower, - element, max_txpower_in_half_dbm); - - ch_info = priv->channel_info; - for (ch = 0; ch < priv->channel_count; ch++) { - /* find matching channel and update tx power if needed */ - if (ch_info->channel == channel) { - if ((ch_info->max_power_avg < max_txpower_avg) && - (!enhinfo[section].is_ht40)) { - /* Update regulatory-based run-time data */ - ch_info->max_power_avg = max_txpower_avg; - ch_info->curr_txpow = max_txpower_avg; - ch_info->scan_power = max_txpower_avg; - } - if ((enhinfo[section].is_ht40) && - (ch_info->ht40_max_power_avg < max_txpower_avg)) { - /* Update regulatory-based run-time data */ - ch_info->ht40_max_power_avg = max_txpower_avg; - } - break; - } - ch_info++; - } - return max_txpower_avg; -} - -/** - * iwlcore_eeprom_enhanced_txpower: process enhanced tx power info - */ -void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv) -{ - int eeprom_section_count = 0; - int section, element; - struct iwl_eeprom_enhanced_txpwr *enhanced_txpower; - u32 offset; - s8 max_txpower_avg; /* (dBm) */ - s8 max_txpower_in_half_dbm; /* (half-dBm) */ - - /* Loop through all the sections - * adjust bands and channel's max tx power - * Set the tx_power_user_lmt to the highest power - * supported by any channels and chains - */ - for (section = 0; section < ARRAY_SIZE(enhinfo); section++) { - eeprom_section_count = enhinfo[section].count; - offset = enhinfo[section].offset; - enhanced_txpower = (struct iwl_eeprom_enhanced_txpwr *) - iwl_eeprom_query_addr(priv, offset); - - /* - * check for valid entry - - * different version of EEPROM might contain different set - * of enhanced tx power table - * always check for valid entry before process - * the information - */ - if (!enhanced_txpower->common || enhanced_txpower->reserved) - continue; - - for (element = 0; element < eeprom_section_count; element++) { - if (enhinfo[section].is_common) - max_txpower_avg = - iwl_update_common_txpower(priv, - enhanced_txpower, section, - element, - &max_txpower_in_half_dbm); - else - max_txpower_avg = - iwl_update_channel_txpower(priv, - enhanced_txpower, section, - element, - &max_txpower_in_half_dbm); - - /* Update the tx_power_user_lmt to the highest power - * supported by any channel */ - if (max_txpower_avg > priv->tx_power_user_lmt) - priv->tx_power_user_lmt = max_txpower_avg; - - /* - * Update the tx_power_lmt_in_half_dbm to - * the highest power supported by any channel - */ - if (max_txpower_in_half_dbm > - priv->tx_power_lmt_in_half_dbm) - priv->tx_power_lmt_in_half_dbm = - max_txpower_in_half_dbm; - } - } -} -EXPORT_SYMBOL(iwlcore_eeprom_enhanced_txpower); - #define CHECK_AND_PRINT_I(x) ((eeprom_ch_info[ch].flags & EEPROM_CHANNEL_##x) \ ? # x " " : "") @@ -1161,4 +816,3 @@ const struct iwl_channel_info *iwl_get_channel_info(const struct iwl_priv *priv, return NULL; } 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 2ae0a11e523b..d9b590625ae4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h @@ -501,18 +501,13 @@ struct iwl_eeprom_ops { }; -void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac); int iwl_eeprom_init(struct iwl_priv *priv); void iwl_eeprom_free(struct iwl_priv *priv); int iwl_eeprom_check_version(struct iwl_priv *priv); const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset); -u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset); - 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); +u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset); const u8 *iwlcore_eeprom_query_addr(const struct iwl_priv *priv, size_t offset); -void iwlcore_eeprom_enhanced_txpower(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 *iwl_get_channel_info( From 898c914a0871ea7e5557b77156d4358c0f15d98a Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 12 Oct 2010 14:02:53 +0200 Subject: [PATCH 110/127] ath9k: do not track cycle counter updates in powersave mode While the chip is in powersave mode, the cycle counter updates do not contain useful values. While the chip is in full sleep, the rx_clear signal stays high, indicating a busy medium. To ensure sane values, update cycle counters before going into powersave, and clear them right after switching back to awake. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/main.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index bcd3892dca8d..74ff51d4c339 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -121,6 +121,7 @@ bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode) void ath9k_ps_wakeup(struct ath_softc *sc) { + struct ath_common *common = ath9k_hw_common(sc->sc_ah); unsigned long flags; spin_lock_irqsave(&sc->sc_pm_lock, flags); @@ -129,18 +130,33 @@ void ath9k_ps_wakeup(struct ath_softc *sc) ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE); + /* + * While the hardware is asleep, the cycle counters contain no + * useful data. Better clear them now so that they don't mess up + * survey data results. + */ + spin_lock(&common->cc_lock); + ath_hw_cycle_counters_update(common); + memset(&common->cc_survey, 0, sizeof(common->cc_survey)); + spin_unlock(&common->cc_lock); + unlock: spin_unlock_irqrestore(&sc->sc_pm_lock, flags); } void ath9k_ps_restore(struct ath_softc *sc) { + struct ath_common *common = ath9k_hw_common(sc->sc_ah); unsigned long flags; spin_lock_irqsave(&sc->sc_pm_lock, flags); if (--sc->ps_usecount != 0) goto unlock; + spin_lock(&common->cc_lock); + ath_hw_cycle_counters_update(common); + spin_unlock(&common->cc_lock); + if (sc->ps_idle) ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP); else if (sc->ps_enabled && @@ -196,7 +212,8 @@ static void ath_update_survey_stats(struct ath_softc *sc) struct ath_cycle_counters *cc = &common->cc_survey; unsigned int div = common->clockrate * 1000; - ath_hw_cycle_counters_update(common); + if (ah->power_mode == ATH9K_PM_AWAKE) + ath_hw_cycle_counters_update(common); if (cc->cycles > 0) { survey->filled |= SURVEY_INFO_CHANNEL_TIME | From e49f913750bb8745085cc4c547912c330cd3eacb Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 12 Oct 2010 16:08:01 +0200 Subject: [PATCH 111/127] ath9k_hw: fix division by zero in the ANI monitor code The commit "ath9k_hw: remove code duplication in phy error counter handling" split off some duplicate code into a separate function, but did not have a return code for aborting ANI processing based on counter values. This introduced a divide by zero issue. This patch adds the missing return code check in ath9k_hw_ani_monitor Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ani.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index 3aa8fb1ad77f..9297f574b71c 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c @@ -633,7 +633,7 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning) REGWRITE_BUFFER_FLUSH(ah); } -static void ath9k_hw_ani_read_counters(struct ath_hw *ah) +static bool ath9k_hw_ani_read_counters(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); struct ar5416AniState *aniState = &ah->curchan->ani; @@ -646,10 +646,10 @@ static void ath9k_hw_ani_read_counters(struct ath_hw *ah) ath_hw_cycle_counters_update(common); listenTime = ath_hw_get_listen_time(common); - if (listenTime < 0) { + if (listenTime <= 0) { ah->stats.ast_ani_lneg++; ath9k_ani_restart(ah); - return; + return false; } if (!use_new_ani(ah)) { @@ -683,7 +683,7 @@ static void ath9k_hw_ani_read_counters(struct ath_hw *ah) REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); } - return; + return false; } ofdmPhyErrCnt = phyCnt1 - ofdm_base; @@ -695,7 +695,7 @@ static void ath9k_hw_ani_read_counters(struct ath_hw *ah) ah->stats.ast_ani_cckerrs += cckPhyErrCnt - aniState->cckPhyErrCount; aniState->cckPhyErrCount = cckPhyErrCnt; - + return true; } void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan) @@ -711,7 +711,8 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan) if (WARN_ON(!aniState)) return; - ath9k_hw_ani_read_counters(ah); + if (!ath9k_hw_ani_read_counters(ah)) + return; ofdmPhyErrRate = aniState->ofdmPhyErrCount * 1000 / aniState->listenTime; From 431c74821432a6078d54f08de7cd561f8ef8f1ba Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 12 Oct 2010 16:08:02 +0200 Subject: [PATCH 112/127] ath9k_hw: fix PHY counter overflow handling in ANI v1 PHY counter overflows need to be checked for the old ANI version, because of its use of interrupt based counter overflow reports when the counters exceed the configured thresholds. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ani.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index 9297f574b71c..63ccb39cdcd4 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c @@ -664,7 +664,7 @@ static bool ath9k_hw_ani_read_counters(struct ath_hw *ah) phyCnt1 = REG_READ(ah, AR_PHY_ERR_1); phyCnt2 = REG_READ(ah, AR_PHY_ERR_2); - if (use_new_ani(ah) && (phyCnt1 < ofdm_base || phyCnt2 < cck_base)) { + if (!use_new_ani(ah) && (phyCnt1 < ofdm_base || phyCnt2 < cck_base)) { if (phyCnt1 < ofdm_base) { ath_print(common, ATH_DBG_ANI, "phyCnt1 0x%x, resetting " From 88eac2dad876a58b9c6a4c4805c3fc27b02c048f Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 12 Oct 2010 16:08:03 +0200 Subject: [PATCH 113/127] ath9k: add missing locking around ath9k_hw_proc_mib_event ath9k_hw_proc_mib_event updates the cycle counters, so it common->cc_lock must be acquired. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 74ff51d4c339..2c7f28e022b8 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -779,7 +779,9 @@ irqreturn_t ath_isr(int irq, void *dev) * it will clear whatever condition caused * the interrupt. */ + spin_lock(&common->cc_lock); ath9k_hw_proc_mib_event(ah); + spin_unlock(&common->cc_lock); ath9k_hw_set_interrupts(ah, ah->imask); } From 772d5515635fef5bc7a9d0efee785b58b0181ee5 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 13 Oct 2010 16:43:26 +0200 Subject: [PATCH 114/127] ath9k: make rate control debugfs stats per station Move them to the same debugfs file that the other rc modules use. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/debug.c | 93 -------------------- drivers/net/wireless/ath/ath9k/debug.h | 21 ----- drivers/net/wireless/ath/ath9k/rc.c | 115 ++++++++++++++++++++++++- drivers/net/wireless/ath/ath9k/rc.h | 11 +++ 4 files changed, 124 insertions(+), 116 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 74a4570dc87f..7f764e3d1c0a 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -378,95 +378,6 @@ static const struct file_operations fops_interrupt = { .owner = THIS_MODULE }; -void ath_debug_stat_rc(struct ath_softc *sc, int final_rate) -{ - struct ath_rc_stats *stats; - - stats = &sc->debug.stats.rcstats[final_rate]; - stats->success++; -} - -void ath_debug_stat_retries(struct ath_softc *sc, int rix, - int xretries, int retries, u8 per) -{ - struct ath_rc_stats *stats = &sc->debug.stats.rcstats[rix]; - - stats->xretries += xretries; - stats->retries += retries; - stats->per = per; -} - -static ssize_t read_file_rcstat(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath_softc *sc = file->private_data; - char *buf; - unsigned int len = 0, max; - int i = 0; - ssize_t retval; - - if (sc->cur_rate_table == NULL) - return 0; - - max = 80 + sc->cur_rate_table->rate_cnt * 1024 + 1; - buf = kmalloc(max, GFP_KERNEL); - if (buf == NULL) - return -ENOMEM; - - len += sprintf(buf, "%6s %6s %6s " - "%10s %10s %10s %10s\n", - "HT", "MCS", "Rate", - "Success", "Retries", "XRetries", "PER"); - - for (i = 0; i < sc->cur_rate_table->rate_cnt; i++) { - u32 ratekbps = sc->cur_rate_table->info[i].ratekbps; - struct ath_rc_stats *stats = &sc->debug.stats.rcstats[i]; - char mcs[5]; - char htmode[5]; - int used_mcs = 0, used_htmode = 0; - - if (WLAN_RC_PHY_HT(sc->cur_rate_table->info[i].phy)) { - used_mcs = snprintf(mcs, 5, "%d", - sc->cur_rate_table->info[i].ratecode); - - if (WLAN_RC_PHY_40(sc->cur_rate_table->info[i].phy)) - used_htmode = snprintf(htmode, 5, "HT40"); - else if (WLAN_RC_PHY_20(sc->cur_rate_table->info[i].phy)) - used_htmode = snprintf(htmode, 5, "HT20"); - else - used_htmode = snprintf(htmode, 5, "????"); - } - - mcs[used_mcs] = '\0'; - htmode[used_htmode] = '\0'; - - len += snprintf(buf + len, max - len, - "%6s %6s %3u.%d: " - "%10u %10u %10u %10u\n", - htmode, - mcs, - ratekbps / 1000, - (ratekbps % 1000) / 100, - stats->success, - stats->retries, - stats->xretries, - stats->per); - } - - if (len > max) - len = max; - - retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); - kfree(buf); - return retval; -} - -static const struct file_operations fops_rcstat = { - .read = read_file_rcstat, - .open = ath9k_debugfs_open, - .owner = THIS_MODULE -}; - static const char * ath_wiphy_state_str(enum ath_wiphy_state state) { switch (state) { @@ -977,10 +888,6 @@ int ath9k_init_debug(struct ath_hw *ah) sc, &fops_interrupt)) goto err; - if (!debugfs_create_file("rcstat", S_IRUSR, sc->debug.debugfs_phy, - sc, &fops_rcstat)) - goto err; - if (!debugfs_create_file("wiphy", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, sc, &fops_wiphy)) goto err; diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index 822b6f3f23c5..bb0823242ba0 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h @@ -80,13 +80,6 @@ struct ath_interrupt_stats { u32 bb_watchdog; }; -struct ath_rc_stats { - u32 success; - u32 retries; - u32 xretries; - u8 per; -}; - /** * struct ath_tx_stats - Statistics about TX * @tx_pkts_all: No. of total frames transmitted, including ones that @@ -160,7 +153,6 @@ struct ath_rx_stats { struct ath_stats { struct ath_interrupt_stats istats; - struct ath_rc_stats rcstats[RATE_TABLE_SIZE]; struct ath_tx_stats txstats[ATH9K_NUM_TX_QUEUES]; struct ath_rx_stats rxstats; }; @@ -177,12 +169,9 @@ void ath9k_exit_debug(struct ath_hw *ah); int ath9k_debug_create_root(void); void ath9k_debug_remove_root(void); void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status); -void ath_debug_stat_rc(struct ath_softc *sc, int final_rate); void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq, struct ath_buf *bf, struct ath_tx_status *ts); void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs); -void ath_debug_stat_retries(struct ath_softc *sc, int rix, - int xretries, int retries, u8 per); #else @@ -209,11 +198,6 @@ static inline void ath_debug_stat_interrupt(struct ath_softc *sc, { } -static inline void ath_debug_stat_rc(struct ath_softc *sc, - int final_rate) -{ -} - static inline void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq, struct ath_buf *bf, @@ -226,11 +210,6 @@ static inline void ath_debug_stat_rx(struct ath_softc *sc, { } -static inline void ath_debug_stat_retries(struct ath_softc *sc, int rix, - int xretries, int retries, u8 per) -{ -} - #endif /* CONFIG_ATH9K_DEBUGFS */ #endif /* DEBUG_H */ diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index abebf2466a13..5db3a12356ec 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -1026,6 +1026,16 @@ static bool ath_rc_update_per(struct ath_softc *sc, return state_change; } +static void ath_debug_stat_retries(struct ath_rate_priv *rc, int rix, + int xretries, int retries, u8 per) +{ + struct ath_rc_stats *stats = &rc->rcstats[rix]; + + stats->xretries += xretries; + stats->retries += retries; + stats->per = per; +} + /* Update PER, RSSI and whatever else that the code thinks it is doing. If you can make sense of all this, you really need to go out more. */ @@ -1098,7 +1108,7 @@ static void ath_rc_update_ht(struct ath_softc *sc, ath_rc_priv->per_down_time = now_msec; } - ath_debug_stat_retries(sc, tx_rate, xretries, retries, + ath_debug_stat_retries(ath_rc_priv, tx_rate, xretries, retries, ath_rc_priv->per[tx_rate]); } @@ -1294,6 +1304,7 @@ static void ath_rc_init(struct ath_softc *sc, ath_rc_sort_validrates(rate_table, ath_rc_priv); ath_rc_priv->rate_max_phy = ath_rc_priv->valid_rate_index[k-4]; sc->cur_rate_table = rate_table; + ath_rc_priv->rate_table = rate_table; ath_print(common, ATH_DBG_CONFIG, "RC Initialized with capabilities: 0x%x\n", @@ -1340,6 +1351,15 @@ static bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, /* mac80211 Rate Control callbacks */ /***********************************/ +static void ath_debug_stat_rc(struct ath_rate_priv *rc, int final_rate) +{ + struct ath_rc_stats *stats; + + stats = &rc->rcstats[final_rate]; + stats->success++; +} + + static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, struct ieee80211_sta *sta, void *priv_sta, struct sk_buff *skb) @@ -1419,7 +1439,7 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, } } - ath_debug_stat_rc(sc, ath_rc_get_rateindex(sc->cur_rate_table, + ath_debug_stat_rc(ath_rc_priv, ath_rc_get_rateindex(sc->cur_rate_table, &tx_info->status.rates[final_ts_idx])); } @@ -1521,6 +1541,94 @@ static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband, } } +#ifdef CONFIG_ATH9K_DEBUGFS + +static int ath9k_debugfs_open(struct inode *inode, struct file *file) +{ + file->private_data = inode->i_private; + return 0; +} + +static ssize_t read_file_rcstat(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath_rate_priv *rc = file->private_data; + char *buf; + unsigned int len = 0, max; + int i = 0; + ssize_t retval; + + if (rc->rate_table == NULL) + return 0; + + max = 80 + rc->rate_table->rate_cnt * 1024 + 1; + buf = kmalloc(max, GFP_KERNEL); + if (buf == NULL) + return -ENOMEM; + + len += sprintf(buf, "%6s %6s %6s " + "%10s %10s %10s %10s\n", + "HT", "MCS", "Rate", + "Success", "Retries", "XRetries", "PER"); + + for (i = 0; i < rc->rate_table->rate_cnt; i++) { + u32 ratekbps = rc->rate_table->info[i].ratekbps; + struct ath_rc_stats *stats = &rc->rcstats[i]; + char mcs[5]; + char htmode[5]; + int used_mcs = 0, used_htmode = 0; + + if (WLAN_RC_PHY_HT(rc->rate_table->info[i].phy)) { + used_mcs = snprintf(mcs, 5, "%d", + rc->rate_table->info[i].ratecode); + + if (WLAN_RC_PHY_40(rc->rate_table->info[i].phy)) + used_htmode = snprintf(htmode, 5, "HT40"); + else if (WLAN_RC_PHY_20(rc->rate_table->info[i].phy)) + used_htmode = snprintf(htmode, 5, "HT20"); + else + used_htmode = snprintf(htmode, 5, "????"); + } + + mcs[used_mcs] = '\0'; + htmode[used_htmode] = '\0'; + + len += snprintf(buf + len, max - len, + "%6s %6s %3u.%d: " + "%10u %10u %10u %10u\n", + htmode, + mcs, + ratekbps / 1000, + (ratekbps % 1000) / 100, + stats->success, + stats->retries, + stats->xretries, + stats->per); + } + + if (len > max) + len = max; + + retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); + kfree(buf); + return retval; +} + +static const struct file_operations fops_rcstat = { + .read = read_file_rcstat, + .open = ath9k_debugfs_open, + .owner = THIS_MODULE +}; + +static void ath_rate_add_sta_debugfs(void *priv, void *priv_sta, + struct dentry *dir) +{ + struct ath_rate_priv *rc = priv_sta; + debugfs_create_file("rc_stats", S_IRUGO, dir, rc, &fops_rcstat); +} + +#endif /* CONFIG_ATH9K_DEBUGFS */ + static void *ath_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) { struct ath_wiphy *aphy = hw->priv; @@ -1567,6 +1675,9 @@ static struct rate_control_ops ath_rate_ops = { .free = ath_rate_free, .alloc_sta = ath_rate_alloc_sta, .free_sta = ath_rate_free_sta, +#ifdef CONFIG_ATH9K_DEBUGFS + .add_sta_debugfs = ath_rate_add_sta_debugfs, +#endif }; int ath_rate_control_register(void) diff --git a/drivers/net/wireless/ath/ath9k/rc.h b/drivers/net/wireless/ath/ath9k/rc.h index fbb1d33ee4b7..2f46a2266ba1 100644 --- a/drivers/net/wireless/ath/ath9k/rc.h +++ b/drivers/net/wireless/ath/ath9k/rc.h @@ -176,6 +176,13 @@ struct ath_rateset { u8 rs_rates[ATH_RATE_MAX]; }; +struct ath_rc_stats { + u32 success; + u32 retries; + u32 xretries; + u8 per; +}; + /** * struct ath_rate_priv - Rate Control priv data * @state: RC state @@ -212,6 +219,10 @@ struct ath_rate_priv { struct ath_rateset neg_rates; struct ath_rateset neg_ht_rates; struct ath_rate_softc *asc; + const struct ath_rate_table *rate_table; + + struct dentry *debugfs_rcstats; + struct ath_rc_stats rcstats[RATE_TABLE_SIZE]; }; #define ATH_TX_INFO_FRAME_TYPE_INTERNAL (1 << 0) From 4e9900180eb72b3b22fc9742999045b11607eb24 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 13 Oct 2010 16:43:27 +0200 Subject: [PATCH 115/127] ath9k: remove sc->cur_rate_table and sc->cur_rate_mode Set the rate table in the rc module properly based on band and HT capabilities instead, which was already partially done, but not for every mode. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 2 -- drivers/net/wireless/ath/ath9k/main.c | 35 -------------------------- drivers/net/wireless/ath/ath9k/rc.c | 24 ++++++------------ 3 files changed, 8 insertions(+), 53 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 4e81fe35aa3f..e435c1d38826 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -623,8 +623,6 @@ struct ath_softc { struct ath_rx rx; struct ath_tx tx; struct ath_beacon beacon; - const struct ath_rate_table *cur_rate_table; - enum wireless_mode cur_rate_mode; struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; struct ath_led radio_led; diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 2c7f28e022b8..3ff0e476c2b3 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -18,36 +18,6 @@ #include "ath9k.h" #include "btcoex.h" -static void ath_cache_conf_rate(struct ath_softc *sc, - struct ieee80211_conf *conf) -{ - switch (conf->channel->band) { - case IEEE80211_BAND_2GHZ: - if (conf_is_ht20(conf)) - sc->cur_rate_mode = ATH9K_MODE_11NG_HT20; - else if (conf_is_ht40_minus(conf)) - sc->cur_rate_mode = ATH9K_MODE_11NG_HT40MINUS; - else if (conf_is_ht40_plus(conf)) - sc->cur_rate_mode = ATH9K_MODE_11NG_HT40PLUS; - else - sc->cur_rate_mode = ATH9K_MODE_11G; - break; - case IEEE80211_BAND_5GHZ: - if (conf_is_ht20(conf)) - sc->cur_rate_mode = ATH9K_MODE_11NA_HT20; - else if (conf_is_ht40_minus(conf)) - sc->cur_rate_mode = ATH9K_MODE_11NA_HT40MINUS; - else if (conf_is_ht40_plus(conf)) - sc->cur_rate_mode = ATH9K_MODE_11NA_HT40PLUS; - else - sc->cur_rate_mode = ATH9K_MODE_11A; - break; - default: - BUG_ON(1); - break; - } -} - static void ath_update_txpow(struct ath_softc *sc) { struct ath_hw *ah = sc->sc_ah; @@ -306,7 +276,6 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, goto ps_restore; } - ath_cache_conf_rate(sc, &hw->conf); ath_update_txpow(sc); ath9k_hw_set_interrupts(ah, ah->imask); @@ -1013,8 +982,6 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) * that changes the channel so update any state that * might change as a result. */ - ath_cache_conf_rate(sc, &hw->conf); - ath_update_txpow(sc); if ((sc->sc_flags & SC_OP_BEACONS) || !(sc->sc_flags & (SC_OP_OFFCHANNEL))) @@ -1221,8 +1188,6 @@ static int ath9k_start(struct ieee80211_hw *hw) if (ah->caps.hw_caps & ATH9K_HW_CAP_HT) ah->imask |= ATH9K_INT_CST; - ath_cache_conf_rate(sc, &hw->conf); - sc->sc_flags &= ~SC_OP_INVALID; /* Disable BMISS interrupt when we're not associated */ diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 5db3a12356ec..2d3a67fc9bbf 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -791,7 +791,7 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, */ try_per_rate = 4; - rate_table = sc->cur_rate_table; + rate_table = ath_rc_priv->rate_table; rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table, &is_probe); /* @@ -1048,7 +1048,7 @@ static void ath_rc_update_ht(struct ath_softc *sc, int rate; u8 last_per; bool state_change = false; - const struct ath_rate_table *rate_table = sc->cur_rate_table; + const struct ath_rate_table *rate_table = ath_rc_priv->rate_table; int size = ath_rc_priv->rate_table_size; if ((tx_rate < 0) || (tx_rate > rate_table->rate_cnt)) @@ -1150,7 +1150,7 @@ static void ath_rc_tx_status(struct ath_softc *sc, u8 flags; u32 i = 0, rix; - rate_table = sc->cur_rate_table; + rate_table = ath_rc_priv->rate_table; /* * If the first rate is not the final index, there @@ -1231,7 +1231,6 @@ struct ath_rate_table *ath_choose_rate_table(struct ath_softc *sc, ath_print(common, ATH_DBG_CONFIG, "Choosing rate table for mode: %d\n", mode); - sc->cur_rate_mode = mode; return hw_rate_table[mode]; } @@ -1303,7 +1302,6 @@ static void ath_rc_init(struct ath_softc *sc, ath_rc_priv->max_valid_rate = k; ath_rc_sort_validrates(rate_table, ath_rc_priv); ath_rc_priv->rate_max_phy = ath_rc_priv->valid_rate_index[k-4]; - sc->cur_rate_table = rate_table; ath_rc_priv->rate_table = rate_table; ath_print(common, ATH_DBG_CONFIG, @@ -1439,8 +1437,9 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, } } - ath_debug_stat_rc(ath_rc_priv, ath_rc_get_rateindex(sc->cur_rate_table, - &tx_info->status.rates[final_ts_idx])); + ath_debug_stat_rc(ath_rc_priv, + ath_rc_get_rateindex(ath_rc_priv->rate_table, + &tx_info->status.rates[final_ts_idx])); } static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, @@ -1480,14 +1479,8 @@ static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, /* Choose rate table first */ - if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) || - (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT) || - (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC)) { - rate_table = ath_choose_rate_table(sc, sband->band, - sta->ht_cap.ht_supported, is_cw40); - } else { - rate_table = hw_rate_table[sc->cur_rate_mode]; - } + rate_table = ath_choose_rate_table(sc, sband->band, + sta->ht_cap.ht_supported, is_cw40); ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta, is_cw40, is_sgi); ath_rc_init(sc, priv_sta, sband, sta, rate_table); @@ -1536,7 +1529,6 @@ static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband, ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_CONFIG, "Operating HT Bandwidth changed to: %d\n", sc->hw->conf.channel_type); - sc->cur_rate_table = hw_rate_table[sc->cur_rate_mode]; } } } From d4659912b557e9f68c0ad8be14e2cafd3210dd16 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 14 Oct 2010 16:02:39 +0200 Subject: [PATCH 116/127] ath9k_hw: remove enum wireless_mode and its users The wireless mode bitfield was only used to detect 2.4 and 5 GHz support, which can be simplified by using ATH9K_HW_CAP_* capabilities. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc_drv_init.c | 12 +++--- drivers/net/wireless/ath/ath9k/hw.c | 34 ++------------- drivers/net/wireless/ath/ath9k/hw.h | 15 +------ drivers/net/wireless/ath/ath9k/init.c | 12 +++--- drivers/net/wireless/ath/ath9k/rc.c | 41 ++++--------------- 5 files changed, 25 insertions(+), 89 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index bbb54bc28a44..3d7b97f1b3ae 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -566,7 +566,7 @@ static void ath9k_init_crypto(struct ath9k_htc_priv *priv) static void ath9k_init_channels_rates(struct ath9k_htc_priv *priv) { - if (test_bit(ATH9K_MODE_11G, priv->ah->caps.wireless_modes)) { + if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) { priv->sbands[IEEE80211_BAND_2GHZ].channels = ath9k_2ghz_channels; priv->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ; @@ -577,7 +577,7 @@ static void ath9k_init_channels_rates(struct ath9k_htc_priv *priv) ARRAY_SIZE(ath9k_legacy_rates); } - if (test_bit(ATH9K_MODE_11A, priv->ah->caps.wireless_modes)) { + if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) { priv->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_channels; priv->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ; priv->sbands[IEEE80211_BAND_5GHZ].n_channels = @@ -740,18 +740,18 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv, hw->extra_tx_headroom = sizeof(struct tx_frame_hdr) + sizeof(struct htc_frame_hdr) + 4; - if (test_bit(ATH9K_MODE_11G, priv->ah->caps.wireless_modes)) + if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->sbands[IEEE80211_BAND_2GHZ]; - if (test_bit(ATH9K_MODE_11A, priv->ah->caps.wireless_modes)) + if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &priv->sbands[IEEE80211_BAND_5GHZ]; if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_HT) { - if (test_bit(ATH9K_MODE_11G, priv->ah->caps.wireless_modes)) + if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) setup_ht_cap(priv, &priv->sbands[IEEE80211_BAND_2GHZ].ht_cap); - if (test_bit(ATH9K_MODE_11A, priv->ah->caps.wireless_modes)) + if (priv->ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) setup_ht_cap(priv, &priv->sbands[IEEE80211_BAND_5GHZ].ht_cap); } diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index f5d79177770c..cc13ee117823 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1800,37 +1800,11 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) return -EINVAL; } - bitmap_zero(pCap->wireless_modes, ATH9K_MODE_MAX); + if (eeval & AR5416_OPFLAGS_11A) + pCap->hw_caps |= ATH9K_HW_CAP_5GHZ; - if (eeval & AR5416_OPFLAGS_11A) { - set_bit(ATH9K_MODE_11A, pCap->wireless_modes); - if (ah->config.ht_enable) { - if (!(eeval & AR5416_OPFLAGS_N_5G_HT20)) - set_bit(ATH9K_MODE_11NA_HT20, - pCap->wireless_modes); - if (!(eeval & AR5416_OPFLAGS_N_5G_HT40)) { - set_bit(ATH9K_MODE_11NA_HT40PLUS, - pCap->wireless_modes); - set_bit(ATH9K_MODE_11NA_HT40MINUS, - pCap->wireless_modes); - } - } - } - - if (eeval & AR5416_OPFLAGS_11G) { - set_bit(ATH9K_MODE_11G, pCap->wireless_modes); - if (ah->config.ht_enable) { - if (!(eeval & AR5416_OPFLAGS_N_2G_HT20)) - set_bit(ATH9K_MODE_11NG_HT20, - pCap->wireless_modes); - if (!(eeval & AR5416_OPFLAGS_N_2G_HT40)) { - set_bit(ATH9K_MODE_11NG_HT40PLUS, - pCap->wireless_modes); - set_bit(ATH9K_MODE_11NG_HT40MINUS, - pCap->wireless_modes); - } - } - } + if (eeval & AR5416_OPFLAGS_11G) + pCap->hw_caps |= ATH9K_HW_CAP_2GHZ; pCap->tx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_TX_MASK); /* diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 6b9233472fbf..d032939768b0 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -164,18 +164,6 @@ enum ath_ini_subsys { ATH_INI_NUM_SPLIT, }; -enum wireless_mode { - ATH9K_MODE_11A = 0, - ATH9K_MODE_11G, - ATH9K_MODE_11NA_HT20, - ATH9K_MODE_11NG_HT20, - ATH9K_MODE_11NA_HT40PLUS, - ATH9K_MODE_11NA_HT40MINUS, - ATH9K_MODE_11NG_HT40PLUS, - ATH9K_MODE_11NG_HT40MINUS, - ATH9K_MODE_MAX, -}; - enum ath9k_hw_caps { ATH9K_HW_CAP_HT = BIT(0), ATH9K_HW_CAP_RFSILENT = BIT(1), @@ -190,11 +178,12 @@ enum ath9k_hw_caps { ATH9K_HW_CAP_SGI_20 = BIT(10), ATH9K_HW_CAP_PAPRD = BIT(11), ATH9K_HW_CAP_ANT_DIV_COMB = BIT(12), + ATH9K_HW_CAP_2GHZ = BIT(13), + ATH9K_HW_CAP_5GHZ = BIT(14), }; struct ath9k_hw_capabilities { u32 hw_caps; /* ATH9K_HW_CAP_* from ath9k_hw_caps */ - DECLARE_BITMAP(wireless_modes, ATH9K_MODE_MAX); /* ATH9K_MODE_* */ u16 total_queues; u16 keycache_size; u16 low_5ghz_chan, high_5ghz_chan; diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index a4c5ed41b176..bc6c4df9712c 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -485,7 +485,7 @@ static int ath9k_init_channels_rates(struct ath_softc *sc) ARRAY_SIZE(ath9k_5ghz_chantable) != ATH9K_NUM_CHANNELS); - if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes)) { + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) { channels = kmemdup(ath9k_2ghz_chantable, sizeof(ath9k_2ghz_chantable), GFP_KERNEL); if (!channels) @@ -500,7 +500,7 @@ static int ath9k_init_channels_rates(struct ath_softc *sc) ARRAY_SIZE(ath9k_legacy_rates); } - if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) { + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) { channels = kmemdup(ath9k_5ghz_chantable, sizeof(ath9k_5ghz_chantable), GFP_KERNEL); if (!channels) { @@ -681,17 +681,17 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) hw->rate_control_algorithm = "ath9k_rate_control"; #endif - if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes)) + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &sc->sbands[IEEE80211_BAND_2GHZ]; - if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &sc->sbands[IEEE80211_BAND_5GHZ]; if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) { - if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes)) + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap); - if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) + if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap); } diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index 2d3a67fc9bbf..0cee90cf8dc9 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -378,17 +378,6 @@ static const struct ath_rate_table ar5416_11g_ratetable = { 0, /* Phy rates allowed initially */ }; -static const struct ath_rate_table *hw_rate_table[ATH9K_MODE_MAX] = { - [ATH9K_MODE_11A] = &ar5416_11a_ratetable, - [ATH9K_MODE_11G] = &ar5416_11g_ratetable, - [ATH9K_MODE_11NA_HT20] = &ar5416_11na_ratetable, - [ATH9K_MODE_11NG_HT20] = &ar5416_11ng_ratetable, - [ATH9K_MODE_11NA_HT40PLUS] = &ar5416_11na_ratetable, - [ATH9K_MODE_11NA_HT40MINUS] = &ar5416_11na_ratetable, - [ATH9K_MODE_11NG_HT40PLUS] = &ar5416_11ng_ratetable, - [ATH9K_MODE_11NG_HT40MINUS] = &ar5416_11ng_ratetable, -}; - static int ath_rc_get_rateindex(const struct ath_rate_table *rate_table, struct ieee80211_tx_rate *rate); @@ -1200,38 +1189,23 @@ static void ath_rc_tx_status(struct ath_softc *sc, static const struct ath_rate_table *ath_choose_rate_table(struct ath_softc *sc, enum ieee80211_band band, - bool is_ht, - bool is_cw_40) + bool is_ht) { - int mode = 0; struct ath_common *common = ath9k_hw_common(sc->sc_ah); switch(band) { case IEEE80211_BAND_2GHZ: - mode = ATH9K_MODE_11G; if (is_ht) - mode = ATH9K_MODE_11NG_HT20; - if (is_cw_40) - mode = ATH9K_MODE_11NG_HT40PLUS; - break; + return &ar5416_11ng_ratetable; + return &ar5416_11g_ratetable; case IEEE80211_BAND_5GHZ: - mode = ATH9K_MODE_11A; if (is_ht) - mode = ATH9K_MODE_11NA_HT20; - if (is_cw_40) - mode = ATH9K_MODE_11NA_HT40PLUS; - break; + return &ar5416_11na_ratetable; + return &ar5416_11a_ratetable; default: ath_print(common, ATH_DBG_CONFIG, "Invalid band\n"); return NULL; } - - BUG_ON(mode >= ATH9K_MODE_MAX); - - ath_print(common, ATH_DBG_CONFIG, - "Choosing rate table for mode: %d\n", mode); - - return hw_rate_table[mode]; } static void ath_rc_init(struct ath_softc *sc, @@ -1480,7 +1454,7 @@ static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, /* Choose rate table first */ rate_table = ath_choose_rate_table(sc, sband->band, - sta->ht_cap.ht_supported, is_cw40); + sta->ht_cap.ht_supported); ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta, is_cw40, is_sgi); ath_rc_init(sc, priv_sta, sband, sta, rate_table); @@ -1520,8 +1494,7 @@ static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband, if ((local_cw40 != oper_cw40) || (local_sgi != oper_sgi)) { rate_table = ath_choose_rate_table(sc, sband->band, - sta->ht_cap.ht_supported, - oper_cw40); + sta->ht_cap.ht_supported); ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta, oper_cw40, oper_sgi); ath_rc_init(sc, priv_sta, sband, sta, rate_table); From 4f329c043ba3495f0f97ec782948cbba7bd01047 Mon Sep 17 00:00:00 2001 From: Paul Fox Date: Wed, 13 Oct 2010 20:14:56 +0100 Subject: [PATCH 117/127] libertas: Communicate USB transfer errors The return code was being overwritten with -1. Useful for debugging. Signed-off-by: Paul Fox Signed-off-by: Daniel Drake Acked-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/libertas/if_usb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c index 238de10a4b57..b70f0f490118 100644 --- a/drivers/net/wireless/libertas/if_usb.c +++ b/drivers/net/wireless/libertas/if_usb.c @@ -484,11 +484,12 @@ static int if_usb_reset_device(struct if_usb_card *cardp) */ static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload, uint16_t nb) { - int ret = -1; + int ret; /* check if device is removed */ if (cardp->surprise_removed) { lbs_deb_usbd(&cardp->udev->dev, "Device removed\n"); + ret = -ENODEV; goto tx_ret; } @@ -501,7 +502,6 @@ static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload, uint16_t nb if ((ret = usb_submit_urb(cardp->tx_urb, GFP_ATOMIC))) { lbs_deb_usbd(&cardp->udev->dev, "usb_submit_urb failed: %d\n", ret); - ret = -1; } else { lbs_deb_usb2(&cardp->udev->dev, "usb_submit_urb success\n"); ret = 0; From 94a40c0c6bcc47ceba12e0247c5a23fb1e6c81e4 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Thu, 14 Oct 2010 10:50:26 +0530 Subject: [PATCH 118/127] ath9k_htc: set probe request rx filter This patch enables to receive probe request frames on p2p client mode. Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/htc_drv_main.c | 1 + drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index f12591f5d02a..55c80866dfc6 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -1454,6 +1454,7 @@ out: FIF_PSPOLL | \ FIF_OTHER_BSS | \ FIF_BCN_PRBRESP_PROMISC | \ + FIF_PROBE_REQ | \ FIF_FCSFAIL) static void ath9k_htc_configure_filter(struct ieee80211_hw *hw, diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index c99600aff76d..3d19b5bc937f 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -369,8 +369,7 @@ u32 ath9k_htc_calcrxfilter(struct ath9k_htc_priv *priv) | ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST | ATH9K_RX_FILTER_MCAST; - /* If not a STA, enable processing of Probe Requests */ - if (ah->opmode != NL80211_IFTYPE_STATION) + if (priv->rxfilter & FIF_PROBE_REQ) rfilt |= ATH9K_RX_FILTER_PROBEREQ; /* From 9ebad4ab87f2ffa6eca825327721e647c7457264 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 14 Oct 2010 13:41:35 +0200 Subject: [PATCH 119/127] radiotap: fix vendor namespace parsing There's a bug with radiotap vendor namespace parsing if you don't register for the given namespace extensions. Fix this by passing only the unknown vendor namespaces and the registered data to frontends, but not both. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/wireless/radiotap.c | 58 +++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 26 deletions(-) diff --git a/net/wireless/radiotap.c b/net/wireless/radiotap.c index c774bc0f155e..dbe35e138e94 100644 --- a/net/wireless/radiotap.c +++ b/net/wireless/radiotap.c @@ -201,7 +201,7 @@ int ieee80211_radiotap_iterator_next( { while (1) { int hit = 0; - int pad, align, size, subns, vnslen; + int pad, align, size, subns; uint32_t oui; /* if no more EXT bits, that's it */ @@ -261,6 +261,27 @@ int ieee80211_radiotap_iterator_next( if (pad) iterator->_arg += align - pad; + if (iterator->_arg_index % 32 == IEEE80211_RADIOTAP_VENDOR_NAMESPACE) { + int vnslen; + + if ((unsigned long)iterator->_arg + size - + (unsigned long)iterator->_rtheader > + (unsigned long)iterator->_max_length) + return -EINVAL; + + oui = (*iterator->_arg << 16) | + (*(iterator->_arg + 1) << 8) | + *(iterator->_arg + 2); + subns = *(iterator->_arg + 3); + + find_ns(iterator, oui, subns); + + vnslen = get_unaligned_le16(iterator->_arg + 4); + iterator->_next_ns_data = iterator->_arg + size + vnslen; + if (!iterator->current_namespace) + size += vnslen; + } + /* * this is what we will return to user, but we need to * move on first so next call has something fresh to test @@ -287,40 +308,25 @@ int ieee80211_radiotap_iterator_next( /* these special ones are valid in each bitmap word */ switch (iterator->_arg_index % 32) { case IEEE80211_RADIOTAP_VENDOR_NAMESPACE: - iterator->_bitmap_shifter >>= 1; - iterator->_arg_index++; - iterator->_reset_on_ext = 1; - vnslen = get_unaligned_le16(iterator->this_arg + 4); - iterator->_next_ns_data = iterator->_arg + vnslen; - oui = (*iterator->this_arg << 16) | - (*(iterator->this_arg + 1) << 8) | - *(iterator->this_arg + 2); - subns = *(iterator->this_arg + 3); - - find_ns(iterator, oui, subns); - iterator->is_radiotap_ns = 0; - /* allow parsers to show this information */ + /* + * If parser didn't register this vendor + * namespace with us, allow it to show it + * as 'raw. Do do that, set argument index + * to vendor namespace. + */ iterator->this_arg_index = IEEE80211_RADIOTAP_VENDOR_NAMESPACE; - iterator->this_arg_size += vnslen; - if ((unsigned long)iterator->this_arg + - iterator->this_arg_size - - (unsigned long)iterator->_rtheader > - (unsigned long)(unsigned long)iterator->_max_length) - return -EINVAL; - hit = 1; - break; + if (!iterator->current_namespace) + hit = 1; + goto next_entry; case IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE: - iterator->_bitmap_shifter >>= 1; - iterator->_arg_index++; - iterator->_reset_on_ext = 1; iterator->current_namespace = &radiotap_ns; iterator->is_radiotap_ns = 1; - break; + goto next_entry; case IEEE80211_RADIOTAP_EXT: /* * bit 31 was set, there is more From 204a665ba390bca861ad7b1a061f3ccded0e7eab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Thu, 14 Oct 2010 19:33:34 +0200 Subject: [PATCH 120/127] b43: N-PHY: replace N-specific radio_chanspec with common code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_common.h | 1 + drivers/net/wireless/b43/phy_n.c | 55 +++++++++++---------------- drivers/net/wireless/b43/phy_n.h | 7 +--- 3 files changed, 26 insertions(+), 37 deletions(-) diff --git a/drivers/net/wireless/b43/phy_common.h b/drivers/net/wireless/b43/phy_common.h index 6dcd0334ed02..0e6194228845 100644 --- a/drivers/net/wireless/b43/phy_common.h +++ b/drivers/net/wireless/b43/phy_common.h @@ -253,6 +253,7 @@ struct b43_phy { /* Current channel */ unsigned int channel; + u16 channel_freq; enum nl80211_channel_type channel_type; /* PHY TX errors counter. */ diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index e532901246b6..3ade0191f319 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -81,21 +81,6 @@ static inline bool b43_channel_type_is_40mhz( channel_type == NL80211_CHAN_HT40PLUS); } -static inline bool b43_empty_chanspec(struct b43_chanspec *chanspec) -{ - return !chanspec->channel && !chanspec->sideband && - !chanspec->b_width && !chanspec->b_freq; -} - -static inline bool b43_eq_chanspecs(struct b43_chanspec *chanspec1, - struct b43_chanspec *chanspec2) -{ - return (chanspec1->channel == chanspec2->channel && - chanspec1->sideband == chanspec2->sideband && - chanspec1->b_width == chanspec2->b_width && - chanspec1->b_freq == chanspec2->b_freq); -} - void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna) {//TODO } @@ -788,7 +773,7 @@ static void b43_nphy_spur_workaround(struct b43_wldev *dev) { struct b43_phy_n *nphy = dev->phy.n; - u8 channel = nphy->radio_chanspec.channel; + u8 channel = dev->phy.channel; int tone[2] = { 57, 58 }; u32 noise[2] = { 0x3FF, 0x3FF }; @@ -862,9 +847,9 @@ static void b43_nphy_adjust_lna_gain_table(struct b43_wldev *dev) gain[0] = 6; gain[1] = 6; } else { - tmp = 40370 - 315 * nphy->radio_chanspec.channel; + tmp = 40370 - 315 * dev->phy.channel; gain[0] = ((tmp >> 13) + ((tmp >> 12) & 1)); - tmp = 23242 - 224 * nphy->radio_chanspec.channel; + tmp = 23242 - 224 * dev->phy.channel; gain[1] = ((tmp >> 13) + ((tmp >> 12) & 1)); } } else { @@ -2090,12 +2075,12 @@ static void b43_nphy_restore_rssi_cal(struct b43_wldev *dev) u16 *rssical_phy_regs = NULL; if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { - if (b43_empty_chanspec(&nphy->rssical_chanspec_2G)) + if (!nphy->rssical_chanspec_2G.center_freq) return; rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_2G; rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_2G; } else { - if (b43_empty_chanspec(&nphy->rssical_chanspec_5G)) + if (!nphy->rssical_chanspec_5G.center_freq) return; rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_5G; rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G; @@ -2551,7 +2536,8 @@ static void b43_nphy_save_cal(struct b43_wldev *dev) txcal_radio_regs[2] = b43_radio_read(dev, 0x8D); txcal_radio_regs[3] = b43_radio_read(dev, 0xBC); } - *iqcal_chanspec = nphy->radio_chanspec; + iqcal_chanspec->center_freq = dev->phy.channel_freq; + iqcal_chanspec->channel_type = dev->phy.channel_type; b43_ntab_write_bulk(dev, B43_NTAB16(15, 80), 8, table); if (nphy->hang_avoid) @@ -2572,12 +2558,12 @@ static void b43_nphy_restore_cal(struct b43_wldev *dev) struct b43_phy_n_iq_comp *rxcal_coeffs = NULL; if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { - if (b43_empty_chanspec(&nphy->iqcal_chanspec_2G)) + if (!nphy->iqcal_chanspec_2G.center_freq) return; table = nphy->cal_cache.txcal_coeffs_2G; loft = &nphy->cal_cache.txcal_coeffs_2G[5]; } else { - if (b43_empty_chanspec(&nphy->iqcal_chanspec_5G)) + if (!nphy->iqcal_chanspec_5G.center_freq) return; table = nphy->cal_cache.txcal_coeffs_5G; loft = &nphy->cal_cache.txcal_coeffs_5G[5]; @@ -2822,7 +2808,10 @@ static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev, b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length, nphy->txiqlocal_bestc); nphy->txiqlocal_coeffsvalid = true; - nphy->txiqlocal_chanspec = nphy->radio_chanspec; + nphy->txiqlocal_chanspec.center_freq = + dev->phy.channel_freq; + nphy->txiqlocal_chanspec.channel_type = + dev->phy.channel_type; } else { length = 11; if (dev->phy.rev < 3) @@ -2858,7 +2847,8 @@ static void b43_nphy_reapply_tx_cal_coeffs(struct b43_wldev *dev) bool equal = true; if (!nphy->txiqlocal_coeffsvalid || - b43_eq_chanspecs(&nphy->txiqlocal_chanspec, &nphy->radio_chanspec)) + nphy->txiqlocal_chanspec.center_freq != dev->phy.channel_freq || + nphy->txiqlocal_chanspec.channel_type != dev->phy.channel_type) return; b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 7, buffer); @@ -3264,11 +3254,9 @@ int b43_phy_initn(struct b43_wldev *dev) do_rssi_cal = false; if (phy->rev >= 3) { if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) - do_rssi_cal = - b43_empty_chanspec(&nphy->rssical_chanspec_2G); + do_rssi_cal = !nphy->rssical_chanspec_2G.center_freq; else - do_rssi_cal = - b43_empty_chanspec(&nphy->rssical_chanspec_5G); + do_rssi_cal = !nphy->rssical_chanspec_5G.center_freq; if (do_rssi_cal) b43_nphy_rssi_cal(dev); @@ -3280,9 +3268,9 @@ int b43_phy_initn(struct b43_wldev *dev) if (!((nphy->measure_hold & 0x6) != 0)) { if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) - do_cal = b43_empty_chanspec(&nphy->iqcal_chanspec_2G); + do_cal = !nphy->iqcal_chanspec_2G.center_freq; else - do_cal = b43_empty_chanspec(&nphy->iqcal_chanspec_5G); + do_cal = !nphy->iqcal_chanspec_5G.center_freq; if (nphy->mute) do_cal = false; @@ -3411,7 +3399,10 @@ static int b43_nphy_set_channel(struct b43_wldev *dev, return -ESRCH; } - nphy->radio_chanspec.channel = channel->hw_value; + /* Channel is set later in common code, but we need to set it on our + own to let this function's subcalls work properly. */ + phy->channel = channel->hw_value; + phy->channel_freq = channel->center_freq; if (b43_channel_type_is_40mhz(phy->channel_type) != b43_channel_type_is_40mhz(channel_type)) diff --git a/drivers/net/wireless/b43/phy_n.h b/drivers/net/wireless/b43/phy_n.h index e7acae278be0..f915c83b46d7 100644 --- a/drivers/net/wireless/b43/phy_n.h +++ b/drivers/net/wireless/b43/phy_n.h @@ -927,10 +927,8 @@ struct b43_wldev; struct b43_chanspec { - u8 channel; - u8 sideband; - u8 b_width; - u8 b_freq; + u16 center_freq; + enum nl80211_channel_type channel_type; }; struct b43_phy_n_iq_comp { @@ -984,7 +982,6 @@ struct b43_phy_n { u16 papd_epsilon_offset[2]; s32 preamble_override; u32 bb_mult_save; - struct b43_chanspec radio_chanspec; bool gain_boost; bool elna_gain_config; From 5818e989360b06d249cf1d88e7d4601ca70a7322 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Thu, 14 Oct 2010 19:33:35 +0200 Subject: [PATCH 121/127] b43: N-PHY: fix typo: read table when caching IQ LO calibration (do not write) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/phy_n.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 3ade0191f319..dd9cfe58f762 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -2538,7 +2538,7 @@ static void b43_nphy_save_cal(struct b43_wldev *dev) } iqcal_chanspec->center_freq = dev->phy.channel_freq; iqcal_chanspec->channel_type = dev->phy.channel_type; - b43_ntab_write_bulk(dev, B43_NTAB16(15, 80), 8, table); + b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 8, table); if (nphy->hang_avoid) b43_nphy_stay_in_carrier_search(dev, 0); From 6db507ff9232cc3874306f7b25b399cb2cdc1675 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Thu, 14 Oct 2010 19:33:36 +0200 Subject: [PATCH 122/127] b43: N-PHY: put radio-specific code in separated file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/Makefile | 1 + drivers/net/wireless/b43/phy_n.c | 1 + drivers/net/wireless/b43/phy_n.h | 210 ---- drivers/net/wireless/b43/radio_2055.c | 1332 ++++++++++++++++++++++++ drivers/net/wireless/b43/radio_2055.h | 254 +++++ drivers/net/wireless/b43/tables_nphy.c | 1309 ----------------------- drivers/net/wireless/b43/tables_nphy.h | 44 - 7 files changed, 1588 insertions(+), 1563 deletions(-) create mode 100644 drivers/net/wireless/b43/radio_2055.c create mode 100644 drivers/net/wireless/b43/radio_2055.h diff --git a/drivers/net/wireless/b43/Makefile b/drivers/net/wireless/b43/Makefile index 5e83b6f0a3a0..0398c7cd2d15 100644 --- a/drivers/net/wireless/b43/Makefile +++ b/drivers/net/wireless/b43/Makefile @@ -1,6 +1,7 @@ b43-y += main.o b43-y += tables.o b43-$(CONFIG_B43_NPHY) += tables_nphy.o +b43-$(CONFIG_B43_NPHY) += radio_2055.o b43-y += phy_common.o b43-y += phy_g.o b43-y += phy_a.o diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index dd9cfe58f762..284b54fde41d 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -29,6 +29,7 @@ #include "b43.h" #include "phy_n.h" #include "tables_nphy.h" +#include "radio_2055.h" #include "main.h" struct nphy_txgains { diff --git a/drivers/net/wireless/b43/phy_n.h b/drivers/net/wireless/b43/phy_n.h index f915c83b46d7..c144e59a708b 100644 --- a/drivers/net/wireless/b43/phy_n.h +++ b/drivers/net/wireless/b43/phy_n.h @@ -714,216 +714,6 @@ #define B43_PHY_B_BBCFG B43_PHY_N_BMODE(0x001) /* BB config */ #define B43_PHY_B_TEST B43_PHY_N_BMODE(0x00A) - -/* Broadcom 2055 radio registers */ - -#define B2055_GEN_SPARE 0x00 /* GEN spare */ -#define B2055_SP_PINPD 0x02 /* SP PIN PD */ -#define B2055_C1_SP_RSSI 0x03 /* SP RSSI Core 1 */ -#define B2055_C1_SP_PDMISC 0x04 /* SP PD MISC Core 1 */ -#define B2055_C2_SP_RSSI 0x05 /* SP RSSI Core 2 */ -#define B2055_C2_SP_PDMISC 0x06 /* SP PD MISC Core 2 */ -#define B2055_C1_SP_RXGC1 0x07 /* SP RX GC1 Core 1 */ -#define B2055_C1_SP_RXGC2 0x08 /* SP RX GC2 Core 1 */ -#define B2055_C2_SP_RXGC1 0x09 /* SP RX GC1 Core 2 */ -#define B2055_C2_SP_RXGC2 0x0A /* SP RX GC2 Core 2 */ -#define B2055_C1_SP_LPFBWSEL 0x0B /* SP LPF BW select Core 1 */ -#define B2055_C2_SP_LPFBWSEL 0x0C /* SP LPF BW select Core 2 */ -#define B2055_C1_SP_TXGC1 0x0D /* SP TX GC1 Core 1 */ -#define B2055_C1_SP_TXGC2 0x0E /* SP TX GC2 Core 1 */ -#define B2055_C2_SP_TXGC1 0x0F /* SP TX GC1 Core 2 */ -#define B2055_C2_SP_TXGC2 0x10 /* SP TX GC2 Core 2 */ -#define B2055_MASTER1 0x11 /* Master control 1 */ -#define B2055_MASTER2 0x12 /* Master control 2 */ -#define B2055_PD_LGEN 0x13 /* PD LGEN */ -#define B2055_PD_PLLTS 0x14 /* PD PLL TS */ -#define B2055_C1_PD_LGBUF 0x15 /* PD Core 1 LGBUF */ -#define B2055_C1_PD_TX 0x16 /* PD Core 1 TX */ -#define B2055_C1_PD_RXTX 0x17 /* PD Core 1 RXTX */ -#define B2055_C1_PD_RSSIMISC 0x18 /* PD Core 1 RSSI MISC */ -#define B2055_C2_PD_LGBUF 0x19 /* PD Core 2 LGBUF */ -#define B2055_C2_PD_TX 0x1A /* PD Core 2 TX */ -#define B2055_C2_PD_RXTX 0x1B /* PD Core 2 RXTX */ -#define B2055_C2_PD_RSSIMISC 0x1C /* PD Core 2 RSSI MISC */ -#define B2055_PWRDET_LGEN 0x1D /* PWRDET LGEN */ -#define B2055_C1_PWRDET_LGBUF 0x1E /* PWRDET LGBUF Core 1 */ -#define B2055_C1_PWRDET_RXTX 0x1F /* PWRDET RXTX Core 1 */ -#define B2055_C2_PWRDET_LGBUF 0x20 /* PWRDET LGBUF Core 2 */ -#define B2055_C2_PWRDET_RXTX 0x21 /* PWRDET RXTX Core 2 */ -#define B2055_RRCCAL_CS 0x22 /* RRCCAL Control spare */ -#define B2055_RRCCAL_NOPTSEL 0x23 /* RRCCAL N OPT SEL */ -#define B2055_CAL_MISC 0x24 /* CAL MISC */ -#define B2055_CAL_COUT 0x25 /* CAL Counter out */ -#define B2055_CAL_COUT2 0x26 /* CAL Counter out 2 */ -#define B2055_CAL_CVARCTL 0x27 /* CAL CVAR Control */ -#define B2055_CAL_RVARCTL 0x28 /* CAL RVAR Control */ -#define B2055_CAL_LPOCTL 0x29 /* CAL LPO Control */ -#define B2055_CAL_TS 0x2A /* CAL TS */ -#define B2055_CAL_RCCALRTS 0x2B /* CAL RCCAL READ TS */ -#define B2055_CAL_RCALRTS 0x2C /* CAL RCAL READ TS */ -#define B2055_PADDRV 0x2D /* PAD driver */ -#define B2055_XOCTL1 0x2E /* XO Control 1 */ -#define B2055_XOCTL2 0x2F /* XO Control 2 */ -#define B2055_XOREGUL 0x30 /* XO Regulator */ -#define B2055_XOMISC 0x31 /* XO misc */ -#define B2055_PLL_LFC1 0x32 /* PLL LF C1 */ -#define B2055_PLL_CALVTH 0x33 /* PLL CAL VTH */ -#define B2055_PLL_LFC2 0x34 /* PLL LF C2 */ -#define B2055_PLL_REF 0x35 /* PLL reference */ -#define B2055_PLL_LFR1 0x36 /* PLL LF R1 */ -#define B2055_PLL_PFDCP 0x37 /* PLL PFD CP */ -#define B2055_PLL_IDAC_CPOPAMP 0x38 /* PLL IDAC CPOPAMP */ -#define B2055_PLL_CPREG 0x39 /* PLL CP Regulator */ -#define B2055_PLL_RCAL 0x3A /* PLL RCAL */ -#define B2055_RF_PLLMOD0 0x3B /* RF PLL MOD0 */ -#define B2055_RF_PLLMOD1 0x3C /* RF PLL MOD1 */ -#define B2055_RF_MMDIDAC1 0x3D /* RF MMD IDAC 1 */ -#define B2055_RF_MMDIDAC0 0x3E /* RF MMD IDAC 0 */ -#define B2055_RF_MMDSP 0x3F /* RF MMD spare */ -#define B2055_VCO_CAL1 0x40 /* VCO cal 1 */ -#define B2055_VCO_CAL2 0x41 /* VCO cal 2 */ -#define B2055_VCO_CAL3 0x42 /* VCO cal 3 */ -#define B2055_VCO_CAL4 0x43 /* VCO cal 4 */ -#define B2055_VCO_CAL5 0x44 /* VCO cal 5 */ -#define B2055_VCO_CAL6 0x45 /* VCO cal 6 */ -#define B2055_VCO_CAL7 0x46 /* VCO cal 7 */ -#define B2055_VCO_CAL8 0x47 /* VCO cal 8 */ -#define B2055_VCO_CAL9 0x48 /* VCO cal 9 */ -#define B2055_VCO_CAL10 0x49 /* VCO cal 10 */ -#define B2055_VCO_CAL11 0x4A /* VCO cal 11 */ -#define B2055_VCO_CAL12 0x4B /* VCO cal 12 */ -#define B2055_VCO_CAL13 0x4C /* VCO cal 13 */ -#define B2055_VCO_CAL14 0x4D /* VCO cal 14 */ -#define B2055_VCO_CAL15 0x4E /* VCO cal 15 */ -#define B2055_VCO_CAL16 0x4F /* VCO cal 16 */ -#define B2055_VCO_KVCO 0x50 /* VCO KVCO */ -#define B2055_VCO_CAPTAIL 0x51 /* VCO CAP TAIL */ -#define B2055_VCO_IDACVCO 0x52 /* VCO IDAC VCO */ -#define B2055_VCO_REG 0x53 /* VCO Regulator */ -#define B2055_PLL_RFVTH 0x54 /* PLL RF VTH */ -#define B2055_LGBUF_CENBUF 0x55 /* LGBUF CEN BUF */ -#define B2055_LGEN_TUNE1 0x56 /* LGEN tune 1 */ -#define B2055_LGEN_TUNE2 0x57 /* LGEN tune 2 */ -#define B2055_LGEN_IDAC1 0x58 /* LGEN IDAC 1 */ -#define B2055_LGEN_IDAC2 0x59 /* LGEN IDAC 2 */ -#define B2055_LGEN_BIASC 0x5A /* LGEN BIAS counter */ -#define B2055_LGEN_BIASIDAC 0x5B /* LGEN BIAS IDAC */ -#define B2055_LGEN_RCAL 0x5C /* LGEN RCAL */ -#define B2055_LGEN_DIV 0x5D /* LGEN div */ -#define B2055_LGEN_SPARE2 0x5E /* LGEN spare 2 */ -#define B2055_C1_LGBUF_ATUNE 0x5F /* Core 1 LGBUF A tune */ -#define B2055_C1_LGBUF_GTUNE 0x60 /* Core 1 LGBUF G tune */ -#define B2055_C1_LGBUF_DIV 0x61 /* Core 1 LGBUF div */ -#define B2055_C1_LGBUF_AIDAC 0x62 /* Core 1 LGBUF A IDAC */ -#define B2055_C1_LGBUF_GIDAC 0x63 /* Core 1 LGBUF G IDAC */ -#define B2055_C1_LGBUF_IDACFO 0x64 /* Core 1 LGBUF IDAC filter override */ -#define B2055_C1_LGBUF_SPARE 0x65 /* Core 1 LGBUF spare */ -#define B2055_C1_RX_RFSPC1 0x66 /* Core 1 RX RF SPC1 */ -#define B2055_C1_RX_RFR1 0x67 /* Core 1 RX RF reg 1 */ -#define B2055_C1_RX_RFR2 0x68 /* Core 1 RX RF reg 2 */ -#define B2055_C1_RX_RFRCAL 0x69 /* Core 1 RX RF RCAL */ -#define B2055_C1_RX_BB_BLCMP 0x6A /* Core 1 RX Baseband BUFI LPF CMP */ -#define B2055_C1_RX_BB_LPF 0x6B /* Core 1 RX Baseband LPF */ -#define B2055_C1_RX_BB_MIDACHP 0x6C /* Core 1 RX Baseband MIDAC High-pass */ -#define B2055_C1_RX_BB_VGA1IDAC 0x6D /* Core 1 RX Baseband VGA1 IDAC */ -#define B2055_C1_RX_BB_VGA2IDAC 0x6E /* Core 1 RX Baseband VGA2 IDAC */ -#define B2055_C1_RX_BB_VGA3IDAC 0x6F /* Core 1 RX Baseband VGA3 IDAC */ -#define B2055_C1_RX_BB_BUFOCTL 0x70 /* Core 1 RX Baseband BUFO Control */ -#define B2055_C1_RX_BB_RCCALCTL 0x71 /* Core 1 RX Baseband RCCAL Control */ -#define B2055_C1_RX_BB_RSSICTL1 0x72 /* Core 1 RX Baseband RSSI Control 1 */ -#define B2055_C1_RX_BB_RSSICTL2 0x73 /* Core 1 RX Baseband RSSI Control 2 */ -#define B2055_C1_RX_BB_RSSICTL3 0x74 /* Core 1 RX Baseband RSSI Control 3 */ -#define B2055_C1_RX_BB_RSSICTL4 0x75 /* Core 1 RX Baseband RSSI Control 4 */ -#define B2055_C1_RX_BB_RSSICTL5 0x76 /* Core 1 RX Baseband RSSI Control 5 */ -#define B2055_C1_RX_BB_REG 0x77 /* Core 1 RX Baseband Regulator */ -#define B2055_C1_RX_BB_SPARE1 0x78 /* Core 1 RX Baseband spare 1 */ -#define B2055_C1_RX_TXBBRCAL 0x79 /* Core 1 RX TX BB RCAL */ -#define B2055_C1_TX_RF_SPGA 0x7A /* Core 1 TX RF SGM PGA */ -#define B2055_C1_TX_RF_SPAD 0x7B /* Core 1 TX RF SGM PAD */ -#define B2055_C1_TX_RF_CNTPGA1 0x7C /* Core 1 TX RF counter PGA 1 */ -#define B2055_C1_TX_RF_CNTPAD1 0x7D /* Core 1 TX RF counter PAD 1 */ -#define B2055_C1_TX_RF_PGAIDAC 0x7E /* Core 1 TX RF PGA IDAC */ -#define B2055_C1_TX_PGAPADTN 0x7F /* Core 1 TX PGA PAD TN */ -#define B2055_C1_TX_PADIDAC1 0x80 /* Core 1 TX PAD IDAC 1 */ -#define B2055_C1_TX_PADIDAC2 0x81 /* Core 1 TX PAD IDAC 2 */ -#define B2055_C1_TX_MXBGTRIM 0x82 /* Core 1 TX MX B/G TRIM */ -#define B2055_C1_TX_RF_RCAL 0x83 /* Core 1 TX RF RCAL */ -#define B2055_C1_TX_RF_PADTSSI1 0x84 /* Core 1 TX RF PAD TSSI1 */ -#define B2055_C1_TX_RF_PADTSSI2 0x85 /* Core 1 TX RF PAD TSSI2 */ -#define B2055_C1_TX_RF_SPARE 0x86 /* Core 1 TX RF spare */ -#define B2055_C1_TX_RF_IQCAL1 0x87 /* Core 1 TX RF I/Q CAL 1 */ -#define B2055_C1_TX_RF_IQCAL2 0x88 /* Core 1 TX RF I/Q CAL 2 */ -#define B2055_C1_TXBB_RCCAL 0x89 /* Core 1 TXBB RC CAL Control */ -#define B2055_C1_TXBB_LPF1 0x8A /* Core 1 TXBB LPF 1 */ -#define B2055_C1_TX_VOSCNCL 0x8B /* Core 1 TX VOS CNCL */ -#define B2055_C1_TX_LPF_MXGMIDAC 0x8C /* Core 1 TX LPF MXGM IDAC */ -#define B2055_C1_TX_BB_MXGM 0x8D /* Core 1 TX BB MXGM */ -#define B2055_C2_LGBUF_ATUNE 0x8E /* Core 2 LGBUF A tune */ -#define B2055_C2_LGBUF_GTUNE 0x8F /* Core 2 LGBUF G tune */ -#define B2055_C2_LGBUF_DIV 0x90 /* Core 2 LGBUF div */ -#define B2055_C2_LGBUF_AIDAC 0x91 /* Core 2 LGBUF A IDAC */ -#define B2055_C2_LGBUF_GIDAC 0x92 /* Core 2 LGBUF G IDAC */ -#define B2055_C2_LGBUF_IDACFO 0x93 /* Core 2 LGBUF IDAC filter override */ -#define B2055_C2_LGBUF_SPARE 0x94 /* Core 2 LGBUF spare */ -#define B2055_C2_RX_RFSPC1 0x95 /* Core 2 RX RF SPC1 */ -#define B2055_C2_RX_RFR1 0x96 /* Core 2 RX RF reg 1 */ -#define B2055_C2_RX_RFR2 0x97 /* Core 2 RX RF reg 2 */ -#define B2055_C2_RX_RFRCAL 0x98 /* Core 2 RX RF RCAL */ -#define B2055_C2_RX_BB_BLCMP 0x99 /* Core 2 RX Baseband BUFI LPF CMP */ -#define B2055_C2_RX_BB_LPF 0x9A /* Core 2 RX Baseband LPF */ -#define B2055_C2_RX_BB_MIDACHP 0x9B /* Core 2 RX Baseband MIDAC High-pass */ -#define B2055_C2_RX_BB_VGA1IDAC 0x9C /* Core 2 RX Baseband VGA1 IDAC */ -#define B2055_C2_RX_BB_VGA2IDAC 0x9D /* Core 2 RX Baseband VGA2 IDAC */ -#define B2055_C2_RX_BB_VGA3IDAC 0x9E /* Core 2 RX Baseband VGA3 IDAC */ -#define B2055_C2_RX_BB_BUFOCTL 0x9F /* Core 2 RX Baseband BUFO Control */ -#define B2055_C2_RX_BB_RCCALCTL 0xA0 /* Core 2 RX Baseband RCCAL Control */ -#define B2055_C2_RX_BB_RSSICTL1 0xA1 /* Core 2 RX Baseband RSSI Control 1 */ -#define B2055_C2_RX_BB_RSSICTL2 0xA2 /* Core 2 RX Baseband RSSI Control 2 */ -#define B2055_C2_RX_BB_RSSICTL3 0xA3 /* Core 2 RX Baseband RSSI Control 3 */ -#define B2055_C2_RX_BB_RSSICTL4 0xA4 /* Core 2 RX Baseband RSSI Control 4 */ -#define B2055_C2_RX_BB_RSSICTL5 0xA5 /* Core 2 RX Baseband RSSI Control 5 */ -#define B2055_C2_RX_BB_REG 0xA6 /* Core 2 RX Baseband Regulator */ -#define B2055_C2_RX_BB_SPARE1 0xA7 /* Core 2 RX Baseband spare 1 */ -#define B2055_C2_RX_TXBBRCAL 0xA8 /* Core 2 RX TX BB RCAL */ -#define B2055_C2_TX_RF_SPGA 0xA9 /* Core 2 TX RF SGM PGA */ -#define B2055_C2_TX_RF_SPAD 0xAA /* Core 2 TX RF SGM PAD */ -#define B2055_C2_TX_RF_CNTPGA1 0xAB /* Core 2 TX RF counter PGA 1 */ -#define B2055_C2_TX_RF_CNTPAD1 0xAC /* Core 2 TX RF counter PAD 1 */ -#define B2055_C2_TX_RF_PGAIDAC 0xAD /* Core 2 TX RF PGA IDAC */ -#define B2055_C2_TX_PGAPADTN 0xAE /* Core 2 TX PGA PAD TN */ -#define B2055_C2_TX_PADIDAC1 0xAF /* Core 2 TX PAD IDAC 1 */ -#define B2055_C2_TX_PADIDAC2 0xB0 /* Core 2 TX PAD IDAC 2 */ -#define B2055_C2_TX_MXBGTRIM 0xB1 /* Core 2 TX MX B/G TRIM */ -#define B2055_C2_TX_RF_RCAL 0xB2 /* Core 2 TX RF RCAL */ -#define B2055_C2_TX_RF_PADTSSI1 0xB3 /* Core 2 TX RF PAD TSSI1 */ -#define B2055_C2_TX_RF_PADTSSI2 0xB4 /* Core 2 TX RF PAD TSSI2 */ -#define B2055_C2_TX_RF_SPARE 0xB5 /* Core 2 TX RF spare */ -#define B2055_C2_TX_RF_IQCAL1 0xB6 /* Core 2 TX RF I/Q CAL 1 */ -#define B2055_C2_TX_RF_IQCAL2 0xB7 /* Core 2 TX RF I/Q CAL 2 */ -#define B2055_C2_TXBB_RCCAL 0xB8 /* Core 2 TXBB RC CAL Control */ -#define B2055_C2_TXBB_LPF1 0xB9 /* Core 2 TXBB LPF 1 */ -#define B2055_C2_TX_VOSCNCL 0xBA /* Core 2 TX VOS CNCL */ -#define B2055_C2_TX_LPF_MXGMIDAC 0xBB /* Core 2 TX LPF MXGM IDAC */ -#define B2055_C2_TX_BB_MXGM 0xBC /* Core 2 TX BB MXGM */ -#define B2055_PRG_GCHP21 0xBD /* PRG GC HPVGA23 21 */ -#define B2055_PRG_GCHP22 0xBE /* PRG GC HPVGA23 22 */ -#define B2055_PRG_GCHP23 0xBF /* PRG GC HPVGA23 23 */ -#define B2055_PRG_GCHP24 0xC0 /* PRG GC HPVGA23 24 */ -#define B2055_PRG_GCHP25 0xC1 /* PRG GC HPVGA23 25 */ -#define B2055_PRG_GCHP26 0xC2 /* PRG GC HPVGA23 26 */ -#define B2055_PRG_GCHP27 0xC3 /* PRG GC HPVGA23 27 */ -#define B2055_PRG_GCHP28 0xC4 /* PRG GC HPVGA23 28 */ -#define B2055_PRG_GCHP29 0xC5 /* PRG GC HPVGA23 29 */ -#define B2055_PRG_GCHP30 0xC6 /* PRG GC HPVGA23 30 */ -#define B2055_C1_LNA_GAINBST 0xCD /* Core 1 LNA GAINBST */ -#define B2055_C1_B0NB_RSSIVCM 0xD2 /* Core 1 B0 narrow-band RSSI VCM */ -#define B2055_C1_GENSPARE2 0xD6 /* Core 1 GEN spare 2 */ -#define B2055_C2_LNA_GAINBST 0xD9 /* Core 2 LNA GAINBST */ -#define B2055_C2_B0NB_RSSIVCM 0xDE /* Core 2 B0 narrow-band RSSI VCM */ -#define B2055_C2_GENSPARE2 0xE2 /* Core 2 GEN spare 2 */ - - - struct b43_wldev; struct b43_chanspec { diff --git a/drivers/net/wireless/b43/radio_2055.c b/drivers/net/wireless/b43/radio_2055.c new file mode 100644 index 000000000000..1b5316586cbf --- /dev/null +++ b/drivers/net/wireless/b43/radio_2055.c @@ -0,0 +1,1332 @@ +/* + + Broadcom B43 wireless driver + IEEE 802.11n PHY and radio device data tables + + Copyright (c) 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 "radio_2055.h" +#include "phy_common.h" + +struct b2055_inittab_entry { + /* Value to write if we use the 5GHz band. */ + u16 ghz5; + /* Value to write if we use the 2.4GHz band. */ + u16 ghz2; + /* Flags */ + u8 flags; +#define B2055_INITTAB_ENTRY_OK 0x01 +#define B2055_INITTAB_UPLOAD 0x02 +}; +#define UPLOAD .flags = B2055_INITTAB_ENTRY_OK | B2055_INITTAB_UPLOAD +#define NOUPLOAD .flags = B2055_INITTAB_ENTRY_OK + +static const struct b2055_inittab_entry b2055_inittab [] = { + [B2055_SP_PINPD] = { .ghz5 = 0x0080, .ghz2 = 0x0080, NOUPLOAD, }, + [B2055_C1_SP_RSSI] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2055_C1_SP_PDMISC] = { .ghz5 = 0x0027, .ghz2 = 0x0027, NOUPLOAD, }, + [B2055_C2_SP_RSSI] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2055_C2_SP_PDMISC] = { .ghz5 = 0x0027, .ghz2 = 0x0027, NOUPLOAD, }, + [B2055_C1_SP_RXGC1] = { .ghz5 = 0x007F, .ghz2 = 0x007F, UPLOAD, }, + [B2055_C1_SP_RXGC2] = { .ghz5 = 0x0007, .ghz2 = 0x0007, UPLOAD, }, + [B2055_C2_SP_RXGC1] = { .ghz5 = 0x007F, .ghz2 = 0x007F, UPLOAD, }, + [B2055_C2_SP_RXGC2] = { .ghz5 = 0x0007, .ghz2 = 0x0007, UPLOAD, }, + [B2055_C1_SP_LPFBWSEL] = { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, }, + [B2055_C2_SP_LPFBWSEL] = { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, }, + [B2055_C1_SP_TXGC1] = { .ghz5 = 0x004F, .ghz2 = 0x004F, UPLOAD, }, + [B2055_C1_SP_TXGC2] = { .ghz5 = 0x0005, .ghz2 = 0x0005, UPLOAD, }, + [B2055_C2_SP_TXGC1] = { .ghz5 = 0x004F, .ghz2 = 0x004F, UPLOAD, }, + [B2055_C2_SP_TXGC2] = { .ghz5 = 0x0005, .ghz2 = 0x0005, UPLOAD, }, + [B2055_MASTER1] = { .ghz5 = 0x00D0, .ghz2 = 0x00D0, NOUPLOAD, }, + [B2055_MASTER2] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2055_PD_LGEN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2055_PD_PLLTS] = { .ghz5 = 0x0040, .ghz2 = 0x0040, NOUPLOAD, }, + [B2055_C1_PD_LGBUF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2055_C1_PD_TX] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2055_C1_PD_RXTX] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2055_C1_PD_RSSIMISC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2055_C2_PD_LGBUF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2055_C2_PD_TX] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2055_C2_PD_RXTX] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2055_C2_PD_RSSIMISC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2055_PWRDET_LGEN] = { .ghz5 = 0x00C0, .ghz2 = 0x00C0, NOUPLOAD, }, + [B2055_C1_PWRDET_LGBUF] = { .ghz5 = 0x00FF, .ghz2 = 0x00FF, NOUPLOAD, }, + [B2055_C1_PWRDET_RXTX] = { .ghz5 = 0x00C0, .ghz2 = 0x00C0, NOUPLOAD, }, + [B2055_C2_PWRDET_LGBUF] = { .ghz5 = 0x00FF, .ghz2 = 0x00FF, NOUPLOAD, }, + [B2055_C2_PWRDET_RXTX] = { .ghz5 = 0x00C0, .ghz2 = 0x00C0, NOUPLOAD, }, + [B2055_RRCCAL_CS] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2055_RRCCAL_NOPTSEL] = { .ghz5 = 0x002C, .ghz2 = 0x002C, NOUPLOAD, }, + [B2055_CAL_MISC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2055_CAL_COUT] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2055_CAL_COUT2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2055_CAL_CVARCTL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2055_CAL_RVARCTL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2055_CAL_LPOCTL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2055_CAL_TS] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2055_CAL_RCCALRTS] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2055_CAL_RCALRTS] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2055_PADDRV] = { .ghz5 = 0x00A4, .ghz2 = 0x00A4, NOUPLOAD, }, + [B2055_XOCTL1] = { .ghz5 = 0x0038, .ghz2 = 0x0038, NOUPLOAD, }, + [B2055_XOCTL2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2055_XOREGUL] = { .ghz5 = 0x0004, .ghz2 = 0x0004, UPLOAD, }, + [B2055_XOMISC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2055_PLL_LFC1] = { .ghz5 = 0x000A, .ghz2 = 0x000A, NOUPLOAD, }, + [B2055_PLL_CALVTH] = { .ghz5 = 0x0087, .ghz2 = 0x0087, NOUPLOAD, }, + [B2055_PLL_LFC2] = { .ghz5 = 0x0009, .ghz2 = 0x0009, NOUPLOAD, }, + [B2055_PLL_REF] = { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, }, + [B2055_PLL_LFR1] = { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, }, + [B2055_PLL_PFDCP] = { .ghz5 = 0x0018, .ghz2 = 0x0018, UPLOAD, }, + [B2055_PLL_IDAC_CPOPAMP] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, + [B2055_PLL_CPREG] = { .ghz5 = 0x0004, .ghz2 = 0x0004, UPLOAD, }, + [B2055_PLL_RCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, + [B2055_RF_PLLMOD0] = { .ghz5 = 0x009E, .ghz2 = 0x009E, NOUPLOAD, }, + [B2055_RF_PLLMOD1] = { .ghz5 = 0x0009, .ghz2 = 0x0009, NOUPLOAD, }, + [B2055_RF_MMDIDAC1] = { .ghz5 = 0x00C8, .ghz2 = 0x00C8, UPLOAD, }, + [B2055_RF_MMDIDAC0] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2055_RF_MMDSP] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2055_VCO_CAL1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2055_VCO_CAL2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2055_VCO_CAL3] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, + [B2055_VCO_CAL4] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2055_VCO_CAL5] = { .ghz5 = 0x0096, .ghz2 = 0x0096, NOUPLOAD, }, + [B2055_VCO_CAL6] = { .ghz5 = 0x003E, .ghz2 = 0x003E, NOUPLOAD, }, + [B2055_VCO_CAL7] = { .ghz5 = 0x003E, .ghz2 = 0x003E, NOUPLOAD, }, + [B2055_VCO_CAL8] = { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, }, + [B2055_VCO_CAL9] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, + [B2055_VCO_CAL10] = { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, }, + [B2055_VCO_CAL11] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, + [B2055_VCO_CAL12] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2055_VCO_CAL13] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2055_VCO_CAL14] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2055_VCO_CAL15] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2055_VCO_CAL16] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2055_VCO_KVCO] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, + [B2055_VCO_CAPTAIL] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, + [B2055_VCO_IDACVCO] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, + [B2055_VCO_REG] = { .ghz5 = 0x0084, .ghz2 = 0x0084, UPLOAD, }, + [B2055_PLL_RFVTH] = { .ghz5 = 0x00C3, .ghz2 = 0x00C3, NOUPLOAD, }, + [B2055_LGBUF_CENBUF] = { .ghz5 = 0x008F, .ghz2 = 0x008F, NOUPLOAD, }, + [B2055_LGEN_TUNE1] = { .ghz5 = 0x00FF, .ghz2 = 0x00FF, NOUPLOAD, }, + [B2055_LGEN_TUNE2] = { .ghz5 = 0x00FF, .ghz2 = 0x00FF, NOUPLOAD, }, + [B2055_LGEN_IDAC1] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2055_LGEN_IDAC2] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2055_LGEN_BIASC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2055_LGEN_BIASIDAC] = { .ghz5 = 0x00CC, .ghz2 = 0x00CC, NOUPLOAD, }, + [B2055_LGEN_RCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, + [B2055_LGEN_DIV] = { .ghz5 = 0x0080, .ghz2 = 0x0080, NOUPLOAD, }, + [B2055_LGEN_SPARE2] = { .ghz5 = 0x0080, .ghz2 = 0x0080, NOUPLOAD, }, + [B2055_C1_LGBUF_ATUNE] = { .ghz5 = 0x00F8, .ghz2 = 0x00F8, NOUPLOAD, }, + [B2055_C1_LGBUF_GTUNE] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2055_C1_LGBUF_DIV] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2055_C1_LGBUF_AIDAC] = { .ghz5 = 0x0088, .ghz2 = 0x0008, UPLOAD, }, + [B2055_C1_LGBUF_GIDAC] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2055_C1_LGBUF_IDACFO] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2055_C1_LGBUF_SPARE] = { .ghz5 = 0x0001, .ghz2 = 0x0001, UPLOAD, }, + [B2055_C1_RX_RFSPC1] = { .ghz5 = 0x008A, .ghz2 = 0x008A, NOUPLOAD, }, + [B2055_C1_RX_RFR1] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, + [B2055_C1_RX_RFR2] = { .ghz5 = 0x0083, .ghz2 = 0x0083, NOUPLOAD, }, + [B2055_C1_RX_RFRCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, + [B2055_C1_RX_BB_BLCMP] = { .ghz5 = 0x00A0, .ghz2 = 0x00A0, NOUPLOAD, }, + [B2055_C1_RX_BB_LPF] = { .ghz5 = 0x000A, .ghz2 = 0x000A, NOUPLOAD, }, + [B2055_C1_RX_BB_MIDACHP] = { .ghz5 = 0x0087, .ghz2 = 0x0087, UPLOAD, }, + [B2055_C1_RX_BB_VGA1IDAC] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, }, + [B2055_C1_RX_BB_VGA2IDAC] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, }, + [B2055_C1_RX_BB_VGA3IDAC] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, }, + [B2055_C1_RX_BB_BUFOCTL] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, }, + [B2055_C1_RX_BB_RCCALCTL] = { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, }, + [B2055_C1_RX_BB_RSSICTL1] = { .ghz5 = 0x006A, .ghz2 = 0x006A, UPLOAD, }, + [B2055_C1_RX_BB_RSSICTL2] = { .ghz5 = 0x00AB, .ghz2 = 0x00AB, UPLOAD, }, + [B2055_C1_RX_BB_RSSICTL3] = { .ghz5 = 0x0013, .ghz2 = 0x0013, UPLOAD, }, + [B2055_C1_RX_BB_RSSICTL4] = { .ghz5 = 0x00C1, .ghz2 = 0x00C1, UPLOAD, }, + [B2055_C1_RX_BB_RSSICTL5] = { .ghz5 = 0x00AA, .ghz2 = 0x00AA, UPLOAD, }, + [B2055_C1_RX_BB_REG] = { .ghz5 = 0x0087, .ghz2 = 0x0087, UPLOAD, }, + [B2055_C1_RX_BB_SPARE1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2055_C1_RX_TXBBRCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, + [B2055_C1_TX_RF_SPGA] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, + [B2055_C1_TX_RF_SPAD] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, + [B2055_C1_TX_RF_CNTPGA1] = { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, }, + [B2055_C1_TX_RF_CNTPAD1] = { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, }, + [B2055_C1_TX_RF_PGAIDAC] = { .ghz5 = 0x0097, .ghz2 = 0x0097, UPLOAD, }, + [B2055_C1_TX_PGAPADTN] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, + [B2055_C1_TX_PADIDAC1] = { .ghz5 = 0x0014, .ghz2 = 0x0014, UPLOAD, }, + [B2055_C1_TX_PADIDAC2] = { .ghz5 = 0x0033, .ghz2 = 0x0033, NOUPLOAD, }, + [B2055_C1_TX_MXBGTRIM] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2055_C1_TX_RF_RCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, + [B2055_C1_TX_RF_PADTSSI1] = { .ghz5 = 0x0003, .ghz2 = 0x0003, UPLOAD, }, + [B2055_C1_TX_RF_PADTSSI2] = { .ghz5 = 0x000A, .ghz2 = 0x000A, NOUPLOAD, }, + [B2055_C1_TX_RF_SPARE] = { .ghz5 = 0x0003, .ghz2 = 0x0003, UPLOAD, }, + [B2055_C1_TX_RF_IQCAL1] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, }, + [B2055_C1_TX_RF_IQCAL2] = { .ghz5 = 0x00A4, .ghz2 = 0x00A4, NOUPLOAD, }, + [B2055_C1_TXBB_RCCAL] = { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, }, + [B2055_C1_TXBB_LPF1] = { .ghz5 = 0x0028, .ghz2 = 0x0028, NOUPLOAD, }, + [B2055_C1_TX_VOSCNCL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2055_C1_TX_LPF_MXGMIDAC] = { .ghz5 = 0x004A, .ghz2 = 0x004A, NOUPLOAD, }, + [B2055_C1_TX_BB_MXGM] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2055_C2_LGBUF_ATUNE] = { .ghz5 = 0x00F8, .ghz2 = 0x00F8, NOUPLOAD, }, + [B2055_C2_LGBUF_GTUNE] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2055_C2_LGBUF_DIV] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2055_C2_LGBUF_AIDAC] = { .ghz5 = 0x0088, .ghz2 = 0x0008, UPLOAD, }, + [B2055_C2_LGBUF_GIDAC] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2055_C2_LGBUF_IDACFO] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2055_C2_LGBUF_SPARE] = { .ghz5 = 0x0001, .ghz2 = 0x0001, UPLOAD, }, + [B2055_C2_RX_RFSPC1] = { .ghz5 = 0x008A, .ghz2 = 0x008A, NOUPLOAD, }, + [B2055_C2_RX_RFR1] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, + [B2055_C2_RX_RFR2] = { .ghz5 = 0x0083, .ghz2 = 0x0083, NOUPLOAD, }, + [B2055_C2_RX_RFRCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, + [B2055_C2_RX_BB_BLCMP] = { .ghz5 = 0x00A0, .ghz2 = 0x00A0, NOUPLOAD, }, + [B2055_C2_RX_BB_LPF] = { .ghz5 = 0x000A, .ghz2 = 0x000A, NOUPLOAD, }, + [B2055_C2_RX_BB_MIDACHP] = { .ghz5 = 0x0087, .ghz2 = 0x0087, UPLOAD, }, + [B2055_C2_RX_BB_VGA1IDAC] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, }, + [B2055_C2_RX_BB_VGA2IDAC] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, }, + [B2055_C2_RX_BB_VGA3IDAC] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, }, + [B2055_C2_RX_BB_BUFOCTL] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, }, + [B2055_C2_RX_BB_RCCALCTL] = { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, }, + [B2055_C2_RX_BB_RSSICTL1] = { .ghz5 = 0x006A, .ghz2 = 0x006A, UPLOAD, }, + [B2055_C2_RX_BB_RSSICTL2] = { .ghz5 = 0x00AB, .ghz2 = 0x00AB, UPLOAD, }, + [B2055_C2_RX_BB_RSSICTL3] = { .ghz5 = 0x0013, .ghz2 = 0x0013, UPLOAD, }, + [B2055_C2_RX_BB_RSSICTL4] = { .ghz5 = 0x00C1, .ghz2 = 0x00C1, UPLOAD, }, + [B2055_C2_RX_BB_RSSICTL5] = { .ghz5 = 0x00AA, .ghz2 = 0x00AA, UPLOAD, }, + [B2055_C2_RX_BB_REG] = { .ghz5 = 0x0087, .ghz2 = 0x0087, UPLOAD, }, + [B2055_C2_RX_BB_SPARE1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2055_C2_RX_TXBBRCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, + [B2055_C2_TX_RF_SPGA] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, + [B2055_C2_TX_RF_SPAD] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, + [B2055_C2_TX_RF_CNTPGA1] = { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, }, + [B2055_C2_TX_RF_CNTPAD1] = { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, }, + [B2055_C2_TX_RF_PGAIDAC] = { .ghz5 = 0x0097, .ghz2 = 0x0097, UPLOAD, }, + [B2055_C2_TX_PGAPADTN] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, + [B2055_C2_TX_PADIDAC1] = { .ghz5 = 0x0014, .ghz2 = 0x0014, UPLOAD, }, + [B2055_C2_TX_PADIDAC2] = { .ghz5 = 0x0033, .ghz2 = 0x0033, NOUPLOAD, }, + [B2055_C2_TX_MXBGTRIM] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [B2055_C2_TX_RF_RCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, + [B2055_C2_TX_RF_PADTSSI1] = { .ghz5 = 0x0003, .ghz2 = 0x0003, UPLOAD, }, + [B2055_C2_TX_RF_PADTSSI2] = { .ghz5 = 0x000A, .ghz2 = 0x000A, NOUPLOAD, }, + [B2055_C2_TX_RF_SPARE] = { .ghz5 = 0x0003, .ghz2 = 0x0003, UPLOAD, }, + [B2055_C2_TX_RF_IQCAL1] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, }, + [B2055_C2_TX_RF_IQCAL2] = { .ghz5 = 0x00A4, .ghz2 = 0x00A4, NOUPLOAD, }, + [B2055_C2_TXBB_RCCAL] = { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, }, + [B2055_C2_TXBB_LPF1] = { .ghz5 = 0x0028, .ghz2 = 0x0028, NOUPLOAD, }, + [B2055_C2_TX_VOSCNCL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2055_C2_TX_LPF_MXGMIDAC] = { .ghz5 = 0x004A, .ghz2 = 0x004A, NOUPLOAD, }, + [B2055_C2_TX_BB_MXGM] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2055_PRG_GCHP21] = { .ghz5 = 0x0071, .ghz2 = 0x0071, NOUPLOAD, }, + [B2055_PRG_GCHP22] = { .ghz5 = 0x0072, .ghz2 = 0x0072, NOUPLOAD, }, + [B2055_PRG_GCHP23] = { .ghz5 = 0x0073, .ghz2 = 0x0073, NOUPLOAD, }, + [B2055_PRG_GCHP24] = { .ghz5 = 0x0074, .ghz2 = 0x0074, NOUPLOAD, }, + [B2055_PRG_GCHP25] = { .ghz5 = 0x0075, .ghz2 = 0x0075, NOUPLOAD, }, + [B2055_PRG_GCHP26] = { .ghz5 = 0x0076, .ghz2 = 0x0076, NOUPLOAD, }, + [B2055_PRG_GCHP27] = { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, }, + [B2055_PRG_GCHP28] = { .ghz5 = 0x0078, .ghz2 = 0x0078, NOUPLOAD, }, + [B2055_PRG_GCHP29] = { .ghz5 = 0x0079, .ghz2 = 0x0079, NOUPLOAD, }, + [B2055_PRG_GCHP30] = { .ghz5 = 0x007A, .ghz2 = 0x007A, NOUPLOAD, }, + [0xC7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [0xC8] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [0xC9] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [0xCA] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [0xCB] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [0xCC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2055_C1_LNA_GAINBST] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [0xCE] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [0xCF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [0xD0] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [0xD1] = { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, }, + [B2055_C1_B0NB_RSSIVCM] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [0xD3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [0xD4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [0xD5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2055_C1_GENSPARE2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [0xD7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [0xD8] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2055_C2_LNA_GAINBST] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [0xDA] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [0xDB] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [0xDC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [0xDD] = { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, }, + [B2055_C2_B0NB_RSSIVCM] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, + [0xDF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [0xE0] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [0xE1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, + [B2055_C2_GENSPARE2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, +}; + +#define RADIOREGS(r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, \ + r12, r13, r14, r15, r16, r17, r18, r19, r20, r21) \ + .radio_pll_ref = r0, \ + .radio_rf_pllmod0 = r1, \ + .radio_rf_pllmod1 = r2, \ + .radio_vco_captail = r3, \ + .radio_vco_cal1 = r4, \ + .radio_vco_cal2 = r5, \ + .radio_pll_lfc1 = r6, \ + .radio_pll_lfr1 = r7, \ + .radio_pll_lfc2 = r8, \ + .radio_lgbuf_cenbuf = r9, \ + .radio_lgen_tune1 = r10, \ + .radio_lgen_tune2 = r11, \ + .radio_c1_lgbuf_atune = r12, \ + .radio_c1_lgbuf_gtune = r13, \ + .radio_c1_rx_rfr1 = r14, \ + .radio_c1_tx_pgapadtn = r15, \ + .radio_c1_tx_mxbgtrim = r16, \ + .radio_c2_lgbuf_atune = r17, \ + .radio_c2_lgbuf_gtune = r18, \ + .radio_c2_rx_rfr1 = r19, \ + .radio_c2_tx_pgapadtn = r20, \ + .radio_c2_tx_mxbgtrim = r21 + +#define PHYREGS(r0, r1, r2, r3, r4, r5) \ + .phy_regs.phy_bw1a = r0, \ + .phy_regs.phy_bw2 = r1, \ + .phy_regs.phy_bw3 = r2, \ + .phy_regs.phy_bw4 = r3, \ + .phy_regs.phy_bw5 = r4, \ + .phy_regs.phy_bw6 = r5 + +static const struct b43_nphy_channeltab_entry_rev2 b43_nphy_channeltab_rev2[] = { + { .channel = 184, + .freq = 4920, /* MHz */ + .unk2 = 3280, + RADIOREGS(0x71, 0x01, 0xEC, 0x0F, 0xFF, 0x01, 0x04, 0x0A, + 0x00, 0x8F, 0xFF, 0xFF, 0xFF, 0x00, 0x0F, 0x0F, + 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), + PHYREGS(0xB407, 0xB007, 0xAC07, 0x1402, 0x1502, 0x1602), + }, + { .channel = 186, + .freq = 4930, /* MHz */ + .unk2 = 3287, + RADIOREGS(0x71, 0x01, 0xED, 0x0F, 0xFF, 0x01, 0x04, 0x0A, + 0x00, 0x8F, 0xFF, 0xFF, 0xFF, 0x00, 0x0F, 0x0F, + 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), + PHYREGS(0xB807, 0xB407, 0xB007, 0x1302, 0x1402, 0x1502), + }, + { .channel = 188, + .freq = 4940, /* MHz */ + .unk2 = 3293, + RADIOREGS(0x71, 0x01, 0xEE, 0x0F, 0xFF, 0x01, 0x04, 0x0A, + 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, + 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), + PHYREGS(0xBC07, 0xB807, 0xB407, 0x1202, 0x1302, 0x1402), + }, + { .channel = 190, + .freq = 4950, /* MHz */ + .unk2 = 3300, + RADIOREGS(0x71, 0x01, 0xEF, 0x0F, 0xFF, 0x01, 0x04, 0x0A, + 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, + 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), + PHYREGS(0xC007, 0xBC07, 0xB807, 0x1102, 0x1202, 0x1302), + }, + { .channel = 192, + .freq = 4960, /* MHz */ + .unk2 = 3307, + RADIOREGS(0x71, 0x01, 0xF0, 0x0F, 0xFF, 0x01, 0x04, 0x0A, + 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, + 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), + PHYREGS(0xC407, 0xC007, 0xBC07, 0x0F02, 0x1102, 0x1202), + }, + { .channel = 194, + .freq = 4970, /* MHz */ + .unk2 = 3313, + RADIOREGS(0x71, 0x01, 0xF1, 0x0F, 0xFF, 0x01, 0x04, 0x0A, + 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, + 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), + PHYREGS(0xC807, 0xC407, 0xC007, 0x0E02, 0x0F02, 0x1102), + }, + { .channel = 196, + .freq = 4980, /* MHz */ + .unk2 = 3320, + RADIOREGS(0x71, 0x01, 0xF2, 0x0E, 0xFF, 0x01, 0x04, 0x0A, + 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, + 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), + PHYREGS(0xCC07, 0xC807, 0xC407, 0x0D02, 0x0E02, 0x0F02), + }, + { .channel = 198, + .freq = 4990, /* MHz */ + .unk2 = 3327, + RADIOREGS(0x71, 0x01, 0xF3, 0x0E, 0xFF, 0x01, 0x04, 0x0A, + 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, + 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), + PHYREGS(0xD007, 0xCC07, 0xC807, 0x0C02, 0x0D02, 0x0E02), + }, + { .channel = 200, + .freq = 5000, /* MHz */ + .unk2 = 3333, + RADIOREGS(0x71, 0x01, 0xF4, 0x0E, 0xFF, 0x01, 0x04, 0x0A, + 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, + 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), + PHYREGS(0xD407, 0xD007, 0xCC07, 0x0B02, 0x0C02, 0x0D02), + }, + { .channel = 202, + .freq = 5010, /* MHz */ + .unk2 = 3340, + RADIOREGS(0x71, 0x01, 0xF5, 0x0E, 0xFF, 0x01, 0x04, 0x0A, + 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, + 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), + PHYREGS(0xD807, 0xD407, 0xD007, 0x0A02, 0x0B02, 0x0C02), + }, + { .channel = 204, + .freq = 5020, /* MHz */ + .unk2 = 3347, + RADIOREGS(0x71, 0x01, 0xF6, 0x0E, 0xF7, 0x01, 0x04, 0x0A, + 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, + 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), + PHYREGS(0xDC07, 0xD807, 0xD407, 0x0902, 0x0A02, 0x0B02), + }, + { .channel = 206, + .freq = 5030, /* MHz */ + .unk2 = 3353, + RADIOREGS(0x71, 0x01, 0xF7, 0x0E, 0xF7, 0x01, 0x04, 0x0A, + 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, + 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), + PHYREGS(0xE007, 0xDC07, 0xD807, 0x0802, 0x0902, 0x0A02), + }, + { .channel = 208, + .freq = 5040, /* MHz */ + .unk2 = 3360, + RADIOREGS(0x71, 0x01, 0xF8, 0x0D, 0xEF, 0x01, 0x04, 0x0A, + 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, + 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), + PHYREGS(0xE407, 0xE007, 0xDC07, 0x0702, 0x0802, 0x0902), + }, + { .channel = 210, + .freq = 5050, /* MHz */ + .unk2 = 3367, + RADIOREGS(0x71, 0x01, 0xF9, 0x0D, 0xEF, 0x01, 0x04, 0x0A, + 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, + 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), + PHYREGS(0xE807, 0xE407, 0xE007, 0x0602, 0x0702, 0x0802), + }, + { .channel = 212, + .freq = 5060, /* MHz */ + .unk2 = 3373, + RADIOREGS(0x71, 0x01, 0xFA, 0x0D, 0xE6, 0x01, 0x04, 0x0A, + 0x00, 0x8F, 0xBB, 0xBB, 0xFF, 0x00, 0x0E, 0x0F, + 0x8E, 0xFF, 0x00, 0x0E, 0x0F, 0x8E), + PHYREGS(0xEC07, 0xE807, 0xE407, 0x0502, 0x0602, 0x0702), + }, + { .channel = 214, + .freq = 5070, /* MHz */ + .unk2 = 3380, + RADIOREGS(0x71, 0x01, 0xFB, 0x0D, 0xE6, 0x01, 0x04, 0x0A, + 0x00, 0x8F, 0xBB, 0xBB, 0xFF, 0x00, 0x0E, 0x0F, + 0x8E, 0xFF, 0x00, 0x0E, 0x0F, 0x8E), + PHYREGS(0xF007, 0xEC07, 0xE807, 0x0402, 0x0502, 0x0602), + }, + { .channel = 216, + .freq = 5080, /* MHz */ + .unk2 = 3387, + RADIOREGS(0x71, 0x01, 0xFC, 0x0D, 0xDE, 0x01, 0x04, 0x0A, + 0x00, 0x8E, 0xBB, 0xBB, 0xEE, 0x00, 0x0E, 0x0F, + 0x8D, 0xEE, 0x00, 0x0E, 0x0F, 0x8D), + PHYREGS(0xF407, 0xF007, 0xEC07, 0x0302, 0x0402, 0x0502), + }, + { .channel = 218, + .freq = 5090, /* MHz */ + .unk2 = 3393, + RADIOREGS(0x71, 0x01, 0xFD, 0x0D, 0xDE, 0x01, 0x04, 0x0A, + 0x00, 0x8E, 0xBB, 0xBB, 0xEE, 0x00, 0x0E, 0x0F, + 0x8D, 0xEE, 0x00, 0x0E, 0x0F, 0x8D), + PHYREGS(0xF807, 0xF407, 0xF007, 0x0202, 0x0302, 0x0402), + }, + { .channel = 220, + .freq = 5100, /* MHz */ + .unk2 = 3400, + RADIOREGS(0x71, 0x01, 0xFE, 0x0C, 0xD6, 0x01, 0x04, 0x0A, + 0x00, 0x8E, 0xAA, 0xAA, 0xEE, 0x00, 0x0D, 0x0F, + 0x8D, 0xEE, 0x00, 0x0D, 0x0F, 0x8D), + PHYREGS(0xFC07, 0xF807, 0xF407, 0x0102, 0x0202, 0x0302), + }, + { .channel = 222, + .freq = 5110, /* MHz */ + .unk2 = 3407, + RADIOREGS(0x71, 0x01, 0xFF, 0x0C, 0xD6, 0x01, 0x04, 0x0A, + 0x00, 0x8E, 0xAA, 0xAA, 0xEE, 0x00, 0x0D, 0x0F, + 0x8D, 0xEE, 0x00, 0x0D, 0x0F, 0x8D), + PHYREGS(0x0008, 0xFC07, 0xF807, 0x0002, 0x0102, 0x0202), + }, + { .channel = 224, + .freq = 5120, /* MHz */ + .unk2 = 3413, + RADIOREGS(0x71, 0x02, 0x00, 0x0C, 0xCE, 0x01, 0x04, 0x0A, + 0x00, 0x8D, 0xAA, 0xAA, 0xDD, 0x00, 0x0D, 0x0F, + 0x8C, 0xDD, 0x00, 0x0D, 0x0F, 0x8C), + PHYREGS(0x0408, 0x0008, 0xFC07, 0xFF01, 0x0002, 0x0102), + }, + { .channel = 226, + .freq = 5130, /* MHz */ + .unk2 = 3420, + RADIOREGS(0x71, 0x02, 0x01, 0x0C, 0xCE, 0x01, 0x04, 0x0A, + 0x00, 0x8D, 0xAA, 0xAA, 0xDD, 0x00, 0x0D, 0x0F, + 0x8C, 0xDD, 0x00, 0x0D, 0x0F, 0x8C), + PHYREGS(0x0808, 0x0408, 0x0008, 0xFE01, 0xFF01, 0x0002), + }, + { .channel = 228, + .freq = 5140, /* MHz */ + .unk2 = 3427, + RADIOREGS(0x71, 0x02, 0x02, 0x0C, 0xC6, 0x01, 0x04, 0x0A, + 0x00, 0x8D, 0x99, 0x99, 0xDD, 0x00, 0x0C, 0x0E, + 0x8B, 0xDD, 0x00, 0x0C, 0x0E, 0x8B), + PHYREGS(0x0C08, 0x0808, 0x0408, 0xFD01, 0xFE01, 0xFF01), + }, + { .channel = 32, + .freq = 5160, /* MHz */ + .unk2 = 3440, + RADIOREGS(0x71, 0x02, 0x04, 0x0B, 0xBE, 0x01, 0x04, 0x0A, + 0x00, 0x8C, 0x99, 0x99, 0xCC, 0x00, 0x0B, 0x0D, + 0x8A, 0xCC, 0x00, 0x0B, 0x0D, 0x8A), + PHYREGS(0x1408, 0x1008, 0x0C08, 0xFB01, 0xFC01, 0xFD01), + }, + { .channel = 34, + .freq = 5170, /* MHz */ + .unk2 = 3447, + RADIOREGS(0x71, 0x02, 0x05, 0x0B, 0xBE, 0x01, 0x04, 0x0A, + 0x00, 0x8C, 0x99, 0x99, 0xCC, 0x00, 0x0B, 0x0D, + 0x8A, 0xCC, 0x00, 0x0B, 0x0D, 0x8A), + PHYREGS(0x1808, 0x1408, 0x1008, 0xFA01, 0xFB01, 0xFC01), + }, + { .channel = 36, + .freq = 5180, /* MHz */ + .unk2 = 3453, + RADIOREGS(0x71, 0x02, 0x06, 0x0B, 0xB6, 0x01, 0x04, 0x0A, + 0x00, 0x8C, 0x88, 0x88, 0xCC, 0x00, 0x0B, 0x0C, + 0x89, 0xCC, 0x00, 0x0B, 0x0C, 0x89), + PHYREGS(0x1C08, 0x1808, 0x1408, 0xF901, 0xFA01, 0xFB01), + }, + { .channel = 38, + .freq = 5190, /* MHz */ + .unk2 = 3460, + RADIOREGS(0x71, 0x02, 0x07, 0x0B, 0xB6, 0x01, 0x04, 0x0A, + 0x00, 0x8C, 0x88, 0x88, 0xCC, 0x00, 0x0B, 0x0C, + 0x89, 0xCC, 0x00, 0x0B, 0x0C, 0x89), + PHYREGS(0x2008, 0x1C08, 0x1808, 0xF801, 0xF901, 0xFA01), + }, + { .channel = 40, + .freq = 5200, /* MHz */ + .unk2 = 3467, + RADIOREGS(0x71, 0x02, 0x08, 0x0B, 0xAF, 0x01, 0x04, 0x0A, + 0x00, 0x8B, 0x88, 0x88, 0xBB, 0x00, 0x0A, 0x0B, + 0x89, 0xBB, 0x00, 0x0A, 0x0B, 0x89), + PHYREGS(0x2408, 0x2008, 0x1C08, 0xF701, 0xF801, 0xF901), + }, + { .channel = 42, + .freq = 5210, /* MHz */ + .unk2 = 3473, + RADIOREGS(0x71, 0x02, 0x09, 0x0B, 0xAF, 0x01, 0x04, 0x0A, + 0x00, 0x8B, 0x88, 0x88, 0xBB, 0x00, 0x0A, 0x0B, + 0x89, 0xBB, 0x00, 0x0A, 0x0B, 0x89), + PHYREGS(0x2808, 0x2408, 0x2008, 0xF601, 0xF701, 0xF801), + }, + { .channel = 44, + .freq = 5220, /* MHz */ + .unk2 = 3480, + RADIOREGS(0x71, 0x02, 0x0A, 0x0A, 0xA7, 0x01, 0x04, 0x0A, + 0x00, 0x8B, 0x77, 0x77, 0xBB, 0x00, 0x09, 0x0A, + 0x88, 0xBB, 0x00, 0x09, 0x0A, 0x88), + PHYREGS(0x2C08, 0x2808, 0x2408, 0xF501, 0xF601, 0xF701), + }, + { .channel = 46, + .freq = 5230, /* MHz */ + .unk2 = 3487, + RADIOREGS(0x71, 0x02, 0x0B, 0x0A, 0xA7, 0x01, 0x04, 0x0A, + 0x00, 0x8B, 0x77, 0x77, 0xBB, 0x00, 0x09, 0x0A, + 0x88, 0xBB, 0x00, 0x09, 0x0A, 0x88), + PHYREGS(0x3008, 0x2C08, 0x2808, 0xF401, 0xF501, 0xF601), + }, + { .channel = 48, + .freq = 5240, /* MHz */ + .unk2 = 3493, + RADIOREGS(0x71, 0x02, 0x0C, 0x0A, 0xA0, 0x01, 0x04, 0x0A, + 0x00, 0x8A, 0x77, 0x77, 0xAA, 0x00, 0x09, 0x0A, + 0x87, 0xAA, 0x00, 0x09, 0x0A, 0x87), + PHYREGS(0x3408, 0x3008, 0x2C08, 0xF301, 0xF401, 0xF501), + }, + { .channel = 50, + .freq = 5250, /* MHz */ + .unk2 = 3500, + RADIOREGS(0x71, 0x02, 0x0D, 0x0A, 0xA0, 0x01, 0x04, 0x0A, + 0x00, 0x8A, 0x77, 0x77, 0xAA, 0x00, 0x09, 0x0A, + 0x87, 0xAA, 0x00, 0x09, 0x0A, 0x87), + PHYREGS(0x3808, 0x3408, 0x3008, 0xF201, 0xF301, 0xF401), + }, + { .channel = 52, + .freq = 5260, /* MHz */ + .unk2 = 3507, + RADIOREGS(0x71, 0x02, 0x0E, 0x0A, 0x98, 0x01, 0x04, 0x0A, + 0x00, 0x8A, 0x66, 0x66, 0xAA, 0x00, 0x08, 0x09, + 0x87, 0xAA, 0x00, 0x08, 0x09, 0x87), + PHYREGS(0x3C08, 0x3808, 0x3408, 0xF101, 0xF201, 0xF301), + }, + { .channel = 54, + .freq = 5270, /* MHz */ + .unk2 = 3513, + RADIOREGS(0x71, 0x02, 0x0F, 0x0A, 0x98, 0x01, 0x04, 0x0A, + 0x00, 0x8A, 0x66, 0x66, 0xAA, 0x00, 0x08, 0x09, + 0x87, 0xAA, 0x00, 0x08, 0x09, 0x87), + PHYREGS(0x4008, 0x3C08, 0x3808, 0xF001, 0xF101, 0xF201), + }, + { .channel = 56, + .freq = 5280, /* MHz */ + .unk2 = 3520, + RADIOREGS(0x71, 0x02, 0x10, 0x09, 0x91, 0x01, 0x04, 0x0A, + 0x00, 0x89, 0x66, 0x66, 0x99, 0x00, 0x08, 0x08, + 0x86, 0x99, 0x00, 0x08, 0x08, 0x86), + PHYREGS(0x4408, 0x4008, 0x3C08, 0xF001, 0xF001, 0xF101), + }, + { .channel = 58, + .freq = 5290, /* MHz */ + .unk2 = 3527, + RADIOREGS(0x71, 0x02, 0x11, 0x09, 0x91, 0x01, 0x04, 0x0A, + 0x00, 0x89, 0x66, 0x66, 0x99, 0x00, 0x08, 0x08, + 0x86, 0x99, 0x00, 0x08, 0x08, 0x86), + PHYREGS(0x4808, 0x4408, 0x4008, 0xEF01, 0xF001, 0xF001), + }, + { .channel = 60, + .freq = 5300, /* MHz */ + .unk2 = 3533, + RADIOREGS(0x71, 0x02, 0x12, 0x09, 0x8A, 0x01, 0x04, 0x0A, + 0x00, 0x89, 0x55, 0x55, 0x99, 0x00, 0x08, 0x07, + 0x85, 0x99, 0x00, 0x08, 0x07, 0x85), + PHYREGS(0x4C08, 0x4808, 0x4408, 0xEE01, 0xEF01, 0xF001), + }, + { .channel = 62, + .freq = 5310, /* MHz */ + .unk2 = 3540, + RADIOREGS(0x71, 0x02, 0x13, 0x09, 0x8A, 0x01, 0x04, 0x0A, + 0x00, 0x89, 0x55, 0x55, 0x99, 0x00, 0x08, 0x07, + 0x85, 0x99, 0x00, 0x08, 0x07, 0x85), + PHYREGS(0x5008, 0x4C08, 0x4808, 0xED01, 0xEE01, 0xEF01), + }, + { .channel = 64, + .freq = 5320, /* MHz */ + .unk2 = 3547, + RADIOREGS(0x71, 0x02, 0x14, 0x09, 0x83, 0x01, 0x04, 0x0A, + 0x00, 0x88, 0x55, 0x55, 0x88, 0x00, 0x07, 0x07, + 0x84, 0x88, 0x00, 0x07, 0x07, 0x84), + PHYREGS(0x5408, 0x5008, 0x4C08, 0xEC01, 0xED01, 0xEE01), + }, + { .channel = 66, + .freq = 5330, /* MHz */ + .unk2 = 3553, + RADIOREGS(0x71, 0x02, 0x15, 0x09, 0x83, 0x01, 0x04, 0x0A, + 0x00, 0x88, 0x55, 0x55, 0x88, 0x00, 0x07, 0x07, + 0x84, 0x88, 0x00, 0x07, 0x07, 0x84), + PHYREGS(0x5808, 0x5408, 0x5008, 0xEB01, 0xEC01, 0xED01), + }, + { .channel = 68, + .freq = 5340, /* MHz */ + .unk2 = 3560, + RADIOREGS(0x71, 0x02, 0x16, 0x08, 0x7C, 0x01, 0x04, 0x0A, + 0x00, 0x88, 0x44, 0x44, 0x88, 0x00, 0x07, 0x06, + 0x84, 0x88, 0x00, 0x07, 0x06, 0x84), + PHYREGS(0x5C08, 0x5808, 0x5408, 0xEA01, 0xEB01, 0xEC01), + }, + { .channel = 70, + .freq = 5350, /* MHz */ + .unk2 = 3567, + RADIOREGS(0x71, 0x02, 0x17, 0x08, 0x7C, 0x01, 0x04, 0x0A, + 0x00, 0x88, 0x44, 0x44, 0x88, 0x00, 0x07, 0x06, + 0x84, 0x88, 0x00, 0x07, 0x06, 0x84), + PHYREGS(0x6008, 0x5C08, 0x5808, 0xE901, 0xEA01, 0xEB01), + }, + { .channel = 72, + .freq = 5360, /* MHz */ + .unk2 = 3573, + RADIOREGS(0x71, 0x02, 0x18, 0x08, 0x75, 0x01, 0x04, 0x0A, + 0x00, 0x87, 0x44, 0x44, 0x77, 0x00, 0x06, 0x05, + 0x83, 0x77, 0x00, 0x06, 0x05, 0x83), + PHYREGS(0x6408, 0x6008, 0x5C08, 0xE801, 0xE901, 0xEA01), + }, + { .channel = 74, + .freq = 5370, /* MHz */ + .unk2 = 3580, + RADIOREGS(0x71, 0x02, 0x19, 0x08, 0x75, 0x01, 0x04, 0x0A, + 0x00, 0x87, 0x44, 0x44, 0x77, 0x00, 0x06, 0x05, + 0x83, 0x77, 0x00, 0x06, 0x05, 0x83), + PHYREGS(0x6808, 0x6408, 0x6008, 0xE701, 0xE801, 0xE901), + }, + { .channel = 76, + .freq = 5380, /* MHz */ + .unk2 = 3587, + RADIOREGS(0x71, 0x02, 0x1A, 0x08, 0x6E, 0x01, 0x04, 0x0A, + 0x00, 0x87, 0x33, 0x33, 0x77, 0x00, 0x06, 0x04, + 0x82, 0x77, 0x00, 0x06, 0x04, 0x82), + PHYREGS(0x6C08, 0x6808, 0x6408, 0xE601, 0xE701, 0xE801), + }, + { .channel = 78, + .freq = 5390, /* MHz */ + .unk2 = 3593, + RADIOREGS(0x71, 0x02, 0x1B, 0x08, 0x6E, 0x01, 0x04, 0x0A, + 0x00, 0x87, 0x33, 0x33, 0x77, 0x00, 0x06, 0x04, + 0x82, 0x77, 0x00, 0x06, 0x04, 0x82), + PHYREGS(0x7008, 0x6C08, 0x6808, 0xE501, 0xE601, 0xE701), + }, + { .channel = 80, + .freq = 5400, /* MHz */ + .unk2 = 3600, + RADIOREGS(0x71, 0x02, 0x1C, 0x07, 0x67, 0x01, 0x04, 0x0A, + 0x00, 0x86, 0x33, 0x33, 0x66, 0x00, 0x05, 0x04, + 0x81, 0x66, 0x00, 0x05, 0x04, 0x81), + PHYREGS(0x7408, 0x7008, 0x6C08, 0xE501, 0xE501, 0xE601), + }, + { .channel = 82, + .freq = 5410, /* MHz */ + .unk2 = 3607, + RADIOREGS(0x71, 0x02, 0x1D, 0x07, 0x67, 0x01, 0x04, 0x0A, + 0x00, 0x86, 0x33, 0x33, 0x66, 0x00, 0x05, 0x04, + 0x81, 0x66, 0x00, 0x05, 0x04, 0x81), + PHYREGS(0x7808, 0x7408, 0x7008, 0xE401, 0xE501, 0xE501), + }, + { .channel = 84, + .freq = 5420, /* MHz */ + .unk2 = 3613, + RADIOREGS(0x71, 0x02, 0x1E, 0x07, 0x61, 0x01, 0x04, 0x0A, + 0x00, 0x86, 0x22, 0x22, 0x66, 0x00, 0x05, 0x03, + 0x80, 0x66, 0x00, 0x05, 0x03, 0x80), + PHYREGS(0x7C08, 0x7808, 0x7408, 0xE301, 0xE401, 0xE501), + }, + { .channel = 86, + .freq = 5430, /* MHz */ + .unk2 = 3620, + RADIOREGS(0x71, 0x02, 0x1F, 0x07, 0x61, 0x01, 0x04, 0x0A, + 0x00, 0x86, 0x22, 0x22, 0x66, 0x00, 0x05, 0x03, + 0x80, 0x66, 0x00, 0x05, 0x03, 0x80), + PHYREGS(0x8008, 0x7C08, 0x7808, 0xE201, 0xE301, 0xE401), + }, + { .channel = 88, + .freq = 5440, /* MHz */ + .unk2 = 3627, + RADIOREGS(0x71, 0x02, 0x20, 0x07, 0x5A, 0x01, 0x04, 0x0A, + 0x00, 0x85, 0x22, 0x22, 0x55, 0x00, 0x04, 0x02, + 0x80, 0x55, 0x00, 0x04, 0x02, 0x80), + PHYREGS(0x8408, 0x8008, 0x7C08, 0xE101, 0xE201, 0xE301), + }, + { .channel = 90, + .freq = 5450, /* MHz */ + .unk2 = 3633, + RADIOREGS(0x71, 0x02, 0x21, 0x07, 0x5A, 0x01, 0x04, 0x0A, + 0x00, 0x85, 0x22, 0x22, 0x55, 0x00, 0x04, 0x02, + 0x80, 0x55, 0x00, 0x04, 0x02, 0x80), + PHYREGS(0x8808, 0x8408, 0x8008, 0xE001, 0xE101, 0xE201), + }, + { .channel = 92, + .freq = 5460, /* MHz */ + .unk2 = 3640, + RADIOREGS(0x71, 0x02, 0x22, 0x06, 0x53, 0x01, 0x04, 0x0A, + 0x00, 0x85, 0x11, 0x11, 0x55, 0x00, 0x04, 0x01, + 0x80, 0x55, 0x00, 0x04, 0x01, 0x80), + PHYREGS(0x8C08, 0x8808, 0x8408, 0xDF01, 0xE001, 0xE101), + }, + { .channel = 94, + .freq = 5470, /* MHz */ + .unk2 = 3647, + RADIOREGS(0x71, 0x02, 0x23, 0x06, 0x53, 0x01, 0x04, 0x0A, + 0x00, 0x85, 0x11, 0x11, 0x55, 0x00, 0x04, 0x01, + 0x80, 0x55, 0x00, 0x04, 0x01, 0x80), + PHYREGS(0x9008, 0x8C08, 0x8808, 0xDE01, 0xDF01, 0xE001), + }, + { .channel = 96, + .freq = 5480, /* MHz */ + .unk2 = 3653, + RADIOREGS(0x71, 0x02, 0x24, 0x06, 0x4D, 0x01, 0x04, 0x0A, + 0x00, 0x84, 0x11, 0x11, 0x44, 0x00, 0x03, 0x00, + 0x80, 0x44, 0x00, 0x03, 0x00, 0x80), + PHYREGS(0x9408, 0x9008, 0x8C08, 0xDD01, 0xDE01, 0xDF01), + }, + { .channel = 98, + .freq = 5490, /* MHz */ + .unk2 = 3660, + RADIOREGS(0x71, 0x02, 0x25, 0x06, 0x4D, 0x01, 0x04, 0x0A, + 0x00, 0x84, 0x11, 0x11, 0x44, 0x00, 0x03, 0x00, + 0x80, 0x44, 0x00, 0x03, 0x00, 0x80), + PHYREGS(0x9808, 0x9408, 0x9008, 0xDD01, 0xDD01, 0xDE01), + }, + { .channel = 100, + .freq = 5500, /* MHz */ + .unk2 = 3667, + RADIOREGS(0x71, 0x02, 0x26, 0x06, 0x47, 0x01, 0x04, 0x0A, + 0x00, 0x84, 0x00, 0x00, 0x44, 0x00, 0x03, 0x00, + 0x80, 0x44, 0x00, 0x03, 0x00, 0x80), + PHYREGS(0x9C08, 0x9808, 0x9408, 0xDC01, 0xDD01, 0xDD01), + }, + { .channel = 102, + .freq = 5510, /* MHz */ + .unk2 = 3673, + RADIOREGS(0x71, 0x02, 0x27, 0x06, 0x47, 0x01, 0x04, 0x0A, + 0x00, 0x84, 0x00, 0x00, 0x44, 0x00, 0x03, 0x00, + 0x80, 0x44, 0x00, 0x03, 0x00, 0x80), + PHYREGS(0xA008, 0x9C08, 0x9808, 0xDB01, 0xDC01, 0xDD01), + }, + { .channel = 104, + .freq = 5520, /* MHz */ + .unk2 = 3680, + RADIOREGS(0x71, 0x02, 0x28, 0x05, 0x40, 0x01, 0x04, 0x0A, + 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, + 0x80, 0x33, 0x00, 0x02, 0x00, 0x80), + PHYREGS(0xA408, 0xA008, 0x9C08, 0xDA01, 0xDB01, 0xDC01), + }, + { .channel = 106, + .freq = 5530, /* MHz */ + .unk2 = 3687, + RADIOREGS(0x71, 0x02, 0x29, 0x05, 0x40, 0x01, 0x04, 0x0A, + 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, + 0x80, 0x33, 0x00, 0x02, 0x00, 0x80), + PHYREGS(0xA808, 0xA408, 0xA008, 0xD901, 0xDA01, 0xDB01), + }, + { .channel = 108, + .freq = 5540, /* MHz */ + .unk2 = 3693, + RADIOREGS(0x71, 0x02, 0x2A, 0x05, 0x3A, 0x01, 0x04, 0x0A, + 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, + 0x80, 0x33, 0x00, 0x02, 0x00, 0x80), + PHYREGS(0xAC08, 0xA808, 0xA408, 0xD801, 0xD901, 0xDA01), + }, + { .channel = 110, + .freq = 5550, /* MHz */ + .unk2 = 3700, + RADIOREGS(0x71, 0x02, 0x2B, 0x05, 0x3A, 0x01, 0x04, 0x0A, + 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, + 0x80, 0x33, 0x00, 0x02, 0x00, 0x80), + PHYREGS(0xB008, 0xAC08, 0xA808, 0xD701, 0xD801, 0xD901), + }, + { .channel = 112, + .freq = 5560, /* MHz */ + .unk2 = 3707, + RADIOREGS(0x71, 0x02, 0x2C, 0x05, 0x34, 0x01, 0x04, 0x0A, + 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, + 0x80, 0x22, 0x00, 0x01, 0x00, 0x80), + PHYREGS(0xB408, 0xB008, 0xAC08, 0xD701, 0xD701, 0xD801), + }, + { .channel = 114, + .freq = 5570, /* MHz */ + .unk2 = 3713, + RADIOREGS(0x71, 0x02, 0x2D, 0x05, 0x34, 0x01, 0x04, 0x0A, + 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, + 0x80, 0x22, 0x00, 0x01, 0x00, 0x80), + PHYREGS(0xB808, 0xB408, 0xB008, 0xD601, 0xD701, 0xD701), + }, + { .channel = 116, + .freq = 5580, /* MHz */ + .unk2 = 3720, + RADIOREGS(0x71, 0x02, 0x2E, 0x04, 0x2E, 0x01, 0x04, 0x0A, + 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, + 0x80, 0x22, 0x00, 0x01, 0x00, 0x80), + PHYREGS(0xBC08, 0xB808, 0xB408, 0xD501, 0xD601, 0xD701), + }, + { .channel = 118, + .freq = 5590, /* MHz */ + .unk2 = 3727, + RADIOREGS(0x71, 0x02, 0x2F, 0x04, 0x2E, 0x01, 0x04, 0x0A, + 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, + 0x80, 0x22, 0x00, 0x01, 0x00, 0x80), + PHYREGS(0xC008, 0xBC08, 0xB808, 0xD401, 0xD501, 0xD601), + }, + { .channel = 120, + .freq = 5600, /* MHz */ + .unk2 = 3733, + RADIOREGS(0x71, 0x02, 0x30, 0x04, 0x28, 0x01, 0x04, 0x0A, + 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x01, 0x00, + 0x80, 0x11, 0x00, 0x01, 0x00, 0x80), + PHYREGS(0xC408, 0xC008, 0xBC08, 0xD301, 0xD401, 0xD501), + }, + { .channel = 122, + .freq = 5610, /* MHz */ + .unk2 = 3740, + RADIOREGS(0x71, 0x02, 0x31, 0x04, 0x28, 0x01, 0x04, 0x0A, + 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x01, 0x00, + 0x80, 0x11, 0x00, 0x01, 0x00, 0x80), + PHYREGS(0xC808, 0xC408, 0xC008, 0xD201, 0xD301, 0xD401), + }, + { .channel = 124, + .freq = 5620, /* MHz */ + .unk2 = 3747, + RADIOREGS(0x71, 0x02, 0x32, 0x04, 0x21, 0x01, 0x04, 0x0A, + 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x80, 0x11, 0x00, 0x00, 0x00, 0x80), + PHYREGS(0xCC08, 0xC808, 0xC408, 0xD201, 0xD201, 0xD301), + }, + { .channel = 126, + .freq = 5630, /* MHz */ + .unk2 = 3753, + RADIOREGS(0x71, 0x02, 0x33, 0x04, 0x21, 0x01, 0x04, 0x0A, + 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, + 0x80, 0x11, 0x00, 0x00, 0x00, 0x80), + PHYREGS(0xD008, 0xCC08, 0xC808, 0xD101, 0xD201, 0xD201), + }, + { .channel = 128, + .freq = 5640, /* MHz */ + .unk2 = 3760, + RADIOREGS(0x71, 0x02, 0x34, 0x03, 0x1C, 0x01, 0x04, 0x0A, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), + PHYREGS(0xD408, 0xD008, 0xCC08, 0xD001, 0xD101, 0xD201), + }, + { .channel = 130, + .freq = 5650, /* MHz */ + .unk2 = 3767, + RADIOREGS(0x71, 0x02, 0x35, 0x03, 0x1C, 0x01, 0x04, 0x0A, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), + PHYREGS(0xD808, 0xD408, 0xD008, 0xCF01, 0xD001, 0xD101), + }, + { .channel = 132, + .freq = 5660, /* MHz */ + .unk2 = 3773, + RADIOREGS(0x71, 0x02, 0x36, 0x03, 0x16, 0x01, 0x04, 0x0A, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), + PHYREGS(0xDC08, 0xD808, 0xD408, 0xCE01, 0xCF01, 0xD001), + }, + { .channel = 134, + .freq = 5670, /* MHz */ + .unk2 = 3780, + RADIOREGS(0x71, 0x02, 0x37, 0x03, 0x16, 0x01, 0x04, 0x0A, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), + PHYREGS(0xE008, 0xDC08, 0xD808, 0xCE01, 0xCE01, 0xCF01), + }, + { .channel = 136, + .freq = 5680, /* MHz */ + .unk2 = 3787, + RADIOREGS(0x71, 0x02, 0x38, 0x03, 0x10, 0x01, 0x04, 0x0A, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), + PHYREGS(0xE408, 0xE008, 0xDC08, 0xCD01, 0xCE01, 0xCE01), + }, + { .channel = 138, + .freq = 5690, /* MHz */ + .unk2 = 3793, + RADIOREGS(0x71, 0x02, 0x39, 0x03, 0x10, 0x01, 0x04, 0x0A, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), + PHYREGS(0xE808, 0xE408, 0xE008, 0xCC01, 0xCD01, 0xCE01), + }, + { .channel = 140, + .freq = 5700, /* MHz */ + .unk2 = 3800, + RADIOREGS(0x71, 0x02, 0x3A, 0x02, 0x0A, 0x01, 0x04, 0x0A, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), + PHYREGS(0xEC08, 0xE808, 0xE408, 0xCB01, 0xCC01, 0xCD01), + }, + { .channel = 142, + .freq = 5710, /* MHz */ + .unk2 = 3807, + RADIOREGS(0x71, 0x02, 0x3B, 0x02, 0x0A, 0x01, 0x04, 0x0A, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), + PHYREGS(0xF008, 0xEC08, 0xE808, 0xCA01, 0xCB01, 0xCC01), + }, + { .channel = 144, + .freq = 5720, /* MHz */ + .unk2 = 3813, + RADIOREGS(0x71, 0x02, 0x3C, 0x02, 0x0A, 0x01, 0x04, 0x0A, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), + PHYREGS(0xF408, 0xF008, 0xEC08, 0xC901, 0xCA01, 0xCB01), + }, + { .channel = 145, + .freq = 5725, /* MHz */ + .unk2 = 3817, + RADIOREGS(0x72, 0x04, 0x79, 0x02, 0x03, 0x01, 0x03, 0x14, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), + PHYREGS(0xF608, 0xF208, 0xEE08, 0xC901, 0xCA01, 0xCB01), + }, + { .channel = 146, + .freq = 5730, /* MHz */ + .unk2 = 3820, + RADIOREGS(0x71, 0x02, 0x3D, 0x02, 0x0A, 0x01, 0x04, 0x0A, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), + PHYREGS(0xF808, 0xF408, 0xF008, 0xC901, 0xC901, 0xCA01), + }, + { .channel = 147, + .freq = 5735, /* MHz */ + .unk2 = 3823, + RADIOREGS(0x72, 0x04, 0x7B, 0x02, 0x03, 0x01, 0x03, 0x14, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), + PHYREGS(0xFA08, 0xF608, 0xF208, 0xC801, 0xC901, 0xCA01), + }, + { .channel = 148, + .freq = 5740, /* MHz */ + .unk2 = 3827, + RADIOREGS(0x71, 0x02, 0x3E, 0x02, 0x0A, 0x01, 0x04, 0x0A, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), + PHYREGS(0xFC08, 0xF808, 0xF408, 0xC801, 0xC901, 0xC901), + }, + { .channel = 149, + .freq = 5745, /* MHz */ + .unk2 = 3830, + RADIOREGS(0x72, 0x04, 0x7D, 0x02, 0xFE, 0x00, 0x03, 0x14, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), + PHYREGS(0xFE08, 0xFA08, 0xF608, 0xC801, 0xC801, 0xC901), + }, + { .channel = 150, + .freq = 5750, /* MHz */ + .unk2 = 3833, + RADIOREGS(0x71, 0x02, 0x3F, 0x02, 0x0A, 0x01, 0x04, 0x0A, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), + PHYREGS(0x0009, 0xFC08, 0xF808, 0xC701, 0xC801, 0xC901), + }, + { .channel = 151, + .freq = 5755, /* MHz */ + .unk2 = 3837, + RADIOREGS(0x72, 0x04, 0x7F, 0x02, 0xFE, 0x00, 0x03, 0x14, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), + PHYREGS(0x0209, 0xFE08, 0xFA08, 0xC701, 0xC801, 0xC801), + }, + { .channel = 152, + .freq = 5760, /* MHz */ + .unk2 = 3840, + RADIOREGS(0x71, 0x02, 0x40, 0x02, 0x0A, 0x01, 0x04, 0x0A, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), + PHYREGS(0x0409, 0x0009, 0xFC08, 0xC601, 0xC701, 0xC801), + }, + { .channel = 153, + .freq = 5765, /* MHz */ + .unk2 = 3843, + RADIOREGS(0x72, 0x04, 0x81, 0x02, 0xF8, 0x00, 0x03, 0x14, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), + PHYREGS(0x0609, 0x0209, 0xFE08, 0xC601, 0xC701, 0xC801), + }, + { .channel = 154, + .freq = 5770, /* MHz */ + .unk2 = 3847, + RADIOREGS(0x71, 0x02, 0x41, 0x02, 0x0A, 0x01, 0x04, 0x0A, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), + PHYREGS(0x0809, 0x0409, 0x0009, 0xC601, 0xC601, 0xC701), + }, + { .channel = 155, + .freq = 5775, /* MHz */ + .unk2 = 3850, + RADIOREGS(0x72, 0x04, 0x83, 0x02, 0xF8, 0x00, 0x03, 0x14, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), + PHYREGS(0x0A09, 0x0609, 0x0209, 0xC501, 0xC601, 0xC701), + }, + { .channel = 156, + .freq = 5780, /* MHz */ + .unk2 = 3853, + RADIOREGS(0x71, 0x02, 0x42, 0x02, 0x0A, 0x01, 0x04, 0x0A, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), + PHYREGS(0x0C09, 0x0809, 0x0409, 0xC501, 0xC601, 0xC601), + }, + { .channel = 157, + .freq = 5785, /* MHz */ + .unk2 = 3857, + RADIOREGS(0x72, 0x04, 0x85, 0x02, 0xF2, 0x00, 0x03, 0x14, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), + PHYREGS(0x0E09, 0x0A09, 0x0609, 0xC401, 0xC501, 0xC601), + }, + { .channel = 158, + .freq = 5790, /* MHz */ + .unk2 = 3860, + RADIOREGS(0x71, 0x02, 0x43, 0x02, 0x0A, 0x01, 0x04, 0x0A, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), + PHYREGS(0x1009, 0x0C09, 0x0809, 0xC401, 0xC501, 0xC601), + }, + { .channel = 159, + .freq = 5795, /* MHz */ + .unk2 = 3863, + RADIOREGS(0x72, 0x04, 0x87, 0x02, 0xF2, 0x00, 0x03, 0x14, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), + PHYREGS(0x1209, 0x0E09, 0x0A09, 0xC401, 0xC401, 0xC501), + }, + { .channel = 160, + .freq = 5800, /* MHz */ + .unk2 = 3867, + RADIOREGS(0x71, 0x02, 0x44, 0x01, 0x0A, 0x01, 0x04, 0x0A, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), + PHYREGS(0x1409, 0x1009, 0x0C09, 0xC301, 0xC401, 0xC501), + }, + { .channel = 161, + .freq = 5805, /* MHz */ + .unk2 = 3870, + RADIOREGS(0x72, 0x04, 0x89, 0x01, 0xED, 0x00, 0x03, 0x14, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), + PHYREGS(0x1609, 0x1209, 0x0E09, 0xC301, 0xC401, 0xC401), + }, + { .channel = 162, + .freq = 5810, /* MHz */ + .unk2 = 3873, + RADIOREGS(0x71, 0x02, 0x45, 0x01, 0x0A, 0x01, 0x04, 0x0A, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), + PHYREGS(0x1809, 0x1409, 0x1009, 0xC201, 0xC301, 0xC401), + }, + { .channel = 163, + .freq = 5815, /* MHz */ + .unk2 = 3877, + RADIOREGS(0x72, 0x04, 0x8B, 0x01, 0xED, 0x00, 0x03, 0x14, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), + PHYREGS(0x1A09, 0x1609, 0x1209, 0xC201, 0xC301, 0xC401), + }, + { .channel = 164, + .freq = 5820, /* MHz */ + .unk2 = 3880, + RADIOREGS(0x71, 0x02, 0x46, 0x01, 0x0A, 0x01, 0x04, 0x0A, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), + PHYREGS(0x1C09, 0x1809, 0x1409, 0xC201, 0xC201, 0xC301), + }, + { .channel = 165, + .freq = 5825, /* MHz */ + .unk2 = 3883, + RADIOREGS(0x72, 0x04, 0x8D, 0x01, 0xED, 0x00, 0x03, 0x14, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), + PHYREGS(0x1E09, 0x1A09, 0x1609, 0xC101, 0xC201, 0xC301), + }, + { .channel = 166, + .freq = 5830, /* MHz */ + .unk2 = 3887, + RADIOREGS(0x71, 0x02, 0x47, 0x01, 0x0A, 0x01, 0x04, 0x0A, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), + PHYREGS(0x2009, 0x1C09, 0x1809, 0xC101, 0xC201, 0xC201), + }, + { .channel = 168, + .freq = 5840, /* MHz */ + .unk2 = 3893, + RADIOREGS(0x71, 0x02, 0x48, 0x01, 0x0A, 0x01, 0x04, 0x0A, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), + PHYREGS(0x2409, 0x2009, 0x1C09, 0xC001, 0xC101, 0xC201), + }, + { .channel = 170, + .freq = 5850, /* MHz */ + .unk2 = 3900, + RADIOREGS(0x71, 0x02, 0x49, 0x01, 0xE0, 0x00, 0x04, 0x0A, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), + PHYREGS(0x2809, 0x2409, 0x2009, 0xBF01, 0xC001, 0xC101), + }, + { .channel = 172, + .freq = 5860, /* MHz */ + .unk2 = 3907, + RADIOREGS(0x71, 0x02, 0x4A, 0x01, 0xDE, 0x00, 0x04, 0x0A, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), + PHYREGS(0x2C09, 0x2809, 0x2409, 0xBF01, 0xBF01, 0xC001), + }, + { .channel = 174, + .freq = 5870, /* MHz */ + .unk2 = 3913, + RADIOREGS(0x71, 0x02, 0x4B, 0x00, 0xDB, 0x00, 0x04, 0x0A, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), + PHYREGS(0x3009, 0x2C09, 0x2809, 0xBE01, 0xBF01, 0xBF01), + }, + { .channel = 176, + .freq = 5880, /* MHz */ + .unk2 = 3920, + RADIOREGS(0x71, 0x02, 0x4C, 0x00, 0xD8, 0x00, 0x04, 0x0A, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), + PHYREGS(0x3409, 0x3009, 0x2C09, 0xBD01, 0xBE01, 0xBF01), + }, + { .channel = 178, + .freq = 5890, /* MHz */ + .unk2 = 3927, + RADIOREGS(0x71, 0x02, 0x4D, 0x00, 0xD6, 0x00, 0x04, 0x0A, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), + PHYREGS(0x3809, 0x3409, 0x3009, 0xBC01, 0xBD01, 0xBE01), + }, + { .channel = 180, + .freq = 5900, /* MHz */ + .unk2 = 3933, + RADIOREGS(0x71, 0x02, 0x4E, 0x00, 0xD3, 0x00, 0x04, 0x0A, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), + PHYREGS(0x3C09, 0x3809, 0x3409, 0xBC01, 0xBC01, 0xBD01), + }, + { .channel = 182, + .freq = 5910, /* MHz */ + .unk2 = 3940, + RADIOREGS(0x71, 0x02, 0x4F, 0x00, 0xD6, 0x00, 0x04, 0x0A, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), + PHYREGS(0x4009, 0x3C09, 0x3809, 0xBB01, 0xBC01, 0xBC01), + }, + { .channel = 1, + .freq = 2412, /* MHz */ + .unk2 = 3216, + RADIOREGS(0x73, 0x09, 0x6C, 0x0F, 0x00, 0x01, 0x07, 0x15, + 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0D, 0x0C, + 0x80, 0xFF, 0x88, 0x0D, 0x0C, 0x80), + PHYREGS(0xC903, 0xC503, 0xC103, 0x3A04, 0x3F04, 0x4304), + }, + { .channel = 2, + .freq = 2417, /* MHz */ + .unk2 = 3223, + RADIOREGS(0x73, 0x09, 0x71, 0x0F, 0x00, 0x01, 0x07, 0x15, + 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0B, + 0x80, 0xFF, 0x88, 0x0C, 0x0B, 0x80), + PHYREGS(0xCB03, 0xC703, 0xC303, 0x3804, 0x3D04, 0x4104), + }, + { .channel = 3, + .freq = 2422, /* MHz */ + .unk2 = 3229, + RADIOREGS(0x73, 0x09, 0x76, 0x0F, 0x00, 0x01, 0x07, 0x15, + 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0A, + 0x80, 0xFF, 0x88, 0x0C, 0x0A, 0x80), + PHYREGS(0xCD03, 0xC903, 0xC503, 0x3604, 0x3A04, 0x3F04), + }, + { .channel = 4, + .freq = 2427, /* MHz */ + .unk2 = 3236, + RADIOREGS(0x73, 0x09, 0x7B, 0x0F, 0x00, 0x01, 0x07, 0x15, + 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0A, + 0x80, 0xFF, 0x88, 0x0C, 0x0A, 0x80), + PHYREGS(0xCF03, 0xCB03, 0xC703, 0x3404, 0x3804, 0x3D04), + }, + { .channel = 5, + .freq = 2432, /* MHz */ + .unk2 = 3243, + RADIOREGS(0x73, 0x09, 0x80, 0x0F, 0x00, 0x01, 0x07, 0x15, + 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x09, + 0x80, 0xFF, 0x88, 0x0C, 0x09, 0x80), + PHYREGS(0xD103, 0xCD03, 0xC903, 0x3104, 0x3604, 0x3A04), + }, + { .channel = 6, + .freq = 2437, /* MHz */ + .unk2 = 3249, + RADIOREGS(0x73, 0x09, 0x85, 0x0F, 0x00, 0x01, 0x07, 0x15, + 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0B, 0x08, + 0x80, 0xFF, 0x88, 0x0B, 0x08, 0x80), + PHYREGS(0xD303, 0xCF03, 0xCB03, 0x2F04, 0x3404, 0x3804), + }, + { .channel = 7, + .freq = 2442, /* MHz */ + .unk2 = 3256, + RADIOREGS(0x73, 0x09, 0x8A, 0x0F, 0x00, 0x01, 0x07, 0x15, + 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0A, 0x07, + 0x80, 0xFF, 0x88, 0x0A, 0x07, 0x80), + PHYREGS(0xD503, 0xD103, 0xCD03, 0x2D04, 0x3104, 0x3604), + }, + { .channel = 8, + .freq = 2447, /* MHz */ + .unk2 = 3263, + RADIOREGS(0x73, 0x09, 0x8F, 0x0F, 0x00, 0x01, 0x07, 0x15, + 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0A, 0x06, + 0x80, 0xFF, 0x88, 0x0A, 0x06, 0x80), + PHYREGS(0xD703, 0xD303, 0xCF03, 0x2B04, 0x2F04, 0x3404), + }, + { .channel = 9, + .freq = 2452, /* MHz */ + .unk2 = 3269, + RADIOREGS(0x73, 0x09, 0x94, 0x0F, 0x00, 0x01, 0x07, 0x15, + 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x09, 0x06, + 0x80, 0xFF, 0x88, 0x09, 0x06, 0x80), + PHYREGS(0xD903, 0xD503, 0xD103, 0x2904, 0x2D04, 0x3104), + }, + { .channel = 10, + .freq = 2457, /* MHz */ + .unk2 = 3276, + RADIOREGS(0x73, 0x09, 0x99, 0x0F, 0x00, 0x01, 0x07, 0x15, + 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x05, + 0x80, 0xFF, 0x88, 0x08, 0x05, 0x80), + PHYREGS(0xDB03, 0xD703, 0xD303, 0x2704, 0x2B04, 0x2F04), + }, + { .channel = 11, + .freq = 2462, /* MHz */ + .unk2 = 3283, + RADIOREGS(0x73, 0x09, 0x9E, 0x0F, 0x00, 0x01, 0x07, 0x15, + 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x04, + 0x80, 0xFF, 0x88, 0x08, 0x04, 0x80), + PHYREGS(0xDD03, 0xD903, 0xD503, 0x2404, 0x2904, 0x2D04), + }, + { .channel = 12, + .freq = 2467, /* MHz */ + .unk2 = 3289, + RADIOREGS(0x73, 0x09, 0xA3, 0x0F, 0x00, 0x01, 0x07, 0x15, + 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x03, + 0x80, 0xFF, 0x88, 0x08, 0x03, 0x80), + PHYREGS(0xDF03, 0xDB03, 0xD703, 0x2204, 0x2704, 0x2B04), + }, + { .channel = 13, + .freq = 2472, /* MHz */ + .unk2 = 3296, + RADIOREGS(0x73, 0x09, 0xA8, 0x0F, 0x00, 0x01, 0x07, 0x15, + 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x07, 0x03, + 0x80, 0xFF, 0x88, 0x07, 0x03, 0x80), + PHYREGS(0xE103, 0xDD03, 0xD903, 0x2004, 0x2404, 0x2904), + }, + { .channel = 14, + .freq = 2484, /* MHz */ + .unk2 = 3312, + RADIOREGS(0x73, 0x09, 0xB4, 0x0F, 0xFF, 0x01, 0x07, 0x15, + 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x07, 0x01, + 0x80, 0xFF, 0x88, 0x07, 0x01, 0x80), + PHYREGS(0xE603, 0xE203, 0xDE03, 0x1B04, 0x1F04, 0x2404), + }, +}; + +void b2055_upload_inittab(struct b43_wldev *dev, + bool ghz5, bool ignore_uploadflag) +{ + const struct b2055_inittab_entry *e; + unsigned int i; + u16 value; + + for (i = 0; i < ARRAY_SIZE(b2055_inittab); i++) { + e = &(b2055_inittab[i]); + if (!(e->flags & B2055_INITTAB_ENTRY_OK)) + continue; + if ((e->flags & B2055_INITTAB_UPLOAD) || ignore_uploadflag) { + if (ghz5) + value = e->ghz5; + else + value = e->ghz2; + b43_radio_write16(dev, i, value); + } + } +} + +const struct b43_nphy_channeltab_entry_rev2 * +b43_nphy_get_chantabent_rev2(struct b43_wldev *dev, u8 channel) +{ + const struct b43_nphy_channeltab_entry_rev2 *e; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(b43_nphy_channeltab_rev2); i++) { + e = &(b43_nphy_channeltab_rev2[i]); + if (e->channel == channel) + return e; + } + + return NULL; +} diff --git a/drivers/net/wireless/b43/radio_2055.h b/drivers/net/wireless/b43/radio_2055.h new file mode 100644 index 000000000000..d9bfa0f21b72 --- /dev/null +++ b/drivers/net/wireless/b43/radio_2055.h @@ -0,0 +1,254 @@ +#ifndef B43_RADIO_2055_H_ +#define B43_RADIO_2055_H_ + +#include + +#include "tables_nphy.h" + +#define B2055_GEN_SPARE 0x00 /* GEN spare */ +#define B2055_SP_PINPD 0x02 /* SP PIN PD */ +#define B2055_C1_SP_RSSI 0x03 /* SP RSSI Core 1 */ +#define B2055_C1_SP_PDMISC 0x04 /* SP PD MISC Core 1 */ +#define B2055_C2_SP_RSSI 0x05 /* SP RSSI Core 2 */ +#define B2055_C2_SP_PDMISC 0x06 /* SP PD MISC Core 2 */ +#define B2055_C1_SP_RXGC1 0x07 /* SP RX GC1 Core 1 */ +#define B2055_C1_SP_RXGC2 0x08 /* SP RX GC2 Core 1 */ +#define B2055_C2_SP_RXGC1 0x09 /* SP RX GC1 Core 2 */ +#define B2055_C2_SP_RXGC2 0x0A /* SP RX GC2 Core 2 */ +#define B2055_C1_SP_LPFBWSEL 0x0B /* SP LPF BW select Core 1 */ +#define B2055_C2_SP_LPFBWSEL 0x0C /* SP LPF BW select Core 2 */ +#define B2055_C1_SP_TXGC1 0x0D /* SP TX GC1 Core 1 */ +#define B2055_C1_SP_TXGC2 0x0E /* SP TX GC2 Core 1 */ +#define B2055_C2_SP_TXGC1 0x0F /* SP TX GC1 Core 2 */ +#define B2055_C2_SP_TXGC2 0x10 /* SP TX GC2 Core 2 */ +#define B2055_MASTER1 0x11 /* Master control 1 */ +#define B2055_MASTER2 0x12 /* Master control 2 */ +#define B2055_PD_LGEN 0x13 /* PD LGEN */ +#define B2055_PD_PLLTS 0x14 /* PD PLL TS */ +#define B2055_C1_PD_LGBUF 0x15 /* PD Core 1 LGBUF */ +#define B2055_C1_PD_TX 0x16 /* PD Core 1 TX */ +#define B2055_C1_PD_RXTX 0x17 /* PD Core 1 RXTX */ +#define B2055_C1_PD_RSSIMISC 0x18 /* PD Core 1 RSSI MISC */ +#define B2055_C2_PD_LGBUF 0x19 /* PD Core 2 LGBUF */ +#define B2055_C2_PD_TX 0x1A /* PD Core 2 TX */ +#define B2055_C2_PD_RXTX 0x1B /* PD Core 2 RXTX */ +#define B2055_C2_PD_RSSIMISC 0x1C /* PD Core 2 RSSI MISC */ +#define B2055_PWRDET_LGEN 0x1D /* PWRDET LGEN */ +#define B2055_C1_PWRDET_LGBUF 0x1E /* PWRDET LGBUF Core 1 */ +#define B2055_C1_PWRDET_RXTX 0x1F /* PWRDET RXTX Core 1 */ +#define B2055_C2_PWRDET_LGBUF 0x20 /* PWRDET LGBUF Core 2 */ +#define B2055_C2_PWRDET_RXTX 0x21 /* PWRDET RXTX Core 2 */ +#define B2055_RRCCAL_CS 0x22 /* RRCCAL Control spare */ +#define B2055_RRCCAL_NOPTSEL 0x23 /* RRCCAL N OPT SEL */ +#define B2055_CAL_MISC 0x24 /* CAL MISC */ +#define B2055_CAL_COUT 0x25 /* CAL Counter out */ +#define B2055_CAL_COUT2 0x26 /* CAL Counter out 2 */ +#define B2055_CAL_CVARCTL 0x27 /* CAL CVAR Control */ +#define B2055_CAL_RVARCTL 0x28 /* CAL RVAR Control */ +#define B2055_CAL_LPOCTL 0x29 /* CAL LPO Control */ +#define B2055_CAL_TS 0x2A /* CAL TS */ +#define B2055_CAL_RCCALRTS 0x2B /* CAL RCCAL READ TS */ +#define B2055_CAL_RCALRTS 0x2C /* CAL RCAL READ TS */ +#define B2055_PADDRV 0x2D /* PAD driver */ +#define B2055_XOCTL1 0x2E /* XO Control 1 */ +#define B2055_XOCTL2 0x2F /* XO Control 2 */ +#define B2055_XOREGUL 0x30 /* XO Regulator */ +#define B2055_XOMISC 0x31 /* XO misc */ +#define B2055_PLL_LFC1 0x32 /* PLL LF C1 */ +#define B2055_PLL_CALVTH 0x33 /* PLL CAL VTH */ +#define B2055_PLL_LFC2 0x34 /* PLL LF C2 */ +#define B2055_PLL_REF 0x35 /* PLL reference */ +#define B2055_PLL_LFR1 0x36 /* PLL LF R1 */ +#define B2055_PLL_PFDCP 0x37 /* PLL PFD CP */ +#define B2055_PLL_IDAC_CPOPAMP 0x38 /* PLL IDAC CPOPAMP */ +#define B2055_PLL_CPREG 0x39 /* PLL CP Regulator */ +#define B2055_PLL_RCAL 0x3A /* PLL RCAL */ +#define B2055_RF_PLLMOD0 0x3B /* RF PLL MOD0 */ +#define B2055_RF_PLLMOD1 0x3C /* RF PLL MOD1 */ +#define B2055_RF_MMDIDAC1 0x3D /* RF MMD IDAC 1 */ +#define B2055_RF_MMDIDAC0 0x3E /* RF MMD IDAC 0 */ +#define B2055_RF_MMDSP 0x3F /* RF MMD spare */ +#define B2055_VCO_CAL1 0x40 /* VCO cal 1 */ +#define B2055_VCO_CAL2 0x41 /* VCO cal 2 */ +#define B2055_VCO_CAL3 0x42 /* VCO cal 3 */ +#define B2055_VCO_CAL4 0x43 /* VCO cal 4 */ +#define B2055_VCO_CAL5 0x44 /* VCO cal 5 */ +#define B2055_VCO_CAL6 0x45 /* VCO cal 6 */ +#define B2055_VCO_CAL7 0x46 /* VCO cal 7 */ +#define B2055_VCO_CAL8 0x47 /* VCO cal 8 */ +#define B2055_VCO_CAL9 0x48 /* VCO cal 9 */ +#define B2055_VCO_CAL10 0x49 /* VCO cal 10 */ +#define B2055_VCO_CAL11 0x4A /* VCO cal 11 */ +#define B2055_VCO_CAL12 0x4B /* VCO cal 12 */ +#define B2055_VCO_CAL13 0x4C /* VCO cal 13 */ +#define B2055_VCO_CAL14 0x4D /* VCO cal 14 */ +#define B2055_VCO_CAL15 0x4E /* VCO cal 15 */ +#define B2055_VCO_CAL16 0x4F /* VCO cal 16 */ +#define B2055_VCO_KVCO 0x50 /* VCO KVCO */ +#define B2055_VCO_CAPTAIL 0x51 /* VCO CAP TAIL */ +#define B2055_VCO_IDACVCO 0x52 /* VCO IDAC VCO */ +#define B2055_VCO_REG 0x53 /* VCO Regulator */ +#define B2055_PLL_RFVTH 0x54 /* PLL RF VTH */ +#define B2055_LGBUF_CENBUF 0x55 /* LGBUF CEN BUF */ +#define B2055_LGEN_TUNE1 0x56 /* LGEN tune 1 */ +#define B2055_LGEN_TUNE2 0x57 /* LGEN tune 2 */ +#define B2055_LGEN_IDAC1 0x58 /* LGEN IDAC 1 */ +#define B2055_LGEN_IDAC2 0x59 /* LGEN IDAC 2 */ +#define B2055_LGEN_BIASC 0x5A /* LGEN BIAS counter */ +#define B2055_LGEN_BIASIDAC 0x5B /* LGEN BIAS IDAC */ +#define B2055_LGEN_RCAL 0x5C /* LGEN RCAL */ +#define B2055_LGEN_DIV 0x5D /* LGEN div */ +#define B2055_LGEN_SPARE2 0x5E /* LGEN spare 2 */ +#define B2055_C1_LGBUF_ATUNE 0x5F /* Core 1 LGBUF A tune */ +#define B2055_C1_LGBUF_GTUNE 0x60 /* Core 1 LGBUF G tune */ +#define B2055_C1_LGBUF_DIV 0x61 /* Core 1 LGBUF div */ +#define B2055_C1_LGBUF_AIDAC 0x62 /* Core 1 LGBUF A IDAC */ +#define B2055_C1_LGBUF_GIDAC 0x63 /* Core 1 LGBUF G IDAC */ +#define B2055_C1_LGBUF_IDACFO 0x64 /* Core 1 LGBUF IDAC filter override */ +#define B2055_C1_LGBUF_SPARE 0x65 /* Core 1 LGBUF spare */ +#define B2055_C1_RX_RFSPC1 0x66 /* Core 1 RX RF SPC1 */ +#define B2055_C1_RX_RFR1 0x67 /* Core 1 RX RF reg 1 */ +#define B2055_C1_RX_RFR2 0x68 /* Core 1 RX RF reg 2 */ +#define B2055_C1_RX_RFRCAL 0x69 /* Core 1 RX RF RCAL */ +#define B2055_C1_RX_BB_BLCMP 0x6A /* Core 1 RX Baseband BUFI LPF CMP */ +#define B2055_C1_RX_BB_LPF 0x6B /* Core 1 RX Baseband LPF */ +#define B2055_C1_RX_BB_MIDACHP 0x6C /* Core 1 RX Baseband MIDAC High-pass */ +#define B2055_C1_RX_BB_VGA1IDAC 0x6D /* Core 1 RX Baseband VGA1 IDAC */ +#define B2055_C1_RX_BB_VGA2IDAC 0x6E /* Core 1 RX Baseband VGA2 IDAC */ +#define B2055_C1_RX_BB_VGA3IDAC 0x6F /* Core 1 RX Baseband VGA3 IDAC */ +#define B2055_C1_RX_BB_BUFOCTL 0x70 /* Core 1 RX Baseband BUFO Control */ +#define B2055_C1_RX_BB_RCCALCTL 0x71 /* Core 1 RX Baseband RCCAL Control */ +#define B2055_C1_RX_BB_RSSICTL1 0x72 /* Core 1 RX Baseband RSSI Control 1 */ +#define B2055_C1_RX_BB_RSSICTL2 0x73 /* Core 1 RX Baseband RSSI Control 2 */ +#define B2055_C1_RX_BB_RSSICTL3 0x74 /* Core 1 RX Baseband RSSI Control 3 */ +#define B2055_C1_RX_BB_RSSICTL4 0x75 /* Core 1 RX Baseband RSSI Control 4 */ +#define B2055_C1_RX_BB_RSSICTL5 0x76 /* Core 1 RX Baseband RSSI Control 5 */ +#define B2055_C1_RX_BB_REG 0x77 /* Core 1 RX Baseband Regulator */ +#define B2055_C1_RX_BB_SPARE1 0x78 /* Core 1 RX Baseband spare 1 */ +#define B2055_C1_RX_TXBBRCAL 0x79 /* Core 1 RX TX BB RCAL */ +#define B2055_C1_TX_RF_SPGA 0x7A /* Core 1 TX RF SGM PGA */ +#define B2055_C1_TX_RF_SPAD 0x7B /* Core 1 TX RF SGM PAD */ +#define B2055_C1_TX_RF_CNTPGA1 0x7C /* Core 1 TX RF counter PGA 1 */ +#define B2055_C1_TX_RF_CNTPAD1 0x7D /* Core 1 TX RF counter PAD 1 */ +#define B2055_C1_TX_RF_PGAIDAC 0x7E /* Core 1 TX RF PGA IDAC */ +#define B2055_C1_TX_PGAPADTN 0x7F /* Core 1 TX PGA PAD TN */ +#define B2055_C1_TX_PADIDAC1 0x80 /* Core 1 TX PAD IDAC 1 */ +#define B2055_C1_TX_PADIDAC2 0x81 /* Core 1 TX PAD IDAC 2 */ +#define B2055_C1_TX_MXBGTRIM 0x82 /* Core 1 TX MX B/G TRIM */ +#define B2055_C1_TX_RF_RCAL 0x83 /* Core 1 TX RF RCAL */ +#define B2055_C1_TX_RF_PADTSSI1 0x84 /* Core 1 TX RF PAD TSSI1 */ +#define B2055_C1_TX_RF_PADTSSI2 0x85 /* Core 1 TX RF PAD TSSI2 */ +#define B2055_C1_TX_RF_SPARE 0x86 /* Core 1 TX RF spare */ +#define B2055_C1_TX_RF_IQCAL1 0x87 /* Core 1 TX RF I/Q CAL 1 */ +#define B2055_C1_TX_RF_IQCAL2 0x88 /* Core 1 TX RF I/Q CAL 2 */ +#define B2055_C1_TXBB_RCCAL 0x89 /* Core 1 TXBB RC CAL Control */ +#define B2055_C1_TXBB_LPF1 0x8A /* Core 1 TXBB LPF 1 */ +#define B2055_C1_TX_VOSCNCL 0x8B /* Core 1 TX VOS CNCL */ +#define B2055_C1_TX_LPF_MXGMIDAC 0x8C /* Core 1 TX LPF MXGM IDAC */ +#define B2055_C1_TX_BB_MXGM 0x8D /* Core 1 TX BB MXGM */ +#define B2055_C2_LGBUF_ATUNE 0x8E /* Core 2 LGBUF A tune */ +#define B2055_C2_LGBUF_GTUNE 0x8F /* Core 2 LGBUF G tune */ +#define B2055_C2_LGBUF_DIV 0x90 /* Core 2 LGBUF div */ +#define B2055_C2_LGBUF_AIDAC 0x91 /* Core 2 LGBUF A IDAC */ +#define B2055_C2_LGBUF_GIDAC 0x92 /* Core 2 LGBUF G IDAC */ +#define B2055_C2_LGBUF_IDACFO 0x93 /* Core 2 LGBUF IDAC filter override */ +#define B2055_C2_LGBUF_SPARE 0x94 /* Core 2 LGBUF spare */ +#define B2055_C2_RX_RFSPC1 0x95 /* Core 2 RX RF SPC1 */ +#define B2055_C2_RX_RFR1 0x96 /* Core 2 RX RF reg 1 */ +#define B2055_C2_RX_RFR2 0x97 /* Core 2 RX RF reg 2 */ +#define B2055_C2_RX_RFRCAL 0x98 /* Core 2 RX RF RCAL */ +#define B2055_C2_RX_BB_BLCMP 0x99 /* Core 2 RX Baseband BUFI LPF CMP */ +#define B2055_C2_RX_BB_LPF 0x9A /* Core 2 RX Baseband LPF */ +#define B2055_C2_RX_BB_MIDACHP 0x9B /* Core 2 RX Baseband MIDAC High-pass */ +#define B2055_C2_RX_BB_VGA1IDAC 0x9C /* Core 2 RX Baseband VGA1 IDAC */ +#define B2055_C2_RX_BB_VGA2IDAC 0x9D /* Core 2 RX Baseband VGA2 IDAC */ +#define B2055_C2_RX_BB_VGA3IDAC 0x9E /* Core 2 RX Baseband VGA3 IDAC */ +#define B2055_C2_RX_BB_BUFOCTL 0x9F /* Core 2 RX Baseband BUFO Control */ +#define B2055_C2_RX_BB_RCCALCTL 0xA0 /* Core 2 RX Baseband RCCAL Control */ +#define B2055_C2_RX_BB_RSSICTL1 0xA1 /* Core 2 RX Baseband RSSI Control 1 */ +#define B2055_C2_RX_BB_RSSICTL2 0xA2 /* Core 2 RX Baseband RSSI Control 2 */ +#define B2055_C2_RX_BB_RSSICTL3 0xA3 /* Core 2 RX Baseband RSSI Control 3 */ +#define B2055_C2_RX_BB_RSSICTL4 0xA4 /* Core 2 RX Baseband RSSI Control 4 */ +#define B2055_C2_RX_BB_RSSICTL5 0xA5 /* Core 2 RX Baseband RSSI Control 5 */ +#define B2055_C2_RX_BB_REG 0xA6 /* Core 2 RX Baseband Regulator */ +#define B2055_C2_RX_BB_SPARE1 0xA7 /* Core 2 RX Baseband spare 1 */ +#define B2055_C2_RX_TXBBRCAL 0xA8 /* Core 2 RX TX BB RCAL */ +#define B2055_C2_TX_RF_SPGA 0xA9 /* Core 2 TX RF SGM PGA */ +#define B2055_C2_TX_RF_SPAD 0xAA /* Core 2 TX RF SGM PAD */ +#define B2055_C2_TX_RF_CNTPGA1 0xAB /* Core 2 TX RF counter PGA 1 */ +#define B2055_C2_TX_RF_CNTPAD1 0xAC /* Core 2 TX RF counter PAD 1 */ +#define B2055_C2_TX_RF_PGAIDAC 0xAD /* Core 2 TX RF PGA IDAC */ +#define B2055_C2_TX_PGAPADTN 0xAE /* Core 2 TX PGA PAD TN */ +#define B2055_C2_TX_PADIDAC1 0xAF /* Core 2 TX PAD IDAC 1 */ +#define B2055_C2_TX_PADIDAC2 0xB0 /* Core 2 TX PAD IDAC 2 */ +#define B2055_C2_TX_MXBGTRIM 0xB1 /* Core 2 TX MX B/G TRIM */ +#define B2055_C2_TX_RF_RCAL 0xB2 /* Core 2 TX RF RCAL */ +#define B2055_C2_TX_RF_PADTSSI1 0xB3 /* Core 2 TX RF PAD TSSI1 */ +#define B2055_C2_TX_RF_PADTSSI2 0xB4 /* Core 2 TX RF PAD TSSI2 */ +#define B2055_C2_TX_RF_SPARE 0xB5 /* Core 2 TX RF spare */ +#define B2055_C2_TX_RF_IQCAL1 0xB6 /* Core 2 TX RF I/Q CAL 1 */ +#define B2055_C2_TX_RF_IQCAL2 0xB7 /* Core 2 TX RF I/Q CAL 2 */ +#define B2055_C2_TXBB_RCCAL 0xB8 /* Core 2 TXBB RC CAL Control */ +#define B2055_C2_TXBB_LPF1 0xB9 /* Core 2 TXBB LPF 1 */ +#define B2055_C2_TX_VOSCNCL 0xBA /* Core 2 TX VOS CNCL */ +#define B2055_C2_TX_LPF_MXGMIDAC 0xBB /* Core 2 TX LPF MXGM IDAC */ +#define B2055_C2_TX_BB_MXGM 0xBC /* Core 2 TX BB MXGM */ +#define B2055_PRG_GCHP21 0xBD /* PRG GC HPVGA23 21 */ +#define B2055_PRG_GCHP22 0xBE /* PRG GC HPVGA23 22 */ +#define B2055_PRG_GCHP23 0xBF /* PRG GC HPVGA23 23 */ +#define B2055_PRG_GCHP24 0xC0 /* PRG GC HPVGA23 24 */ +#define B2055_PRG_GCHP25 0xC1 /* PRG GC HPVGA23 25 */ +#define B2055_PRG_GCHP26 0xC2 /* PRG GC HPVGA23 26 */ +#define B2055_PRG_GCHP27 0xC3 /* PRG GC HPVGA23 27 */ +#define B2055_PRG_GCHP28 0xC4 /* PRG GC HPVGA23 28 */ +#define B2055_PRG_GCHP29 0xC5 /* PRG GC HPVGA23 29 */ +#define B2055_PRG_GCHP30 0xC6 /* PRG GC HPVGA23 30 */ +#define B2055_C1_LNA_GAINBST 0xCD /* Core 1 LNA GAINBST */ +#define B2055_C1_B0NB_RSSIVCM 0xD2 /* Core 1 B0 narrow-band RSSI VCM */ +#define B2055_C1_GENSPARE2 0xD6 /* Core 1 GEN spare 2 */ +#define B2055_C2_LNA_GAINBST 0xD9 /* Core 2 LNA GAINBST */ +#define B2055_C2_B0NB_RSSIVCM 0xDE /* Core 2 B0 narrow-band RSSI VCM */ +#define B2055_C2_GENSPARE2 0xE2 /* Core 2 GEN spare 2 */ + +struct b43_nphy_channeltab_entry_rev2 { + /* The channel number */ + u8 channel; + /* The channel frequency in MHz */ + u16 freq; + /* An unknown value */ + u16 unk2; + /* Radio register values on channelswitch */ + u8 radio_pll_ref; + u8 radio_rf_pllmod0; + u8 radio_rf_pllmod1; + u8 radio_vco_captail; + u8 radio_vco_cal1; + u8 radio_vco_cal2; + u8 radio_pll_lfc1; + u8 radio_pll_lfr1; + u8 radio_pll_lfc2; + u8 radio_lgbuf_cenbuf; + u8 radio_lgen_tune1; + u8 radio_lgen_tune2; + u8 radio_c1_lgbuf_atune; + u8 radio_c1_lgbuf_gtune; + u8 radio_c1_rx_rfr1; + u8 radio_c1_tx_pgapadtn; + u8 radio_c1_tx_mxbgtrim; + u8 radio_c2_lgbuf_atune; + u8 radio_c2_lgbuf_gtune; + u8 radio_c2_rx_rfr1; + u8 radio_c2_tx_pgapadtn; + u8 radio_c2_tx_mxbgtrim; + /* PHY register values on channelswitch */ + struct b43_phy_n_sfo_cfg phy_regs; +}; + +/* Upload the default register value table. + * If "ghz5" is true, we upload the 5Ghz table. Otherwise the 2.4Ghz + * table is uploaded. If "ignore_uploadflag" is true, we upload any value + * and ignore the "UPLOAD" flag. */ +void b2055_upload_inittab(struct b43_wldev *dev, + bool ghz5, bool ignore_uploadflag); + +#endif /* B43_RADIO_2055_H_ */ diff --git a/drivers/net/wireless/b43/tables_nphy.c b/drivers/net/wireless/b43/tables_nphy.c index e74b8eb5795c..cff7bd379ad8 100644 --- a/drivers/net/wireless/b43/tables_nphy.c +++ b/drivers/net/wireless/b43/tables_nphy.c @@ -27,1314 +27,6 @@ #include "phy_common.h" #include "phy_n.h" - -struct b2055_inittab_entry { - /* Value to write if we use the 5GHz band. */ - u16 ghz5; - /* Value to write if we use the 2.4GHz band. */ - u16 ghz2; - /* Flags */ - u8 flags; -#define B2055_INITTAB_ENTRY_OK 0x01 -#define B2055_INITTAB_UPLOAD 0x02 -}; -#define UPLOAD .flags = B2055_INITTAB_ENTRY_OK | B2055_INITTAB_UPLOAD -#define NOUPLOAD .flags = B2055_INITTAB_ENTRY_OK - -static const struct b2055_inittab_entry b2055_inittab [] = { - [B2055_SP_PINPD] = { .ghz5 = 0x0080, .ghz2 = 0x0080, NOUPLOAD, }, - [B2055_C1_SP_RSSI] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_C1_SP_PDMISC] = { .ghz5 = 0x0027, .ghz2 = 0x0027, NOUPLOAD, }, - [B2055_C2_SP_RSSI] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_C2_SP_PDMISC] = { .ghz5 = 0x0027, .ghz2 = 0x0027, NOUPLOAD, }, - [B2055_C1_SP_RXGC1] = { .ghz5 = 0x007F, .ghz2 = 0x007F, UPLOAD, }, - [B2055_C1_SP_RXGC2] = { .ghz5 = 0x0007, .ghz2 = 0x0007, UPLOAD, }, - [B2055_C2_SP_RXGC1] = { .ghz5 = 0x007F, .ghz2 = 0x007F, UPLOAD, }, - [B2055_C2_SP_RXGC2] = { .ghz5 = 0x0007, .ghz2 = 0x0007, UPLOAD, }, - [B2055_C1_SP_LPFBWSEL] = { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, }, - [B2055_C2_SP_LPFBWSEL] = { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, }, - [B2055_C1_SP_TXGC1] = { .ghz5 = 0x004F, .ghz2 = 0x004F, UPLOAD, }, - [B2055_C1_SP_TXGC2] = { .ghz5 = 0x0005, .ghz2 = 0x0005, UPLOAD, }, - [B2055_C2_SP_TXGC1] = { .ghz5 = 0x004F, .ghz2 = 0x004F, UPLOAD, }, - [B2055_C2_SP_TXGC2] = { .ghz5 = 0x0005, .ghz2 = 0x0005, UPLOAD, }, - [B2055_MASTER1] = { .ghz5 = 0x00D0, .ghz2 = 0x00D0, NOUPLOAD, }, - [B2055_MASTER2] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, - [B2055_PD_LGEN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_PD_PLLTS] = { .ghz5 = 0x0040, .ghz2 = 0x0040, NOUPLOAD, }, - [B2055_C1_PD_LGBUF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_C1_PD_TX] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_C1_PD_RXTX] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_C1_PD_RSSIMISC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_C2_PD_LGBUF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_C2_PD_TX] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_C2_PD_RXTX] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_C2_PD_RSSIMISC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_PWRDET_LGEN] = { .ghz5 = 0x00C0, .ghz2 = 0x00C0, NOUPLOAD, }, - [B2055_C1_PWRDET_LGBUF] = { .ghz5 = 0x00FF, .ghz2 = 0x00FF, NOUPLOAD, }, - [B2055_C1_PWRDET_RXTX] = { .ghz5 = 0x00C0, .ghz2 = 0x00C0, NOUPLOAD, }, - [B2055_C2_PWRDET_LGBUF] = { .ghz5 = 0x00FF, .ghz2 = 0x00FF, NOUPLOAD, }, - [B2055_C2_PWRDET_RXTX] = { .ghz5 = 0x00C0, .ghz2 = 0x00C0, NOUPLOAD, }, - [B2055_RRCCAL_CS] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_RRCCAL_NOPTSEL] = { .ghz5 = 0x002C, .ghz2 = 0x002C, NOUPLOAD, }, - [B2055_CAL_MISC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_CAL_COUT] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_CAL_COUT2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_CAL_CVARCTL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_CAL_RVARCTL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_CAL_LPOCTL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_CAL_TS] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_CAL_RCCALRTS] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_CAL_RCALRTS] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_PADDRV] = { .ghz5 = 0x00A4, .ghz2 = 0x00A4, NOUPLOAD, }, - [B2055_XOCTL1] = { .ghz5 = 0x0038, .ghz2 = 0x0038, NOUPLOAD, }, - [B2055_XOCTL2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_XOREGUL] = { .ghz5 = 0x0004, .ghz2 = 0x0004, UPLOAD, }, - [B2055_XOMISC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_PLL_LFC1] = { .ghz5 = 0x000A, .ghz2 = 0x000A, NOUPLOAD, }, - [B2055_PLL_CALVTH] = { .ghz5 = 0x0087, .ghz2 = 0x0087, NOUPLOAD, }, - [B2055_PLL_LFC2] = { .ghz5 = 0x0009, .ghz2 = 0x0009, NOUPLOAD, }, - [B2055_PLL_REF] = { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, }, - [B2055_PLL_LFR1] = { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, }, - [B2055_PLL_PFDCP] = { .ghz5 = 0x0018, .ghz2 = 0x0018, UPLOAD, }, - [B2055_PLL_IDAC_CPOPAMP] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, - [B2055_PLL_CPREG] = { .ghz5 = 0x0004, .ghz2 = 0x0004, UPLOAD, }, - [B2055_PLL_RCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, - [B2055_RF_PLLMOD0] = { .ghz5 = 0x009E, .ghz2 = 0x009E, NOUPLOAD, }, - [B2055_RF_PLLMOD1] = { .ghz5 = 0x0009, .ghz2 = 0x0009, NOUPLOAD, }, - [B2055_RF_MMDIDAC1] = { .ghz5 = 0x00C8, .ghz2 = 0x00C8, UPLOAD, }, - [B2055_RF_MMDIDAC0] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, - [B2055_RF_MMDSP] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_VCO_CAL1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_VCO_CAL2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_VCO_CAL3] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, - [B2055_VCO_CAL4] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, - [B2055_VCO_CAL5] = { .ghz5 = 0x0096, .ghz2 = 0x0096, NOUPLOAD, }, - [B2055_VCO_CAL6] = { .ghz5 = 0x003E, .ghz2 = 0x003E, NOUPLOAD, }, - [B2055_VCO_CAL7] = { .ghz5 = 0x003E, .ghz2 = 0x003E, NOUPLOAD, }, - [B2055_VCO_CAL8] = { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, }, - [B2055_VCO_CAL9] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, - [B2055_VCO_CAL10] = { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, }, - [B2055_VCO_CAL11] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, - [B2055_VCO_CAL12] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_VCO_CAL13] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_VCO_CAL14] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_VCO_CAL15] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_VCO_CAL16] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_VCO_KVCO] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, - [B2055_VCO_CAPTAIL] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, - [B2055_VCO_IDACVCO] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, - [B2055_VCO_REG] = { .ghz5 = 0x0084, .ghz2 = 0x0084, UPLOAD, }, - [B2055_PLL_RFVTH] = { .ghz5 = 0x00C3, .ghz2 = 0x00C3, NOUPLOAD, }, - [B2055_LGBUF_CENBUF] = { .ghz5 = 0x008F, .ghz2 = 0x008F, NOUPLOAD, }, - [B2055_LGEN_TUNE1] = { .ghz5 = 0x00FF, .ghz2 = 0x00FF, NOUPLOAD, }, - [B2055_LGEN_TUNE2] = { .ghz5 = 0x00FF, .ghz2 = 0x00FF, NOUPLOAD, }, - [B2055_LGEN_IDAC1] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, - [B2055_LGEN_IDAC2] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, - [B2055_LGEN_BIASC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_LGEN_BIASIDAC] = { .ghz5 = 0x00CC, .ghz2 = 0x00CC, NOUPLOAD, }, - [B2055_LGEN_RCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, - [B2055_LGEN_DIV] = { .ghz5 = 0x0080, .ghz2 = 0x0080, NOUPLOAD, }, - [B2055_LGEN_SPARE2] = { .ghz5 = 0x0080, .ghz2 = 0x0080, NOUPLOAD, }, - [B2055_C1_LGBUF_ATUNE] = { .ghz5 = 0x00F8, .ghz2 = 0x00F8, NOUPLOAD, }, - [B2055_C1_LGBUF_GTUNE] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, - [B2055_C1_LGBUF_DIV] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, - [B2055_C1_LGBUF_AIDAC] = { .ghz5 = 0x0088, .ghz2 = 0x0008, UPLOAD, }, - [B2055_C1_LGBUF_GIDAC] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, - [B2055_C1_LGBUF_IDACFO] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_C1_LGBUF_SPARE] = { .ghz5 = 0x0001, .ghz2 = 0x0001, UPLOAD, }, - [B2055_C1_RX_RFSPC1] = { .ghz5 = 0x008A, .ghz2 = 0x008A, NOUPLOAD, }, - [B2055_C1_RX_RFR1] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, - [B2055_C1_RX_RFR2] = { .ghz5 = 0x0083, .ghz2 = 0x0083, NOUPLOAD, }, - [B2055_C1_RX_RFRCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, - [B2055_C1_RX_BB_BLCMP] = { .ghz5 = 0x00A0, .ghz2 = 0x00A0, NOUPLOAD, }, - [B2055_C1_RX_BB_LPF] = { .ghz5 = 0x000A, .ghz2 = 0x000A, NOUPLOAD, }, - [B2055_C1_RX_BB_MIDACHP] = { .ghz5 = 0x0087, .ghz2 = 0x0087, UPLOAD, }, - [B2055_C1_RX_BB_VGA1IDAC] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, }, - [B2055_C1_RX_BB_VGA2IDAC] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, }, - [B2055_C1_RX_BB_VGA3IDAC] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, }, - [B2055_C1_RX_BB_BUFOCTL] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, }, - [B2055_C1_RX_BB_RCCALCTL] = { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, }, - [B2055_C1_RX_BB_RSSICTL1] = { .ghz5 = 0x006A, .ghz2 = 0x006A, UPLOAD, }, - [B2055_C1_RX_BB_RSSICTL2] = { .ghz5 = 0x00AB, .ghz2 = 0x00AB, UPLOAD, }, - [B2055_C1_RX_BB_RSSICTL3] = { .ghz5 = 0x0013, .ghz2 = 0x0013, UPLOAD, }, - [B2055_C1_RX_BB_RSSICTL4] = { .ghz5 = 0x00C1, .ghz2 = 0x00C1, UPLOAD, }, - [B2055_C1_RX_BB_RSSICTL5] = { .ghz5 = 0x00AA, .ghz2 = 0x00AA, UPLOAD, }, - [B2055_C1_RX_BB_REG] = { .ghz5 = 0x0087, .ghz2 = 0x0087, UPLOAD, }, - [B2055_C1_RX_BB_SPARE1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_C1_RX_TXBBRCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, - [B2055_C1_TX_RF_SPGA] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, - [B2055_C1_TX_RF_SPAD] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, - [B2055_C1_TX_RF_CNTPGA1] = { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, }, - [B2055_C1_TX_RF_CNTPAD1] = { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, }, - [B2055_C1_TX_RF_PGAIDAC] = { .ghz5 = 0x0097, .ghz2 = 0x0097, UPLOAD, }, - [B2055_C1_TX_PGAPADTN] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, - [B2055_C1_TX_PADIDAC1] = { .ghz5 = 0x0014, .ghz2 = 0x0014, UPLOAD, }, - [B2055_C1_TX_PADIDAC2] = { .ghz5 = 0x0033, .ghz2 = 0x0033, NOUPLOAD, }, - [B2055_C1_TX_MXBGTRIM] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, - [B2055_C1_TX_RF_RCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, - [B2055_C1_TX_RF_PADTSSI1] = { .ghz5 = 0x0003, .ghz2 = 0x0003, UPLOAD, }, - [B2055_C1_TX_RF_PADTSSI2] = { .ghz5 = 0x000A, .ghz2 = 0x000A, NOUPLOAD, }, - [B2055_C1_TX_RF_SPARE] = { .ghz5 = 0x0003, .ghz2 = 0x0003, UPLOAD, }, - [B2055_C1_TX_RF_IQCAL1] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, }, - [B2055_C1_TX_RF_IQCAL2] = { .ghz5 = 0x00A4, .ghz2 = 0x00A4, NOUPLOAD, }, - [B2055_C1_TXBB_RCCAL] = { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, }, - [B2055_C1_TXBB_LPF1] = { .ghz5 = 0x0028, .ghz2 = 0x0028, NOUPLOAD, }, - [B2055_C1_TX_VOSCNCL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_C1_TX_LPF_MXGMIDAC] = { .ghz5 = 0x004A, .ghz2 = 0x004A, NOUPLOAD, }, - [B2055_C1_TX_BB_MXGM] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_C2_LGBUF_ATUNE] = { .ghz5 = 0x00F8, .ghz2 = 0x00F8, NOUPLOAD, }, - [B2055_C2_LGBUF_GTUNE] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, - [B2055_C2_LGBUF_DIV] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, - [B2055_C2_LGBUF_AIDAC] = { .ghz5 = 0x0088, .ghz2 = 0x0008, UPLOAD, }, - [B2055_C2_LGBUF_GIDAC] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, - [B2055_C2_LGBUF_IDACFO] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_C2_LGBUF_SPARE] = { .ghz5 = 0x0001, .ghz2 = 0x0001, UPLOAD, }, - [B2055_C2_RX_RFSPC1] = { .ghz5 = 0x008A, .ghz2 = 0x008A, NOUPLOAD, }, - [B2055_C2_RX_RFR1] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, - [B2055_C2_RX_RFR2] = { .ghz5 = 0x0083, .ghz2 = 0x0083, NOUPLOAD, }, - [B2055_C2_RX_RFRCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, - [B2055_C2_RX_BB_BLCMP] = { .ghz5 = 0x00A0, .ghz2 = 0x00A0, NOUPLOAD, }, - [B2055_C2_RX_BB_LPF] = { .ghz5 = 0x000A, .ghz2 = 0x000A, NOUPLOAD, }, - [B2055_C2_RX_BB_MIDACHP] = { .ghz5 = 0x0087, .ghz2 = 0x0087, UPLOAD, }, - [B2055_C2_RX_BB_VGA1IDAC] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, }, - [B2055_C2_RX_BB_VGA2IDAC] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, }, - [B2055_C2_RX_BB_VGA3IDAC] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, }, - [B2055_C2_RX_BB_BUFOCTL] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, }, - [B2055_C2_RX_BB_RCCALCTL] = { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, }, - [B2055_C2_RX_BB_RSSICTL1] = { .ghz5 = 0x006A, .ghz2 = 0x006A, UPLOAD, }, - [B2055_C2_RX_BB_RSSICTL2] = { .ghz5 = 0x00AB, .ghz2 = 0x00AB, UPLOAD, }, - [B2055_C2_RX_BB_RSSICTL3] = { .ghz5 = 0x0013, .ghz2 = 0x0013, UPLOAD, }, - [B2055_C2_RX_BB_RSSICTL4] = { .ghz5 = 0x00C1, .ghz2 = 0x00C1, UPLOAD, }, - [B2055_C2_RX_BB_RSSICTL5] = { .ghz5 = 0x00AA, .ghz2 = 0x00AA, UPLOAD, }, - [B2055_C2_RX_BB_REG] = { .ghz5 = 0x0087, .ghz2 = 0x0087, UPLOAD, }, - [B2055_C2_RX_BB_SPARE1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_C2_RX_TXBBRCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, - [B2055_C2_TX_RF_SPGA] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, - [B2055_C2_TX_RF_SPAD] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, - [B2055_C2_TX_RF_CNTPGA1] = { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, }, - [B2055_C2_TX_RF_CNTPAD1] = { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, }, - [B2055_C2_TX_RF_PGAIDAC] = { .ghz5 = 0x0097, .ghz2 = 0x0097, UPLOAD, }, - [B2055_C2_TX_PGAPADTN] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, - [B2055_C2_TX_PADIDAC1] = { .ghz5 = 0x0014, .ghz2 = 0x0014, UPLOAD, }, - [B2055_C2_TX_PADIDAC2] = { .ghz5 = 0x0033, .ghz2 = 0x0033, NOUPLOAD, }, - [B2055_C2_TX_MXBGTRIM] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, - [B2055_C2_TX_RF_RCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, - [B2055_C2_TX_RF_PADTSSI1] = { .ghz5 = 0x0003, .ghz2 = 0x0003, UPLOAD, }, - [B2055_C2_TX_RF_PADTSSI2] = { .ghz5 = 0x000A, .ghz2 = 0x000A, NOUPLOAD, }, - [B2055_C2_TX_RF_SPARE] = { .ghz5 = 0x0003, .ghz2 = 0x0003, UPLOAD, }, - [B2055_C2_TX_RF_IQCAL1] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, }, - [B2055_C2_TX_RF_IQCAL2] = { .ghz5 = 0x00A4, .ghz2 = 0x00A4, NOUPLOAD, }, - [B2055_C2_TXBB_RCCAL] = { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, }, - [B2055_C2_TXBB_LPF1] = { .ghz5 = 0x0028, .ghz2 = 0x0028, NOUPLOAD, }, - [B2055_C2_TX_VOSCNCL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_C2_TX_LPF_MXGMIDAC] = { .ghz5 = 0x004A, .ghz2 = 0x004A, NOUPLOAD, }, - [B2055_C2_TX_BB_MXGM] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_PRG_GCHP21] = { .ghz5 = 0x0071, .ghz2 = 0x0071, NOUPLOAD, }, - [B2055_PRG_GCHP22] = { .ghz5 = 0x0072, .ghz2 = 0x0072, NOUPLOAD, }, - [B2055_PRG_GCHP23] = { .ghz5 = 0x0073, .ghz2 = 0x0073, NOUPLOAD, }, - [B2055_PRG_GCHP24] = { .ghz5 = 0x0074, .ghz2 = 0x0074, NOUPLOAD, }, - [B2055_PRG_GCHP25] = { .ghz5 = 0x0075, .ghz2 = 0x0075, NOUPLOAD, }, - [B2055_PRG_GCHP26] = { .ghz5 = 0x0076, .ghz2 = 0x0076, NOUPLOAD, }, - [B2055_PRG_GCHP27] = { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, }, - [B2055_PRG_GCHP28] = { .ghz5 = 0x0078, .ghz2 = 0x0078, NOUPLOAD, }, - [B2055_PRG_GCHP29] = { .ghz5 = 0x0079, .ghz2 = 0x0079, NOUPLOAD, }, - [B2055_PRG_GCHP30] = { .ghz5 = 0x007A, .ghz2 = 0x007A, NOUPLOAD, }, - [0xC7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [0xC8] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [0xC9] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [0xCA] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [0xCB] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [0xCC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_C1_LNA_GAINBST] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [0xCE] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [0xCF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [0xD0] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [0xD1] = { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, }, - [B2055_C1_B0NB_RSSIVCM] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, - [0xD3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [0xD4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [0xD5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_C1_GENSPARE2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [0xD7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [0xD8] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_C2_LNA_GAINBST] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [0xDA] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [0xDB] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [0xDC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [0xDD] = { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, }, - [B2055_C2_B0NB_RSSIVCM] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, - [0xDF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [0xE0] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [0xE1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_C2_GENSPARE2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, -}; - - -void b2055_upload_inittab(struct b43_wldev *dev, - bool ghz5, bool ignore_uploadflag) -{ - const struct b2055_inittab_entry *e; - unsigned int i; - u16 value; - - for (i = 0; i < ARRAY_SIZE(b2055_inittab); i++) { - e = &(b2055_inittab[i]); - if (!(e->flags & B2055_INITTAB_ENTRY_OK)) - continue; - if ((e->flags & B2055_INITTAB_UPLOAD) || ignore_uploadflag) { - if (ghz5) - value = e->ghz5; - else - value = e->ghz2; - b43_radio_write16(dev, i, value); - } - } -} - - -#define RADIOREGS(r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, \ - r12, r13, r14, r15, r16, r17, r18, r19, r20, r21) \ - .radio_pll_ref = r0, \ - .radio_rf_pllmod0 = r1, \ - .radio_rf_pllmod1 = r2, \ - .radio_vco_captail = r3, \ - .radio_vco_cal1 = r4, \ - .radio_vco_cal2 = r5, \ - .radio_pll_lfc1 = r6, \ - .radio_pll_lfr1 = r7, \ - .radio_pll_lfc2 = r8, \ - .radio_lgbuf_cenbuf = r9, \ - .radio_lgen_tune1 = r10, \ - .radio_lgen_tune2 = r11, \ - .radio_c1_lgbuf_atune = r12, \ - .radio_c1_lgbuf_gtune = r13, \ - .radio_c1_rx_rfr1 = r14, \ - .radio_c1_tx_pgapadtn = r15, \ - .radio_c1_tx_mxbgtrim = r16, \ - .radio_c2_lgbuf_atune = r17, \ - .radio_c2_lgbuf_gtune = r18, \ - .radio_c2_rx_rfr1 = r19, \ - .radio_c2_tx_pgapadtn = r20, \ - .radio_c2_tx_mxbgtrim = r21 - -#define PHYREGS(r0, r1, r2, r3, r4, r5) \ - .phy_regs.phy_bw1a = r0, \ - .phy_regs.phy_bw2 = r1, \ - .phy_regs.phy_bw3 = r2, \ - .phy_regs.phy_bw4 = r3, \ - .phy_regs.phy_bw5 = r4, \ - .phy_regs.phy_bw6 = r5 - -static const struct b43_nphy_channeltab_entry_rev2 b43_nphy_channeltab_rev2[] = { - { .channel = 184, - .freq = 4920, /* MHz */ - .unk2 = 3280, - RADIOREGS(0x71, 0x01, 0xEC, 0x0F, 0xFF, 0x01, 0x04, 0x0A, - 0x00, 0x8F, 0xFF, 0xFF, 0xFF, 0x00, 0x0F, 0x0F, - 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xB407, 0xB007, 0xAC07, 0x1402, 0x1502, 0x1602), - }, - { .channel = 186, - .freq = 4930, /* MHz */ - .unk2 = 3287, - RADIOREGS(0x71, 0x01, 0xED, 0x0F, 0xFF, 0x01, 0x04, 0x0A, - 0x00, 0x8F, 0xFF, 0xFF, 0xFF, 0x00, 0x0F, 0x0F, - 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xB807, 0xB407, 0xB007, 0x1302, 0x1402, 0x1502), - }, - { .channel = 188, - .freq = 4940, /* MHz */ - .unk2 = 3293, - RADIOREGS(0x71, 0x01, 0xEE, 0x0F, 0xFF, 0x01, 0x04, 0x0A, - 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, - 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xBC07, 0xB807, 0xB407, 0x1202, 0x1302, 0x1402), - }, - { .channel = 190, - .freq = 4950, /* MHz */ - .unk2 = 3300, - RADIOREGS(0x71, 0x01, 0xEF, 0x0F, 0xFF, 0x01, 0x04, 0x0A, - 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, - 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xC007, 0xBC07, 0xB807, 0x1102, 0x1202, 0x1302), - }, - { .channel = 192, - .freq = 4960, /* MHz */ - .unk2 = 3307, - RADIOREGS(0x71, 0x01, 0xF0, 0x0F, 0xFF, 0x01, 0x04, 0x0A, - 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, - 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xC407, 0xC007, 0xBC07, 0x0F02, 0x1102, 0x1202), - }, - { .channel = 194, - .freq = 4970, /* MHz */ - .unk2 = 3313, - RADIOREGS(0x71, 0x01, 0xF1, 0x0F, 0xFF, 0x01, 0x04, 0x0A, - 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, - 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xC807, 0xC407, 0xC007, 0x0E02, 0x0F02, 0x1102), - }, - { .channel = 196, - .freq = 4980, /* MHz */ - .unk2 = 3320, - RADIOREGS(0x71, 0x01, 0xF2, 0x0E, 0xFF, 0x01, 0x04, 0x0A, - 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, - 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xCC07, 0xC807, 0xC407, 0x0D02, 0x0E02, 0x0F02), - }, - { .channel = 198, - .freq = 4990, /* MHz */ - .unk2 = 3327, - RADIOREGS(0x71, 0x01, 0xF3, 0x0E, 0xFF, 0x01, 0x04, 0x0A, - 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, - 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xD007, 0xCC07, 0xC807, 0x0C02, 0x0D02, 0x0E02), - }, - { .channel = 200, - .freq = 5000, /* MHz */ - .unk2 = 3333, - RADIOREGS(0x71, 0x01, 0xF4, 0x0E, 0xFF, 0x01, 0x04, 0x0A, - 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, - 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xD407, 0xD007, 0xCC07, 0x0B02, 0x0C02, 0x0D02), - }, - { .channel = 202, - .freq = 5010, /* MHz */ - .unk2 = 3340, - RADIOREGS(0x71, 0x01, 0xF5, 0x0E, 0xFF, 0x01, 0x04, 0x0A, - 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, - 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xD807, 0xD407, 0xD007, 0x0A02, 0x0B02, 0x0C02), - }, - { .channel = 204, - .freq = 5020, /* MHz */ - .unk2 = 3347, - RADIOREGS(0x71, 0x01, 0xF6, 0x0E, 0xF7, 0x01, 0x04, 0x0A, - 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, - 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xDC07, 0xD807, 0xD407, 0x0902, 0x0A02, 0x0B02), - }, - { .channel = 206, - .freq = 5030, /* MHz */ - .unk2 = 3353, - RADIOREGS(0x71, 0x01, 0xF7, 0x0E, 0xF7, 0x01, 0x04, 0x0A, - 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, - 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xE007, 0xDC07, 0xD807, 0x0802, 0x0902, 0x0A02), - }, - { .channel = 208, - .freq = 5040, /* MHz */ - .unk2 = 3360, - RADIOREGS(0x71, 0x01, 0xF8, 0x0D, 0xEF, 0x01, 0x04, 0x0A, - 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, - 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xE407, 0xE007, 0xDC07, 0x0702, 0x0802, 0x0902), - }, - { .channel = 210, - .freq = 5050, /* MHz */ - .unk2 = 3367, - RADIOREGS(0x71, 0x01, 0xF9, 0x0D, 0xEF, 0x01, 0x04, 0x0A, - 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, - 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xE807, 0xE407, 0xE007, 0x0602, 0x0702, 0x0802), - }, - { .channel = 212, - .freq = 5060, /* MHz */ - .unk2 = 3373, - RADIOREGS(0x71, 0x01, 0xFA, 0x0D, 0xE6, 0x01, 0x04, 0x0A, - 0x00, 0x8F, 0xBB, 0xBB, 0xFF, 0x00, 0x0E, 0x0F, - 0x8E, 0xFF, 0x00, 0x0E, 0x0F, 0x8E), - PHYREGS(0xEC07, 0xE807, 0xE407, 0x0502, 0x0602, 0x0702), - }, - { .channel = 214, - .freq = 5070, /* MHz */ - .unk2 = 3380, - RADIOREGS(0x71, 0x01, 0xFB, 0x0D, 0xE6, 0x01, 0x04, 0x0A, - 0x00, 0x8F, 0xBB, 0xBB, 0xFF, 0x00, 0x0E, 0x0F, - 0x8E, 0xFF, 0x00, 0x0E, 0x0F, 0x8E), - PHYREGS(0xF007, 0xEC07, 0xE807, 0x0402, 0x0502, 0x0602), - }, - { .channel = 216, - .freq = 5080, /* MHz */ - .unk2 = 3387, - RADIOREGS(0x71, 0x01, 0xFC, 0x0D, 0xDE, 0x01, 0x04, 0x0A, - 0x00, 0x8E, 0xBB, 0xBB, 0xEE, 0x00, 0x0E, 0x0F, - 0x8D, 0xEE, 0x00, 0x0E, 0x0F, 0x8D), - PHYREGS(0xF407, 0xF007, 0xEC07, 0x0302, 0x0402, 0x0502), - }, - { .channel = 218, - .freq = 5090, /* MHz */ - .unk2 = 3393, - RADIOREGS(0x71, 0x01, 0xFD, 0x0D, 0xDE, 0x01, 0x04, 0x0A, - 0x00, 0x8E, 0xBB, 0xBB, 0xEE, 0x00, 0x0E, 0x0F, - 0x8D, 0xEE, 0x00, 0x0E, 0x0F, 0x8D), - PHYREGS(0xF807, 0xF407, 0xF007, 0x0202, 0x0302, 0x0402), - }, - { .channel = 220, - .freq = 5100, /* MHz */ - .unk2 = 3400, - RADIOREGS(0x71, 0x01, 0xFE, 0x0C, 0xD6, 0x01, 0x04, 0x0A, - 0x00, 0x8E, 0xAA, 0xAA, 0xEE, 0x00, 0x0D, 0x0F, - 0x8D, 0xEE, 0x00, 0x0D, 0x0F, 0x8D), - PHYREGS(0xFC07, 0xF807, 0xF407, 0x0102, 0x0202, 0x0302), - }, - { .channel = 222, - .freq = 5110, /* MHz */ - .unk2 = 3407, - RADIOREGS(0x71, 0x01, 0xFF, 0x0C, 0xD6, 0x01, 0x04, 0x0A, - 0x00, 0x8E, 0xAA, 0xAA, 0xEE, 0x00, 0x0D, 0x0F, - 0x8D, 0xEE, 0x00, 0x0D, 0x0F, 0x8D), - PHYREGS(0x0008, 0xFC07, 0xF807, 0x0002, 0x0102, 0x0202), - }, - { .channel = 224, - .freq = 5120, /* MHz */ - .unk2 = 3413, - RADIOREGS(0x71, 0x02, 0x00, 0x0C, 0xCE, 0x01, 0x04, 0x0A, - 0x00, 0x8D, 0xAA, 0xAA, 0xDD, 0x00, 0x0D, 0x0F, - 0x8C, 0xDD, 0x00, 0x0D, 0x0F, 0x8C), - PHYREGS(0x0408, 0x0008, 0xFC07, 0xFF01, 0x0002, 0x0102), - }, - { .channel = 226, - .freq = 5130, /* MHz */ - .unk2 = 3420, - RADIOREGS(0x71, 0x02, 0x01, 0x0C, 0xCE, 0x01, 0x04, 0x0A, - 0x00, 0x8D, 0xAA, 0xAA, 0xDD, 0x00, 0x0D, 0x0F, - 0x8C, 0xDD, 0x00, 0x0D, 0x0F, 0x8C), - PHYREGS(0x0808, 0x0408, 0x0008, 0xFE01, 0xFF01, 0x0002), - }, - { .channel = 228, - .freq = 5140, /* MHz */ - .unk2 = 3427, - RADIOREGS(0x71, 0x02, 0x02, 0x0C, 0xC6, 0x01, 0x04, 0x0A, - 0x00, 0x8D, 0x99, 0x99, 0xDD, 0x00, 0x0C, 0x0E, - 0x8B, 0xDD, 0x00, 0x0C, 0x0E, 0x8B), - PHYREGS(0x0C08, 0x0808, 0x0408, 0xFD01, 0xFE01, 0xFF01), - }, - { .channel = 32, - .freq = 5160, /* MHz */ - .unk2 = 3440, - RADIOREGS(0x71, 0x02, 0x04, 0x0B, 0xBE, 0x01, 0x04, 0x0A, - 0x00, 0x8C, 0x99, 0x99, 0xCC, 0x00, 0x0B, 0x0D, - 0x8A, 0xCC, 0x00, 0x0B, 0x0D, 0x8A), - PHYREGS(0x1408, 0x1008, 0x0C08, 0xFB01, 0xFC01, 0xFD01), - }, - { .channel = 34, - .freq = 5170, /* MHz */ - .unk2 = 3447, - RADIOREGS(0x71, 0x02, 0x05, 0x0B, 0xBE, 0x01, 0x04, 0x0A, - 0x00, 0x8C, 0x99, 0x99, 0xCC, 0x00, 0x0B, 0x0D, - 0x8A, 0xCC, 0x00, 0x0B, 0x0D, 0x8A), - PHYREGS(0x1808, 0x1408, 0x1008, 0xFA01, 0xFB01, 0xFC01), - }, - { .channel = 36, - .freq = 5180, /* MHz */ - .unk2 = 3453, - RADIOREGS(0x71, 0x02, 0x06, 0x0B, 0xB6, 0x01, 0x04, 0x0A, - 0x00, 0x8C, 0x88, 0x88, 0xCC, 0x00, 0x0B, 0x0C, - 0x89, 0xCC, 0x00, 0x0B, 0x0C, 0x89), - PHYREGS(0x1C08, 0x1808, 0x1408, 0xF901, 0xFA01, 0xFB01), - }, - { .channel = 38, - .freq = 5190, /* MHz */ - .unk2 = 3460, - RADIOREGS(0x71, 0x02, 0x07, 0x0B, 0xB6, 0x01, 0x04, 0x0A, - 0x00, 0x8C, 0x88, 0x88, 0xCC, 0x00, 0x0B, 0x0C, - 0x89, 0xCC, 0x00, 0x0B, 0x0C, 0x89), - PHYREGS(0x2008, 0x1C08, 0x1808, 0xF801, 0xF901, 0xFA01), - }, - { .channel = 40, - .freq = 5200, /* MHz */ - .unk2 = 3467, - RADIOREGS(0x71, 0x02, 0x08, 0x0B, 0xAF, 0x01, 0x04, 0x0A, - 0x00, 0x8B, 0x88, 0x88, 0xBB, 0x00, 0x0A, 0x0B, - 0x89, 0xBB, 0x00, 0x0A, 0x0B, 0x89), - PHYREGS(0x2408, 0x2008, 0x1C08, 0xF701, 0xF801, 0xF901), - }, - { .channel = 42, - .freq = 5210, /* MHz */ - .unk2 = 3473, - RADIOREGS(0x71, 0x02, 0x09, 0x0B, 0xAF, 0x01, 0x04, 0x0A, - 0x00, 0x8B, 0x88, 0x88, 0xBB, 0x00, 0x0A, 0x0B, - 0x89, 0xBB, 0x00, 0x0A, 0x0B, 0x89), - PHYREGS(0x2808, 0x2408, 0x2008, 0xF601, 0xF701, 0xF801), - }, - { .channel = 44, - .freq = 5220, /* MHz */ - .unk2 = 3480, - RADIOREGS(0x71, 0x02, 0x0A, 0x0A, 0xA7, 0x01, 0x04, 0x0A, - 0x00, 0x8B, 0x77, 0x77, 0xBB, 0x00, 0x09, 0x0A, - 0x88, 0xBB, 0x00, 0x09, 0x0A, 0x88), - PHYREGS(0x2C08, 0x2808, 0x2408, 0xF501, 0xF601, 0xF701), - }, - { .channel = 46, - .freq = 5230, /* MHz */ - .unk2 = 3487, - RADIOREGS(0x71, 0x02, 0x0B, 0x0A, 0xA7, 0x01, 0x04, 0x0A, - 0x00, 0x8B, 0x77, 0x77, 0xBB, 0x00, 0x09, 0x0A, - 0x88, 0xBB, 0x00, 0x09, 0x0A, 0x88), - PHYREGS(0x3008, 0x2C08, 0x2808, 0xF401, 0xF501, 0xF601), - }, - { .channel = 48, - .freq = 5240, /* MHz */ - .unk2 = 3493, - RADIOREGS(0x71, 0x02, 0x0C, 0x0A, 0xA0, 0x01, 0x04, 0x0A, - 0x00, 0x8A, 0x77, 0x77, 0xAA, 0x00, 0x09, 0x0A, - 0x87, 0xAA, 0x00, 0x09, 0x0A, 0x87), - PHYREGS(0x3408, 0x3008, 0x2C08, 0xF301, 0xF401, 0xF501), - }, - { .channel = 50, - .freq = 5250, /* MHz */ - .unk2 = 3500, - RADIOREGS(0x71, 0x02, 0x0D, 0x0A, 0xA0, 0x01, 0x04, 0x0A, - 0x00, 0x8A, 0x77, 0x77, 0xAA, 0x00, 0x09, 0x0A, - 0x87, 0xAA, 0x00, 0x09, 0x0A, 0x87), - PHYREGS(0x3808, 0x3408, 0x3008, 0xF201, 0xF301, 0xF401), - }, - { .channel = 52, - .freq = 5260, /* MHz */ - .unk2 = 3507, - RADIOREGS(0x71, 0x02, 0x0E, 0x0A, 0x98, 0x01, 0x04, 0x0A, - 0x00, 0x8A, 0x66, 0x66, 0xAA, 0x00, 0x08, 0x09, - 0x87, 0xAA, 0x00, 0x08, 0x09, 0x87), - PHYREGS(0x3C08, 0x3808, 0x3408, 0xF101, 0xF201, 0xF301), - }, - { .channel = 54, - .freq = 5270, /* MHz */ - .unk2 = 3513, - RADIOREGS(0x71, 0x02, 0x0F, 0x0A, 0x98, 0x01, 0x04, 0x0A, - 0x00, 0x8A, 0x66, 0x66, 0xAA, 0x00, 0x08, 0x09, - 0x87, 0xAA, 0x00, 0x08, 0x09, 0x87), - PHYREGS(0x4008, 0x3C08, 0x3808, 0xF001, 0xF101, 0xF201), - }, - { .channel = 56, - .freq = 5280, /* MHz */ - .unk2 = 3520, - RADIOREGS(0x71, 0x02, 0x10, 0x09, 0x91, 0x01, 0x04, 0x0A, - 0x00, 0x89, 0x66, 0x66, 0x99, 0x00, 0x08, 0x08, - 0x86, 0x99, 0x00, 0x08, 0x08, 0x86), - PHYREGS(0x4408, 0x4008, 0x3C08, 0xF001, 0xF001, 0xF101), - }, - { .channel = 58, - .freq = 5290, /* MHz */ - .unk2 = 3527, - RADIOREGS(0x71, 0x02, 0x11, 0x09, 0x91, 0x01, 0x04, 0x0A, - 0x00, 0x89, 0x66, 0x66, 0x99, 0x00, 0x08, 0x08, - 0x86, 0x99, 0x00, 0x08, 0x08, 0x86), - PHYREGS(0x4808, 0x4408, 0x4008, 0xEF01, 0xF001, 0xF001), - }, - { .channel = 60, - .freq = 5300, /* MHz */ - .unk2 = 3533, - RADIOREGS(0x71, 0x02, 0x12, 0x09, 0x8A, 0x01, 0x04, 0x0A, - 0x00, 0x89, 0x55, 0x55, 0x99, 0x00, 0x08, 0x07, - 0x85, 0x99, 0x00, 0x08, 0x07, 0x85), - PHYREGS(0x4C08, 0x4808, 0x4408, 0xEE01, 0xEF01, 0xF001), - }, - { .channel = 62, - .freq = 5310, /* MHz */ - .unk2 = 3540, - RADIOREGS(0x71, 0x02, 0x13, 0x09, 0x8A, 0x01, 0x04, 0x0A, - 0x00, 0x89, 0x55, 0x55, 0x99, 0x00, 0x08, 0x07, - 0x85, 0x99, 0x00, 0x08, 0x07, 0x85), - PHYREGS(0x5008, 0x4C08, 0x4808, 0xED01, 0xEE01, 0xEF01), - }, - { .channel = 64, - .freq = 5320, /* MHz */ - .unk2 = 3547, - RADIOREGS(0x71, 0x02, 0x14, 0x09, 0x83, 0x01, 0x04, 0x0A, - 0x00, 0x88, 0x55, 0x55, 0x88, 0x00, 0x07, 0x07, - 0x84, 0x88, 0x00, 0x07, 0x07, 0x84), - PHYREGS(0x5408, 0x5008, 0x4C08, 0xEC01, 0xED01, 0xEE01), - }, - { .channel = 66, - .freq = 5330, /* MHz */ - .unk2 = 3553, - RADIOREGS(0x71, 0x02, 0x15, 0x09, 0x83, 0x01, 0x04, 0x0A, - 0x00, 0x88, 0x55, 0x55, 0x88, 0x00, 0x07, 0x07, - 0x84, 0x88, 0x00, 0x07, 0x07, 0x84), - PHYREGS(0x5808, 0x5408, 0x5008, 0xEB01, 0xEC01, 0xED01), - }, - { .channel = 68, - .freq = 5340, /* MHz */ - .unk2 = 3560, - RADIOREGS(0x71, 0x02, 0x16, 0x08, 0x7C, 0x01, 0x04, 0x0A, - 0x00, 0x88, 0x44, 0x44, 0x88, 0x00, 0x07, 0x06, - 0x84, 0x88, 0x00, 0x07, 0x06, 0x84), - PHYREGS(0x5C08, 0x5808, 0x5408, 0xEA01, 0xEB01, 0xEC01), - }, - { .channel = 70, - .freq = 5350, /* MHz */ - .unk2 = 3567, - RADIOREGS(0x71, 0x02, 0x17, 0x08, 0x7C, 0x01, 0x04, 0x0A, - 0x00, 0x88, 0x44, 0x44, 0x88, 0x00, 0x07, 0x06, - 0x84, 0x88, 0x00, 0x07, 0x06, 0x84), - PHYREGS(0x6008, 0x5C08, 0x5808, 0xE901, 0xEA01, 0xEB01), - }, - { .channel = 72, - .freq = 5360, /* MHz */ - .unk2 = 3573, - RADIOREGS(0x71, 0x02, 0x18, 0x08, 0x75, 0x01, 0x04, 0x0A, - 0x00, 0x87, 0x44, 0x44, 0x77, 0x00, 0x06, 0x05, - 0x83, 0x77, 0x00, 0x06, 0x05, 0x83), - PHYREGS(0x6408, 0x6008, 0x5C08, 0xE801, 0xE901, 0xEA01), - }, - { .channel = 74, - .freq = 5370, /* MHz */ - .unk2 = 3580, - RADIOREGS(0x71, 0x02, 0x19, 0x08, 0x75, 0x01, 0x04, 0x0A, - 0x00, 0x87, 0x44, 0x44, 0x77, 0x00, 0x06, 0x05, - 0x83, 0x77, 0x00, 0x06, 0x05, 0x83), - PHYREGS(0x6808, 0x6408, 0x6008, 0xE701, 0xE801, 0xE901), - }, - { .channel = 76, - .freq = 5380, /* MHz */ - .unk2 = 3587, - RADIOREGS(0x71, 0x02, 0x1A, 0x08, 0x6E, 0x01, 0x04, 0x0A, - 0x00, 0x87, 0x33, 0x33, 0x77, 0x00, 0x06, 0x04, - 0x82, 0x77, 0x00, 0x06, 0x04, 0x82), - PHYREGS(0x6C08, 0x6808, 0x6408, 0xE601, 0xE701, 0xE801), - }, - { .channel = 78, - .freq = 5390, /* MHz */ - .unk2 = 3593, - RADIOREGS(0x71, 0x02, 0x1B, 0x08, 0x6E, 0x01, 0x04, 0x0A, - 0x00, 0x87, 0x33, 0x33, 0x77, 0x00, 0x06, 0x04, - 0x82, 0x77, 0x00, 0x06, 0x04, 0x82), - PHYREGS(0x7008, 0x6C08, 0x6808, 0xE501, 0xE601, 0xE701), - }, - { .channel = 80, - .freq = 5400, /* MHz */ - .unk2 = 3600, - RADIOREGS(0x71, 0x02, 0x1C, 0x07, 0x67, 0x01, 0x04, 0x0A, - 0x00, 0x86, 0x33, 0x33, 0x66, 0x00, 0x05, 0x04, - 0x81, 0x66, 0x00, 0x05, 0x04, 0x81), - PHYREGS(0x7408, 0x7008, 0x6C08, 0xE501, 0xE501, 0xE601), - }, - { .channel = 82, - .freq = 5410, /* MHz */ - .unk2 = 3607, - RADIOREGS(0x71, 0x02, 0x1D, 0x07, 0x67, 0x01, 0x04, 0x0A, - 0x00, 0x86, 0x33, 0x33, 0x66, 0x00, 0x05, 0x04, - 0x81, 0x66, 0x00, 0x05, 0x04, 0x81), - PHYREGS(0x7808, 0x7408, 0x7008, 0xE401, 0xE501, 0xE501), - }, - { .channel = 84, - .freq = 5420, /* MHz */ - .unk2 = 3613, - RADIOREGS(0x71, 0x02, 0x1E, 0x07, 0x61, 0x01, 0x04, 0x0A, - 0x00, 0x86, 0x22, 0x22, 0x66, 0x00, 0x05, 0x03, - 0x80, 0x66, 0x00, 0x05, 0x03, 0x80), - PHYREGS(0x7C08, 0x7808, 0x7408, 0xE301, 0xE401, 0xE501), - }, - { .channel = 86, - .freq = 5430, /* MHz */ - .unk2 = 3620, - RADIOREGS(0x71, 0x02, 0x1F, 0x07, 0x61, 0x01, 0x04, 0x0A, - 0x00, 0x86, 0x22, 0x22, 0x66, 0x00, 0x05, 0x03, - 0x80, 0x66, 0x00, 0x05, 0x03, 0x80), - PHYREGS(0x8008, 0x7C08, 0x7808, 0xE201, 0xE301, 0xE401), - }, - { .channel = 88, - .freq = 5440, /* MHz */ - .unk2 = 3627, - RADIOREGS(0x71, 0x02, 0x20, 0x07, 0x5A, 0x01, 0x04, 0x0A, - 0x00, 0x85, 0x22, 0x22, 0x55, 0x00, 0x04, 0x02, - 0x80, 0x55, 0x00, 0x04, 0x02, 0x80), - PHYREGS(0x8408, 0x8008, 0x7C08, 0xE101, 0xE201, 0xE301), - }, - { .channel = 90, - .freq = 5450, /* MHz */ - .unk2 = 3633, - RADIOREGS(0x71, 0x02, 0x21, 0x07, 0x5A, 0x01, 0x04, 0x0A, - 0x00, 0x85, 0x22, 0x22, 0x55, 0x00, 0x04, 0x02, - 0x80, 0x55, 0x00, 0x04, 0x02, 0x80), - PHYREGS(0x8808, 0x8408, 0x8008, 0xE001, 0xE101, 0xE201), - }, - { .channel = 92, - .freq = 5460, /* MHz */ - .unk2 = 3640, - RADIOREGS(0x71, 0x02, 0x22, 0x06, 0x53, 0x01, 0x04, 0x0A, - 0x00, 0x85, 0x11, 0x11, 0x55, 0x00, 0x04, 0x01, - 0x80, 0x55, 0x00, 0x04, 0x01, 0x80), - PHYREGS(0x8C08, 0x8808, 0x8408, 0xDF01, 0xE001, 0xE101), - }, - { .channel = 94, - .freq = 5470, /* MHz */ - .unk2 = 3647, - RADIOREGS(0x71, 0x02, 0x23, 0x06, 0x53, 0x01, 0x04, 0x0A, - 0x00, 0x85, 0x11, 0x11, 0x55, 0x00, 0x04, 0x01, - 0x80, 0x55, 0x00, 0x04, 0x01, 0x80), - PHYREGS(0x9008, 0x8C08, 0x8808, 0xDE01, 0xDF01, 0xE001), - }, - { .channel = 96, - .freq = 5480, /* MHz */ - .unk2 = 3653, - RADIOREGS(0x71, 0x02, 0x24, 0x06, 0x4D, 0x01, 0x04, 0x0A, - 0x00, 0x84, 0x11, 0x11, 0x44, 0x00, 0x03, 0x00, - 0x80, 0x44, 0x00, 0x03, 0x00, 0x80), - PHYREGS(0x9408, 0x9008, 0x8C08, 0xDD01, 0xDE01, 0xDF01), - }, - { .channel = 98, - .freq = 5490, /* MHz */ - .unk2 = 3660, - RADIOREGS(0x71, 0x02, 0x25, 0x06, 0x4D, 0x01, 0x04, 0x0A, - 0x00, 0x84, 0x11, 0x11, 0x44, 0x00, 0x03, 0x00, - 0x80, 0x44, 0x00, 0x03, 0x00, 0x80), - PHYREGS(0x9808, 0x9408, 0x9008, 0xDD01, 0xDD01, 0xDE01), - }, - { .channel = 100, - .freq = 5500, /* MHz */ - .unk2 = 3667, - RADIOREGS(0x71, 0x02, 0x26, 0x06, 0x47, 0x01, 0x04, 0x0A, - 0x00, 0x84, 0x00, 0x00, 0x44, 0x00, 0x03, 0x00, - 0x80, 0x44, 0x00, 0x03, 0x00, 0x80), - PHYREGS(0x9C08, 0x9808, 0x9408, 0xDC01, 0xDD01, 0xDD01), - }, - { .channel = 102, - .freq = 5510, /* MHz */ - .unk2 = 3673, - RADIOREGS(0x71, 0x02, 0x27, 0x06, 0x47, 0x01, 0x04, 0x0A, - 0x00, 0x84, 0x00, 0x00, 0x44, 0x00, 0x03, 0x00, - 0x80, 0x44, 0x00, 0x03, 0x00, 0x80), - PHYREGS(0xA008, 0x9C08, 0x9808, 0xDB01, 0xDC01, 0xDD01), - }, - { .channel = 104, - .freq = 5520, /* MHz */ - .unk2 = 3680, - RADIOREGS(0x71, 0x02, 0x28, 0x05, 0x40, 0x01, 0x04, 0x0A, - 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, - 0x80, 0x33, 0x00, 0x02, 0x00, 0x80), - PHYREGS(0xA408, 0xA008, 0x9C08, 0xDA01, 0xDB01, 0xDC01), - }, - { .channel = 106, - .freq = 5530, /* MHz */ - .unk2 = 3687, - RADIOREGS(0x71, 0x02, 0x29, 0x05, 0x40, 0x01, 0x04, 0x0A, - 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, - 0x80, 0x33, 0x00, 0x02, 0x00, 0x80), - PHYREGS(0xA808, 0xA408, 0xA008, 0xD901, 0xDA01, 0xDB01), - }, - { .channel = 108, - .freq = 5540, /* MHz */ - .unk2 = 3693, - RADIOREGS(0x71, 0x02, 0x2A, 0x05, 0x3A, 0x01, 0x04, 0x0A, - 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, - 0x80, 0x33, 0x00, 0x02, 0x00, 0x80), - PHYREGS(0xAC08, 0xA808, 0xA408, 0xD801, 0xD901, 0xDA01), - }, - { .channel = 110, - .freq = 5550, /* MHz */ - .unk2 = 3700, - RADIOREGS(0x71, 0x02, 0x2B, 0x05, 0x3A, 0x01, 0x04, 0x0A, - 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, - 0x80, 0x33, 0x00, 0x02, 0x00, 0x80), - PHYREGS(0xB008, 0xAC08, 0xA808, 0xD701, 0xD801, 0xD901), - }, - { .channel = 112, - .freq = 5560, /* MHz */ - .unk2 = 3707, - RADIOREGS(0x71, 0x02, 0x2C, 0x05, 0x34, 0x01, 0x04, 0x0A, - 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, - 0x80, 0x22, 0x00, 0x01, 0x00, 0x80), - PHYREGS(0xB408, 0xB008, 0xAC08, 0xD701, 0xD701, 0xD801), - }, - { .channel = 114, - .freq = 5570, /* MHz */ - .unk2 = 3713, - RADIOREGS(0x71, 0x02, 0x2D, 0x05, 0x34, 0x01, 0x04, 0x0A, - 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, - 0x80, 0x22, 0x00, 0x01, 0x00, 0x80), - PHYREGS(0xB808, 0xB408, 0xB008, 0xD601, 0xD701, 0xD701), - }, - { .channel = 116, - .freq = 5580, /* MHz */ - .unk2 = 3720, - RADIOREGS(0x71, 0x02, 0x2E, 0x04, 0x2E, 0x01, 0x04, 0x0A, - 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, - 0x80, 0x22, 0x00, 0x01, 0x00, 0x80), - PHYREGS(0xBC08, 0xB808, 0xB408, 0xD501, 0xD601, 0xD701), - }, - { .channel = 118, - .freq = 5590, /* MHz */ - .unk2 = 3727, - RADIOREGS(0x71, 0x02, 0x2F, 0x04, 0x2E, 0x01, 0x04, 0x0A, - 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, - 0x80, 0x22, 0x00, 0x01, 0x00, 0x80), - PHYREGS(0xC008, 0xBC08, 0xB808, 0xD401, 0xD501, 0xD601), - }, - { .channel = 120, - .freq = 5600, /* MHz */ - .unk2 = 3733, - RADIOREGS(0x71, 0x02, 0x30, 0x04, 0x28, 0x01, 0x04, 0x0A, - 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x01, 0x00, - 0x80, 0x11, 0x00, 0x01, 0x00, 0x80), - PHYREGS(0xC408, 0xC008, 0xBC08, 0xD301, 0xD401, 0xD501), - }, - { .channel = 122, - .freq = 5610, /* MHz */ - .unk2 = 3740, - RADIOREGS(0x71, 0x02, 0x31, 0x04, 0x28, 0x01, 0x04, 0x0A, - 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x01, 0x00, - 0x80, 0x11, 0x00, 0x01, 0x00, 0x80), - PHYREGS(0xC808, 0xC408, 0xC008, 0xD201, 0xD301, 0xD401), - }, - { .channel = 124, - .freq = 5620, /* MHz */ - .unk2 = 3747, - RADIOREGS(0x71, 0x02, 0x32, 0x04, 0x21, 0x01, 0x04, 0x0A, - 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, - 0x80, 0x11, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xCC08, 0xC808, 0xC408, 0xD201, 0xD201, 0xD301), - }, - { .channel = 126, - .freq = 5630, /* MHz */ - .unk2 = 3753, - RADIOREGS(0x71, 0x02, 0x33, 0x04, 0x21, 0x01, 0x04, 0x0A, - 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, - 0x80, 0x11, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xD008, 0xCC08, 0xC808, 0xD101, 0xD201, 0xD201), - }, - { .channel = 128, - .freq = 5640, /* MHz */ - .unk2 = 3760, - RADIOREGS(0x71, 0x02, 0x34, 0x03, 0x1C, 0x01, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xD408, 0xD008, 0xCC08, 0xD001, 0xD101, 0xD201), - }, - { .channel = 130, - .freq = 5650, /* MHz */ - .unk2 = 3767, - RADIOREGS(0x71, 0x02, 0x35, 0x03, 0x1C, 0x01, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xD808, 0xD408, 0xD008, 0xCF01, 0xD001, 0xD101), - }, - { .channel = 132, - .freq = 5660, /* MHz */ - .unk2 = 3773, - RADIOREGS(0x71, 0x02, 0x36, 0x03, 0x16, 0x01, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xDC08, 0xD808, 0xD408, 0xCE01, 0xCF01, 0xD001), - }, - { .channel = 134, - .freq = 5670, /* MHz */ - .unk2 = 3780, - RADIOREGS(0x71, 0x02, 0x37, 0x03, 0x16, 0x01, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xE008, 0xDC08, 0xD808, 0xCE01, 0xCE01, 0xCF01), - }, - { .channel = 136, - .freq = 5680, /* MHz */ - .unk2 = 3787, - RADIOREGS(0x71, 0x02, 0x38, 0x03, 0x10, 0x01, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xE408, 0xE008, 0xDC08, 0xCD01, 0xCE01, 0xCE01), - }, - { .channel = 138, - .freq = 5690, /* MHz */ - .unk2 = 3793, - RADIOREGS(0x71, 0x02, 0x39, 0x03, 0x10, 0x01, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xE808, 0xE408, 0xE008, 0xCC01, 0xCD01, 0xCE01), - }, - { .channel = 140, - .freq = 5700, /* MHz */ - .unk2 = 3800, - RADIOREGS(0x71, 0x02, 0x3A, 0x02, 0x0A, 0x01, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xEC08, 0xE808, 0xE408, 0xCB01, 0xCC01, 0xCD01), - }, - { .channel = 142, - .freq = 5710, /* MHz */ - .unk2 = 3807, - RADIOREGS(0x71, 0x02, 0x3B, 0x02, 0x0A, 0x01, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xF008, 0xEC08, 0xE808, 0xCA01, 0xCB01, 0xCC01), - }, - { .channel = 144, - .freq = 5720, /* MHz */ - .unk2 = 3813, - RADIOREGS(0x71, 0x02, 0x3C, 0x02, 0x0A, 0x01, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xF408, 0xF008, 0xEC08, 0xC901, 0xCA01, 0xCB01), - }, - { .channel = 145, - .freq = 5725, /* MHz */ - .unk2 = 3817, - RADIOREGS(0x72, 0x04, 0x79, 0x02, 0x03, 0x01, 0x03, 0x14, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xF608, 0xF208, 0xEE08, 0xC901, 0xCA01, 0xCB01), - }, - { .channel = 146, - .freq = 5730, /* MHz */ - .unk2 = 3820, - RADIOREGS(0x71, 0x02, 0x3D, 0x02, 0x0A, 0x01, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xF808, 0xF408, 0xF008, 0xC901, 0xC901, 0xCA01), - }, - { .channel = 147, - .freq = 5735, /* MHz */ - .unk2 = 3823, - RADIOREGS(0x72, 0x04, 0x7B, 0x02, 0x03, 0x01, 0x03, 0x14, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xFA08, 0xF608, 0xF208, 0xC801, 0xC901, 0xCA01), - }, - { .channel = 148, - .freq = 5740, /* MHz */ - .unk2 = 3827, - RADIOREGS(0x71, 0x02, 0x3E, 0x02, 0x0A, 0x01, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xFC08, 0xF808, 0xF408, 0xC801, 0xC901, 0xC901), - }, - { .channel = 149, - .freq = 5745, /* MHz */ - .unk2 = 3830, - RADIOREGS(0x72, 0x04, 0x7D, 0x02, 0xFE, 0x00, 0x03, 0x14, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xFE08, 0xFA08, 0xF608, 0xC801, 0xC801, 0xC901), - }, - { .channel = 150, - .freq = 5750, /* MHz */ - .unk2 = 3833, - RADIOREGS(0x71, 0x02, 0x3F, 0x02, 0x0A, 0x01, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x0009, 0xFC08, 0xF808, 0xC701, 0xC801, 0xC901), - }, - { .channel = 151, - .freq = 5755, /* MHz */ - .unk2 = 3837, - RADIOREGS(0x72, 0x04, 0x7F, 0x02, 0xFE, 0x00, 0x03, 0x14, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x0209, 0xFE08, 0xFA08, 0xC701, 0xC801, 0xC801), - }, - { .channel = 152, - .freq = 5760, /* MHz */ - .unk2 = 3840, - RADIOREGS(0x71, 0x02, 0x40, 0x02, 0x0A, 0x01, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x0409, 0x0009, 0xFC08, 0xC601, 0xC701, 0xC801), - }, - { .channel = 153, - .freq = 5765, /* MHz */ - .unk2 = 3843, - RADIOREGS(0x72, 0x04, 0x81, 0x02, 0xF8, 0x00, 0x03, 0x14, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x0609, 0x0209, 0xFE08, 0xC601, 0xC701, 0xC801), - }, - { .channel = 154, - .freq = 5770, /* MHz */ - .unk2 = 3847, - RADIOREGS(0x71, 0x02, 0x41, 0x02, 0x0A, 0x01, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x0809, 0x0409, 0x0009, 0xC601, 0xC601, 0xC701), - }, - { .channel = 155, - .freq = 5775, /* MHz */ - .unk2 = 3850, - RADIOREGS(0x72, 0x04, 0x83, 0x02, 0xF8, 0x00, 0x03, 0x14, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x0A09, 0x0609, 0x0209, 0xC501, 0xC601, 0xC701), - }, - { .channel = 156, - .freq = 5780, /* MHz */ - .unk2 = 3853, - RADIOREGS(0x71, 0x02, 0x42, 0x02, 0x0A, 0x01, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x0C09, 0x0809, 0x0409, 0xC501, 0xC601, 0xC601), - }, - { .channel = 157, - .freq = 5785, /* MHz */ - .unk2 = 3857, - RADIOREGS(0x72, 0x04, 0x85, 0x02, 0xF2, 0x00, 0x03, 0x14, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x0E09, 0x0A09, 0x0609, 0xC401, 0xC501, 0xC601), - }, - { .channel = 158, - .freq = 5790, /* MHz */ - .unk2 = 3860, - RADIOREGS(0x71, 0x02, 0x43, 0x02, 0x0A, 0x01, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x1009, 0x0C09, 0x0809, 0xC401, 0xC501, 0xC601), - }, - { .channel = 159, - .freq = 5795, /* MHz */ - .unk2 = 3863, - RADIOREGS(0x72, 0x04, 0x87, 0x02, 0xF2, 0x00, 0x03, 0x14, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x1209, 0x0E09, 0x0A09, 0xC401, 0xC401, 0xC501), - }, - { .channel = 160, - .freq = 5800, /* MHz */ - .unk2 = 3867, - RADIOREGS(0x71, 0x02, 0x44, 0x01, 0x0A, 0x01, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x1409, 0x1009, 0x0C09, 0xC301, 0xC401, 0xC501), - }, - { .channel = 161, - .freq = 5805, /* MHz */ - .unk2 = 3870, - RADIOREGS(0x72, 0x04, 0x89, 0x01, 0xED, 0x00, 0x03, 0x14, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x1609, 0x1209, 0x0E09, 0xC301, 0xC401, 0xC401), - }, - { .channel = 162, - .freq = 5810, /* MHz */ - .unk2 = 3873, - RADIOREGS(0x71, 0x02, 0x45, 0x01, 0x0A, 0x01, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x1809, 0x1409, 0x1009, 0xC201, 0xC301, 0xC401), - }, - { .channel = 163, - .freq = 5815, /* MHz */ - .unk2 = 3877, - RADIOREGS(0x72, 0x04, 0x8B, 0x01, 0xED, 0x00, 0x03, 0x14, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x1A09, 0x1609, 0x1209, 0xC201, 0xC301, 0xC401), - }, - { .channel = 164, - .freq = 5820, /* MHz */ - .unk2 = 3880, - RADIOREGS(0x71, 0x02, 0x46, 0x01, 0x0A, 0x01, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x1C09, 0x1809, 0x1409, 0xC201, 0xC201, 0xC301), - }, - { .channel = 165, - .freq = 5825, /* MHz */ - .unk2 = 3883, - RADIOREGS(0x72, 0x04, 0x8D, 0x01, 0xED, 0x00, 0x03, 0x14, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x1E09, 0x1A09, 0x1609, 0xC101, 0xC201, 0xC301), - }, - { .channel = 166, - .freq = 5830, /* MHz */ - .unk2 = 3887, - RADIOREGS(0x71, 0x02, 0x47, 0x01, 0x0A, 0x01, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x2009, 0x1C09, 0x1809, 0xC101, 0xC201, 0xC201), - }, - { .channel = 168, - .freq = 5840, /* MHz */ - .unk2 = 3893, - RADIOREGS(0x71, 0x02, 0x48, 0x01, 0x0A, 0x01, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x2409, 0x2009, 0x1C09, 0xC001, 0xC101, 0xC201), - }, - { .channel = 170, - .freq = 5850, /* MHz */ - .unk2 = 3900, - RADIOREGS(0x71, 0x02, 0x49, 0x01, 0xE0, 0x00, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x2809, 0x2409, 0x2009, 0xBF01, 0xC001, 0xC101), - }, - { .channel = 172, - .freq = 5860, /* MHz */ - .unk2 = 3907, - RADIOREGS(0x71, 0x02, 0x4A, 0x01, 0xDE, 0x00, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x2C09, 0x2809, 0x2409, 0xBF01, 0xBF01, 0xC001), - }, - { .channel = 174, - .freq = 5870, /* MHz */ - .unk2 = 3913, - RADIOREGS(0x71, 0x02, 0x4B, 0x00, 0xDB, 0x00, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x3009, 0x2C09, 0x2809, 0xBE01, 0xBF01, 0xBF01), - }, - { .channel = 176, - .freq = 5880, /* MHz */ - .unk2 = 3920, - RADIOREGS(0x71, 0x02, 0x4C, 0x00, 0xD8, 0x00, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x3409, 0x3009, 0x2C09, 0xBD01, 0xBE01, 0xBF01), - }, - { .channel = 178, - .freq = 5890, /* MHz */ - .unk2 = 3927, - RADIOREGS(0x71, 0x02, 0x4D, 0x00, 0xD6, 0x00, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x3809, 0x3409, 0x3009, 0xBC01, 0xBD01, 0xBE01), - }, - { .channel = 180, - .freq = 5900, /* MHz */ - .unk2 = 3933, - RADIOREGS(0x71, 0x02, 0x4E, 0x00, 0xD3, 0x00, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x3C09, 0x3809, 0x3409, 0xBC01, 0xBC01, 0xBD01), - }, - { .channel = 182, - .freq = 5910, /* MHz */ - .unk2 = 3940, - RADIOREGS(0x71, 0x02, 0x4F, 0x00, 0xD6, 0x00, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x4009, 0x3C09, 0x3809, 0xBB01, 0xBC01, 0xBC01), - }, - { .channel = 1, - .freq = 2412, /* MHz */ - .unk2 = 3216, - RADIOREGS(0x73, 0x09, 0x6C, 0x0F, 0x00, 0x01, 0x07, 0x15, - 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0D, 0x0C, - 0x80, 0xFF, 0x88, 0x0D, 0x0C, 0x80), - PHYREGS(0xC903, 0xC503, 0xC103, 0x3A04, 0x3F04, 0x4304), - }, - { .channel = 2, - .freq = 2417, /* MHz */ - .unk2 = 3223, - RADIOREGS(0x73, 0x09, 0x71, 0x0F, 0x00, 0x01, 0x07, 0x15, - 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0B, - 0x80, 0xFF, 0x88, 0x0C, 0x0B, 0x80), - PHYREGS(0xCB03, 0xC703, 0xC303, 0x3804, 0x3D04, 0x4104), - }, - { .channel = 3, - .freq = 2422, /* MHz */ - .unk2 = 3229, - RADIOREGS(0x73, 0x09, 0x76, 0x0F, 0x00, 0x01, 0x07, 0x15, - 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0A, - 0x80, 0xFF, 0x88, 0x0C, 0x0A, 0x80), - PHYREGS(0xCD03, 0xC903, 0xC503, 0x3604, 0x3A04, 0x3F04), - }, - { .channel = 4, - .freq = 2427, /* MHz */ - .unk2 = 3236, - RADIOREGS(0x73, 0x09, 0x7B, 0x0F, 0x00, 0x01, 0x07, 0x15, - 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0A, - 0x80, 0xFF, 0x88, 0x0C, 0x0A, 0x80), - PHYREGS(0xCF03, 0xCB03, 0xC703, 0x3404, 0x3804, 0x3D04), - }, - { .channel = 5, - .freq = 2432, /* MHz */ - .unk2 = 3243, - RADIOREGS(0x73, 0x09, 0x80, 0x0F, 0x00, 0x01, 0x07, 0x15, - 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x09, - 0x80, 0xFF, 0x88, 0x0C, 0x09, 0x80), - PHYREGS(0xD103, 0xCD03, 0xC903, 0x3104, 0x3604, 0x3A04), - }, - { .channel = 6, - .freq = 2437, /* MHz */ - .unk2 = 3249, - RADIOREGS(0x73, 0x09, 0x85, 0x0F, 0x00, 0x01, 0x07, 0x15, - 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0B, 0x08, - 0x80, 0xFF, 0x88, 0x0B, 0x08, 0x80), - PHYREGS(0xD303, 0xCF03, 0xCB03, 0x2F04, 0x3404, 0x3804), - }, - { .channel = 7, - .freq = 2442, /* MHz */ - .unk2 = 3256, - RADIOREGS(0x73, 0x09, 0x8A, 0x0F, 0x00, 0x01, 0x07, 0x15, - 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0A, 0x07, - 0x80, 0xFF, 0x88, 0x0A, 0x07, 0x80), - PHYREGS(0xD503, 0xD103, 0xCD03, 0x2D04, 0x3104, 0x3604), - }, - { .channel = 8, - .freq = 2447, /* MHz */ - .unk2 = 3263, - RADIOREGS(0x73, 0x09, 0x8F, 0x0F, 0x00, 0x01, 0x07, 0x15, - 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0A, 0x06, - 0x80, 0xFF, 0x88, 0x0A, 0x06, 0x80), - PHYREGS(0xD703, 0xD303, 0xCF03, 0x2B04, 0x2F04, 0x3404), - }, - { .channel = 9, - .freq = 2452, /* MHz */ - .unk2 = 3269, - RADIOREGS(0x73, 0x09, 0x94, 0x0F, 0x00, 0x01, 0x07, 0x15, - 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x09, 0x06, - 0x80, 0xFF, 0x88, 0x09, 0x06, 0x80), - PHYREGS(0xD903, 0xD503, 0xD103, 0x2904, 0x2D04, 0x3104), - }, - { .channel = 10, - .freq = 2457, /* MHz */ - .unk2 = 3276, - RADIOREGS(0x73, 0x09, 0x99, 0x0F, 0x00, 0x01, 0x07, 0x15, - 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x05, - 0x80, 0xFF, 0x88, 0x08, 0x05, 0x80), - PHYREGS(0xDB03, 0xD703, 0xD303, 0x2704, 0x2B04, 0x2F04), - }, - { .channel = 11, - .freq = 2462, /* MHz */ - .unk2 = 3283, - RADIOREGS(0x73, 0x09, 0x9E, 0x0F, 0x00, 0x01, 0x07, 0x15, - 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x04, - 0x80, 0xFF, 0x88, 0x08, 0x04, 0x80), - PHYREGS(0xDD03, 0xD903, 0xD503, 0x2404, 0x2904, 0x2D04), - }, - { .channel = 12, - .freq = 2467, /* MHz */ - .unk2 = 3289, - RADIOREGS(0x73, 0x09, 0xA3, 0x0F, 0x00, 0x01, 0x07, 0x15, - 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x03, - 0x80, 0xFF, 0x88, 0x08, 0x03, 0x80), - PHYREGS(0xDF03, 0xDB03, 0xD703, 0x2204, 0x2704, 0x2B04), - }, - { .channel = 13, - .freq = 2472, /* MHz */ - .unk2 = 3296, - RADIOREGS(0x73, 0x09, 0xA8, 0x0F, 0x00, 0x01, 0x07, 0x15, - 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x07, 0x03, - 0x80, 0xFF, 0x88, 0x07, 0x03, 0x80), - PHYREGS(0xE103, 0xDD03, 0xD903, 0x2004, 0x2404, 0x2904), - }, - { .channel = 14, - .freq = 2484, /* MHz */ - .unk2 = 3312, - RADIOREGS(0x73, 0x09, 0xB4, 0x0F, 0xFF, 0x01, 0x07, 0x15, - 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x07, 0x01, - 0x80, 0xFF, 0x88, 0x07, 0x01, 0x80), - PHYREGS(0xE603, 0xE203, 0xDE03, 0x1B04, 0x1F04, 0x2404), - }, -}; - -const struct b43_nphy_channeltab_entry_rev2 * -b43_nphy_get_chantabent_rev2(struct b43_wldev *dev, u8 channel) -{ - const struct b43_nphy_channeltab_entry_rev2 *e; - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(b43_nphy_channeltab_rev2); i++) { - e = &(b43_nphy_channeltab_rev2[i]); - if (e->channel == channel) - return e; - } - - return NULL; -} - static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_rev3[] = { }; @@ -1353,7 +45,6 @@ b43_nphy_get_chantabent_rev3(struct b43_wldev *dev, u16 freq) return NULL; } - static const u8 b43_ntab_adjustpower0[] = { 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, diff --git a/drivers/net/wireless/b43/tables_nphy.h b/drivers/net/wireless/b43/tables_nphy.h index 3eedb869f492..cb06d397ea2d 100644 --- a/drivers/net/wireless/b43/tables_nphy.h +++ b/drivers/net/wireless/b43/tables_nphy.h @@ -3,7 +3,6 @@ #include - struct b43_phy_n_sfo_cfg { u16 phy_bw1a; u16 phy_bw2; @@ -13,40 +12,6 @@ struct b43_phy_n_sfo_cfg { u16 phy_bw6; }; -struct b43_nphy_channeltab_entry_rev2 { - /* The channel number */ - u8 channel; - /* The channel frequency in MHz */ - u16 freq; - /* An unknown value */ - u16 unk2; - /* Radio register values on channelswitch */ - u8 radio_pll_ref; - u8 radio_rf_pllmod0; - u8 radio_rf_pllmod1; - u8 radio_vco_captail; - u8 radio_vco_cal1; - u8 radio_vco_cal2; - u8 radio_pll_lfc1; - u8 radio_pll_lfr1; - u8 radio_pll_lfc2; - u8 radio_lgbuf_cenbuf; - u8 radio_lgen_tune1; - u8 radio_lgen_tune2; - u8 radio_c1_lgbuf_atune; - u8 radio_c1_lgbuf_gtune; - u8 radio_c1_rx_rfr1; - u8 radio_c1_tx_pgapadtn; - u8 radio_c1_tx_mxbgtrim; - u8 radio_c2_lgbuf_atune; - u8 radio_c2_lgbuf_gtune; - u8 radio_c2_rx_rfr1; - u8 radio_c2_tx_pgapadtn; - u8 radio_c2_tx_mxbgtrim; - /* PHY register values on channelswitch */ - struct b43_phy_n_sfo_cfg phy_regs; -}; - struct b43_nphy_channeltab_entry_rev3 { /* The channel number */ u8 channel; @@ -58,7 +23,6 @@ struct b43_nphy_channeltab_entry_rev3 { struct b43_phy_n_sfo_cfg phy_regs; }; - struct b43_wldev; struct nphy_txiqcal_ladder { @@ -82,14 +46,6 @@ struct nphy_rf_control_override_rev3 { u8 val_addr1; }; -/* Upload the default register value table. - * If "ghz5" is true, we upload the 5Ghz table. Otherwise the 2.4Ghz - * table is uploaded. If "ignore_uploadflag" is true, we upload any value - * and ignore the "UPLOAD" flag. */ -void b2055_upload_inittab(struct b43_wldev *dev, - bool ghz5, bool ignore_uploadflag); - - /* Get the NPHY Channel Switch Table entry for a channel. * Returns NULL on failure to find an entry. */ const struct b43_nphy_channeltab_entry_rev2 * From 886b42bf5e54098061c8bae3d5e292a8b6897401 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 14 Oct 2010 11:44:27 -0700 Subject: [PATCH 123/127] ath9k_hw: remove AR9003 2.0 support These chipsets will not hit the market, all customers will be on >= AR9003 2.2. This shaves down the ath9k_hw size by 24161 bytes (24 KB) on my system. Before: $ size drivers/net/wireless/ath/ath9k/ath9k_hw.ko text data bss dec hex filename 292328 616 1824 294768 47f70 drivers/net/wireless/ath/ath9k/ath9k_hw.ko $ du -b drivers/net/wireless/ath/ath9k/ath9k_hw.ko 5987825 drivers/net/wireless/ath/ath9k/ath9k_hw.ko After: $ size drivers/net/wireless/ath/ath9k/ath9k_hw.ko text data bss dec hex filename 277192 616 1824 279632 44450 drivers/net/wireless/ath/ath9k/ath9k_hw.ko $ du -b drivers/net/wireless/ath/ath9k/ath9k_hw.ko 5963664 drivers/net/wireless/ath/ath9k/ath9k_hw.ko Cc: Yixiang Li Cc: Don Breslin Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- .../wireless/ath/ath9k/ar9003_2p0_initvals.h | 1784 ----------------- drivers/net/wireless/ath/ath9k/ar9003_hw.c | 162 +- drivers/net/wireless/ath/ath9k/reg.h | 3 - 3 files changed, 26 insertions(+), 1923 deletions(-) delete mode 100644 drivers/net/wireless/ath/ath9k/ar9003_2p0_initvals.h diff --git a/drivers/net/wireless/ath/ath9k/ar9003_2p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_2p0_initvals.h deleted file mode 100644 index d3375fc4ce8b..000000000000 --- a/drivers/net/wireless/ath/ath9k/ar9003_2p0_initvals.h +++ /dev/null @@ -1,1784 +0,0 @@ -/* - * Copyright (c) 2010 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or 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 INITVALS_9003_2P0_H -#define INITVALS_9003_2P0_H - -/* AR9003 2.0 */ - -static const u32 ar9300_2p0_radio_postamble[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0001609c, 0x0dd08f29, 0x0dd08f29, 0x0b283f31, 0x0b283f31}, - {0x000160ac, 0xa4653c00, 0xa4653c00, 0x24652800, 0x24652800}, - {0x000160b0, 0x03284f3e, 0x03284f3e, 0x05d08f20, 0x05d08f20}, - {0x0001610c, 0x08000000, 0x00000000, 0x00000000, 0x00000000}, - {0x00016140, 0x10804008, 0x10804008, 0x50804008, 0x50804008}, - {0x0001650c, 0x08000000, 0x00000000, 0x00000000, 0x00000000}, - {0x00016540, 0x10804008, 0x10804008, 0x50804008, 0x50804008}, - {0x0001690c, 0x08000000, 0x00000000, 0x00000000, 0x00000000}, - {0x00016940, 0x10804008, 0x10804008, 0x50804008, 0x50804008}, -}; - -static const u32 ar9300Modes_lowest_ob_db_tx_gain_table_2p0[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, - {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, - {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, - {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, - {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, - {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400}, - {0x0000a518, 0x21020220, 0x21020220, 0x16000402, 0x16000402}, - {0x0000a51c, 0x27020223, 0x27020223, 0x19000404, 0x19000404}, - {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603}, - {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02}, - {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04}, - {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20}, - {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20}, - {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22}, - {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24}, - {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640}, - {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, - {0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861}, - {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81}, - {0x0000a54c, 0x5c04286b, 0x5c04286b, 0x47001a83, 0x47001a83}, - {0x0000a550, 0x61042a6c, 0x61042a6c, 0x4a001c84, 0x4a001c84}, - {0x0000a554, 0x66062a6c, 0x66062a6c, 0x4e001ce3, 0x4e001ce3}, - {0x0000a558, 0x6b062e6c, 0x6b062e6c, 0x52001ce5, 0x52001ce5}, - {0x0000a55c, 0x7006308c, 0x7006308c, 0x56001ce9, 0x56001ce9}, - {0x0000a560, 0x730a308a, 0x730a308a, 0x5a001ceb, 0x5a001ceb}, - {0x0000a564, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, - {0x0000a568, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, - {0x0000a56c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, - {0x0000a570, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, - {0x0000a574, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, - {0x0000a578, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, - {0x0000a57c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, - {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, - {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, - {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, - {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, - {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202}, - {0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400}, - {0x0000a598, 0x21820220, 0x21820220, 0x16800402, 0x16800402}, - {0x0000a59c, 0x27820223, 0x27820223, 0x19800404, 0x19800404}, - {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603}, - {0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02}, - {0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04}, - {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20}, - {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20}, - {0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22}, - {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24}, - {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640}, - {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660}, - {0x0000a5c4, 0x5382266c, 0x5382266c, 0x3f801861, 0x3f801861}, - {0x0000a5c8, 0x5782286c, 0x5782286c, 0x43801a81, 0x43801a81}, - {0x0000a5cc, 0x5c84286b, 0x5c84286b, 0x47801a83, 0x47801a83}, - {0x0000a5d0, 0x61842a6c, 0x61842a6c, 0x4a801c84, 0x4a801c84}, - {0x0000a5d4, 0x66862a6c, 0x66862a6c, 0x4e801ce3, 0x4e801ce3}, - {0x0000a5d8, 0x6b862e6c, 0x6b862e6c, 0x52801ce5, 0x52801ce5}, - {0x0000a5dc, 0x7086308c, 0x7086308c, 0x56801ce9, 0x56801ce9}, - {0x0000a5e0, 0x738a308a, 0x738a308a, 0x5a801ceb, 0x5a801ceb}, - {0x0000a5e4, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, - {0x0000a5e8, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, - {0x0000a5ec, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, - {0x0000a5f0, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, - {0x0000a5f4, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, - {0x0000a5f8, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, - {0x0000a5fc, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, - {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, - {0x00016048, 0x62480001, 0x62480001, 0x62480001, 0x62480001}, - {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, - {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, - {0x00016448, 0x62480001, 0x62480001, 0x62480001, 0x62480001}, - {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, - {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, - {0x00016848, 0x62480001, 0x62480001, 0x62480001, 0x62480001}, - {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, -}; - -static const u32 ar9300Modes_fast_clock_2p0[][3] = { - /* Addr 5G_HT20 5G_HT40 */ - {0x00001030, 0x00000268, 0x000004d0}, - {0x00001070, 0x0000018c, 0x00000318}, - {0x000010b0, 0x00000fd0, 0x00001fa0}, - {0x00008014, 0x044c044c, 0x08980898}, - {0x0000801c, 0x148ec02b, 0x148ec057}, - {0x00008318, 0x000044c0, 0x00008980}, - {0x00009e00, 0x03721821, 0x03721821}, - {0x0000a230, 0x0000000b, 0x00000016}, - {0x0000a254, 0x00000898, 0x00001130}, -}; - -static const u32 ar9300_2p0_radio_core[][2] = { - /* Addr allmodes */ - {0x00016000, 0x36db6db6}, - {0x00016004, 0x6db6db40}, - {0x00016008, 0x73f00000}, - {0x0001600c, 0x00000000}, - {0x00016040, 0x7f80fff8}, - {0x0001604c, 0x76d005b5}, - {0x00016050, 0x556cf031}, - {0x00016054, 0x13449440}, - {0x00016058, 0x0c51c92c}, - {0x0001605c, 0x3db7fffc}, - {0x00016060, 0xfffffffc}, - {0x00016064, 0x000f0278}, - {0x0001606c, 0x6db60000}, - {0x00016080, 0x00000000}, - {0x00016084, 0x0e48048c}, - {0x00016088, 0x54214514}, - {0x0001608c, 0x119f481e}, - {0x00016090, 0x24926490}, - {0x00016098, 0xd2888888}, - {0x000160a0, 0x0a108ffe}, - {0x000160a4, 0x812fc370}, - {0x000160a8, 0x423c8000}, - {0x000160b4, 0x92480080}, - {0x000160c0, 0x00adb6d0}, - {0x000160c4, 0x6db6db60}, - {0x000160c8, 0x6db6db6c}, - {0x000160cc, 0x01e6c000}, - {0x00016100, 0x3fffbe01}, - {0x00016104, 0xfff80000}, - {0x00016108, 0x00080010}, - {0x00016144, 0x02084080}, - {0x00016148, 0x00000000}, - {0x00016280, 0x058a0001}, - {0x00016284, 0x3d840208}, - {0x00016288, 0x05a20408}, - {0x0001628c, 0x00038c07}, - {0x00016290, 0x40000004}, - {0x00016294, 0x458aa14f}, - {0x00016380, 0x00000000}, - {0x00016384, 0x00000000}, - {0x00016388, 0x00800700}, - {0x0001638c, 0x00800700}, - {0x00016390, 0x00800700}, - {0x00016394, 0x00000000}, - {0x00016398, 0x00000000}, - {0x0001639c, 0x00000000}, - {0x000163a0, 0x00000001}, - {0x000163a4, 0x00000001}, - {0x000163a8, 0x00000000}, - {0x000163ac, 0x00000000}, - {0x000163b0, 0x00000000}, - {0x000163b4, 0x00000000}, - {0x000163b8, 0x00000000}, - {0x000163bc, 0x00000000}, - {0x000163c0, 0x000000a0}, - {0x000163c4, 0x000c0000}, - {0x000163c8, 0x14021402}, - {0x000163cc, 0x00001402}, - {0x000163d0, 0x00000000}, - {0x000163d4, 0x00000000}, - {0x00016400, 0x36db6db6}, - {0x00016404, 0x6db6db40}, - {0x00016408, 0x73f00000}, - {0x0001640c, 0x00000000}, - {0x00016440, 0x7f80fff8}, - {0x0001644c, 0x76d005b5}, - {0x00016450, 0x556cf031}, - {0x00016454, 0x13449440}, - {0x00016458, 0x0c51c92c}, - {0x0001645c, 0x3db7fffc}, - {0x00016460, 0xfffffffc}, - {0x00016464, 0x000f0278}, - {0x0001646c, 0x6db60000}, - {0x00016500, 0x3fffbe01}, - {0x00016504, 0xfff80000}, - {0x00016508, 0x00080010}, - {0x00016544, 0x02084080}, - {0x00016548, 0x00000000}, - {0x00016780, 0x00000000}, - {0x00016784, 0x00000000}, - {0x00016788, 0x00800700}, - {0x0001678c, 0x00800700}, - {0x00016790, 0x00800700}, - {0x00016794, 0x00000000}, - {0x00016798, 0x00000000}, - {0x0001679c, 0x00000000}, - {0x000167a0, 0x00000001}, - {0x000167a4, 0x00000001}, - {0x000167a8, 0x00000000}, - {0x000167ac, 0x00000000}, - {0x000167b0, 0x00000000}, - {0x000167b4, 0x00000000}, - {0x000167b8, 0x00000000}, - {0x000167bc, 0x00000000}, - {0x000167c0, 0x000000a0}, - {0x000167c4, 0x000c0000}, - {0x000167c8, 0x14021402}, - {0x000167cc, 0x00001402}, - {0x000167d0, 0x00000000}, - {0x000167d4, 0x00000000}, - {0x00016800, 0x36db6db6}, - {0x00016804, 0x6db6db40}, - {0x00016808, 0x73f00000}, - {0x0001680c, 0x00000000}, - {0x00016840, 0x7f80fff8}, - {0x0001684c, 0x76d005b5}, - {0x00016850, 0x556cf031}, - {0x00016854, 0x13449440}, - {0x00016858, 0x0c51c92c}, - {0x0001685c, 0x3db7fffc}, - {0x00016860, 0xfffffffc}, - {0x00016864, 0x000f0278}, - {0x0001686c, 0x6db60000}, - {0x00016900, 0x3fffbe01}, - {0x00016904, 0xfff80000}, - {0x00016908, 0x00080010}, - {0x00016944, 0x02084080}, - {0x00016948, 0x00000000}, - {0x00016b80, 0x00000000}, - {0x00016b84, 0x00000000}, - {0x00016b88, 0x00800700}, - {0x00016b8c, 0x00800700}, - {0x00016b90, 0x00800700}, - {0x00016b94, 0x00000000}, - {0x00016b98, 0x00000000}, - {0x00016b9c, 0x00000000}, - {0x00016ba0, 0x00000001}, - {0x00016ba4, 0x00000001}, - {0x00016ba8, 0x00000000}, - {0x00016bac, 0x00000000}, - {0x00016bb0, 0x00000000}, - {0x00016bb4, 0x00000000}, - {0x00016bb8, 0x00000000}, - {0x00016bbc, 0x00000000}, - {0x00016bc0, 0x000000a0}, - {0x00016bc4, 0x000c0000}, - {0x00016bc8, 0x14021402}, - {0x00016bcc, 0x00001402}, - {0x00016bd0, 0x00000000}, - {0x00016bd4, 0x00000000}, -}; - -static const u32 ar9300Common_rx_gain_table_merlin_2p0[][2] = { - /* Addr allmodes */ - {0x0000a000, 0x02000101}, - {0x0000a004, 0x02000102}, - {0x0000a008, 0x02000103}, - {0x0000a00c, 0x02000104}, - {0x0000a010, 0x02000200}, - {0x0000a014, 0x02000201}, - {0x0000a018, 0x02000202}, - {0x0000a01c, 0x02000203}, - {0x0000a020, 0x02000204}, - {0x0000a024, 0x02000205}, - {0x0000a028, 0x02000208}, - {0x0000a02c, 0x02000302}, - {0x0000a030, 0x02000303}, - {0x0000a034, 0x02000304}, - {0x0000a038, 0x02000400}, - {0x0000a03c, 0x02010300}, - {0x0000a040, 0x02010301}, - {0x0000a044, 0x02010302}, - {0x0000a048, 0x02000500}, - {0x0000a04c, 0x02010400}, - {0x0000a050, 0x02020300}, - {0x0000a054, 0x02020301}, - {0x0000a058, 0x02020302}, - {0x0000a05c, 0x02020303}, - {0x0000a060, 0x02020400}, - {0x0000a064, 0x02030300}, - {0x0000a068, 0x02030301}, - {0x0000a06c, 0x02030302}, - {0x0000a070, 0x02030303}, - {0x0000a074, 0x02030400}, - {0x0000a078, 0x02040300}, - {0x0000a07c, 0x02040301}, - {0x0000a080, 0x02040302}, - {0x0000a084, 0x02040303}, - {0x0000a088, 0x02030500}, - {0x0000a08c, 0x02040400}, - {0x0000a090, 0x02050203}, - {0x0000a094, 0x02050204}, - {0x0000a098, 0x02050205}, - {0x0000a09c, 0x02040500}, - {0x0000a0a0, 0x02050301}, - {0x0000a0a4, 0x02050302}, - {0x0000a0a8, 0x02050303}, - {0x0000a0ac, 0x02050400}, - {0x0000a0b0, 0x02050401}, - {0x0000a0b4, 0x02050402}, - {0x0000a0b8, 0x02050403}, - {0x0000a0bc, 0x02050500}, - {0x0000a0c0, 0x02050501}, - {0x0000a0c4, 0x02050502}, - {0x0000a0c8, 0x02050503}, - {0x0000a0cc, 0x02050504}, - {0x0000a0d0, 0x02050600}, - {0x0000a0d4, 0x02050601}, - {0x0000a0d8, 0x02050602}, - {0x0000a0dc, 0x02050603}, - {0x0000a0e0, 0x02050604}, - {0x0000a0e4, 0x02050700}, - {0x0000a0e8, 0x02050701}, - {0x0000a0ec, 0x02050702}, - {0x0000a0f0, 0x02050703}, - {0x0000a0f4, 0x02050704}, - {0x0000a0f8, 0x02050705}, - {0x0000a0fc, 0x02050708}, - {0x0000a100, 0x02050709}, - {0x0000a104, 0x0205070a}, - {0x0000a108, 0x0205070b}, - {0x0000a10c, 0x0205070c}, - {0x0000a110, 0x0205070d}, - {0x0000a114, 0x02050710}, - {0x0000a118, 0x02050711}, - {0x0000a11c, 0x02050712}, - {0x0000a120, 0x02050713}, - {0x0000a124, 0x02050714}, - {0x0000a128, 0x02050715}, - {0x0000a12c, 0x02050730}, - {0x0000a130, 0x02050731}, - {0x0000a134, 0x02050732}, - {0x0000a138, 0x02050733}, - {0x0000a13c, 0x02050734}, - {0x0000a140, 0x02050735}, - {0x0000a144, 0x02050750}, - {0x0000a148, 0x02050751}, - {0x0000a14c, 0x02050752}, - {0x0000a150, 0x02050753}, - {0x0000a154, 0x02050754}, - {0x0000a158, 0x02050755}, - {0x0000a15c, 0x02050770}, - {0x0000a160, 0x02050771}, - {0x0000a164, 0x02050772}, - {0x0000a168, 0x02050773}, - {0x0000a16c, 0x02050774}, - {0x0000a170, 0x02050775}, - {0x0000a174, 0x00000776}, - {0x0000a178, 0x00000776}, - {0x0000a17c, 0x00000776}, - {0x0000a180, 0x00000776}, - {0x0000a184, 0x00000776}, - {0x0000a188, 0x00000776}, - {0x0000a18c, 0x00000776}, - {0x0000a190, 0x00000776}, - {0x0000a194, 0x00000776}, - {0x0000a198, 0x00000776}, - {0x0000a19c, 0x00000776}, - {0x0000a1a0, 0x00000776}, - {0x0000a1a4, 0x00000776}, - {0x0000a1a8, 0x00000776}, - {0x0000a1ac, 0x00000776}, - {0x0000a1b0, 0x00000776}, - {0x0000a1b4, 0x00000776}, - {0x0000a1b8, 0x00000776}, - {0x0000a1bc, 0x00000776}, - {0x0000a1c0, 0x00000776}, - {0x0000a1c4, 0x00000776}, - {0x0000a1c8, 0x00000776}, - {0x0000a1cc, 0x00000776}, - {0x0000a1d0, 0x00000776}, - {0x0000a1d4, 0x00000776}, - {0x0000a1d8, 0x00000776}, - {0x0000a1dc, 0x00000776}, - {0x0000a1e0, 0x00000776}, - {0x0000a1e4, 0x00000776}, - {0x0000a1e8, 0x00000776}, - {0x0000a1ec, 0x00000776}, - {0x0000a1f0, 0x00000776}, - {0x0000a1f4, 0x00000776}, - {0x0000a1f8, 0x00000776}, - {0x0000a1fc, 0x00000776}, - {0x0000b000, 0x02000101}, - {0x0000b004, 0x02000102}, - {0x0000b008, 0x02000103}, - {0x0000b00c, 0x02000104}, - {0x0000b010, 0x02000200}, - {0x0000b014, 0x02000201}, - {0x0000b018, 0x02000202}, - {0x0000b01c, 0x02000203}, - {0x0000b020, 0x02000204}, - {0x0000b024, 0x02000205}, - {0x0000b028, 0x02000208}, - {0x0000b02c, 0x02000302}, - {0x0000b030, 0x02000303}, - {0x0000b034, 0x02000304}, - {0x0000b038, 0x02000400}, - {0x0000b03c, 0x02010300}, - {0x0000b040, 0x02010301}, - {0x0000b044, 0x02010302}, - {0x0000b048, 0x02000500}, - {0x0000b04c, 0x02010400}, - {0x0000b050, 0x02020300}, - {0x0000b054, 0x02020301}, - {0x0000b058, 0x02020302}, - {0x0000b05c, 0x02020303}, - {0x0000b060, 0x02020400}, - {0x0000b064, 0x02030300}, - {0x0000b068, 0x02030301}, - {0x0000b06c, 0x02030302}, - {0x0000b070, 0x02030303}, - {0x0000b074, 0x02030400}, - {0x0000b078, 0x02040300}, - {0x0000b07c, 0x02040301}, - {0x0000b080, 0x02040302}, - {0x0000b084, 0x02040303}, - {0x0000b088, 0x02030500}, - {0x0000b08c, 0x02040400}, - {0x0000b090, 0x02050203}, - {0x0000b094, 0x02050204}, - {0x0000b098, 0x02050205}, - {0x0000b09c, 0x02040500}, - {0x0000b0a0, 0x02050301}, - {0x0000b0a4, 0x02050302}, - {0x0000b0a8, 0x02050303}, - {0x0000b0ac, 0x02050400}, - {0x0000b0b0, 0x02050401}, - {0x0000b0b4, 0x02050402}, - {0x0000b0b8, 0x02050403}, - {0x0000b0bc, 0x02050500}, - {0x0000b0c0, 0x02050501}, - {0x0000b0c4, 0x02050502}, - {0x0000b0c8, 0x02050503}, - {0x0000b0cc, 0x02050504}, - {0x0000b0d0, 0x02050600}, - {0x0000b0d4, 0x02050601}, - {0x0000b0d8, 0x02050602}, - {0x0000b0dc, 0x02050603}, - {0x0000b0e0, 0x02050604}, - {0x0000b0e4, 0x02050700}, - {0x0000b0e8, 0x02050701}, - {0x0000b0ec, 0x02050702}, - {0x0000b0f0, 0x02050703}, - {0x0000b0f4, 0x02050704}, - {0x0000b0f8, 0x02050705}, - {0x0000b0fc, 0x02050708}, - {0x0000b100, 0x02050709}, - {0x0000b104, 0x0205070a}, - {0x0000b108, 0x0205070b}, - {0x0000b10c, 0x0205070c}, - {0x0000b110, 0x0205070d}, - {0x0000b114, 0x02050710}, - {0x0000b118, 0x02050711}, - {0x0000b11c, 0x02050712}, - {0x0000b120, 0x02050713}, - {0x0000b124, 0x02050714}, - {0x0000b128, 0x02050715}, - {0x0000b12c, 0x02050730}, - {0x0000b130, 0x02050731}, - {0x0000b134, 0x02050732}, - {0x0000b138, 0x02050733}, - {0x0000b13c, 0x02050734}, - {0x0000b140, 0x02050735}, - {0x0000b144, 0x02050750}, - {0x0000b148, 0x02050751}, - {0x0000b14c, 0x02050752}, - {0x0000b150, 0x02050753}, - {0x0000b154, 0x02050754}, - {0x0000b158, 0x02050755}, - {0x0000b15c, 0x02050770}, - {0x0000b160, 0x02050771}, - {0x0000b164, 0x02050772}, - {0x0000b168, 0x02050773}, - {0x0000b16c, 0x02050774}, - {0x0000b170, 0x02050775}, - {0x0000b174, 0x00000776}, - {0x0000b178, 0x00000776}, - {0x0000b17c, 0x00000776}, - {0x0000b180, 0x00000776}, - {0x0000b184, 0x00000776}, - {0x0000b188, 0x00000776}, - {0x0000b18c, 0x00000776}, - {0x0000b190, 0x00000776}, - {0x0000b194, 0x00000776}, - {0x0000b198, 0x00000776}, - {0x0000b19c, 0x00000776}, - {0x0000b1a0, 0x00000776}, - {0x0000b1a4, 0x00000776}, - {0x0000b1a8, 0x00000776}, - {0x0000b1ac, 0x00000776}, - {0x0000b1b0, 0x00000776}, - {0x0000b1b4, 0x00000776}, - {0x0000b1b8, 0x00000776}, - {0x0000b1bc, 0x00000776}, - {0x0000b1c0, 0x00000776}, - {0x0000b1c4, 0x00000776}, - {0x0000b1c8, 0x00000776}, - {0x0000b1cc, 0x00000776}, - {0x0000b1d0, 0x00000776}, - {0x0000b1d4, 0x00000776}, - {0x0000b1d8, 0x00000776}, - {0x0000b1dc, 0x00000776}, - {0x0000b1e0, 0x00000776}, - {0x0000b1e4, 0x00000776}, - {0x0000b1e8, 0x00000776}, - {0x0000b1ec, 0x00000776}, - {0x0000b1f0, 0x00000776}, - {0x0000b1f4, 0x00000776}, - {0x0000b1f8, 0x00000776}, - {0x0000b1fc, 0x00000776}, -}; - -static const u32 ar9300_2p0_mac_postamble[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160}, - {0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c}, - {0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38}, - {0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00}, - {0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b}, - {0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810}, - {0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a}, - {0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440}, -}; - -static const u32 ar9300_2p0_soc_postamble[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x00007010, 0x00000023, 0x00000023, 0x00000023, 0x00000023}, -}; - -static const u32 ar9200_merlin_2p0_radio_core[][2] = { - /* Addr allmodes */ - {0x00007800, 0x00040000}, - {0x00007804, 0xdb005012}, - {0x00007808, 0x04924914}, - {0x0000780c, 0x21084210}, - {0x00007810, 0x6d801300}, - {0x00007814, 0x0019beff}, - {0x00007818, 0x07e41000}, - {0x0000781c, 0x00392000}, - {0x00007820, 0x92592480}, - {0x00007824, 0x00040000}, - {0x00007828, 0xdb005012}, - {0x0000782c, 0x04924914}, - {0x00007830, 0x21084210}, - {0x00007834, 0x6d801300}, - {0x00007838, 0x0019beff}, - {0x0000783c, 0x07e40000}, - {0x00007840, 0x00392000}, - {0x00007844, 0x92592480}, - {0x00007848, 0x00100000}, - {0x0000784c, 0x773f0567}, - {0x00007850, 0x54214514}, - {0x00007854, 0x12035828}, - {0x00007858, 0x92592692}, - {0x0000785c, 0x00000000}, - {0x00007860, 0x56400000}, - {0x00007864, 0x0a8e370e}, - {0x00007868, 0xc0102850}, - {0x0000786c, 0x812d4000}, - {0x00007870, 0x807ec400}, - {0x00007874, 0x001b6db0}, - {0x00007878, 0x00376b63}, - {0x0000787c, 0x06db6db6}, - {0x00007880, 0x006d8000}, - {0x00007884, 0xffeffffe}, - {0x00007888, 0xffeffffe}, - {0x0000788c, 0x00010000}, - {0x00007890, 0x02060aeb}, - {0x00007894, 0x5a108000}, -}; - -static const u32 ar9300_2p0_baseband_postamble[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8011, 0xd00a8011}, - {0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e}, - {0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0}, - {0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881}, - {0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4}, - {0x00009830, 0x0000059c, 0x0000059c, 0x0000119c, 0x0000119c}, - {0x00009c00, 0x00000044, 0x000000c4, 0x000000c4, 0x00000044}, - {0x00009e00, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0}, - {0x00009e04, 0x00802020, 0x00802020, 0x00802020, 0x00802020}, - {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2}, - {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e}, - {0x00009e14, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e}, - {0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, - {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, - {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, - {0x00009e44, 0x02321e27, 0x02321e27, 0x02291e27, 0x02291e27}, - {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, - {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, - {0x0000a204, 0x000037c0, 0x000037c4, 0x000037c4, 0x000037c0}, - {0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004}, - {0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b}, - {0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018}, - {0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108}, - {0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898}, - {0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002}, - {0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e}, - {0x0000a260, 0x0a021501, 0x0a021501, 0x3a021501, 0x3a021501}, - {0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e}, - {0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b}, - {0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, - {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110}, - {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222}, - {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, - {0x0000a2d0, 0x00071981, 0x00071981, 0x00071981, 0x00071982}, - {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a}, - {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, - {0x0000ae04, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, - {0x0000ae18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000ae1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, - {0x0000ae20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce}, - {0x0000b284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, - {0x0000b830, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, - {0x0000be04, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, - {0x0000be18, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000be1c, 0x0000019c, 0x0000019c, 0x0000019c, 0x0000019c}, - {0x0000be20, 0x000001b5, 0x000001b5, 0x000001ce, 0x000001ce}, - {0x0000c284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, -}; - -static const u32 ar9300_2p0_baseband_core[][2] = { - /* Addr allmodes */ - {0x00009800, 0xafe68e30}, - {0x00009804, 0xfd14e000}, - {0x00009808, 0x9c0a9f6b}, - {0x0000980c, 0x04900000}, - {0x00009814, 0x9280c00a}, - {0x00009818, 0x00000000}, - {0x0000981c, 0x00020028}, - {0x00009834, 0x5f3ca3de}, - {0x00009838, 0x0108ecff}, - {0x0000983c, 0x14750600}, - {0x00009880, 0x201fff00}, - {0x00009884, 0x00001042}, - {0x000098a4, 0x00200400}, - {0x000098b0, 0x52440bbe}, - {0x000098d0, 0x004b6a8e}, - {0x000098d4, 0x00000820}, - {0x000098dc, 0x00000000}, - {0x000098f0, 0x00000000}, - {0x000098f4, 0x00000000}, - {0x00009c04, 0xff55ff55}, - {0x00009c08, 0x0320ff55}, - {0x00009c0c, 0x00000000}, - {0x00009c10, 0x00000000}, - {0x00009c14, 0x00046384}, - {0x00009c18, 0x05b6b440}, - {0x00009c1c, 0x00b6b440}, - {0x00009d00, 0xc080a333}, - {0x00009d04, 0x40206c10}, - {0x00009d08, 0x009c4060}, - {0x00009d0c, 0x9883800a}, - {0x00009d10, 0x01834061}, - {0x00009d14, 0x00c0040b}, - {0x00009d18, 0x00000000}, - {0x00009e08, 0x0038230c}, - {0x00009e24, 0x990bb515}, - {0x00009e28, 0x0c6f0000}, - {0x00009e30, 0x06336f77}, - {0x00009e34, 0x6af6532f}, - {0x00009e38, 0x0cc80c00}, - {0x00009e3c, 0xcf946222}, - {0x00009e40, 0x0d261820}, - {0x00009e4c, 0x00001004}, - {0x00009e50, 0x00ff03f1}, - {0x00009e54, 0x00000000}, - {0x00009fc0, 0x803e4788}, - {0x00009fc4, 0x0001efb5}, - {0x00009fcc, 0x40000014}, - {0x00009fd0, 0x01193b93}, - {0x0000a20c, 0x00000000}, - {0x0000a220, 0x00000000}, - {0x0000a224, 0x00000000}, - {0x0000a228, 0x10002310}, - {0x0000a22c, 0x01036a1e}, - {0x0000a234, 0x10000fff}, - {0x0000a23c, 0x00000000}, - {0x0000a244, 0x0c000000}, - {0x0000a2a0, 0x00000001}, - {0x0000a2c0, 0x00000001}, - {0x0000a2c8, 0x00000000}, - {0x0000a2cc, 0x18c43433}, - {0x0000a2d4, 0x00000000}, - {0x0000a2dc, 0x00000000}, - {0x0000a2e0, 0x00000000}, - {0x0000a2e4, 0x00000000}, - {0x0000a2e8, 0x00000000}, - {0x0000a2ec, 0x00000000}, - {0x0000a2f0, 0x00000000}, - {0x0000a2f4, 0x00000000}, - {0x0000a2f8, 0x00000000}, - {0x0000a344, 0x00000000}, - {0x0000a34c, 0x00000000}, - {0x0000a350, 0x0000a000}, - {0x0000a364, 0x00000000}, - {0x0000a370, 0x00000000}, - {0x0000a390, 0x00000001}, - {0x0000a394, 0x00000444}, - {0x0000a398, 0x001f0e0f}, - {0x0000a39c, 0x0075393f}, - {0x0000a3a0, 0xb79f6427}, - {0x0000a3a4, 0x00000000}, - {0x0000a3a8, 0xaaaaaaaa}, - {0x0000a3ac, 0x3c466478}, - {0x0000a3c0, 0x20202020}, - {0x0000a3c4, 0x22222220}, - {0x0000a3c8, 0x20200020}, - {0x0000a3cc, 0x20202020}, - {0x0000a3d0, 0x20202020}, - {0x0000a3d4, 0x20202020}, - {0x0000a3d8, 0x20202020}, - {0x0000a3dc, 0x20202020}, - {0x0000a3e0, 0x20202020}, - {0x0000a3e4, 0x20202020}, - {0x0000a3e8, 0x20202020}, - {0x0000a3ec, 0x20202020}, - {0x0000a3f0, 0x00000000}, - {0x0000a3f4, 0x00000246}, - {0x0000a3f8, 0x0cdbd380}, - {0x0000a3fc, 0x000f0f01}, - {0x0000a400, 0x8fa91f01}, - {0x0000a404, 0x00000000}, - {0x0000a408, 0x0e79e5c6}, - {0x0000a40c, 0x00820820}, - {0x0000a414, 0x1ce739ce}, - {0x0000a418, 0x2d001dce}, - {0x0000a41c, 0x1ce739ce}, - {0x0000a420, 0x000001ce}, - {0x0000a424, 0x1ce739ce}, - {0x0000a428, 0x000001ce}, - {0x0000a42c, 0x1ce739ce}, - {0x0000a430, 0x1ce739ce}, - {0x0000a434, 0x00000000}, - {0x0000a438, 0x00001801}, - {0x0000a43c, 0x00000000}, - {0x0000a440, 0x00000000}, - {0x0000a444, 0x00000000}, - {0x0000a448, 0x04000080}, - {0x0000a44c, 0x00000001}, - {0x0000a450, 0x00010000}, - {0x0000a458, 0x00000000}, - {0x0000a600, 0x00000000}, - {0x0000a604, 0x00000000}, - {0x0000a608, 0x00000000}, - {0x0000a60c, 0x00000000}, - {0x0000a610, 0x00000000}, - {0x0000a614, 0x00000000}, - {0x0000a618, 0x00000000}, - {0x0000a61c, 0x00000000}, - {0x0000a620, 0x00000000}, - {0x0000a624, 0x00000000}, - {0x0000a628, 0x00000000}, - {0x0000a62c, 0x00000000}, - {0x0000a630, 0x00000000}, - {0x0000a634, 0x00000000}, - {0x0000a638, 0x00000000}, - {0x0000a63c, 0x00000000}, - {0x0000a640, 0x00000000}, - {0x0000a644, 0x3fad9d74}, - {0x0000a648, 0x0048060a}, - {0x0000a64c, 0x00000637}, - {0x0000a670, 0x03020100}, - {0x0000a674, 0x09080504}, - {0x0000a678, 0x0d0c0b0a}, - {0x0000a67c, 0x13121110}, - {0x0000a680, 0x31301514}, - {0x0000a684, 0x35343332}, - {0x0000a688, 0x00000036}, - {0x0000a690, 0x00000838}, - {0x0000a7c0, 0x00000000}, - {0x0000a7c4, 0xfffffffc}, - {0x0000a7c8, 0x00000000}, - {0x0000a7cc, 0x00000000}, - {0x0000a7d0, 0x00000000}, - {0x0000a7d4, 0x00000004}, - {0x0000a7dc, 0x00000001}, - {0x0000a8d0, 0x004b6a8e}, - {0x0000a8d4, 0x00000820}, - {0x0000a8dc, 0x00000000}, - {0x0000a8f0, 0x00000000}, - {0x0000a8f4, 0x00000000}, - {0x0000b2d0, 0x00000080}, - {0x0000b2d4, 0x00000000}, - {0x0000b2dc, 0x00000000}, - {0x0000b2e0, 0x00000000}, - {0x0000b2e4, 0x00000000}, - {0x0000b2e8, 0x00000000}, - {0x0000b2ec, 0x00000000}, - {0x0000b2f0, 0x00000000}, - {0x0000b2f4, 0x00000000}, - {0x0000b2f8, 0x00000000}, - {0x0000b408, 0x0e79e5c0}, - {0x0000b40c, 0x00820820}, - {0x0000b420, 0x00000000}, - {0x0000b8d0, 0x004b6a8e}, - {0x0000b8d4, 0x00000820}, - {0x0000b8dc, 0x00000000}, - {0x0000b8f0, 0x00000000}, - {0x0000b8f4, 0x00000000}, - {0x0000c2d0, 0x00000080}, - {0x0000c2d4, 0x00000000}, - {0x0000c2dc, 0x00000000}, - {0x0000c2e0, 0x00000000}, - {0x0000c2e4, 0x00000000}, - {0x0000c2e8, 0x00000000}, - {0x0000c2ec, 0x00000000}, - {0x0000c2f0, 0x00000000}, - {0x0000c2f4, 0x00000000}, - {0x0000c2f8, 0x00000000}, - {0x0000c408, 0x0e79e5c0}, - {0x0000c40c, 0x00820820}, - {0x0000c420, 0x00000000}, -}; - -static const u32 ar9300Modes_high_power_tx_gain_table_2p0[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, - {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, - {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, - {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004}, - {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200}, - {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202}, - {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400}, - {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402}, - {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404}, - {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603}, - {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02}, - {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04}, - {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20}, - {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20}, - {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22}, - {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24}, - {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640}, - {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660}, - {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861}, - {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81}, - {0x0000a54c, 0x59025eb5, 0x59025eb5, 0x42001a83, 0x42001a83}, - {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84}, - {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3}, - {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5}, - {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9}, - {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb}, - {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, - {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, - {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, - {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, - {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, - {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, - {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, - {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000}, - {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002}, - {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004}, - {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200}, - {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202}, - {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400}, - {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402}, - {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404}, - {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603}, - {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02}, - {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04}, - {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20}, - {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20}, - {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22}, - {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24}, - {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640}, - {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660}, - {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861}, - {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81}, - {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83}, - {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84}, - {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3}, - {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5}, - {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9}, - {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb}, - {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, - {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, - {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, - {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, - {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, - {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, - {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, - {0x00016044, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6}, - {0x00016048, 0xae480001, 0xae480001, 0xae480001, 0xae480001}, - {0x00016068, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c}, - {0x00016444, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6}, - {0x00016448, 0xae480001, 0xae480001, 0xae480001, 0xae480001}, - {0x00016468, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c}, - {0x00016844, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6}, - {0x00016848, 0xae480001, 0xae480001, 0xae480001, 0xae480001}, - {0x00016868, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c}, -}; - -static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p0[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, - {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, - {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, - {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004}, - {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200}, - {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202}, - {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400}, - {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402}, - {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404}, - {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603}, - {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02}, - {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04}, - {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20}, - {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20}, - {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22}, - {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24}, - {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640}, - {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660}, - {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861}, - {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81}, - {0x0000a54c, 0x59025eb5, 0x59025eb5, 0x42001a83, 0x42001a83}, - {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84}, - {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3}, - {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5}, - {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9}, - {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb}, - {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, - {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, - {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, - {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, - {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, - {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, - {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, - {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000}, - {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002}, - {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004}, - {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200}, - {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202}, - {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400}, - {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402}, - {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404}, - {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603}, - {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02}, - {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04}, - {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20}, - {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20}, - {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22}, - {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24}, - {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640}, - {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660}, - {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861}, - {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81}, - {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83}, - {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84}, - {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3}, - {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5}, - {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9}, - {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb}, - {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, - {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, - {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, - {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, - {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, - {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, - {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, - {0x00016044, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4}, - {0x00016048, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001}, - {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, - {0x00016444, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4}, - {0x00016448, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001}, - {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, - {0x00016844, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4}, - {0x00016848, 0x8e480001, 0x8e480001, 0x8e480001, 0x8e480001}, - {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, -}; - -static const u32 ar9300Common_rx_gain_table_2p0[][2] = { - /* Addr allmodes */ - {0x0000a000, 0x00010000}, - {0x0000a004, 0x00030002}, - {0x0000a008, 0x00050004}, - {0x0000a00c, 0x00810080}, - {0x0000a010, 0x00830082}, - {0x0000a014, 0x01810180}, - {0x0000a018, 0x01830182}, - {0x0000a01c, 0x01850184}, - {0x0000a020, 0x01890188}, - {0x0000a024, 0x018b018a}, - {0x0000a028, 0x018d018c}, - {0x0000a02c, 0x01910190}, - {0x0000a030, 0x01930192}, - {0x0000a034, 0x01950194}, - {0x0000a038, 0x038a0196}, - {0x0000a03c, 0x038c038b}, - {0x0000a040, 0x0390038d}, - {0x0000a044, 0x03920391}, - {0x0000a048, 0x03940393}, - {0x0000a04c, 0x03960395}, - {0x0000a050, 0x00000000}, - {0x0000a054, 0x00000000}, - {0x0000a058, 0x00000000}, - {0x0000a05c, 0x00000000}, - {0x0000a060, 0x00000000}, - {0x0000a064, 0x00000000}, - {0x0000a068, 0x00000000}, - {0x0000a06c, 0x00000000}, - {0x0000a070, 0x00000000}, - {0x0000a074, 0x00000000}, - {0x0000a078, 0x00000000}, - {0x0000a07c, 0x00000000}, - {0x0000a080, 0x22222229}, - {0x0000a084, 0x1d1d1d1d}, - {0x0000a088, 0x1d1d1d1d}, - {0x0000a08c, 0x1d1d1d1d}, - {0x0000a090, 0x171d1d1d}, - {0x0000a094, 0x11111717}, - {0x0000a098, 0x00030311}, - {0x0000a09c, 0x00000000}, - {0x0000a0a0, 0x00000000}, - {0x0000a0a4, 0x00000000}, - {0x0000a0a8, 0x00000000}, - {0x0000a0ac, 0x00000000}, - {0x0000a0b0, 0x00000000}, - {0x0000a0b4, 0x00000000}, - {0x0000a0b8, 0x00000000}, - {0x0000a0bc, 0x00000000}, - {0x0000a0c0, 0x001f0000}, - {0x0000a0c4, 0x01000101}, - {0x0000a0c8, 0x011e011f}, - {0x0000a0cc, 0x011c011d}, - {0x0000a0d0, 0x02030204}, - {0x0000a0d4, 0x02010202}, - {0x0000a0d8, 0x021f0200}, - {0x0000a0dc, 0x0302021e}, - {0x0000a0e0, 0x03000301}, - {0x0000a0e4, 0x031e031f}, - {0x0000a0e8, 0x0402031d}, - {0x0000a0ec, 0x04000401}, - {0x0000a0f0, 0x041e041f}, - {0x0000a0f4, 0x0502041d}, - {0x0000a0f8, 0x05000501}, - {0x0000a0fc, 0x051e051f}, - {0x0000a100, 0x06010602}, - {0x0000a104, 0x061f0600}, - {0x0000a108, 0x061d061e}, - {0x0000a10c, 0x07020703}, - {0x0000a110, 0x07000701}, - {0x0000a114, 0x00000000}, - {0x0000a118, 0x00000000}, - {0x0000a11c, 0x00000000}, - {0x0000a120, 0x00000000}, - {0x0000a124, 0x00000000}, - {0x0000a128, 0x00000000}, - {0x0000a12c, 0x00000000}, - {0x0000a130, 0x00000000}, - {0x0000a134, 0x00000000}, - {0x0000a138, 0x00000000}, - {0x0000a13c, 0x00000000}, - {0x0000a140, 0x001f0000}, - {0x0000a144, 0x01000101}, - {0x0000a148, 0x011e011f}, - {0x0000a14c, 0x011c011d}, - {0x0000a150, 0x02030204}, - {0x0000a154, 0x02010202}, - {0x0000a158, 0x021f0200}, - {0x0000a15c, 0x0302021e}, - {0x0000a160, 0x03000301}, - {0x0000a164, 0x031e031f}, - {0x0000a168, 0x0402031d}, - {0x0000a16c, 0x04000401}, - {0x0000a170, 0x041e041f}, - {0x0000a174, 0x0502041d}, - {0x0000a178, 0x05000501}, - {0x0000a17c, 0x051e051f}, - {0x0000a180, 0x06010602}, - {0x0000a184, 0x061f0600}, - {0x0000a188, 0x061d061e}, - {0x0000a18c, 0x07020703}, - {0x0000a190, 0x07000701}, - {0x0000a194, 0x00000000}, - {0x0000a198, 0x00000000}, - {0x0000a19c, 0x00000000}, - {0x0000a1a0, 0x00000000}, - {0x0000a1a4, 0x00000000}, - {0x0000a1a8, 0x00000000}, - {0x0000a1ac, 0x00000000}, - {0x0000a1b0, 0x00000000}, - {0x0000a1b4, 0x00000000}, - {0x0000a1b8, 0x00000000}, - {0x0000a1bc, 0x00000000}, - {0x0000a1c0, 0x00000000}, - {0x0000a1c4, 0x00000000}, - {0x0000a1c8, 0x00000000}, - {0x0000a1cc, 0x00000000}, - {0x0000a1d0, 0x00000000}, - {0x0000a1d4, 0x00000000}, - {0x0000a1d8, 0x00000000}, - {0x0000a1dc, 0x00000000}, - {0x0000a1e0, 0x00000000}, - {0x0000a1e4, 0x00000000}, - {0x0000a1e8, 0x00000000}, - {0x0000a1ec, 0x00000000}, - {0x0000a1f0, 0x00000396}, - {0x0000a1f4, 0x00000396}, - {0x0000a1f8, 0x00000396}, - {0x0000a1fc, 0x00000196}, - {0x0000b000, 0x00010000}, - {0x0000b004, 0x00030002}, - {0x0000b008, 0x00050004}, - {0x0000b00c, 0x00810080}, - {0x0000b010, 0x00830082}, - {0x0000b014, 0x01810180}, - {0x0000b018, 0x01830182}, - {0x0000b01c, 0x01850184}, - {0x0000b020, 0x02810280}, - {0x0000b024, 0x02830282}, - {0x0000b028, 0x02850284}, - {0x0000b02c, 0x02890288}, - {0x0000b030, 0x028b028a}, - {0x0000b034, 0x0388028c}, - {0x0000b038, 0x038a0389}, - {0x0000b03c, 0x038c038b}, - {0x0000b040, 0x0390038d}, - {0x0000b044, 0x03920391}, - {0x0000b048, 0x03940393}, - {0x0000b04c, 0x03960395}, - {0x0000b050, 0x00000000}, - {0x0000b054, 0x00000000}, - {0x0000b058, 0x00000000}, - {0x0000b05c, 0x00000000}, - {0x0000b060, 0x00000000}, - {0x0000b064, 0x00000000}, - {0x0000b068, 0x00000000}, - {0x0000b06c, 0x00000000}, - {0x0000b070, 0x00000000}, - {0x0000b074, 0x00000000}, - {0x0000b078, 0x00000000}, - {0x0000b07c, 0x00000000}, - {0x0000b080, 0x32323232}, - {0x0000b084, 0x2f2f3232}, - {0x0000b088, 0x23282a2d}, - {0x0000b08c, 0x1c1e2123}, - {0x0000b090, 0x14171919}, - {0x0000b094, 0x0e0e1214}, - {0x0000b098, 0x03050707}, - {0x0000b09c, 0x00030303}, - {0x0000b0a0, 0x00000000}, - {0x0000b0a4, 0x00000000}, - {0x0000b0a8, 0x00000000}, - {0x0000b0ac, 0x00000000}, - {0x0000b0b0, 0x00000000}, - {0x0000b0b4, 0x00000000}, - {0x0000b0b8, 0x00000000}, - {0x0000b0bc, 0x00000000}, - {0x0000b0c0, 0x003f0020}, - {0x0000b0c4, 0x00400041}, - {0x0000b0c8, 0x0140005f}, - {0x0000b0cc, 0x0160015f}, - {0x0000b0d0, 0x017e017f}, - {0x0000b0d4, 0x02410242}, - {0x0000b0d8, 0x025f0240}, - {0x0000b0dc, 0x027f0260}, - {0x0000b0e0, 0x0341027e}, - {0x0000b0e4, 0x035f0340}, - {0x0000b0e8, 0x037f0360}, - {0x0000b0ec, 0x04400441}, - {0x0000b0f0, 0x0460045f}, - {0x0000b0f4, 0x0541047f}, - {0x0000b0f8, 0x055f0540}, - {0x0000b0fc, 0x057f0560}, - {0x0000b100, 0x06400641}, - {0x0000b104, 0x0660065f}, - {0x0000b108, 0x067e067f}, - {0x0000b10c, 0x07410742}, - {0x0000b110, 0x075f0740}, - {0x0000b114, 0x077f0760}, - {0x0000b118, 0x07800781}, - {0x0000b11c, 0x07a0079f}, - {0x0000b120, 0x07c107bf}, - {0x0000b124, 0x000007c0}, - {0x0000b128, 0x00000000}, - {0x0000b12c, 0x00000000}, - {0x0000b130, 0x00000000}, - {0x0000b134, 0x00000000}, - {0x0000b138, 0x00000000}, - {0x0000b13c, 0x00000000}, - {0x0000b140, 0x003f0020}, - {0x0000b144, 0x00400041}, - {0x0000b148, 0x0140005f}, - {0x0000b14c, 0x0160015f}, - {0x0000b150, 0x017e017f}, - {0x0000b154, 0x02410242}, - {0x0000b158, 0x025f0240}, - {0x0000b15c, 0x027f0260}, - {0x0000b160, 0x0341027e}, - {0x0000b164, 0x035f0340}, - {0x0000b168, 0x037f0360}, - {0x0000b16c, 0x04400441}, - {0x0000b170, 0x0460045f}, - {0x0000b174, 0x0541047f}, - {0x0000b178, 0x055f0540}, - {0x0000b17c, 0x057f0560}, - {0x0000b180, 0x06400641}, - {0x0000b184, 0x0660065f}, - {0x0000b188, 0x067e067f}, - {0x0000b18c, 0x07410742}, - {0x0000b190, 0x075f0740}, - {0x0000b194, 0x077f0760}, - {0x0000b198, 0x07800781}, - {0x0000b19c, 0x07a0079f}, - {0x0000b1a0, 0x07c107bf}, - {0x0000b1a4, 0x000007c0}, - {0x0000b1a8, 0x00000000}, - {0x0000b1ac, 0x00000000}, - {0x0000b1b0, 0x00000000}, - {0x0000b1b4, 0x00000000}, - {0x0000b1b8, 0x00000000}, - {0x0000b1bc, 0x00000000}, - {0x0000b1c0, 0x00000000}, - {0x0000b1c4, 0x00000000}, - {0x0000b1c8, 0x00000000}, - {0x0000b1cc, 0x00000000}, - {0x0000b1d0, 0x00000000}, - {0x0000b1d4, 0x00000000}, - {0x0000b1d8, 0x00000000}, - {0x0000b1dc, 0x00000000}, - {0x0000b1e0, 0x00000000}, - {0x0000b1e4, 0x00000000}, - {0x0000b1e8, 0x00000000}, - {0x0000b1ec, 0x00000000}, - {0x0000b1f0, 0x00000396}, - {0x0000b1f4, 0x00000396}, - {0x0000b1f8, 0x00000396}, - {0x0000b1fc, 0x00000196}, -}; - -static const u32 ar9300Modes_low_ob_db_tx_gain_table_2p0[][5] = { - /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, - {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, - {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, - {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, - {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, - {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400}, - {0x0000a518, 0x21020220, 0x21020220, 0x16000402, 0x16000402}, - {0x0000a51c, 0x27020223, 0x27020223, 0x19000404, 0x19000404}, - {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603}, - {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02}, - {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04}, - {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20}, - {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20}, - {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22}, - {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24}, - {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640}, - {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, - {0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861}, - {0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81}, - {0x0000a54c, 0x5c04286b, 0x5c04286b, 0x47001a83, 0x47001a83}, - {0x0000a550, 0x61042a6c, 0x61042a6c, 0x4a001c84, 0x4a001c84}, - {0x0000a554, 0x66062a6c, 0x66062a6c, 0x4e001ce3, 0x4e001ce3}, - {0x0000a558, 0x6b062e6c, 0x6b062e6c, 0x52001ce5, 0x52001ce5}, - {0x0000a55c, 0x7006308c, 0x7006308c, 0x56001ce9, 0x56001ce9}, - {0x0000a560, 0x730a308a, 0x730a308a, 0x5a001ceb, 0x5a001ceb}, - {0x0000a564, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, - {0x0000a568, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, - {0x0000a56c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, - {0x0000a570, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, - {0x0000a574, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, - {0x0000a578, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, - {0x0000a57c, 0x770a308c, 0x770a308c, 0x5d001eec, 0x5d001eec}, - {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, - {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, - {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, - {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, - {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202}, - {0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400}, - {0x0000a598, 0x21820220, 0x21820220, 0x16800402, 0x16800402}, - {0x0000a59c, 0x27820223, 0x27820223, 0x19800404, 0x19800404}, - {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603}, - {0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02}, - {0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04}, - {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20}, - {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20}, - {0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22}, - {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24}, - {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640}, - {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660}, - {0x0000a5c4, 0x5382266c, 0x5382266c, 0x3f801861, 0x3f801861}, - {0x0000a5c8, 0x5782286c, 0x5782286c, 0x43801a81, 0x43801a81}, - {0x0000a5cc, 0x5c84286b, 0x5c84286b, 0x47801a83, 0x47801a83}, - {0x0000a5d0, 0x61842a6c, 0x61842a6c, 0x4a801c84, 0x4a801c84}, - {0x0000a5d4, 0x66862a6c, 0x66862a6c, 0x4e801ce3, 0x4e801ce3}, - {0x0000a5d8, 0x6b862e6c, 0x6b862e6c, 0x52801ce5, 0x52801ce5}, - {0x0000a5dc, 0x7086308c, 0x7086308c, 0x56801ce9, 0x56801ce9}, - {0x0000a5e0, 0x738a308a, 0x738a308a, 0x5a801ceb, 0x5a801ceb}, - {0x0000a5e4, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, - {0x0000a5e8, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, - {0x0000a5ec, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, - {0x0000a5f0, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, - {0x0000a5f4, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, - {0x0000a5f8, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, - {0x0000a5fc, 0x778a308c, 0x778a308c, 0x5d801eec, 0x5d801eec}, - {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, - {0x00016048, 0x64000001, 0x64000001, 0x64000001, 0x64000001}, - {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, - {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, - {0x00016448, 0x64000001, 0x64000001, 0x64000001, 0x64000001}, - {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, - {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, - {0x00016848, 0x64000001, 0x64000001, 0x64000001, 0x64000001}, - {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, -}; - -static const u32 ar9300_2p0_mac_core[][2] = { - /* Addr allmodes */ - {0x00000008, 0x00000000}, - {0x00000030, 0x00020085}, - {0x00000034, 0x00000005}, - {0x00000040, 0x00000000}, - {0x00000044, 0x00000000}, - {0x00000048, 0x00000008}, - {0x0000004c, 0x00000010}, - {0x00000050, 0x00000000}, - {0x00001040, 0x002ffc0f}, - {0x00001044, 0x002ffc0f}, - {0x00001048, 0x002ffc0f}, - {0x0000104c, 0x002ffc0f}, - {0x00001050, 0x002ffc0f}, - {0x00001054, 0x002ffc0f}, - {0x00001058, 0x002ffc0f}, - {0x0000105c, 0x002ffc0f}, - {0x00001060, 0x002ffc0f}, - {0x00001064, 0x002ffc0f}, - {0x000010f0, 0x00000100}, - {0x00001270, 0x00000000}, - {0x000012b0, 0x00000000}, - {0x000012f0, 0x00000000}, - {0x0000143c, 0x00000000}, - {0x0000147c, 0x00000000}, - {0x00008000, 0x00000000}, - {0x00008004, 0x00000000}, - {0x00008008, 0x00000000}, - {0x0000800c, 0x00000000}, - {0x00008018, 0x00000000}, - {0x00008020, 0x00000000}, - {0x00008038, 0x00000000}, - {0x0000803c, 0x00000000}, - {0x00008040, 0x00000000}, - {0x00008044, 0x00000000}, - {0x00008048, 0x00000000}, - {0x0000804c, 0xffffffff}, - {0x00008054, 0x00000000}, - {0x00008058, 0x00000000}, - {0x0000805c, 0x000fc78f}, - {0x00008060, 0x0000000f}, - {0x00008064, 0x00000000}, - {0x00008070, 0x00000310}, - {0x00008074, 0x00000020}, - {0x00008078, 0x00000000}, - {0x0000809c, 0x0000000f}, - {0x000080a0, 0x00000000}, - {0x000080a4, 0x02ff0000}, - {0x000080a8, 0x0e070605}, - {0x000080ac, 0x0000000d}, - {0x000080b0, 0x00000000}, - {0x000080b4, 0x00000000}, - {0x000080b8, 0x00000000}, - {0x000080bc, 0x00000000}, - {0x000080c0, 0x2a800000}, - {0x000080c4, 0x06900168}, - {0x000080c8, 0x13881c20}, - {0x000080cc, 0x01f40000}, - {0x000080d0, 0x00252500}, - {0x000080d4, 0x00a00000}, - {0x000080d8, 0x00400000}, - {0x000080dc, 0x00000000}, - {0x000080e0, 0xffffffff}, - {0x000080e4, 0x0000ffff}, - {0x000080e8, 0x3f3f3f3f}, - {0x000080ec, 0x00000000}, - {0x000080f0, 0x00000000}, - {0x000080f4, 0x00000000}, - {0x000080fc, 0x00020000}, - {0x00008100, 0x00000000}, - {0x00008108, 0x00000052}, - {0x0000810c, 0x00000000}, - {0x00008110, 0x00000000}, - {0x00008114, 0x000007ff}, - {0x00008118, 0x000000aa}, - {0x0000811c, 0x00003210}, - {0x00008124, 0x00000000}, - {0x00008128, 0x00000000}, - {0x0000812c, 0x00000000}, - {0x00008130, 0x00000000}, - {0x00008134, 0x00000000}, - {0x00008138, 0x00000000}, - {0x0000813c, 0x0000ffff}, - {0x00008144, 0xffffffff}, - {0x00008168, 0x00000000}, - {0x0000816c, 0x00000000}, - {0x00008170, 0x18486200}, - {0x00008174, 0x33332210}, - {0x00008178, 0x00000000}, - {0x0000817c, 0x00020000}, - {0x000081c0, 0x00000000}, - {0x000081c4, 0x33332210}, - {0x000081c8, 0x00000000}, - {0x000081cc, 0x00000000}, - {0x000081d4, 0x00000000}, - {0x000081ec, 0x00000000}, - {0x000081f0, 0x00000000}, - {0x000081f4, 0x00000000}, - {0x000081f8, 0x00000000}, - {0x000081fc, 0x00000000}, - {0x00008240, 0x00100000}, - {0x00008244, 0x0010f424}, - {0x00008248, 0x00000800}, - {0x0000824c, 0x0001e848}, - {0x00008250, 0x00000000}, - {0x00008254, 0x00000000}, - {0x00008258, 0x00000000}, - {0x0000825c, 0x40000000}, - {0x00008260, 0x00080922}, - {0x00008264, 0x98a00010}, - {0x00008268, 0xffffffff}, - {0x0000826c, 0x0000ffff}, - {0x00008270, 0x00000000}, - {0x00008274, 0x40000000}, - {0x00008278, 0x003e4180}, - {0x0000827c, 0x00000004}, - {0x00008284, 0x0000002c}, - {0x00008288, 0x0000002c}, - {0x0000828c, 0x000000ff}, - {0x00008294, 0x00000000}, - {0x00008298, 0x00000000}, - {0x0000829c, 0x00000000}, - {0x00008300, 0x00000140}, - {0x00008314, 0x00000000}, - {0x0000831c, 0x0000010d}, - {0x00008328, 0x00000000}, - {0x0000832c, 0x00000007}, - {0x00008330, 0x00000302}, - {0x00008334, 0x00000700}, - {0x00008338, 0x00ff0000}, - {0x0000833c, 0x02400000}, - {0x00008340, 0x000107ff}, - {0x00008344, 0xaa48105b}, - {0x00008348, 0x008f0000}, - {0x0000835c, 0x00000000}, - {0x00008360, 0xffffffff}, - {0x00008364, 0xffffffff}, - {0x00008368, 0x00000000}, - {0x00008370, 0x00000000}, - {0x00008374, 0x000000ff}, - {0x00008378, 0x00000000}, - {0x0000837c, 0x00000000}, - {0x00008380, 0xffffffff}, - {0x00008384, 0xffffffff}, - {0x00008390, 0xffffffff}, - {0x00008394, 0xffffffff}, - {0x00008398, 0x00000000}, - {0x0000839c, 0x00000000}, - {0x000083a0, 0x00000000}, - {0x000083a4, 0x0000fa14}, - {0x000083a8, 0x000f0c00}, - {0x000083ac, 0x33332210}, - {0x000083b0, 0x33332210}, - {0x000083b4, 0x33332210}, - {0x000083b8, 0x33332210}, - {0x000083bc, 0x00000000}, - {0x000083c0, 0x00000000}, - {0x000083c4, 0x00000000}, - {0x000083c8, 0x00000000}, - {0x000083cc, 0x00000200}, - {0x000083d0, 0x000301ff}, -}; - -static const u32 ar9300Common_wo_xlna_rx_gain_table_2p0[][2] = { - /* Addr allmodes */ - {0x0000a000, 0x00010000}, - {0x0000a004, 0x00030002}, - {0x0000a008, 0x00050004}, - {0x0000a00c, 0x00810080}, - {0x0000a010, 0x00830082}, - {0x0000a014, 0x01810180}, - {0x0000a018, 0x01830182}, - {0x0000a01c, 0x01850184}, - {0x0000a020, 0x01890188}, - {0x0000a024, 0x018b018a}, - {0x0000a028, 0x018d018c}, - {0x0000a02c, 0x03820190}, - {0x0000a030, 0x03840383}, - {0x0000a034, 0x03880385}, - {0x0000a038, 0x038a0389}, - {0x0000a03c, 0x038c038b}, - {0x0000a040, 0x0390038d}, - {0x0000a044, 0x03920391}, - {0x0000a048, 0x03940393}, - {0x0000a04c, 0x03960395}, - {0x0000a050, 0x00000000}, - {0x0000a054, 0x00000000}, - {0x0000a058, 0x00000000}, - {0x0000a05c, 0x00000000}, - {0x0000a060, 0x00000000}, - {0x0000a064, 0x00000000}, - {0x0000a068, 0x00000000}, - {0x0000a06c, 0x00000000}, - {0x0000a070, 0x00000000}, - {0x0000a074, 0x00000000}, - {0x0000a078, 0x00000000}, - {0x0000a07c, 0x00000000}, - {0x0000a080, 0x29292929}, - {0x0000a084, 0x29292929}, - {0x0000a088, 0x29292929}, - {0x0000a08c, 0x29292929}, - {0x0000a090, 0x22292929}, - {0x0000a094, 0x1d1d2222}, - {0x0000a098, 0x0c111117}, - {0x0000a09c, 0x00030303}, - {0x0000a0a0, 0x00000000}, - {0x0000a0a4, 0x00000000}, - {0x0000a0a8, 0x00000000}, - {0x0000a0ac, 0x00000000}, - {0x0000a0b0, 0x00000000}, - {0x0000a0b4, 0x00000000}, - {0x0000a0b8, 0x00000000}, - {0x0000a0bc, 0x00000000}, - {0x0000a0c0, 0x001f0000}, - {0x0000a0c4, 0x01000101}, - {0x0000a0c8, 0x011e011f}, - {0x0000a0cc, 0x011c011d}, - {0x0000a0d0, 0x02030204}, - {0x0000a0d4, 0x02010202}, - {0x0000a0d8, 0x021f0200}, - {0x0000a0dc, 0x0302021e}, - {0x0000a0e0, 0x03000301}, - {0x0000a0e4, 0x031e031f}, - {0x0000a0e8, 0x0402031d}, - {0x0000a0ec, 0x04000401}, - {0x0000a0f0, 0x041e041f}, - {0x0000a0f4, 0x0502041d}, - {0x0000a0f8, 0x05000501}, - {0x0000a0fc, 0x051e051f}, - {0x0000a100, 0x06010602}, - {0x0000a104, 0x061f0600}, - {0x0000a108, 0x061d061e}, - {0x0000a10c, 0x07020703}, - {0x0000a110, 0x07000701}, - {0x0000a114, 0x00000000}, - {0x0000a118, 0x00000000}, - {0x0000a11c, 0x00000000}, - {0x0000a120, 0x00000000}, - {0x0000a124, 0x00000000}, - {0x0000a128, 0x00000000}, - {0x0000a12c, 0x00000000}, - {0x0000a130, 0x00000000}, - {0x0000a134, 0x00000000}, - {0x0000a138, 0x00000000}, - {0x0000a13c, 0x00000000}, - {0x0000a140, 0x001f0000}, - {0x0000a144, 0x01000101}, - {0x0000a148, 0x011e011f}, - {0x0000a14c, 0x011c011d}, - {0x0000a150, 0x02030204}, - {0x0000a154, 0x02010202}, - {0x0000a158, 0x021f0200}, - {0x0000a15c, 0x0302021e}, - {0x0000a160, 0x03000301}, - {0x0000a164, 0x031e031f}, - {0x0000a168, 0x0402031d}, - {0x0000a16c, 0x04000401}, - {0x0000a170, 0x041e041f}, - {0x0000a174, 0x0502041d}, - {0x0000a178, 0x05000501}, - {0x0000a17c, 0x051e051f}, - {0x0000a180, 0x06010602}, - {0x0000a184, 0x061f0600}, - {0x0000a188, 0x061d061e}, - {0x0000a18c, 0x07020703}, - {0x0000a190, 0x07000701}, - {0x0000a194, 0x00000000}, - {0x0000a198, 0x00000000}, - {0x0000a19c, 0x00000000}, - {0x0000a1a0, 0x00000000}, - {0x0000a1a4, 0x00000000}, - {0x0000a1a8, 0x00000000}, - {0x0000a1ac, 0x00000000}, - {0x0000a1b0, 0x00000000}, - {0x0000a1b4, 0x00000000}, - {0x0000a1b8, 0x00000000}, - {0x0000a1bc, 0x00000000}, - {0x0000a1c0, 0x00000000}, - {0x0000a1c4, 0x00000000}, - {0x0000a1c8, 0x00000000}, - {0x0000a1cc, 0x00000000}, - {0x0000a1d0, 0x00000000}, - {0x0000a1d4, 0x00000000}, - {0x0000a1d8, 0x00000000}, - {0x0000a1dc, 0x00000000}, - {0x0000a1e0, 0x00000000}, - {0x0000a1e4, 0x00000000}, - {0x0000a1e8, 0x00000000}, - {0x0000a1ec, 0x00000000}, - {0x0000a1f0, 0x00000396}, - {0x0000a1f4, 0x00000396}, - {0x0000a1f8, 0x00000396}, - {0x0000a1fc, 0x00000196}, - {0x0000b000, 0x00010000}, - {0x0000b004, 0x00030002}, - {0x0000b008, 0x00050004}, - {0x0000b00c, 0x00810080}, - {0x0000b010, 0x00830082}, - {0x0000b014, 0x01810180}, - {0x0000b018, 0x01830182}, - {0x0000b01c, 0x01850184}, - {0x0000b020, 0x02810280}, - {0x0000b024, 0x02830282}, - {0x0000b028, 0x02850284}, - {0x0000b02c, 0x02890288}, - {0x0000b030, 0x028b028a}, - {0x0000b034, 0x0388028c}, - {0x0000b038, 0x038a0389}, - {0x0000b03c, 0x038c038b}, - {0x0000b040, 0x0390038d}, - {0x0000b044, 0x03920391}, - {0x0000b048, 0x03940393}, - {0x0000b04c, 0x03960395}, - {0x0000b050, 0x00000000}, - {0x0000b054, 0x00000000}, - {0x0000b058, 0x00000000}, - {0x0000b05c, 0x00000000}, - {0x0000b060, 0x00000000}, - {0x0000b064, 0x00000000}, - {0x0000b068, 0x00000000}, - {0x0000b06c, 0x00000000}, - {0x0000b070, 0x00000000}, - {0x0000b074, 0x00000000}, - {0x0000b078, 0x00000000}, - {0x0000b07c, 0x00000000}, - {0x0000b080, 0x32323232}, - {0x0000b084, 0x2f2f3232}, - {0x0000b088, 0x23282a2d}, - {0x0000b08c, 0x1c1e2123}, - {0x0000b090, 0x14171919}, - {0x0000b094, 0x0e0e1214}, - {0x0000b098, 0x03050707}, - {0x0000b09c, 0x00030303}, - {0x0000b0a0, 0x00000000}, - {0x0000b0a4, 0x00000000}, - {0x0000b0a8, 0x00000000}, - {0x0000b0ac, 0x00000000}, - {0x0000b0b0, 0x00000000}, - {0x0000b0b4, 0x00000000}, - {0x0000b0b8, 0x00000000}, - {0x0000b0bc, 0x00000000}, - {0x0000b0c0, 0x003f0020}, - {0x0000b0c4, 0x00400041}, - {0x0000b0c8, 0x0140005f}, - {0x0000b0cc, 0x0160015f}, - {0x0000b0d0, 0x017e017f}, - {0x0000b0d4, 0x02410242}, - {0x0000b0d8, 0x025f0240}, - {0x0000b0dc, 0x027f0260}, - {0x0000b0e0, 0x0341027e}, - {0x0000b0e4, 0x035f0340}, - {0x0000b0e8, 0x037f0360}, - {0x0000b0ec, 0x04400441}, - {0x0000b0f0, 0x0460045f}, - {0x0000b0f4, 0x0541047f}, - {0x0000b0f8, 0x055f0540}, - {0x0000b0fc, 0x057f0560}, - {0x0000b100, 0x06400641}, - {0x0000b104, 0x0660065f}, - {0x0000b108, 0x067e067f}, - {0x0000b10c, 0x07410742}, - {0x0000b110, 0x075f0740}, - {0x0000b114, 0x077f0760}, - {0x0000b118, 0x07800781}, - {0x0000b11c, 0x07a0079f}, - {0x0000b120, 0x07c107bf}, - {0x0000b124, 0x000007c0}, - {0x0000b128, 0x00000000}, - {0x0000b12c, 0x00000000}, - {0x0000b130, 0x00000000}, - {0x0000b134, 0x00000000}, - {0x0000b138, 0x00000000}, - {0x0000b13c, 0x00000000}, - {0x0000b140, 0x003f0020}, - {0x0000b144, 0x00400041}, - {0x0000b148, 0x0140005f}, - {0x0000b14c, 0x0160015f}, - {0x0000b150, 0x017e017f}, - {0x0000b154, 0x02410242}, - {0x0000b158, 0x025f0240}, - {0x0000b15c, 0x027f0260}, - {0x0000b160, 0x0341027e}, - {0x0000b164, 0x035f0340}, - {0x0000b168, 0x037f0360}, - {0x0000b16c, 0x04400441}, - {0x0000b170, 0x0460045f}, - {0x0000b174, 0x0541047f}, - {0x0000b178, 0x055f0540}, - {0x0000b17c, 0x057f0560}, - {0x0000b180, 0x06400641}, - {0x0000b184, 0x0660065f}, - {0x0000b188, 0x067e067f}, - {0x0000b18c, 0x07410742}, - {0x0000b190, 0x075f0740}, - {0x0000b194, 0x077f0760}, - {0x0000b198, 0x07800781}, - {0x0000b19c, 0x07a0079f}, - {0x0000b1a0, 0x07c107bf}, - {0x0000b1a4, 0x000007c0}, - {0x0000b1a8, 0x00000000}, - {0x0000b1ac, 0x00000000}, - {0x0000b1b0, 0x00000000}, - {0x0000b1b4, 0x00000000}, - {0x0000b1b8, 0x00000000}, - {0x0000b1bc, 0x00000000}, - {0x0000b1c0, 0x00000000}, - {0x0000b1c4, 0x00000000}, - {0x0000b1c8, 0x00000000}, - {0x0000b1cc, 0x00000000}, - {0x0000b1d0, 0x00000000}, - {0x0000b1d4, 0x00000000}, - {0x0000b1d8, 0x00000000}, - {0x0000b1dc, 0x00000000}, - {0x0000b1e0, 0x00000000}, - {0x0000b1e4, 0x00000000}, - {0x0000b1e8, 0x00000000}, - {0x0000b1ec, 0x00000000}, - {0x0000b1f0, 0x00000396}, - {0x0000b1f4, 0x00000396}, - {0x0000b1f8, 0x00000396}, - {0x0000b1fc, 0x00000196}, -}; - -static const u32 ar9300_2p0_soc_preamble[][2] = { - /* Addr allmodes */ - {0x000040a4, 0x00a0c1c9}, - {0x00007008, 0x00000000}, - {0x00007020, 0x00000000}, - {0x00007034, 0x00000002}, - {0x00007038, 0x000004c2}, -}; - -static const u32 ar9300PciePhy_pll_on_clkreq_disable_L1_2p0[][2] = { - /* Addr allmodes */ - {0x00004040, 0x08212e5e}, - {0x00004040, 0x0008003b}, - {0x00004044, 0x00000000}, -}; - -static const u32 ar9300PciePhy_clkreq_enable_L1_2p0[][2] = { - /* Addr allmodes */ - {0x00004040, 0x08253e5e}, - {0x00004040, 0x0008003b}, - {0x00004044, 0x00000000}, -}; - -static const u32 ar9300PciePhy_clkreq_disable_L1_2p0[][2] = { - /* Addr allmodes */ - {0x00004040, 0x08213e5e}, - {0x00004040, 0x0008003b}, - {0x00004044, 0x00000000}, -}; - -#endif /* INITVALS_9003_2P0_H */ diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index 02c970819f79..c2a057156bfa 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c @@ -16,7 +16,6 @@ #include "hw.h" #include "ar9003_mac.h" -#include "ar9003_2p0_initvals.h" #include "ar9003_2p2_initvals.h" /* General hardware code for the AR9003 hadware family */ @@ -32,79 +31,12 @@ static bool ar9003_hw_macversion_supported(u32 macversion) return false; } -/* AR9003 2.0 */ -static void ar9003_2p0_hw_init_mode_regs(struct ath_hw *ah) -{ - /* mac */ - INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0); - INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], - ar9300_2p0_mac_core, - ARRAY_SIZE(ar9300_2p0_mac_core), 2); - INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST], - ar9300_2p0_mac_postamble, - ARRAY_SIZE(ar9300_2p0_mac_postamble), 5); - - /* bb */ - INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0); - INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE], - ar9300_2p0_baseband_core, - ARRAY_SIZE(ar9300_2p0_baseband_core), 2); - INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST], - ar9300_2p0_baseband_postamble, - ARRAY_SIZE(ar9300_2p0_baseband_postamble), 5); - - /* radio */ - INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0); - INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE], - ar9300_2p0_radio_core, - ARRAY_SIZE(ar9300_2p0_radio_core), 2); - INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST], - ar9300_2p0_radio_postamble, - ARRAY_SIZE(ar9300_2p0_radio_postamble), 5); - - /* soc */ - INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE], - ar9300_2p0_soc_preamble, - ARRAY_SIZE(ar9300_2p0_soc_preamble), 2); - INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0); - INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST], - ar9300_2p0_soc_postamble, - ARRAY_SIZE(ar9300_2p0_soc_postamble), 5); - - /* rx/tx gain */ - INIT_INI_ARRAY(&ah->iniModesRxGain, - ar9300Common_rx_gain_table_2p0, - ARRAY_SIZE(ar9300Common_rx_gain_table_2p0), 2); - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9300Modes_lowest_ob_db_tx_gain_table_2p0, - ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p0), - 5); - - /* Load PCIE SERDES settings from INI */ - - /* Awake Setting */ - - INIT_INI_ARRAY(&ah->iniPcieSerdes, - ar9300PciePhy_pll_on_clkreq_disable_L1_2p0, - ARRAY_SIZE(ar9300PciePhy_pll_on_clkreq_disable_L1_2p0), - 2); - - /* Sleep Setting */ - - INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, - ar9300PciePhy_clkreq_enable_L1_2p0, - ARRAY_SIZE(ar9300PciePhy_clkreq_enable_L1_2p0), - 2); - - /* Fast clock modal settings */ - INIT_INI_ARRAY(&ah->iniModesAdditional, - ar9300Modes_fast_clock_2p0, - ARRAY_SIZE(ar9300Modes_fast_clock_2p0), - 3); -} - -/* AR9003 2.2 */ -static void ar9003_2p2_hw_init_mode_regs(struct ath_hw *ah) +/* + * The AR9003 family uses a new INI format (pre, core, post + * arrays per subsystem). This provides support for the + * AR9003 2.2 chipsets. + */ +static void ar9003_hw_init_mode_regs(struct ath_hw *ah) { /* mac */ INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0); @@ -174,57 +106,27 @@ static void ar9003_2p2_hw_init_mode_regs(struct ath_hw *ah) 3); } -/* - * The AR9003 family uses a new INI format (pre, core, post - * arrays per subsystem). - */ -static void ar9003_hw_init_mode_regs(struct ath_hw *ah) -{ - if (AR_SREV_9300_20(ah)) - ar9003_2p0_hw_init_mode_regs(ah); - else - ar9003_2p2_hw_init_mode_regs(ah); -} - static void ar9003_tx_gain_table_apply(struct ath_hw *ah) { switch (ar9003_hw_get_tx_gain_idx(ah)) { case 0: default: - if (AR_SREV_9300_20(ah)) - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9300Modes_lowest_ob_db_tx_gain_table_2p0, - ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p0), - 5); - else - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9300Modes_lowest_ob_db_tx_gain_table_2p2, - ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2), - 5); + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9300Modes_lowest_ob_db_tx_gain_table_2p2, + ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2), + 5); break; case 1: - if (AR_SREV_9300_20(ah)) - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9300Modes_high_ob_db_tx_gain_table_2p0, - ARRAY_SIZE(ar9300Modes_high_ob_db_tx_gain_table_2p0), - 5); - else - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9300Modes_high_ob_db_tx_gain_table_2p2, - ARRAY_SIZE(ar9300Modes_high_ob_db_tx_gain_table_2p2), - 5); + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9300Modes_high_ob_db_tx_gain_table_2p2, + ARRAY_SIZE(ar9300Modes_high_ob_db_tx_gain_table_2p2), + 5); break; case 2: - if (AR_SREV_9300_20(ah)) - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9300Modes_low_ob_db_tx_gain_table_2p0, - ARRAY_SIZE(ar9300Modes_low_ob_db_tx_gain_table_2p0), - 5); - else - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9300Modes_low_ob_db_tx_gain_table_2p2, - ARRAY_SIZE(ar9300Modes_low_ob_db_tx_gain_table_2p2), - 5); + INIT_INI_ARRAY(&ah->iniModesTxGain, + ar9300Modes_low_ob_db_tx_gain_table_2p2, + ARRAY_SIZE(ar9300Modes_low_ob_db_tx_gain_table_2p2), + 5); break; } } @@ -234,28 +136,16 @@ static void ar9003_rx_gain_table_apply(struct ath_hw *ah) switch (ar9003_hw_get_rx_gain_idx(ah)) { case 0: default: - if (AR_SREV_9300_20(ah)) - INIT_INI_ARRAY(&ah->iniModesRxGain, - ar9300Common_rx_gain_table_2p0, - ARRAY_SIZE(ar9300Common_rx_gain_table_2p0), - 2); - else - INIT_INI_ARRAY(&ah->iniModesRxGain, - ar9300Common_rx_gain_table_2p2, - ARRAY_SIZE(ar9300Common_rx_gain_table_2p2), - 2); + INIT_INI_ARRAY(&ah->iniModesRxGain, + ar9300Common_rx_gain_table_2p2, + ARRAY_SIZE(ar9300Common_rx_gain_table_2p2), + 2); break; case 1: - if (AR_SREV_9300_20(ah)) - INIT_INI_ARRAY(&ah->iniModesRxGain, - ar9300Common_wo_xlna_rx_gain_table_2p0, - ARRAY_SIZE(ar9300Common_wo_xlna_rx_gain_table_2p0), - 2); - else - INIT_INI_ARRAY(&ah->iniModesRxGain, - ar9300Common_wo_xlna_rx_gain_table_2p2, - ARRAY_SIZE(ar9300Common_wo_xlna_rx_gain_table_2p2), - 2); + INIT_INI_ARRAY(&ah->iniModesRxGain, + ar9300Common_wo_xlna_rx_gain_table_2p2, + ARRAY_SIZE(ar9300Common_wo_xlna_rx_gain_table_2p2), + 2); break; } } diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 017617894533..42976b0a01c1 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -853,9 +853,6 @@ #define AR_SREV_9300(_ah) \ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9300)) -#define AR_SREV_9300_20(_ah) \ - (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9300) && \ - ((_ah)->hw_version.macRev == AR_SREV_REVISION_9300_20)) #define AR_SREV_9300_20_OR_LATER(_ah) \ (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9300) || \ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9300) && \ From 5161bec5a8b3509b8cf69418129a191cf90bbd87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Thu, 14 Oct 2010 21:16:33 +0200 Subject: [PATCH 124/127] b43: N-PHY: put 2056-radio's specific code in separated file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rafał Miłecki Signed-off-by: John W. Linville --- drivers/net/wireless/b43/Makefile | 1 + drivers/net/wireless/b43/phy_n.c | 1 + drivers/net/wireless/b43/radio_2056.c | 43 ++++++++++++++++++++++++++ drivers/net/wireless/b43/radio_2056.h | 42 +++++++++++++++++++++++++ drivers/net/wireless/b43/tables_nphy.c | 20 +----------- drivers/net/wireless/b43/tables_nphy.h | 11 ------- 6 files changed, 88 insertions(+), 30 deletions(-) create mode 100644 drivers/net/wireless/b43/radio_2056.c create mode 100644 drivers/net/wireless/b43/radio_2056.h diff --git a/drivers/net/wireless/b43/Makefile b/drivers/net/wireless/b43/Makefile index 0398c7cd2d15..69d4af09a6cb 100644 --- a/drivers/net/wireless/b43/Makefile +++ b/drivers/net/wireless/b43/Makefile @@ -2,6 +2,7 @@ b43-y += main.o b43-y += tables.o b43-$(CONFIG_B43_NPHY) += tables_nphy.o b43-$(CONFIG_B43_NPHY) += radio_2055.o +b43-$(CONFIG_B43_NPHY) += radio_2056.o b43-y += phy_common.o b43-y += phy_g.o b43-y += phy_a.o diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 284b54fde41d..1bdf20c8c43b 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -30,6 +30,7 @@ #include "phy_n.h" #include "tables_nphy.h" #include "radio_2055.h" +#include "radio_2056.h" #include "main.h" struct nphy_txgains { diff --git a/drivers/net/wireless/b43/radio_2056.c b/drivers/net/wireless/b43/radio_2056.c new file mode 100644 index 000000000000..d8563192ce56 --- /dev/null +++ b/drivers/net/wireless/b43/radio_2056.c @@ -0,0 +1,43 @@ +/* + + Broadcom B43 wireless driver + IEEE 802.11n 2056 radio device data tables + + 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 "radio_2056.h" +#include "phy_common.h" + +static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_rev3[] = { +}; + +const struct b43_nphy_channeltab_entry_rev3 * +b43_nphy_get_chantabent_rev3(struct b43_wldev *dev, u16 freq) +{ + const struct b43_nphy_channeltab_entry_rev3 *e; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(b43_nphy_channeltab_rev3); i++) { + e = &(b43_nphy_channeltab_rev3[i]); + if (e->freq == freq) + return e; + } + + return NULL; +} diff --git a/drivers/net/wireless/b43/radio_2056.h b/drivers/net/wireless/b43/radio_2056.h new file mode 100644 index 000000000000..fda6dafecb8c --- /dev/null +++ b/drivers/net/wireless/b43/radio_2056.h @@ -0,0 +1,42 @@ +/* + + Broadcom B43 wireless driver + + Copyright (c) 2010 Rafał Miłecki + + 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 B43_RADIO_2056_H_ +#define B43_RADIO_2056_H_ + +#include + +#include "tables_nphy.h" + +struct b43_nphy_channeltab_entry_rev3 { + /* The channel number */ + u8 channel; + /* The channel frequency in MHz */ + u16 freq; + /* Radio register values on channelswitch */ + /* TODO */ + /* PHY register values on channelswitch */ + struct b43_phy_n_sfo_cfg phy_regs; +}; + +#endif /* B43_RADIO_2056_H_ */ diff --git a/drivers/net/wireless/b43/tables_nphy.c b/drivers/net/wireless/b43/tables_nphy.c index cff7bd379ad8..d60db078eae2 100644 --- a/drivers/net/wireless/b43/tables_nphy.c +++ b/drivers/net/wireless/b43/tables_nphy.c @@ -1,7 +1,7 @@ /* Broadcom B43 wireless driver - IEEE 802.11n PHY and radio device data tables + IEEE 802.11n PHY data tables Copyright (c) 2008 Michael Buesch @@ -27,24 +27,6 @@ #include "phy_common.h" #include "phy_n.h" -static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_rev3[] = { -}; - -const struct b43_nphy_channeltab_entry_rev3 * -b43_nphy_get_chantabent_rev3(struct b43_wldev *dev, u16 freq) -{ - const struct b43_nphy_channeltab_entry_rev3 *e; - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(b43_nphy_channeltab_rev3); i++) { - e = &(b43_nphy_channeltab_rev3[i]); - if (e->freq == freq) - return e; - } - - return NULL; -} - static const u8 b43_ntab_adjustpower0[] = { 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, diff --git a/drivers/net/wireless/b43/tables_nphy.h b/drivers/net/wireless/b43/tables_nphy.h index cb06d397ea2d..4ec593ba3eef 100644 --- a/drivers/net/wireless/b43/tables_nphy.h +++ b/drivers/net/wireless/b43/tables_nphy.h @@ -12,17 +12,6 @@ struct b43_phy_n_sfo_cfg { u16 phy_bw6; }; -struct b43_nphy_channeltab_entry_rev3 { - /* The channel number */ - u8 channel; - /* The channel frequency in MHz */ - u16 freq; - /* Radio register values on channelswitch */ - /* TODO */ - /* PHY register values on channelswitch */ - struct b43_phy_n_sfo_cfg phy_regs; -}; - struct b43_wldev; struct nphy_txiqcal_ladder { From c1739eb3e61e160f124bc842c219011916f63068 Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Thu, 14 Oct 2010 12:45:29 -0700 Subject: [PATCH 125/127] ath9k: Remove bf_dmacontext. The bf_dmacontext seems to be totally useless and duplicated by bf_buf_addr. Remove it entirely, use bf_buf_addr in its place. Signed-off-by: Ben Greear Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 3 +-- drivers/net/wireless/ath/ath9k/beacon.c | 16 +++++++--------- drivers/net/wireless/ath/ath9k/recv.c | 2 -- drivers/net/wireless/ath/ath9k/xmit.c | 11 ++++------- 4 files changed, 12 insertions(+), 20 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index e435c1d38826..973c919fdd27 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -239,12 +239,11 @@ struct ath_buf { struct sk_buff *bf_mpdu; /* enclosing frame structure */ void *bf_desc; /* virtual addr of desc */ dma_addr_t bf_daddr; /* physical addr of desc */ - dma_addr_t bf_buf_addr; /* physical addr of data buffer */ + dma_addr_t bf_buf_addr; /* physical addr of data buffer, for DMA */ bool bf_stale; bool bf_tx_aborted; u16 bf_flags; struct ath_buf_state bf_state; - dma_addr_t bf_dmacontext; struct ath_wiphy *aphy; }; diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 081192e78a46..af8fedda001b 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -136,7 +136,7 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, bf = avp->av_bcbuf; skb = bf->bf_mpdu; if (skb) { - dma_unmap_single(sc->dev, bf->bf_dmacontext, + dma_unmap_single(sc->dev, bf->bf_buf_addr, skb->len, DMA_TO_DEVICE); dev_kfree_skb_any(skb); } @@ -162,9 +162,8 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no); } - bf->bf_buf_addr = bf->bf_dmacontext = - dma_map_single(sc->dev, skb->data, - skb->len, DMA_TO_DEVICE); + bf->bf_buf_addr = dma_map_single(sc->dev, skb->data, + skb->len, DMA_TO_DEVICE); if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) { dev_kfree_skb_any(skb); bf->bf_mpdu = NULL; @@ -252,7 +251,7 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) bf = avp->av_bcbuf; if (bf->bf_mpdu != NULL) { skb = bf->bf_mpdu; - dma_unmap_single(sc->dev, bf->bf_dmacontext, + dma_unmap_single(sc->dev, bf->bf_buf_addr, skb->len, DMA_TO_DEVICE); dev_kfree_skb_any(skb); bf->bf_mpdu = NULL; @@ -296,9 +295,8 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) avp->tsf_adjust = cpu_to_le64(0); bf->bf_mpdu = skb; - bf->bf_buf_addr = bf->bf_dmacontext = - dma_map_single(sc->dev, skb->data, - skb->len, DMA_TO_DEVICE); + bf->bf_buf_addr = dma_map_single(sc->dev, skb->data, + skb->len, DMA_TO_DEVICE); if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) { dev_kfree_skb_any(skb); bf->bf_mpdu = NULL; @@ -324,7 +322,7 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp) bf = avp->av_bcbuf; if (bf->bf_mpdu != NULL) { struct sk_buff *skb = bf->bf_mpdu; - dma_unmap_single(sc->dev, bf->bf_dmacontext, + dma_unmap_single(sc->dev, bf->bf_buf_addr, skb->len, DMA_TO_DEVICE); dev_kfree_skb_any(skb); bf->bf_mpdu = NULL; diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 7c90eaf9ec55..2e427522672d 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -363,7 +363,6 @@ int ath_rx_init(struct ath_softc *sc, int nbufs) error = -ENOMEM; goto err; } - bf->bf_dmacontext = bf->bf_buf_addr; } sc->rx.rxlink = NULL; } @@ -1739,7 +1738,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) ath_rx_send_to_mac80211(hw, sc, skb, rxs); break; } - bf->bf_dmacontext = bf->bf_buf_addr; /* * change the default rx antenna if rx diversity chooses the diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 9b17108adc7c..b053058ae5ea 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -294,7 +294,6 @@ static struct ath_buf* ath_clone_txbuf(struct ath_softc *sc, struct ath_buf *bf) tbf->bf_buf_addr = bf->bf_buf_addr; memcpy(tbf->bf_desc, bf->bf_desc, sc->sc_ah->caps.tx_desc_len); tbf->bf_state = bf->bf_state; - tbf->bf_dmacontext = bf->bf_dmacontext; return tbf; } @@ -1640,17 +1639,15 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf, bf->bf_mpdu = skb; - bf->bf_dmacontext = dma_map_single(sc->dev, skb->data, - skb->len, DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(sc->dev, bf->bf_dmacontext))) { + bf->bf_buf_addr = dma_map_single(sc->dev, skb->data, + skb->len, DMA_TO_DEVICE); + if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) { bf->bf_mpdu = NULL; ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, "dma_mapping_error() on TX\n"); return -ENOMEM; } - bf->bf_buf_addr = bf->bf_dmacontext; - bf->bf_tx_aborted = false; return 0; @@ -1914,7 +1911,7 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, tx_flags |= ATH_TX_XRETRY; } - dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE); + dma_unmap_single(sc->dev, bf->bf_buf_addr, skb->len, DMA_TO_DEVICE); if (bf->bf_state.bfs_paprd) { if (time_after(jiffies, From 6cf9e995f91e5bbffb2bef85feef490e5b67605d Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Thu, 14 Oct 2010 12:45:30 -0700 Subject: [PATCH 126/127] ath9k: Null out references to stale pointers. This doesn't fix any problem that I'm aware of, but should make it harder to add use-after-free type bugs in the future. Signed-off-by: Ben Greear Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/beacon.c | 5 +++++ drivers/net/wireless/ath/ath9k/recv.c | 5 +++++ drivers/net/wireless/ath/ath9k/xmit.c | 6 ++++++ 3 files changed, 16 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index af8fedda001b..4ed010d4ef96 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -139,6 +139,7 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, dma_unmap_single(sc->dev, bf->bf_buf_addr, skb->len, DMA_TO_DEVICE); dev_kfree_skb_any(skb); + bf->bf_buf_addr = 0; } /* Get a new beacon from mac80211 */ @@ -167,6 +168,7 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) { dev_kfree_skb_any(skb); bf->bf_mpdu = NULL; + bf->bf_buf_addr = 0; ath_print(common, ATH_DBG_FATAL, "dma_mapping_error on beaconing\n"); return NULL; @@ -255,6 +257,7 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) skb->len, DMA_TO_DEVICE); dev_kfree_skb_any(skb); bf->bf_mpdu = NULL; + bf->bf_buf_addr = 0; } /* NB: the beacon data buffer must be 32-bit aligned. */ @@ -300,6 +303,7 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) { dev_kfree_skb_any(skb); bf->bf_mpdu = NULL; + bf->bf_buf_addr = 0; ath_print(common, ATH_DBG_FATAL, "dma_mapping_error on beacon alloc\n"); return -ENOMEM; @@ -326,6 +330,7 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp) skb->len, DMA_TO_DEVICE); dev_kfree_skb_any(skb); bf->bf_mpdu = NULL; + bf->bf_buf_addr = 0; } list_add_tail(&bf->list, &sc->beacon.bbuf); diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 2e427522672d..fe73fc50082a 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -268,6 +268,7 @@ static int ath_rx_edma_init(struct ath_softc *sc, int nbufs) bf->bf_buf_addr))) { dev_kfree_skb_any(skb); bf->bf_mpdu = NULL; + bf->bf_buf_addr = 0; ath_print(common, ATH_DBG_FATAL, "dma_mapping_error() on RX init\n"); error = -ENOMEM; @@ -358,6 +359,7 @@ int ath_rx_init(struct ath_softc *sc, int nbufs) bf->bf_buf_addr))) { dev_kfree_skb_any(skb); bf->bf_mpdu = NULL; + bf->bf_buf_addr = 0; ath_print(common, ATH_DBG_FATAL, "dma_mapping_error() on RX init\n"); error = -ENOMEM; @@ -392,6 +394,8 @@ void ath_rx_cleanup(struct ath_softc *sc) common->rx_bufsize, DMA_FROM_DEVICE); dev_kfree_skb(skb); + bf->bf_buf_addr = 0; + bf->bf_mpdu = NULL; } } @@ -1733,6 +1737,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) bf->bf_buf_addr))) { dev_kfree_skb_any(requeue_skb); bf->bf_mpdu = NULL; + bf->bf_buf_addr = 0; ath_print(common, ATH_DBG_FATAL, "dma_mapping_error() on RX\n"); ath_rx_send_to_mac80211(hw, sc, skb, rxs); diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index b053058ae5ea..d077186da870 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -1643,6 +1643,7 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf, skb->len, DMA_TO_DEVICE); if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) { bf->bf_mpdu = NULL; + bf->bf_buf_addr = 0; ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, "dma_mapping_error() on TX\n"); return -ENOMEM; @@ -1912,6 +1913,7 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, } dma_unmap_single(sc->dev, bf->bf_buf_addr, skb->len, DMA_TO_DEVICE); + bf->bf_buf_addr = 0; if (bf->bf_state.bfs_paprd) { if (time_after(jiffies, @@ -1924,6 +1926,10 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, ath_debug_stat_tx(sc, txq, bf, ts); ath_tx_complete(sc, skb, bf->aphy, tx_flags); } + /* At this point, skb (bf->bf_mpdu) is consumed...make sure we don't + * accidentally reference it later. + */ + bf->bf_mpdu = NULL; /* * Return the list of ath_buf of this mpdu to free queue From 0d91f22b75347d9503b17a42b6c74d3f7750acd6 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Fri, 15 Oct 2010 15:00:06 +0200 Subject: [PATCH 127/127] drivers/net/wireless/p54/eeprom.c: Return -ENOMEM on memory allocation failure In this code, 0 is returned on memory allocation failure, even though other failures return -ENOMEM or other similar values. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @@ expression ret; expression x,e1,e2,e3; @@ ret = 0 ... when != ret = e1 *x = \(kmalloc\|kcalloc\|kzalloc\)(...) ... when != ret = e2 if (x == NULL) { ... when != ret = e3 return ret; } // Signed-off-by: Julia Lawall Cc: Acked-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/eeprom.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/p54/eeprom.c b/drivers/net/wireless/p54/eeprom.c index 8c05266d37f4..35b09aa0529b 100644 --- a/drivers/net/wireless/p54/eeprom.c +++ b/drivers/net/wireless/p54/eeprom.c @@ -261,8 +261,10 @@ static int p54_generate_channel_lists(struct ieee80211_hw *dev) list->max_entries = max_channel_num; list->channels = kzalloc(sizeof(struct p54_channel_entry) * max_channel_num, GFP_KERNEL); - if (!list->channels) + if (!list->channels) { + ret = -ENOMEM; goto free; + } for (i = 0; i < max_channel_num; i++) { if (i < priv->iq_autocal_len) {