diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi')
20 files changed, 591 insertions, 240 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index c281d07..8848333 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -222,6 +222,7 @@ static struct iwl_lib_ops iwl1000_lib = { .rx_stats_read = iwl_ucode_rx_stats_read, .tx_stats_read = iwl_ucode_tx_stats_read, .general_stats_read = iwl_ucode_general_stats_read, + .bt_stats_read = iwl_ucode_bt_stats_read, }, .recover_from_tx_stall = iwl_bg_monitor_recover, .check_plcp_health = iwl_good_plcp_health, diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 3a0d0ad..d6531ad 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -1605,8 +1605,8 @@ static int iwl4965_hw_get_temperature(struct iwl_priv *priv) if (!test_bit(STATUS_TEMPERATURE, &priv->status)) vt = sign_extend(R4, 23); else - vt = sign_extend(le32_to_cpu( - priv->_agn.statistics.general.temperature), 23); + vt = sign_extend(le32_to_cpu(priv->_agn.statistics. + general.common.temperature), 23); IWL_DEBUG_TEMP(priv, "Calib values R[1-3]: %d %d %d R4: %d\n", R1, R2, R3, vt); @@ -2285,6 +2285,7 @@ static struct iwl_lib_ops iwl4965_lib = { .rx_stats_read = iwl_ucode_rx_stats_read, .tx_stats_read = iwl_ucode_tx_stats_read, .general_stats_read = iwl_ucode_general_stats_read, + .bt_stats_read = iwl_ucode_bt_stats_read, }, .recover_from_tx_stall = iwl_bg_monitor_recover, .check_plcp_health = iwl_good_plcp_health, diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 7d89d99..8093ce2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -265,7 +265,7 @@ static void iwl5150_temperature(struct iwl_priv *priv) u32 vt = 0; s32 offset = iwl_temp_calib_to_offset(priv); - vt = le32_to_cpu(priv->_agn.statistics.general.temperature); + vt = le32_to_cpu(priv->_agn.statistics.general.common.temperature); vt = vt / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF + offset; /* now vt hold the temperature in Kelvin */ priv->temperature = KELVIN_TO_CELSIUS(vt); @@ -398,6 +398,7 @@ static struct iwl_lib_ops iwl5000_lib = { .rx_stats_read = iwl_ucode_rx_stats_read, .tx_stats_read = iwl_ucode_tx_stats_read, .general_stats_read = iwl_ucode_general_stats_read, + .bt_stats_read = iwl_ucode_bt_stats_read, }, .recover_from_tx_stall = iwl_bg_monitor_recover, .check_plcp_health = iwl_good_plcp_health, diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 0955219..5827052 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -323,6 +323,7 @@ static struct iwl_lib_ops iwl6000_lib = { .rx_stats_read = iwl_ucode_rx_stats_read, .tx_stats_read = iwl_ucode_tx_stats_read, .general_stats_read = iwl_ucode_general_stats_read, + .bt_stats_read = iwl_ucode_bt_stats_read, }, .recover_from_tx_stall = iwl_bg_monitor_recover, .check_plcp_health = iwl_good_plcp_health, @@ -500,6 +501,7 @@ struct iwl_cfg iwl6000g2b_2agn_cfg = { .sensitivity_calib_by_driver = true, .chain_noise_calib_by_driver = true, .need_dc_calib = true, + .bt_statistics = true, }; struct iwl_cfg iwl6000g2b_2abg_cfg = { @@ -535,6 +537,7 @@ struct iwl_cfg iwl6000g2b_2abg_cfg = { .sensitivity_calib_by_driver = true, .chain_noise_calib_by_driver = true, .need_dc_calib = true, + .bt_statistics = true, }; struct iwl_cfg iwl6000g2b_2bgn_cfg = { @@ -572,6 +575,7 @@ struct iwl_cfg iwl6000g2b_2bgn_cfg = { .sensitivity_calib_by_driver = true, .chain_noise_calib_by_driver = true, .need_dc_calib = true, + .bt_statistics = true, }; struct iwl_cfg iwl6000g2b_2bg_cfg = { @@ -607,6 +611,7 @@ struct iwl_cfg iwl6000g2b_2bg_cfg = { .sensitivity_calib_by_driver = true, .chain_noise_calib_by_driver = true, .need_dc_calib = true, + .bt_statistics = true, }; struct iwl_cfg iwl6000g2b_bgn_cfg = { @@ -644,6 +649,7 @@ struct iwl_cfg iwl6000g2b_bgn_cfg = { .sensitivity_calib_by_driver = true, .chain_noise_calib_by_driver = true, .need_dc_calib = true, + .bt_statistics = true, }; struct iwl_cfg iwl6000g2b_bg_cfg = { @@ -679,6 +685,7 @@ struct iwl_cfg iwl6000g2b_bg_cfg = { .sensitivity_calib_by_driver = true, .chain_noise_calib_by_driver = true, .need_dc_calib = true, + .bt_statistics = true, }; /* diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c index 90033e8..c4c5691 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c @@ -605,8 +605,7 @@ void iwl_init_sensitivity(struct iwl_priv *priv) IWL_DEBUG_CALIB(priv, "<<return 0x%X\n", ret); } -void iwl_sensitivity_calibration(struct iwl_priv *priv, - struct iwl_notif_statistics *resp) +void iwl_sensitivity_calibration(struct iwl_priv *priv, void *resp) { u32 rx_enable_time; u32 fa_cck; @@ -616,8 +615,8 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv, u32 norm_fa_ofdm; u32 norm_fa_cck; struct iwl_sensitivity_data *data = NULL; - struct statistics_rx_non_phy *rx_info = &(resp->rx.general); - struct statistics_rx *statistics = &(resp->rx); + struct statistics_rx_non_phy *rx_info; + struct statistics_rx_phy *ofdm, *cck; unsigned long flags; struct statistics_general_data statis; @@ -632,6 +631,16 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv, } spin_lock_irqsave(&priv->lock, flags); + if (priv->cfg->bt_statistics) { + rx_info = &(((struct iwl_bt_notif_statistics *)resp)-> + rx.general.common); + ofdm = &(((struct iwl_bt_notif_statistics *)resp)->rx.ofdm); + cck = &(((struct iwl_bt_notif_statistics *)resp)->rx.cck); + } else { + rx_info = &(((struct iwl_notif_statistics *)resp)->rx.general); + ofdm = &(((struct iwl_notif_statistics *)resp)->rx.ofdm); + cck = &(((struct iwl_notif_statistics *)resp)->rx.cck); + } if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) { IWL_DEBUG_CALIB(priv, "<< invalid data.\n"); spin_unlock_irqrestore(&priv->lock, flags); @@ -640,23 +649,23 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv, /* Extract Statistics: */ rx_enable_time = le32_to_cpu(rx_info->channel_load); - fa_cck = le32_to_cpu(statistics->cck.false_alarm_cnt); - fa_ofdm = le32_to_cpu(statistics->ofdm.false_alarm_cnt); - bad_plcp_cck = le32_to_cpu(statistics->cck.plcp_err); - bad_plcp_ofdm = le32_to_cpu(statistics->ofdm.plcp_err); + fa_cck = le32_to_cpu(cck->false_alarm_cnt); + fa_ofdm = le32_to_cpu(ofdm->false_alarm_cnt); + bad_plcp_cck = le32_to_cpu(cck->plcp_err); + bad_plcp_ofdm = le32_to_cpu(ofdm->plcp_err); statis.beacon_silence_rssi_a = - le32_to_cpu(statistics->general.beacon_silence_rssi_a); + le32_to_cpu(rx_info->beacon_silence_rssi_a); statis.beacon_silence_rssi_b = - le32_to_cpu(statistics->general.beacon_silence_rssi_b); + le32_to_cpu(rx_info->beacon_silence_rssi_b); statis.beacon_silence_rssi_c = - le32_to_cpu(statistics->general.beacon_silence_rssi_c); + le32_to_cpu(rx_info->beacon_silence_rssi_c); statis.beacon_energy_a = - le32_to_cpu(statistics->general.beacon_energy_a); + le32_to_cpu(rx_info->beacon_energy_a); statis.beacon_energy_b = - le32_to_cpu(statistics->general.beacon_energy_b); + le32_to_cpu(rx_info->beacon_energy_b); statis.beacon_energy_c = - le32_to_cpu(statistics->general.beacon_energy_c); + le32_to_cpu(rx_info->beacon_energy_c); spin_unlock_irqrestore(&priv->lock, flags); @@ -728,8 +737,7 @@ static inline u8 find_first_chain(u8 mask) * 1) Which antennas are connected. * 2) Differential rx gain settings to balance the 3 receivers. */ -void iwl_chain_noise_calibration(struct iwl_priv *priv, - struct iwl_notif_statistics *stat_resp) +void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp) { struct iwl_chain_noise_data *data = NULL; @@ -753,7 +761,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, u32 active_chains = 0; u8 num_tx_chains; unsigned long flags; - struct statistics_rx_non_phy *rx_info = &(stat_resp->rx.general); + struct statistics_rx_non_phy *rx_info; u8 first_chain; if (priv->disable_chain_noise_cal) @@ -772,6 +780,13 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, } spin_lock_irqsave(&priv->lock, flags); + if (priv->cfg->bt_statistics) { + rx_info = &(((struct iwl_bt_notif_statistics *)stat_resp)-> + rx.general.common); + } else { + rx_info = &(((struct iwl_notif_statistics *)stat_resp)-> + rx.general); + } if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) { IWL_DEBUG_CALIB(priv, " << Interference data unavailable\n"); spin_unlock_irqrestore(&priv->lock, flags); @@ -780,8 +795,19 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, rxon_band24 = !!(priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK); rxon_chnum = le16_to_cpu(priv->staging_rxon.channel); - stat_band24 = !!(stat_resp->flag & STATISTICS_REPLY_FLG_BAND_24G_MSK); - stat_chnum = le32_to_cpu(stat_resp->flag) >> 16; + if (priv->cfg->bt_statistics) { + stat_band24 = !!(((struct iwl_bt_notif_statistics *) + stat_resp)->flag & + STATISTICS_REPLY_FLG_BAND_24G_MSK); + stat_chnum = le32_to_cpu(((struct iwl_bt_notif_statistics *) + stat_resp)->flag) >> 16; + } else { + stat_band24 = !!(((struct iwl_notif_statistics *) + stat_resp)->flag & + STATISTICS_REPLY_FLG_BAND_24G_MSK); + stat_chnum = le32_to_cpu(((struct iwl_notif_statistics *) + stat_resp)->flag) >> 16; + } /* Make sure we accumulate data for just the associated channel * (even if scanning). */ diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c index 5e5c512..f052c6d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c @@ -31,21 +31,24 @@ static int iwl_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz) { int p = 0; + u32 flag; - p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n", - le32_to_cpu(priv->_agn.statistics.flag)); - if (le32_to_cpu(priv->_agn.statistics.flag) & - UCODE_STATISTICS_CLEAR_MSK) + if (priv->cfg->bt_statistics) + flag = le32_to_cpu(priv->_agn.statistics_bt.flag); + else + flag = le32_to_cpu(priv->_agn.statistics.flag); + + p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n", flag); + if (flag & UCODE_STATISTICS_CLEAR_MSK) p += scnprintf(buf + p, bufsz - p, - "\tStatistics have been cleared\n"); + "\tStatistics have been cleared\n"); p += scnprintf(buf + p, bufsz - p, "\tOperational Frequency: %s\n", - (le32_to_cpu(priv->_agn.statistics.flag) & - UCODE_STATISTICS_FREQUENCY_MSK) - ? "2.4 GHz" : "5.2 GHz"); + (flag & UCODE_STATISTICS_FREQUENCY_MSK) + ? "2.4 GHz" : "5.2 GHz"); p += scnprintf(buf + p, bufsz - p, "\tTGj Narrow Band: %s\n", - (le32_to_cpu(priv->_agn.statistics.flag) & - UCODE_STATISTICS_NARROW_BAND_MSK) - ? "enabled" : "disabled"); + (flag & UCODE_STATISTICS_NARROW_BAND_MSK) + ? "enabled" : "disabled"); + return p; } @@ -79,22 +82,43 @@ ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf, * the last statistics notification from uCode * might not reflect the current uCode activity */ - ofdm = &priv->_agn.statistics.rx.ofdm; - cck = &priv->_agn.statistics.rx.cck; - general = &priv->_agn.statistics.rx.general; - ht = &priv->_agn.statistics.rx.ofdm_ht; - accum_ofdm = &priv->_agn.accum_statistics.rx.ofdm; - accum_cck = &priv->_agn.accum_statistics.rx.cck; - accum_general = &priv->_agn.accum_statistics.rx.general; - accum_ht = &priv->_agn.accum_statistics.rx.ofdm_ht; - delta_ofdm = &priv->_agn.delta_statistics.rx.ofdm; - delta_cck = &priv->_agn.delta_statistics.rx.cck; - delta_general = &priv->_agn.delta_statistics.rx.general; - delta_ht = &priv->_agn.delta_statistics.rx.ofdm_ht; - max_ofdm = &priv->_agn.max_delta.rx.ofdm; - max_cck = &priv->_agn.max_delta.rx.cck; - max_general = &priv->_agn.max_delta.rx.general; - max_ht = &priv->_agn.max_delta.rx.ofdm_ht; + if (priv->cfg->bt_statistics) { + ofdm = &priv->_agn.statistics_bt.rx.ofdm; + cck = &priv->_agn.statistics_bt.rx.cck; + general = &priv->_agn.statistics_bt.rx.general.common; + ht = &priv->_agn.statistics_bt.rx.ofdm_ht; + accum_ofdm = &priv->_agn.accum_statistics_bt.rx.ofdm; + accum_cck = &priv->_agn.accum_statistics_bt.rx.cck; + accum_general = + &priv->_agn.accum_statistics_bt.rx.general.common; + accum_ht = &priv->_agn.accum_statistics_bt.rx.ofdm_ht; + delta_ofdm = &priv->_agn.delta_statistics_bt.rx.ofdm; + delta_cck = &priv->_agn.delta_statistics_bt.rx.cck; + delta_general = + &priv->_agn.delta_statistics_bt.rx.general.common; + delta_ht = &priv->_agn.delta_statistics_bt.rx.ofdm_ht; + max_ofdm = &priv->_agn.max_delta_bt.rx.ofdm; + max_cck = &priv->_agn.max_delta_bt.rx.cck; + max_general = &priv->_agn.max_delta_bt.rx.general.common; + max_ht = &priv->_agn.max_delta_bt.rx.ofdm_ht; + } else { + ofdm = &priv->_agn.statistics.rx.ofdm; + cck = &priv->_agn.statistics.rx.cck; + general = &priv->_agn.statistics.rx.general; + ht = &priv->_agn.statistics.rx.ofdm_ht; + accum_ofdm = &priv->_agn.accum_statistics.rx.ofdm; + accum_cck = &priv->_agn.accum_statistics.rx.cck; + accum_general = &priv->_agn.accum_statistics.rx.general; + accum_ht = &priv->_agn.accum_statistics.rx.ofdm_ht; + delta_ofdm = &priv->_agn.delta_statistics.rx.ofdm; + delta_cck = &priv->_agn.delta_statistics.rx.cck; + delta_general = &priv->_agn.delta_statistics.rx.general; + delta_ht = &priv->_agn.delta_statistics.rx.ofdm_ht; + max_ofdm = &priv->_agn.max_delta.rx.ofdm; + max_cck = &priv->_agn.max_delta.rx.cck; + max_general = &priv->_agn.max_delta.rx.general; + max_ht = &priv->_agn.max_delta.rx.ofdm_ht; + } pos += iwl_statistics_flag(priv, buf, bufsz); pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" @@ -560,10 +584,18 @@ ssize_t iwl_ucode_tx_stats_read(struct file *file, * the last statistics notification from uCode * might not reflect the current uCode activity */ - tx = &priv->_agn.statistics.tx; - accum_tx = &priv->_agn.accum_statistics.tx; - delta_tx = &priv->_agn.delta_statistics.tx; - max_tx = &priv->_agn.max_delta.tx; + if (priv->cfg->bt_statistics) { + tx = &priv->_agn.statistics_bt.tx; + accum_tx = &priv->_agn.accum_statistics_bt.tx; + delta_tx = &priv->_agn.delta_statistics_bt.tx; + max_tx = &priv->_agn.max_delta_bt.tx; + } else { + tx = &priv->_agn.statistics.tx; + accum_tx = &priv->_agn.accum_statistics.tx; + delta_tx = &priv->_agn.delta_statistics.tx; + max_tx = &priv->_agn.max_delta.tx; + } + pos += iwl_statistics_flag(priv, buf, bufsz); pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" "acumulative delta max\n", @@ -759,8 +791,8 @@ ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf, char *buf; int bufsz = sizeof(struct statistics_general) * 10 + 300; ssize_t ret; - struct statistics_general *general, *accum_general; - struct statistics_general *delta_general, *max_general; + struct statistics_general_common *general, *accum_general; + struct statistics_general_common *delta_general, *max_general; struct statistics_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg; struct statistics_div *div, *accum_div, *delta_div, *max_div; @@ -777,18 +809,34 @@ ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf, * the last statistics notification from uCode * might not reflect the current uCode activity */ - general = &priv->_agn.statistics.general; - dbg = &priv->_agn.statistics.general.dbg; - div = &priv->_agn.statistics.general.div; - accum_general = &priv->_agn.accum_statistics.general; - delta_general = &priv->_agn.delta_statistics.general; - max_general = &priv->_agn.max_delta.general; - accum_dbg = &priv->_agn.accum_statistics.general.dbg; - delta_dbg = &priv->_agn.delta_statistics.general.dbg; - max_dbg = &priv->_agn.max_delta.general.dbg; - accum_div = &priv->_agn.accum_statistics.general.div; - delta_div = &priv->_agn.delta_statistics.general.div; - max_div = &priv->_agn.max_delta.general.div; + if (priv->cfg->bt_statistics) { + general = &priv->_agn.statistics_bt.general.common; + dbg = &priv->_agn.statistics_bt.general.common.dbg; + div = &priv->_agn.statistics_bt.general.common.div; + accum_general = &priv->_agn.accum_statistics_bt.general.common; + accum_dbg = &priv->_agn.accum_statistics_bt.general.common.dbg; + accum_div = &priv->_agn.accum_statistics_bt.general.common.div; + delta_general = &priv->_agn.delta_statistics_bt.general.common; + max_general = &priv->_agn.max_delta_bt.general.common; + delta_dbg = &priv->_agn.delta_statistics_bt.general.common.dbg; + max_dbg = &priv->_agn.max_delta_bt.general.common.dbg; + delta_div = &priv->_agn.delta_statistics_bt.general.common.div; + max_div = &priv->_agn.max_delta_bt.general.common.div; + } else { + general = &priv->_agn.statistics.general.common; + dbg = &priv->_agn.statistics.general.common.dbg; + div = &priv->_agn.statistics.general.common.div; + accum_general = &priv->_agn.accum_statistics.general.common; + accum_dbg = &priv->_agn.accum_statistics.general.common.dbg; + accum_div = &priv->_agn.accum_statistics.general.common.div; + delta_general = &priv->_agn.delta_statistics.general.common; + max_general = &priv->_agn.max_delta.general.common; + delta_dbg = &priv->_agn.delta_statistics.general.common.dbg; + max_dbg = &priv->_agn.max_delta.general.common.dbg; + delta_div = &priv->_agn.delta_statistics.general.common.div; + max_div = &priv->_agn.max_delta.general.common.div; + } + pos += iwl_statistics_flag(priv, buf, bufsz); pos += scnprintf(buf + pos, bufsz - pos, "%-32s current" "acumulative delta max\n", @@ -876,3 +924,90 @@ ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf, kfree(buf); return ret; } + +ssize_t iwl_ucode_bt_stats_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct iwl_priv *priv = (struct iwl_priv *)file->private_data; + int pos = 0; + char *buf; + int bufsz = (sizeof(struct statistics_bt_activity) * 24) + 200; + ssize_t ret; + struct statistics_bt_activity *bt, *accum_bt; + + if (!iwl_is_alive(priv)) + return -EAGAIN; + + /* make request to uCode to retrieve statistics information */ + mutex_lock(&priv->mutex); + ret = iwl_send_statistics_request(priv, CMD_SYNC, false); + mutex_unlock(&priv->mutex); + + if (ret) { + IWL_ERR(priv, + "Error sending statistics request: %zd\n", ret); + return -EAGAIN; + } + buf = kzalloc(bufsz, GFP_KERNEL); + if (!buf) { + IWL_ERR(priv, "Can not allocate Buffer\n"); + return -ENOMEM; + } + + /* + * the statistic information display here is based on + * the last statistics notification from uCode + * might not reflect the current uCode activity + */ + bt = &priv->_agn.statistics_bt.general.activity; + accum_bt = &priv->_agn.accum_statistics_bt.general.activity; + + pos += iwl_statistics_flag(priv, buf, bufsz); + pos += scnprintf(buf + pos, bufsz - pos, "Statistics_BT:\n"); + pos += scnprintf(buf + pos, bufsz - pos, + "\t\t\tcurrent\t\t\taccumulative\n"); + pos += scnprintf(buf + pos, bufsz - pos, + "hi_priority_tx_req_cnt:\t\t%u\t\t\t%u\n", + le32_to_cpu(bt->hi_priority_tx_req_cnt), + accum_bt->hi_priority_tx_req_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + "hi_priority_tx_denied_cnt:\t%u\t\t\t%u\n", + le32_to_cpu(bt->hi_priority_tx_denied_cnt), + accum_bt->hi_priority_tx_denied_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + "lo_priority_tx_req_cnt:\t\t%u\t\t\t%u\n", + le32_to_cpu(bt->lo_priority_tx_req_cnt), + accum_bt->lo_priority_tx_req_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + "lo_priority_rx_denied_cnt:\t%u\t\t\t%u\n", + le32_to_cpu(bt->lo_priority_tx_denied_cnt), + accum_bt->lo_priority_tx_denied_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + "hi_priority_rx_req_cnt:\t\t%u\t\t\t%u\n", + le32_to_cpu(bt->hi_priority_rx_req_cnt), + accum_bt->hi_priority_rx_req_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + "hi_priority_rx_denied_cnt:\t%u\t\t\t%u\n", + le32_to_cpu(bt->hi_priority_rx_denied_cnt), + accum_bt->hi_priority_rx_denied_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + "lo_priority_rx_req_cnt:\t\t%u\t\t\t%u\n", + le32_to_cpu(bt->lo_priority_rx_req_cnt), + accum_bt->lo_priority_rx_req_cnt); + pos += scnprintf(buf + pos, bufsz - pos, + "lo_priority_rx_denied_cnt:\t%u\t\t\t%u\n", + le32_to_cpu(bt->lo_priority_rx_denied_cnt), + accum_bt->lo_priority_rx_denied_cnt); + + pos += scnprintf(buf + pos, bufsz - pos, + "(rx)num_bt_kills:\t\t%u\t\t\t%u\n", + le32_to_cpu(priv->_agn.statistics_bt.rx. + general.num_bt_kills), + priv->_agn.accum_statistics_bt.rx. + general.num_bt_kills); + + ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); + kfree(buf); + return ret; +} diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h index 59b1f25..bbdce59 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.h @@ -37,6 +37,8 @@ ssize_t iwl_ucode_tx_stats_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos); ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos); +ssize_t iwl_ucode_bt_stats_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos); #else static ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) @@ -53,4 +55,9 @@ static ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user { return 0; } +static ssize_t iwl_ucode_bt_stats_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + return 0; +} #endif diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c index f06d1fe..a7216dd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c @@ -164,7 +164,7 @@ static void iwlagn_gain_computation(struct iwl_priv *priv, memset(&cmd, 0, sizeof(cmd)); - cmd.hdr.op_code = IWL_PHY_CALIBRATE_CHAIN_NOISE_GAIN_CMD; + cmd.hdr.op_code = priv->_agn.phy_calib_chain_noise_gain_cmd; cmd.hdr.first_group = 0; cmd.hdr.groups_num = 1; cmd.hdr.data_valid = 1; @@ -197,7 +197,7 @@ static void iwlagn_chain_noise_reset(struct iwl_priv *priv) data->beacon_count = 0; memset(&cmd, 0, sizeof(cmd)); - cmd.hdr.op_code = IWL_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD; + cmd.hdr.op_code = priv->_agn.phy_calib_chain_noise_reset_cmd; cmd.hdr.first_group = 0; cmd.hdr.groups_num = 1; cmd.hdr.data_valid = 1; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 74623e0..a1b6d20 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -364,7 +364,7 @@ void iwlagn_temperature(struct iwl_priv *priv) { /* store temperature from statistics (in Celsius) */ priv->temperature = - le32_to_cpu(priv->_agn.statistics.general.temperature); + le32_to_cpu(priv->_agn.statistics.general.common.temperature); iwl_tt_handler(priv); } @@ -1234,7 +1234,10 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) IWL_DEBUG_INFO(priv, "Scanning while associated...\n"); spin_lock_irqsave(&priv->lock, flags); - interval = vif ? vif->bss_conf.beacon_int : 0; + if (priv->is_internal_short_scan) + interval = 0; + else + interval = vif->bss_conf.beacon_int; spin_unlock_irqrestore(&priv->lock, flags); scan->suspend_time = 0; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c index d54edc3..9490ece 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c @@ -67,17 +67,22 @@ void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, * exactly when to expect beacons, therefore only when we're associated. */ static void iwl_rx_calc_noise(struct iwl_priv *priv) { - struct statistics_rx_non_phy *rx_info - = &(priv->_agn.statistics.rx.general); + struct statistics_rx_non_phy *rx_info; int num_active_rx = 0; int total_silence = 0; - int bcn_silence_a = + int bcn_silence_a, bcn_silence_b, bcn_silence_c; + int last_rx_noise; + + if (priv->cfg->bt_statistics) + rx_info = &(priv->_agn.statistics_bt.rx.general.common); + else + rx_info = &(priv->_agn.statistics.rx.general); + bcn_silence_a = le32_to_cpu(rx_info->beacon_silence_rssi_a) & IN_BAND_FILTER; - int bcn_silence_b = + bcn_silence_b = le32_to_cpu(rx_info->beacon_silence_rssi_b) & IN_BAND_FILTER; - int bcn_silence_c = + bcn_silence_c = le32_to_cpu(rx_info->beacon_silence_rssi_c) & IN_BAND_FILTER; - int last_rx_noise; if (bcn_silence_a) { total_silence += bcn_silence_a; @@ -112,17 +117,35 @@ static void iwl_rx_calc_noise(struct iwl_priv *priv) static void iwl_accumulative_statistics(struct iwl_priv *priv, __le32 *stats) { - int i; + int i, size; __le32 *prev_stats; u32 *accum_stats; u32 *delta, *max_delta; + struct statistics_general_common *general, *accum_general; + struct statistics_tx *tx, *accum_tx; - prev_stats = (__le32 *)&priv->_agn.statistics; - accum_stats = (u32 *)&priv->_agn.accum_statistics; - delta = (u32 *)&priv->_agn.delta_statistics; - max_delta = (u32 *)&priv->_agn.max_delta; - - for (i = sizeof(__le32); i < sizeof(struct iwl_notif_statistics); + if (priv->cfg->bt_statistics) { + prev_stats = (__le32 *)&priv->_agn.statistics_bt; + accum_stats = (u32 *)&priv->_agn.accum_statistics_bt; + size = sizeof(struct iwl_bt_notif_statistics); + general = &priv->_agn.statistics_bt.general.common; + accum_general = &priv->_agn.accum_statistics_bt.general.common; + tx = &priv->_agn.statistics_bt.tx; + accum_tx = &priv->_agn.accum_statistics_bt.tx; + delta = (u32 *)&priv->_agn.delta_statistics_bt; + max_delta = (u32 *)&priv->_agn.max_delta_bt; + } else { + prev_stats = (__le32 *)&priv->_agn.statistics; + accum_stats = (u32 *)&priv->_agn.accum_statistics; + size = sizeof(struct iwl_notif_statistics); + general = &priv->_agn.statistics.general.common; + accum_general = &priv->_agn.accum_statistics.general.common; + tx = &priv->_agn.statistics.tx; + accum_tx = &priv->_agn.accum_statistics.tx; + delta = (u32 *)&priv->_agn.delta_statistics; + max_delta = (u32 *)&priv->_agn.max_delta; + } + for (i = sizeof(__le32); i < size; i += sizeof(__le32), stats++, prev_stats++, delta++, max_delta++, accum_stats++) { if (le32_to_cpu(*stats) > le32_to_cpu(*prev_stats)) { @@ -135,18 +158,12 @@ static void iwl_accumulative_statistics(struct iwl_priv *priv, } /* reset accumulative statistics for "no-counter" type statistics */ - priv->_agn.accum_statistics.general.temperature = - priv->_agn.statistics.general.temperature; - priv->_agn.accum_statistics.general.temperature_m = - priv->_agn.statistics.general.temperature_m; - priv->_agn.accum_statistics.general.ttl_timestamp = - priv->_agn.statistics.general.ttl_timestamp; - priv->_agn.accum_statistics.tx.tx_power.ant_a = - priv->_agn.statistics.tx.tx_power.ant_a; - priv->_agn.accum_statistics.tx.tx_power.ant_b = - priv->_agn.statistics.tx.tx_power.ant_b; - priv->_agn.accum_statistics.tx.tx_power.ant_c = - priv->_agn.statistics.tx.tx_power.ant_c; + accum_general->temperature = general->temperature; + accum_general->temperature_m = general->temperature_m; + accum_general->ttl_timestamp = general->ttl_timestamp; + accum_tx->tx_power.ant_a = tx->tx_power.ant_a; + accum_tx->tx_power.ant_b = tx->tx_power.ant_b; + accum_tx->tx_power.ant_c = tx->tx_power.ant_c; } #endif @@ -185,11 +202,30 @@ bool iwl_good_plcp_health(struct iwl_priv *priv, * by zero. */ if (plcp_msec) { - combined_plcp_delta = - (le32_to_cpu(pkt->u.stats.rx.ofdm.plcp_err) - - le32_to_cpu(priv->_agn.statistics.rx.ofdm.plcp_err)) + - (le32_to_cpu(pkt->u.stats.rx.ofdm_ht.plcp_err) - - le32_to_cpu(priv->_agn.statistics.rx.ofdm_ht.plcp_err)); + struct statistics_rx_phy *ofdm; + struct statistics_rx_ht_phy *ofdm_ht; + + if (priv->cfg->bt_statistics) { + ofdm = &pkt->u.stats_bt.rx.ofdm; + ofdm_ht = &pkt->u.stats_bt.rx.ofdm_ht; + combined_plcp_delta = + (le32_to_cpu(ofdm->plcp_err) - + le32_to_cpu(priv->_agn.statistics_bt. + rx.ofdm.plcp_err)) + + (le32_to_cpu(ofdm_ht->plcp_err) - + le32_to_cpu(priv->_agn.statistics_bt. + rx.ofdm_ht.plcp_err)); + } else { + ofdm = &pkt->u.stats.rx.ofdm; + ofdm_ht = &pkt->u.stats.rx.ofdm_ht; + combined_plcp_delta = + (le32_to_cpu(ofdm->plcp_err) - + le32_to_cpu(priv->_agn.statistics. + rx.ofdm.plcp_err)) + + (le32_to_cpu(ofdm_ht->plcp_err) - + le32_to_cpu(priv->_agn.statistics. + rx.ofdm_ht.plcp_err)); + } if ((combined_plcp_delta > 0) && ((combined_plcp_delta * 100) / plcp_msec) > @@ -206,15 +242,14 @@ bool iwl_good_plcp_health(struct iwl_priv *priv, * plcp_msec */ IWL_DEBUG_RADIO(priv, "plcp_err exceeded %u, " - "%u, %u, %u, %u, %d, %u mSecs\n", - priv->cfg->plcp_delta_threshold, - le32_to_cpu(pkt->u.stats.rx.ofdm.plcp_err), - le32_to_cpu( - priv->_agn.statistics.rx.ofdm.plcp_err), - le32_to_cpu(pkt->u.stats.rx.ofdm_ht.plcp_err), - le32_to_cpu( - priv->_agn.statistics.rx.ofdm_ht.plcp_err), - combined_plcp_delta, plcp_msec); + "%u, %u, %u, %u, %d, %u mSecs\n", + priv->cfg->plcp_delta_threshold, + le32_to_cpu(ofdm->plcp_err), + le32_to_cpu(ofdm->plcp_err), + le32_to_cpu(ofdm_ht->plcp_err), + le32_to_cpu(ofdm_ht->plcp_err), + combined_plcp_delta, plcp_msec); + rc = false; } } @@ -227,24 +262,50 @@ void iwl_rx_statistics(struct iwl_priv *priv, int change; struct iwl_rx_packet *pkt = rxb_addr(rxb); + if (priv->cfg->bt_statistics) { + IWL_DEBUG_RX(priv, + "Statistics notification received (%d vs %d).\n", + (int)sizeof(struct iwl_bt_notif_statistics), + le32_to_cpu(pkt->len_n_flags) & + FH_RSCSR_FRAME_SIZE_MSK); - IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", - (int)sizeof(priv->_agn.statistics), - le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK); + change = ((priv->_agn.statistics_bt.general.common.temperature != + pkt->u.stats_bt.general.common.temperature) || + ((priv->_agn.statistics_bt.flag & + STATISTICS_REPLY_FLG_HT40_MODE_MSK) != + (pkt->u.stats_bt.flag & + STATISTICS_REPLY_FLG_HT40_MODE_MSK))); +#ifdef CONFIG_IWLWIFI_DEBUGFS + iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats_bt); +#endif - change = ((priv->_agn.statistics.general.temperature != - pkt->u.stats.general.temperature) || - ((priv->_agn.statistics.flag & - STATISTICS_REPLY_FLG_HT40_MODE_MSK) != - (pkt->u.stats.flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK))); + } else { + IWL_DEBUG_RX(priv, + "Statistics notification received (%d vs %d).\n", + (int)sizeof(struct iwl_notif_statistics), + le32_to_cpu(pkt->len_n_flags) & + FH_RSCSR_FRAME_SIZE_MSK); + change = ((priv->_agn.statistics.general.common.temperature != + pkt->u.stats.general.common.temperature) || + ((priv->_agn.statistics.flag & + STATISTICS_REPLY_FLG_HT40_MODE_MSK) != + (pkt->u.stats.flag & + STATISTICS_REPLY_FLG_HT40_MODE_MSK))); #ifdef CONFIG_IWLWIFI_DEBUGFS - iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats); + iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats); #endif + + } + iwl_recover_from_statistics(priv, pkt); - memcpy(&priv->_agn.statistics, &pkt->u.stats, - sizeof(priv->_agn.statistics)); + if (priv->cfg->bt_statistics) + memcpy(&priv->_agn.statistics_bt, &pkt->u.stats_bt, + sizeof(priv->_agn.statistics_bt)); + else + memcpy(&priv->_agn.statistics, &pkt->u.stats, + sizeof(priv->_agn.statistics)); set_bit(STATUS_STATISTICS, &priv->status); @@ -277,6 +338,12 @@ void iwl_reply_statistics(struct iwl_priv *priv, sizeof(struct iwl_notif_statistics)); memset(&priv->_agn.max_delta, 0, sizeof(struct iwl_notif_statistics)); + memset(&priv->_agn.accum_statistics_bt, 0, + sizeof(struct iwl_bt_notif_statistics)); + memset(&priv->_agn.delta_statistics_bt, 0, + sizeof(struct iwl_bt_notif_statistics)); + memset(&priv->_agn.max_delta_bt, 0, + sizeof(struct iwl_bt_notif_statistics)); #endif IWL_DEBUG_RX(priv, "Statistics have been cleared\n"); } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 7391c63..35337b1e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -27,6 +27,8 @@ * *****************************************************************************/ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> @@ -292,9 +294,7 @@ static u32 iwl_fill_beacon_frame(struct iwl_priv *priv, struct ieee80211_hdr *hdr, int left) { - if (!iwl_is_associated(priv) || !priv->ibss_beacon || - ((priv->iw_mode != NL80211_IFTYPE_ADHOC) && - (priv->iw_mode != NL80211_IFTYPE_AP))) + if (!priv->ibss_beacon) return 0; if (priv->ibss_beacon->len > left) @@ -1692,6 +1692,7 @@ static void iwl_nic_start(struct iwl_priv *priv) struct iwlagn_ucode_capabilities { u32 max_probe_length; + u32 standard_phy_calibration_size; }; static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context); @@ -1827,7 +1828,6 @@ static int iwlagn_load_firmware(struct iwl_priv *priv, u32 tlv_len; enum iwl_ucode_tlv_type tlv_type; const u8 *tlv_data; - int ret = 0; if (len < sizeof(*ucode)) { IWL_ERR(priv, "uCode has invalid length: %zd\n", len); @@ -1863,9 +1863,8 @@ static int iwlagn_load_firmware(struct iwl_priv *priv, len -= sizeof(*ucode); - while (len >= sizeof(*tlv) && !ret) { + while (len >= sizeof(*tlv)) { u16 tlv_alt; - u32 fixed_tlv_size = 4; len -= sizeof(*tlv); tlv = (void *)data; @@ -1913,59 +1912,57 @@ static int iwlagn_load_firmware(struct iwl_priv *priv, pieces->boot_size = tlv_len; break; case IWL_UCODE_TLV_PROBE_MAX_LEN: - if (tlv_len != fixed_tlv_size) - ret = -EINVAL; - else - capa->max_probe_length = + if (tlv_len != sizeof(u32)) + goto invalid_tlv_len; + capa->max_probe_length = le32_to_cpup((__le32 *)tlv_data); break; case IWL_UCODE_TLV_INIT_EVTLOG_PTR: - if (tlv_len != fixed_tlv_size) - ret = -EINVAL; - else - pieces->init_evtlog_ptr = + if (tlv_len != sizeof(u32)) + goto invalid_tlv_len; + pieces->init_evtlog_ptr = le32_to_cpup((__le32 *)tlv_data); break; case IWL_UCODE_TLV_INIT_EVTLOG_SIZE: - if (tlv_len != fixed_tlv_size) - ret = -EINVAL; - else - pieces->init_evtlog_size = + if (tlv_len != sizeof(u32)) + goto invalid_tlv_len; + pieces->init_evtlog_size = le32_to_cpup((__le32 *)tlv_data); break; case IWL_UCODE_TLV_INIT_ERRLOG_PTR: - if (tlv_len != fixed_tlv_size) - ret = -EINVAL; - else - pieces->init_errlog_ptr = + if (tlv_len != sizeof(u32)) + goto invalid_tlv_len; + pieces->init_errlog_ptr = le32_to_cpup((__le32 *)tlv_data); break; case IWL_UCODE_TLV_RUNT_EVTLOG_PTR: - if (tlv_len != fixed_tlv_size) - ret = -EINVAL; - else - pieces->inst_evtlog_ptr = + if (tlv_len != sizeof(u32)) + goto invalid_tlv_len; + pieces->inst_evtlog_ptr = le32_to_cpup((__le32 *)tlv_data); break; case IWL_UCODE_TLV_RUNT_EVTLOG_SIZE: - if (tlv_len != fixed_tlv_size) - ret = -EINVAL; - else - pieces->inst_evtlog_size = + if (tlv_len != sizeof(u32)) + goto invalid_tlv_len; + pieces->inst_evtlog_size = le32_to_cpup((__le32 *)tlv_data); break; case IWL_UCODE_TLV_RUNT_ERRLOG_PTR: - if (tlv_len != fixed_tlv_size) - ret = -EINVAL; - else - pieces->inst_errlog_ptr = + if (tlv_len != sizeof(u32)) + goto invalid_tlv_len; + pieces->inst_errlog_ptr = le32_to_cpup((__le32 *)tlv_data); break; case IWL_UCODE_TLV_ENHANCE_SENS_TBL: if (tlv_len) - ret = -EINVAL; - else - priv->enhance_sensitivity_table = true; + goto invalid_tlv_len; + priv->enhance_sensitivity_table = true; + break; + case IWL_UCODE_TLV_PHY_CALIBRATION_SIZE: + if (tlv_len != sizeof(u32)) + goto invalid_tlv_len; + capa->standard_phy_calibration_size = + le32_to_cpup((__le32 *)tlv_data); break; default: IWL_WARN(priv, "unknown TLV: %d\n", tlv_type); @@ -1976,14 +1973,16 @@ static int iwlagn_load_firmware(struct iwl_priv *priv, if (len) { IWL_ERR(priv, "invalid TLV after parsing: %zd\n", len); iwl_print_hex_dump(priv, IWL_DL_FW, (u8 *)data, len); - ret = -EINVAL; - } else if (ret) { - IWL_ERR(priv, "TLV %d has invalid size: %u\n", - tlv_type, tlv_len); - iwl_print_hex_dump(priv, IWL_DL_FW, (u8 *)tlv_data, tlv_len); + return -EINVAL; } - return ret; + return 0; + + invalid_tlv_len: + IWL_ERR(priv, "TLV %d has invalid size: %u\n", tlv_type, tlv_len); + iwl_print_hex_dump(priv, IWL_DL_FW, tlv_data, tlv_len); + + return -EINVAL; } /** @@ -2005,6 +2004,8 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) u32 build; struct iwlagn_ucode_capabilities ucode_capa = { .max_probe_length = 200, + .standard_phy_calibration_size = + IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE, }; memset(&pieces, 0, sizeof(pieces)); @@ -2226,6 +2227,20 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) pieces.boot_size); memcpy(priv->ucode_boot.v_addr, pieces.boot, pieces.boot_size); + /* + * figure out the offset of chain noise reset and gain commands + * base on the size of standard phy calibration commands table size + */ + if (ucode_capa.standard_phy_calibration_size > + IWL_MAX_PHY_CALIBRATE_TBL_SIZE) + ucode_capa.standard_phy_calibration_size = + IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE; + + priv->_agn.phy_calib_chain_noise_reset_cmd = + ucode_capa.standard_phy_calibration_size; + priv->_agn.phy_calib_chain_noise_gain_cmd = + ucode_capa.standard_phy_calibration_size + 1; + /************************************************** * This is still part of probe() in a sense... * @@ -3008,9 +3023,17 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work) } if (priv->start_calib) { - iwl_chain_noise_calibration(priv, &priv->_agn.statistics); - - iwl_sensitivity_calibration(priv, &priv->_agn.statistics); + if (priv->cfg->bt_statistics) { + iwl_chain_noise_calibration(priv, + (void *)&priv->_agn.statistics_bt); + iwl_sensitivity_calibration(priv, + (void *)&priv->_agn.statistics_bt); + } else { + iwl_chain_noise_calibration(priv, + (void *)&priv->_agn.statistics); + iwl_sensitivity_calibration(priv, + (void *)&priv->_agn.statistics); + } } mutex_unlock(&priv->mutex); @@ -3909,8 +3932,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) struct ieee80211_hw *hw; struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); unsigned long flags; - u16 pci_cmd; - u8 perm_addr[ETH_ALEN]; + u16 pci_cmd, num_mac; /************************ * 1. Allocating HW data @@ -4028,9 +4050,17 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto out_free_eeprom; /* extract MAC Address */ - iwl_eeprom_get_mac(priv, perm_addr); - IWL_DEBUG_INFO(priv, "MAC address: %pM\n", perm_addr); - SET_IEEE80211_PERM_ADDR(priv->hw, perm_addr); + iwl_eeprom_get_mac(priv, priv->addresses[0].addr); + IWL_DEBUG_INFO(priv, "MAC address: %pM\n", priv->addresses[0].addr); + priv->hw->wiphy->addresses = priv->addresses; + priv->hw->wiphy->n_addresses = 1; + num_mac = iwl_eeprom_query16(priv, EEPROM_NUM_MAC_ADDRESS); + if (num_mac > 1) { + memcpy(priv->addresses[1].addr, priv->addresses[0].addr, + ETH_ALEN); + priv->addresses[1].addr[5]++; + priv->hw->wiphy->n_addresses++; + } /************************ * 5. Setup HW constants @@ -4389,19 +4419,18 @@ static int __init iwl_init(void) { int ret; - printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n"); - printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n"); + pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n"); + pr_info(DRV_COPYRIGHT "\n"); ret = iwlagn_rate_control_register(); if (ret) { - printk(KERN_ERR DRV_NAME - "Unable to register rate control algorithm: %d\n", ret); + pr_err("Unable to register rate control algorithm: %d\n", ret); return ret; } ret = pci_register_driver(&iwl_driver); if (ret) { - printk(KERN_ERR DRV_NAME "Unable to initialize PCI module\n"); + pr_err("Unable to initialize PCI module\n"); goto error_register; } diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.h b/drivers/net/wireless/iwlwifi/iwl-calib.h index 2b7b1df..ba9523f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-calib.h +++ b/drivers/net/wireless/iwlwifi/iwl-calib.h @@ -66,10 +66,8 @@ #include "iwl-core.h" #include "iwl-commands.h" -void iwl_chain_noise_calibration(struct iwl_priv *priv, - struct iwl_notif_statistics *stat_resp); -void iwl_sensitivity_calibration(struct iwl_priv *priv, - struct iwl_notif_statistics *resp); +void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp); +void iwl_sensitivity_calibration(struct iwl_priv *priv, void *resp); void iwl_init_sensitivity(struct iwl_priv *priv); void iwl_reset_run_time_calib(struct iwl_priv *priv); diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index bd1ec93..60725a5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -964,8 +964,8 @@ struct iwl_qosparam_cmd { #define IWL_STATION_COUNT 32 /* MAX(3945,4965)*/ #define IWL_INVALID_STATION 255 -#define STA_FLG_TX_RATE_MSK cpu_to_le32(1 << 2); -#define STA_FLG_PWR_SAVE_MSK cpu_to_le32(1 << 8); +#define STA_FLG_TX_RATE_MSK cpu_to_le32(1 << 2) +#define STA_FLG_PWR_SAVE_MSK cpu_to_le32(1 << 8) #define STA_FLG_RTS_MIMO_PROT_MSK cpu_to_le32(1 << 17) #define STA_FLG_AGG_MPDU_8US_MSK cpu_to_le32(1 << 18) #define STA_FLG_MAX_AGG_SIZE_POS (19) @@ -3127,6 +3127,13 @@ struct statistics_rx_non_phy { __le32 beacon_energy_c; } __packed; +struct statistics_rx_non_phy_bt { + struct statistics_rx_non_phy common; + /* additional stats for bt */ + __le32 num_bt_kills; + __le32 reserved[2]; +} __packed; + struct statistics_rx { struct statistics_rx_phy ofdm; struct statistics_rx_phy cck; @@ -3134,6 +3141,13 @@ struct statistics_rx { struct statistics_rx_ht_phy ofdm_ht; } __packed; +struct statistics_rx_bt { + struct statistics_rx_phy ofdm; + struct statistics_rx_phy cck; + struct statistics_rx_non_phy_bt general; + struct statistics_rx_ht_phy ofdm_ht; +} __packed; + /** * struct statistics_tx_power - current tx power * @@ -3196,7 +3210,7 @@ struct statistics_div { __le32 reserved2; } __packed; -struct statistics_general { +struct statistics_general_common { __le32 temperature; /* radio temperature */ __le32 temperature_m; /* for 5000 and up, this is radio voltage */ struct statistics_dbg dbg; @@ -3212,6 +3226,30 @@ struct statistics_general { * in order to get out of bad PHY status */ __le32 num_of_sos_states; +} __packed; + +struct statistics_bt_activity { + /* Tx statistics */ + __le32 hi_priority_tx_req_cnt; + __le32 hi_priority_tx_denied_cnt; + __le32 lo_priority_tx_req_cnt; + __le32 lo_priority_tx_denied_cnt; + /* Rx statistics */ + __le32 hi_priority_rx_req_cnt; + __le32 hi_priority_rx_denied_cnt; + __le32 lo_priority_rx_req_cnt; + __le32 lo_priority_rx_denied_cnt; +} __packed; + +struct statistics_general { + struct statistics_general_common common; + __le32 reserved2; + __le32 reserved3; +} __packed; + +struct statistics_general_bt { + struct statistics_general_common common; + struct statistics_bt_activity activity; __le32 reserved2; __le32 reserved3; } __packed; @@ -3273,6 +3311,12 @@ struct iwl_notif_statistics { struct statistics_general general; } __packed; +struct iwl_bt_notif_statistics { + __le32 flag; + struct statistics_rx_bt rx; + struct statistics_tx tx; + struct statistics_general_bt general; +} __packed; /* * MISSED_BEACONS_NOTIFICATION = 0xa2 (notification only, not a command) @@ -3616,10 +3660,10 @@ enum { IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD = 15, IWL_PHY_CALIBRATE_BASE_BAND_CMD = 16, IWL_PHY_CALIBRATE_TX_IQ_PERD_CMD = 17, - IWL_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD = 18, - IWL_PHY_CALIBRATE_CHAIN_NOISE_GAIN_CMD = 19, + IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE = 18, }; +#define IWL_MAX_PHY_CALIBRATE_TBL_SIZE (253) #define IWL_CALIB_INIT_CFG_ALL cpu_to_le32(0xffffffff) @@ -3944,6 +3988,7 @@ struct iwl_rx_packet { struct iwl_sleep_notification sleep_notif; struct iwl_spectrum_resp spectrum; struct iwl_notif_statistics stats; + struct iwl_bt_notif_statistics stats_bt; struct iwl_compressed_ba_resp compressed_ba; struct iwl_missed_beacon_notif missed_beacon; struct iwl_coex_medium_notification coex_medium_notif; diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 676d49d..8024d44 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -170,7 +170,7 @@ struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg, struct ieee80211_hw *hw = ieee80211_alloc_hw(sizeof(struct iwl_priv), hw_ops); if (hw == NULL) { - printk(KERN_ERR "%s: Can not allocate network device\n", + pr_err("%s: Can not allocate network device\n", cfg->name); goto out; } @@ -1748,6 +1748,37 @@ static inline void iwl_set_no_assoc(struct iwl_priv *priv) iwlcore_commit_rxon(priv); } +static int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) +{ + struct iwl_priv *priv = hw->priv; + unsigned long flags; + __le64 timestamp; + + IWL_DEBUG_MAC80211(priv, "enter\n"); + + if (!iwl_is_ready_rf(priv)) { + IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n"); + return -EIO; + } + + spin_lock_irqsave(&priv->lock, flags); + + if (priv->ibss_beacon) + dev_kfree_skb(priv->ibss_beacon); + + priv->ibss_beacon = skb; + + timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp; + priv->timestamp = le64_to_cpu(timestamp); + + IWL_DEBUG_MAC80211(priv, "leave\n"); + spin_unlock_irqrestore(&priv->lock, flags); + + priv->cfg->ops->lib->post_associate(priv, priv->vif); + + return 0; +} + void iwl_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf, @@ -1914,38 +1945,6 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, } EXPORT_SYMBOL(iwl_bss_info_changed); -int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) -{ - struct iwl_priv *priv = hw->priv; - unsigned long flags; - __le64 timestamp; - - IWL_DEBUG_MAC80211(priv, "enter\n"); - - if (!iwl_is_ready_rf(priv)) { - IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n"); - return -EIO; - } - - spin_lock_irqsave(&priv->lock, flags); - - if (priv->ibss_beacon) - dev_kfree_skb(priv->ibss_beacon); - - priv->ibss_beacon = skb; - - timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp; - priv->timestamp = le64_to_cpu(timestamp); - - IWL_DEBUG_MAC80211(priv, "leave\n"); - spin_unlock_irqrestore(&priv->lock, flags); - - priv->cfg->ops->lib->post_associate(priv, priv->vif); - - return 0; -} -EXPORT_SYMBOL(iwl_mac_beacon_update); - static int iwl_set_mode(struct iwl_priv *priv, struct ieee80211_vif *vif) { iwl_connection_init_rx_config(priv, vif); diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index fcbba3d..e9d23f2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -125,6 +125,8 @@ struct iwl_debugfs_ops { size_t count, loff_t *ppos); ssize_t (*general_stats_read)(struct file *file, char __user *user_buf, size_t count, loff_t *ppos); + ssize_t (*bt_stats_read)(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos); }; struct iwl_temp_ops { @@ -335,6 +337,7 @@ struct iwl_cfg { u8 scan_rx_antennas[IEEE80211_NUM_BANDS]; u8 scan_tx_antennas[IEEE80211_NUM_BANDS]; const bool need_dc_calib; + const bool bt_statistics; }; /*************************** @@ -377,7 +380,6 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf, u32 changes); -int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb); int iwl_commit_rxon(struct iwl_priv *priv); int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif); diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 7b25d14..e96a1bb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -1519,6 +1519,16 @@ static ssize_t iwl_dbgfs_txfifo_flush_write(struct file *file, return count; } +static ssize_t iwl_dbgfs_ucode_bt_stats_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct iwl_priv *priv = (struct iwl_priv *)file->private_data; + + return priv->cfg->ops->lib->debugfs_ops.bt_stats_read(file, + user_buf, count, ppos); +} + DEBUGFS_READ_FILE_OPS(rx_statistics); DEBUGFS_READ_FILE_OPS(tx_statistics); DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); @@ -1541,6 +1551,7 @@ DEBUGFS_READ_WRITE_FILE_OPS(force_reset); DEBUGFS_READ_FILE_OPS(rxon_flags); DEBUGFS_READ_FILE_OPS(rxon_filter_flags); DEBUGFS_WRITE_FILE_OPS(txfifo_flush); +DEBUGFS_READ_FILE_OPS(ucode_bt_stats); /* * Create the debugfs files and directories @@ -1608,6 +1619,8 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR); if (priv->cfg->ucode_tracing) DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR); + if (priv->cfg->bt_statistics) + DEBUGFS_ADD_FILE(ucode_bt_stats, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR); DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR); if (priv->cfg->sensitivity_calib_by_driver) diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index c4dba62..f35bcad 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -571,6 +571,7 @@ enum iwl_ucode_tlv_type { IWL_UCODE_TLV_INIT_EVTLOG_SIZE = 12, IWL_UCODE_TLV_INIT_ERRLOG_PTR = 13, IWL_UCODE_TLV_ENHANCE_SENS_TBL = 14, + IWL_UCODE_TLV_PHY_CALIBRATION_SIZE = 15, }; struct iwl_ucode_tlv { @@ -1153,6 +1154,9 @@ struct iwl_priv { u32 hw_wa_rev; u8 rev_id; + /* EEPROM MAC addresses */ + struct mac_address addresses[2]; + /* uCode images, save to reload in case of failure */ int fw_index; /* firmware we're trying to load */ u32 ucode_ver; /* version of ucode, copy of @@ -1321,11 +1325,23 @@ struct iwl_priv { u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr; u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr; + /* + * chain noise reset and gain commands are the + * two extra calibration commands follows the standard + * phy calibration commands + */ + u8 phy_calib_chain_noise_reset_cmd; + u8 phy_calib_chain_noise_gain_cmd; + struct iwl_notif_statistics statistics; + struct iwl_bt_notif_statistics statistics_bt; #ifdef CONFIG_IWLWIFI_DEBUGFS struct iwl_notif_statistics accum_statistics; struct iwl_notif_statistics delta_statistics; struct iwl_notif_statistics max_delta; + struct iwl_bt_notif_statistics accum_statistics_bt; + struct iwl_bt_notif_statistics delta_statistics_bt; + struct iwl_bt_notif_statistics max_delta_bt; #endif } _agn; #endif diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h index 3452dfa..a4772af 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h @@ -402,6 +402,7 @@ struct iwl_eeprom_calib_info { #define EEPROM_WOWLAN_MODE (2*0x47) /* 2 bytes */ #define EEPROM_RADIO_CONFIG (2*0x48) /* 2 bytes */ #define EEPROM_3945_M_VERSION (2*0x4A) /* 1 bytes */ +#define EEPROM_NUM_MAC_ADDRESS (2*0x4C) /* 2 bytes */ /* The following masks are to be applied on EEPROM_RADIO_CONFIG */ #define EEPROM_RF_CFG_TYPE_MSK(x) (x & 0x3) /* bits 0-1 */ diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 2a7c399..b0c6b04 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -429,11 +429,10 @@ void iwl_bg_scan_check(struct work_struct *data) return; mutex_lock(&priv->mutex); - if (test_bit(STATUS_SCANNING, &priv->status) || - test_bit(STATUS_SCAN_ABORTING, &priv->status)) { - IWL_DEBUG_SCAN(priv, "Scan completion watchdog resetting " - "adapter (%dms)\n", - jiffies_to_msecs(IWL_SCAN_CHECK_WATCHDOG)); + if (test_bit(STATUS_SCANNING, &priv->status) && + !test_bit(STATUS_SCAN_ABORTING, &priv->status)) { + IWL_DEBUG_SCAN(priv, "Scan completion watchdog (%dms)\n", + jiffies_to_msecs(IWL_SCAN_CHECK_WATCHDOG)); if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) iwl_send_scan_abort(priv); @@ -498,12 +497,11 @@ void iwl_bg_abort_scan(struct work_struct *work) !test_bit(STATUS_GEO_CONFIGURED, &priv->status)) return; - mutex_lock(&priv->mutex); - - cancel_delayed_work_sync(&priv->scan_check); - set_bit(STATUS_SCAN_ABORTING, &priv->status); - iwl_send_scan_abort(priv); + cancel_delayed_work(&priv->scan_check); + mutex_lock(&priv->mutex); + if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) + iwl_send_scan_abort(priv); mutex_unlock(&priv->mutex); } EXPORT_SYMBOL(iwl_bg_abort_scan); diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 8eb3471..d24eb47 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -27,6 +27,8 @@ * *****************************************************************************/ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> @@ -311,9 +313,7 @@ unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv, int left) { - if (!iwl_is_associated(priv) || !priv->ibss_beacon || - ((priv->iw_mode != NL80211_IFTYPE_ADHOC) && - (priv->iw_mode != NL80211_IFTYPE_AP))) + if (!iwl_is_associated(priv) || !priv->ibss_beacon) return 0; if (priv->ibss_beacon->len > left) @@ -2883,7 +2883,10 @@ void iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) IWL_DEBUG_INFO(priv, "Scanning while associated...\n"); spin_lock_irqsave(&priv->lock, flags); - interval = vif ? vif->bss_conf.beacon_int : 0; + if (priv->is_internal_short_scan) + interval = 0; + else + interval = vif->bss_conf.beacon_int; spin_unlock_irqrestore(&priv->lock, flags); scan->suspend_time = 0; @@ -3932,7 +3935,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e * space for this driver's private structure */ hw = iwl_alloc_all(cfg, &iwl3945_hw_ops); if (hw == NULL) { - printk(KERN_ERR DRV_NAME "Can not allocate network device\n"); + pr_err("Can not allocate network device\n"); err = -ENOMEM; goto out; } @@ -4224,19 +4227,18 @@ static int __init iwl3945_init(void) { int ret; - printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n"); - printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n"); + pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n"); + pr_info(DRV_COPYRIGHT "\n"); ret = iwl3945_rate_control_register(); if (ret) { - printk(KERN_ERR DRV_NAME - "Unable to register rate control algorithm: %d\n", ret); + pr_err("Unable to register rate control algorithm: %d\n", ret); return ret; } ret = pci_register_driver(&iwl3945_driver); if (ret) { - printk(KERN_ERR DRV_NAME "Unable to initialize PCI module\n"); + pr_err("Unable to initialize PCI module\n"); goto error_register; } |