summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/iwlwifi/iwl-4965.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-4965.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.c198
1 files changed, 107 insertions, 91 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 8972166386cb..d3afddae8d9f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -46,6 +46,8 @@
#include "iwl-calib.h"
#include "iwl-sta.h"
#include "iwl-agn-led.h"
+#include "iwl-agn.h"
+#include "iwl-agn-debugfs.h"
static int iwl4965_send_tx_power(struct iwl_priv *priv);
static int iwl4965_hw_get_temperature(struct iwl_priv *priv);
@@ -60,14 +62,6 @@ static int iwl4965_hw_get_temperature(struct iwl_priv *priv);
#define _IWL4965_MODULE_FIRMWARE(api) IWL4965_FW_PRE #api ".ucode"
#define IWL4965_MODULE_FIRMWARE(api) _IWL4965_MODULE_FIRMWARE(api)
-
-/* module parameters */
-static struct iwl_mod_params iwl4965_mod_params = {
- .amsdu_size_8K = 1,
- .restart_fw = 1,
- /* the rest are 0 by default */
-};
-
/* check contents of special bootstrap uCode SRAM */
static int iwl4965_verify_bsm(struct iwl_priv *priv)
{
@@ -417,7 +411,7 @@ static void iwl4965_gain_computation(struct iwl_priv *priv,
sizeof(cmd), &cmd);
if (ret)
IWL_DEBUG_CALIB(priv, "fail sending cmd "
- "REPLY_PHY_CALIBRATION_CMD \n");
+ "REPLY_PHY_CALIBRATION_CMD\n");
/* TODO we might want recalculate
* rx_chain in rxon cmd */
@@ -502,14 +496,14 @@ static void iwl4965_tx_queue_set_status(struct iwl_priv *priv,
scd_retry ? "BA" : "AC", txq_id, tx_fifo_id);
}
-static const u16 default_queue_to_tx_fifo[] = {
- IWL_TX_FIFO_AC3,
- IWL_TX_FIFO_AC2,
- IWL_TX_FIFO_AC1,
- IWL_TX_FIFO_AC0,
+static const s8 default_queue_to_tx_fifo[] = {
+ IWL_TX_FIFO_VO,
+ IWL_TX_FIFO_VI,
+ IWL_TX_FIFO_BE,
+ IWL_TX_FIFO_BK,
IWL49_CMD_FIFO_NUM,
- IWL_TX_FIFO_HCCA_1,
- IWL_TX_FIFO_HCCA_2
+ IWL_TX_FIFO_UNUSED,
+ IWL_TX_FIFO_UNUSED,
};
static int iwl4965_alive_notify(struct iwl_priv *priv)
@@ -589,9 +583,15 @@ static int iwl4965_alive_notify(struct iwl_priv *priv)
/* reset to 0 to enable all the queue first */
priv->txq_ctx_active_msk = 0;
/* Map each Tx/cmd queue to its corresponding fifo */
+ BUILD_BUG_ON(ARRAY_SIZE(default_queue_to_tx_fifo) != 7);
for (i = 0; i < ARRAY_SIZE(default_queue_to_tx_fifo); i++) {
int ac = default_queue_to_tx_fifo[i];
+
iwl_txq_ctx_activate(priv, i);
+
+ if (ac == IWL_TX_FIFO_UNUSED)
+ continue;
+
iwl4965_tx_queue_set_status(priv, &priv->txq[i], ac, 0);
}
@@ -1613,19 +1613,19 @@ static int iwl4965_is_temp_calib_needed(struct iwl_priv *priv)
/* get absolute value */
if (temp_diff < 0) {
- IWL_DEBUG_POWER(priv, "Getting cooler, delta %d, \n", temp_diff);
+ IWL_DEBUG_POWER(priv, "Getting cooler, delta %d\n", temp_diff);
temp_diff = -temp_diff;
} else if (temp_diff == 0)
- IWL_DEBUG_POWER(priv, "Same temp, \n");
+ IWL_DEBUG_POWER(priv, "Temperature unchanged\n");
else
- IWL_DEBUG_POWER(priv, "Getting warmer, delta %d, \n", temp_diff);
+ IWL_DEBUG_POWER(priv, "Getting warmer, delta %d\n", temp_diff);
if (temp_diff < IWL_TEMPERATURE_THRESHOLD) {
- IWL_DEBUG_POWER(priv, "Thermal txpower calib not needed\n");
+ IWL_DEBUG_POWER(priv, " => thermal txpower calib not needed\n");
return 0;
}
- IWL_DEBUG_POWER(priv, "Thermal txpower calib needed\n");
+ IWL_DEBUG_POWER(priv, " => thermal txpower calib needed\n");
return 1;
}
@@ -1874,7 +1874,7 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv,
info->status.rates[0].count = tx_resp->failure_frame + 1;
info->flags &= ~IEEE80211_TX_CTL_AMPDU;
info->flags |= iwl_tx_status_to_mac80211(status);
- iwl_hwrate_to_tx_control(priv, rate_n_flags, info);
+ iwlagn_hwrate_to_tx_control(priv, rate_n_flags, info);
/* FIXME: code repetition end */
IWL_DEBUG_TX_REPLY(priv, "1 Frame 0x%x failure :%d\n",
@@ -1953,6 +1953,60 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv,
return 0;
}
+static u8 iwl_find_station(struct iwl_priv *priv, const u8 *addr)
+{
+ int i;
+ int start = 0;
+ int ret = IWL_INVALID_STATION;
+ unsigned long flags;
+
+ if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) ||
+ (priv->iw_mode == NL80211_IFTYPE_AP))
+ start = IWL_STA_ID;
+
+ if (is_broadcast_ether_addr(addr))
+ return priv->hw_params.bcast_sta_id;
+
+ spin_lock_irqsave(&priv->sta_lock, flags);
+ for (i = start; i < priv->hw_params.max_stations; i++)
+ if (priv->stations[i].used &&
+ (!compare_ether_addr(priv->stations[i].sta.sta.addr,
+ addr))) {
+ ret = i;
+ goto out;
+ }
+
+ IWL_DEBUG_ASSOC_LIMIT(priv, "can not find STA %pM total %d\n",
+ addr, priv->num_stations);
+
+ out:
+ /*
+ * It may be possible that more commands interacting with stations
+ * arrive before we completed processing the adding of
+ * station
+ */
+ if (ret != IWL_INVALID_STATION &&
+ (!(priv->stations[ret].used & IWL_STA_UCODE_ACTIVE) ||
+ ((priv->stations[ret].used & IWL_STA_UCODE_ACTIVE) &&
+ (priv->stations[ret].used & IWL_STA_UCODE_INPROGRESS)))) {
+ IWL_ERR(priv, "Requested station info for sta %d before ready.\n",
+ ret);
+ ret = IWL_INVALID_STATION;
+ }
+ spin_unlock_irqrestore(&priv->sta_lock, flags);
+ return ret;
+}
+
+static int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr)
+{
+ if (priv->iw_mode == NL80211_IFTYPE_STATION) {
+ return IWL_AP_ID;
+ } else {
+ u8 *da = ieee80211_get_DA(hdr);
+ return iwl_find_station(priv, da);
+ }
+}
+
/**
* iwl4965_rx_reply_tx - Handle standard (non-aggregation) Tx response
*/
@@ -2014,7 +2068,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd);
IWL_DEBUG_TX_REPLY(priv, "Retry scheduler reclaim scd_ssn "
"%d index %d\n", scd_ssn , index);
- freed = iwl_tx_queue_reclaim(priv, txq_id, index);
+ freed = iwlagn_tx_queue_reclaim(priv, txq_id, index);
if (qc)
iwl_free_tfds_in_queue(priv, sta_id,
tid, freed);
@@ -2031,7 +2085,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
} else {
info->status.rates[0].count = tx_resp->failure_frame + 1;
info->flags |= iwl_tx_status_to_mac80211(status);
- iwl_hwrate_to_tx_control(priv,
+ iwlagn_hwrate_to_tx_control(priv,
le32_to_cpu(tx_resp->rate_n_flags),
info);
@@ -2042,7 +2096,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
le32_to_cpu(tx_resp->rate_n_flags),
tx_resp->failure_frame);
- freed = iwl_tx_queue_reclaim(priv, txq_id, index);
+ freed = iwlagn_tx_queue_reclaim(priv, txq_id, index);
if (qc && likely(sta_id != IWL_INVALID_STATION))
iwl_free_tfds_in_queue(priv, sta_id, tid, freed);
else if (sta_id == IWL_INVALID_STATION)
@@ -2053,10 +2107,9 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
iwl_wake_queue(priv, txq_id);
}
if (qc && likely(sta_id != IWL_INVALID_STATION))
- iwl_txq_check_empty(priv, sta_id, tid, txq_id);
+ iwlagn_txq_check_empty(priv, sta_id, tid, txq_id);
- if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK))
- IWL_ERR(priv, "TODO: Implement Tx ABORT REQUIRED!!!\n");
+ iwl_check_abort_status(priv, tx_resp->frame_count, status);
}
static int iwl4965_calc_rssi(struct iwl_priv *priv,
@@ -2090,7 +2143,7 @@ static int iwl4965_calc_rssi(struct iwl_priv *priv,
/* dBm = max_rssi dB - agc dB - constant.
* Higher AGC (higher radio gain) means lower signal. */
- return max_rssi - agc - IWL49_RSSI_OFFSET;
+ return max_rssi - agc - IWLAGN_RSSI_OFFSET;
}
@@ -2098,7 +2151,7 @@ static int iwl4965_calc_rssi(struct iwl_priv *priv,
static void iwl4965_rx_handler_setup(struct iwl_priv *priv)
{
/* Legacy Rx frames */
- priv->rx_handlers[REPLY_RX] = iwl_rx_reply_rx;
+ priv->rx_handlers[REPLY_RX] = iwlagn_rx_reply_rx;
/* Tx response */
priv->rx_handlers[REPLY_TX] = iwl4965_rx_reply_tx;
}
@@ -2113,50 +2166,13 @@ static void iwl4965_cancel_deferred_work(struct iwl_priv *priv)
cancel_work_sync(&priv->txpower_work);
}
-#define IWL4965_UCODE_GET(item) \
-static u32 iwl4965_ucode_get_##item(const struct iwl_ucode_header *ucode,\
- u32 api_ver) \
-{ \
- return le32_to_cpu(ucode->u.v1.item); \
-}
-
-static u32 iwl4965_ucode_get_header_size(u32 api_ver)
-{
- return UCODE_HEADER_SIZE(1);
-}
-static u32 iwl4965_ucode_get_build(const struct iwl_ucode_header *ucode,
- u32 api_ver)
-{
- return 0;
-}
-static u8 *iwl4965_ucode_get_data(const struct iwl_ucode_header *ucode,
- u32 api_ver)
-{
- return (u8 *) ucode->u.v1.data;
-}
-
-IWL4965_UCODE_GET(inst_size);
-IWL4965_UCODE_GET(data_size);
-IWL4965_UCODE_GET(init_size);
-IWL4965_UCODE_GET(init_data_size);
-IWL4965_UCODE_GET(boot_size);
-
static struct iwl_hcmd_ops iwl4965_hcmd = {
.rxon_assoc = iwl4965_send_rxon_assoc,
.commit_rxon = iwl_commit_rxon,
.set_rxon_chain = iwl_set_rxon_chain,
+ .send_bt_config = iwl_send_bt_config,
};
-static struct iwl_ucode_ops iwl4965_ucode = {
- .get_header_size = iwl4965_ucode_get_header_size,
- .get_build = iwl4965_ucode_get_build,
- .get_inst_size = iwl4965_ucode_get_inst_size,
- .get_data_size = iwl4965_ucode_get_data_size,
- .get_init_size = iwl4965_ucode_get_init_size,
- .get_init_data_size = iwl4965_ucode_get_init_data_size,
- .get_boot_size = iwl4965_ucode_get_boot_size,
- .get_data = iwl4965_ucode_get_data,
-};
static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = {
.get_hcmd_size = iwl4965_get_hcmd_size,
.build_addsta_hcmd = iwl4965_build_addsta_hcmd,
@@ -2164,6 +2180,7 @@ static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = {
.gain_computation = iwl4965_gain_computation,
.rts_tx_cmd_flag = iwlcore_rts_tx_cmd_flag,
.calc_rssi = iwl4965_calc_rssi,
+ .request_scan = iwlagn_request_scan,
};
static struct iwl_lib_ops iwl4965_lib = {
@@ -2184,6 +2201,7 @@ static struct iwl_lib_ops iwl4965_lib = {
.load_ucode = iwl4965_load_bsm,
.dump_nic_event_log = iwl_dump_nic_event_log,
.dump_nic_error_log = iwl_dump_nic_error_log,
+ .dump_fh = iwl_dump_fh,
.set_channel_switch = iwl4965_hw_channel_switch,
.apm_ops = {
.init = iwl_apm_init,
@@ -2216,11 +2234,16 @@ static struct iwl_lib_ops iwl4965_lib = {
.temperature = iwl4965_temperature_calib,
.set_ct_kill = iwl4965_set_ct_threshold,
},
- .add_bcast_station = iwl_add_bcast_station,
+ .manage_ibss_station = iwlagn_manage_ibss_station,
+ .debugfs_ops = {
+ .rx_stats_read = iwl_ucode_rx_stats_read,
+ .tx_stats_read = iwl_ucode_tx_stats_read,
+ .general_stats_read = iwl_ucode_general_stats_read,
+ },
+ .check_plcp_health = iwl_good_plcp_health,
};
static const struct iwl_ops iwl4965_ops = {
- .ucode = &iwl4965_ucode,
.lib = &iwl4965_lib,
.hcmd = &iwl4965_hcmd,
.utils = &iwl4965_hcmd_utils,
@@ -2228,7 +2251,7 @@ static const struct iwl_ops iwl4965_ops = {
};
struct iwl_cfg iwl4965_agn_cfg = {
- .name = "4965AGN",
+ .name = "Intel(R) Wireless WiFi Link 4965AGN",
.fw_name_pre = IWL4965_FW_PRE,
.ucode_api_max = IWL4965_UCODE_API_MAX,
.ucode_api_min = IWL4965_UCODE_API_MIN,
@@ -2239,7 +2262,7 @@ struct iwl_cfg iwl4965_agn_cfg = {
.ops = &iwl4965_ops,
.num_of_queues = IWL49_NUM_QUEUES,
.num_of_ampdu_queues = IWL49_NUM_AMPDU_QUEUES,
- .mod_params = &iwl4965_mod_params,
+ .mod_params = &iwlagn_mod_params,
.valid_tx_ant = ANT_AB,
.valid_rx_ant = ANT_ABC,
.pll_cfg_val = 0,
@@ -2251,27 +2274,20 @@ struct iwl_cfg iwl4965_agn_cfg = {
.led_compensation = 61,
.chain_noise_num_beacons = IWL4965_CAL_NUM_BEACONS,
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
+ .monitor_recover_period = IWL_MONITORING_PERIOD,
+ .temperature_kelvin = true,
+ .max_event_log_size = 512,
+ .tx_power_by_driver = true,
+ .ucode_tracing = true,
+ .sensitivity_calib_by_driver = true,
+ .chain_noise_calib_by_driver = true,
+ /*
+ * Force use of chains B and C for scan RX on 5 GHz band
+ * because the device has off-channel reception on chain A.
+ */
+ .scan_antennas[IEEE80211_BAND_5GHZ] = ANT_BC,
};
/* Module firmware */
MODULE_FIRMWARE(IWL4965_MODULE_FIRMWARE(IWL4965_UCODE_API_MAX));
-module_param_named(antenna, iwl4965_mod_params.antenna, int, S_IRUGO);
-MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])");
-module_param_named(swcrypto, iwl4965_mod_params.sw_crypto, int, S_IRUGO);
-MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])");
-module_param_named(
- disable_hw_scan, iwl4965_mod_params.disable_hw_scan, int, S_IRUGO);
-MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)");
-
-module_param_named(queues_num, iwl4965_mod_params.num_of_queues, int, S_IRUGO);
-MODULE_PARM_DESC(queues_num, "number of hw queues.");
-/* 11n */
-module_param_named(11n_disable, iwl4965_mod_params.disable_11n, int, S_IRUGO);
-MODULE_PARM_DESC(11n_disable, "disable 11n functionality");
-module_param_named(amsdu_size_8K, iwl4965_mod_params.amsdu_size_8K,
- int, S_IRUGO);
-MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size");
-
-module_param_named(fw_restart4965, iwl4965_mod_params.restart_fw, int, S_IRUGO);
-MODULE_PARM_DESC(fw_restart4965, "restart firmware in case of error");