aboutsummaryrefslogtreecommitdiffstats
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.c98
1 files changed, 73 insertions, 25 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index d3afddae8d9f..d6531ad3906a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -346,9 +346,19 @@ static void iwl4965_chain_noise_reset(struct iwl_priv *priv)
346{ 346{
347 struct iwl_chain_noise_data *data = &(priv->chain_noise_data); 347 struct iwl_chain_noise_data *data = &(priv->chain_noise_data);
348 348
349 if ((data->state == IWL_CHAIN_NOISE_ALIVE) && iwl_is_associated(priv)) { 349 if ((data->state == IWL_CHAIN_NOISE_ALIVE) &&
350 iwl_is_associated(priv)) {
350 struct iwl_calib_diff_gain_cmd cmd; 351 struct iwl_calib_diff_gain_cmd cmd;
351 352
353 /* clear data for chain noise calibration algorithm */
354 data->chain_noise_a = 0;
355 data->chain_noise_b = 0;
356 data->chain_noise_c = 0;
357 data->chain_signal_a = 0;
358 data->chain_signal_b = 0;
359 data->chain_signal_c = 0;
360 data->beacon_count = 0;
361
352 memset(&cmd, 0, sizeof(cmd)); 362 memset(&cmd, 0, sizeof(cmd));
353 cmd.hdr.op_code = IWL_PHY_CALIBRATE_DIFF_GAIN_CMD; 363 cmd.hdr.op_code = IWL_PHY_CALIBRATE_DIFF_GAIN_CMD;
354 cmd.diff_gain_a = 0; 364 cmd.diff_gain_a = 0;
@@ -419,13 +429,6 @@ static void iwl4965_gain_computation(struct iwl_priv *priv,
419 /* Mark so we run this algo only once! */ 429 /* Mark so we run this algo only once! */
420 data->state = IWL_CHAIN_NOISE_CALIBRATED; 430 data->state = IWL_CHAIN_NOISE_CALIBRATED;
421 } 431 }
422 data->chain_noise_a = 0;
423 data->chain_noise_b = 0;
424 data->chain_noise_c = 0;
425 data->chain_signal_a = 0;
426 data->chain_signal_b = 0;
427 data->chain_signal_c = 0;
428 data->beacon_count = 0;
429} 432}
430 433
431static void iwl4965_bg_txpower_work(struct work_struct *work) 434static void iwl4965_bg_txpower_work(struct work_struct *work)
@@ -669,6 +672,7 @@ static int iwl4965_hw_set_hw_params(struct iwl_priv *priv)
669 priv->cfg->ops->lib->temp_ops.set_ct_kill(priv); 672 priv->cfg->ops->lib->temp_ops.set_ct_kill(priv);
670 673
671 priv->hw_params.sens = &iwl4965_sensitivity; 674 priv->hw_params.sens = &iwl4965_sensitivity;
675 priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS;
672 676
673 return 0; 677 return 0;
674} 678}
@@ -1441,7 +1445,8 @@ static int iwl4965_send_rxon_assoc(struct iwl_priv *priv)
1441 return ret; 1445 return ret;
1442} 1446}
1443 1447
1444static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel) 1448static int iwl4965_hw_channel_switch(struct iwl_priv *priv,
1449 struct ieee80211_channel_switch *ch_switch)
1445{ 1450{
1446 int rc; 1451 int rc;
1447 u8 band = 0; 1452 u8 band = 0;
@@ -1449,11 +1454,14 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel)
1449 u8 ctrl_chan_high = 0; 1454 u8 ctrl_chan_high = 0;
1450 struct iwl4965_channel_switch_cmd cmd; 1455 struct iwl4965_channel_switch_cmd cmd;
1451 const struct iwl_channel_info *ch_info; 1456 const struct iwl_channel_info *ch_info;
1452 1457 u32 switch_time_in_usec, ucode_switch_time;
1458 u16 ch;
1459 u32 tsf_low;
1460 u8 switch_count;
1461 u16 beacon_interval = le16_to_cpu(priv->rxon_timing.beacon_interval);
1462 struct ieee80211_vif *vif = priv->vif;
1453 band = priv->band == IEEE80211_BAND_2GHZ; 1463 band = priv->band == IEEE80211_BAND_2GHZ;
1454 1464
1455 ch_info = iwl_get_channel_info(priv, priv->band, channel);
1456
1457 is_ht40 = is_ht40_channel(priv->staging_rxon.flags); 1465 is_ht40 = is_ht40_channel(priv->staging_rxon.flags);
1458 1466
1459 if (is_ht40 && 1467 if (is_ht40 &&
@@ -1462,26 +1470,56 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel)
1462 1470
1463 cmd.band = band; 1471 cmd.band = band;
1464 cmd.expect_beacon = 0; 1472 cmd.expect_beacon = 0;
1465 cmd.channel = cpu_to_le16(channel); 1473 ch = ieee80211_frequency_to_channel(ch_switch->channel->center_freq);
1474 cmd.channel = cpu_to_le16(ch);
1466 cmd.rxon_flags = priv->staging_rxon.flags; 1475 cmd.rxon_flags = priv->staging_rxon.flags;
1467 cmd.rxon_filter_flags = priv->staging_rxon.filter_flags; 1476 cmd.rxon_filter_flags = priv->staging_rxon.filter_flags;
1468 cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); 1477 switch_count = ch_switch->count;
1478 tsf_low = ch_switch->timestamp & 0x0ffffffff;
1479 /*
1480 * calculate the ucode channel switch time
1481 * adding TSF as one of the factor for when to switch
1482 */
1483 if ((priv->ucode_beacon_time > tsf_low) && beacon_interval) {
1484 if (switch_count > ((priv->ucode_beacon_time - tsf_low) /
1485 beacon_interval)) {
1486 switch_count -= (priv->ucode_beacon_time -
1487 tsf_low) / beacon_interval;
1488 } else
1489 switch_count = 0;
1490 }
1491 if (switch_count <= 1)
1492 cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
1493 else {
1494 switch_time_in_usec =
1495 vif->bss_conf.beacon_int * switch_count * TIME_UNIT;
1496 ucode_switch_time = iwl_usecs_to_beacons(priv,
1497 switch_time_in_usec,
1498 beacon_interval);
1499 cmd.switch_time = iwl_add_beacon_time(priv,
1500 priv->ucode_beacon_time,
1501 ucode_switch_time,
1502 beacon_interval);
1503 }
1504 IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n",
1505 cmd.switch_time);
1506 ch_info = iwl_get_channel_info(priv, priv->band, ch);
1469 if (ch_info) 1507 if (ch_info)
1470 cmd.expect_beacon = is_channel_radar(ch_info); 1508 cmd.expect_beacon = is_channel_radar(ch_info);
1471 else { 1509 else {
1472 IWL_ERR(priv, "invalid channel switch from %u to %u\n", 1510 IWL_ERR(priv, "invalid channel switch from %u to %u\n",
1473 priv->active_rxon.channel, channel); 1511 priv->active_rxon.channel, ch);
1474 return -EFAULT; 1512 return -EFAULT;
1475 } 1513 }
1476 1514
1477 rc = iwl4965_fill_txpower_tbl(priv, band, channel, is_ht40, 1515 rc = iwl4965_fill_txpower_tbl(priv, band, ch, is_ht40,
1478 ctrl_chan_high, &cmd.tx_power); 1516 ctrl_chan_high, &cmd.tx_power);
1479 if (rc) { 1517 if (rc) {
1480 IWL_DEBUG_11H(priv, "error:%d fill txpower_tbl\n", rc); 1518 IWL_DEBUG_11H(priv, "error:%d fill txpower_tbl\n", rc);
1481 return rc; 1519 return rc;
1482 } 1520 }
1483 1521
1484 priv->switch_rxon.channel = cpu_to_le16(channel); 1522 priv->switch_rxon.channel = cmd.channel;
1485 priv->switch_rxon.switch_in_progress = true; 1523 priv->switch_rxon.switch_in_progress = true;
1486 1524
1487 return iwl_send_cmd_pdu(priv, REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd); 1525 return iwl_send_cmd_pdu(priv, REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd);
@@ -1542,7 +1580,8 @@ static int iwl4965_hw_get_temperature(struct iwl_priv *priv)
1542 u32 R4; 1580 u32 R4;
1543 1581
1544 if (test_bit(STATUS_TEMPERATURE, &priv->status) && 1582 if (test_bit(STATUS_TEMPERATURE, &priv->status) &&
1545 (priv->statistics.flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK)) { 1583 (priv->_agn.statistics.flag &
1584 STATISTICS_REPLY_FLG_HT40_MODE_MSK)) {
1546 IWL_DEBUG_TEMP(priv, "Running HT40 temperature calibration\n"); 1585 IWL_DEBUG_TEMP(priv, "Running HT40 temperature calibration\n");
1547 R1 = (s32)le32_to_cpu(priv->card_alive_init.therm_r1[1]); 1586 R1 = (s32)le32_to_cpu(priv->card_alive_init.therm_r1[1]);
1548 R2 = (s32)le32_to_cpu(priv->card_alive_init.therm_r2[1]); 1587 R2 = (s32)le32_to_cpu(priv->card_alive_init.therm_r2[1]);
@@ -1566,8 +1605,8 @@ static int iwl4965_hw_get_temperature(struct iwl_priv *priv)
1566 if (!test_bit(STATUS_TEMPERATURE, &priv->status)) 1605 if (!test_bit(STATUS_TEMPERATURE, &priv->status))
1567 vt = sign_extend(R4, 23); 1606 vt = sign_extend(R4, 23);
1568 else 1607 else
1569 vt = sign_extend( 1608 vt = sign_extend(le32_to_cpu(priv->_agn.statistics.
1570 le32_to_cpu(priv->statistics.general.temperature), 23); 1609 general.common.temperature), 23);
1571 1610
1572 IWL_DEBUG_TEMP(priv, "Calib values R[1-3]: %d %d %d R4: %d\n", R1, R2, R3, vt); 1611 IWL_DEBUG_TEMP(priv, "Calib values R[1-3]: %d %d %d R4: %d\n", R1, R2, R3, vt);
1573 1612
@@ -1747,6 +1786,7 @@ static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id,
1747{ 1786{
1748 unsigned long flags; 1787 unsigned long flags;
1749 u16 ra_tid; 1788 u16 ra_tid;
1789 int ret;
1750 1790
1751 if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) || 1791 if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) ||
1752 (IWL49_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues 1792 (IWL49_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues
@@ -1762,7 +1802,9 @@ static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id,
1762 ra_tid = BUILD_RAxTID(sta_id, tid); 1802 ra_tid = BUILD_RAxTID(sta_id, tid);
1763 1803
1764 /* Modify device's station table to Tx this TID */ 1804 /* Modify device's station table to Tx this TID */
1765 iwl_sta_tx_modify_enable_tid(priv, sta_id, tid); 1805 ret = iwl_sta_tx_modify_enable_tid(priv, sta_id, tid);
1806 if (ret)
1807 return ret;
1766 1808
1767 spin_lock_irqsave(&priv->lock, flags); 1809 spin_lock_irqsave(&priv->lock, flags);
1768 1810
@@ -1870,7 +1912,7 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv,
1870 IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, StartIdx=%d idx=%d\n", 1912 IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, StartIdx=%d idx=%d\n",
1871 agg->frame_count, agg->start_idx, idx); 1913 agg->frame_count, agg->start_idx, idx);
1872 1914
1873 info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]); 1915 info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb);
1874 info->status.rates[0].count = tx_resp->failure_frame + 1; 1916 info->status.rates[0].count = tx_resp->failure_frame + 1;
1875 info->flags &= ~IEEE80211_TX_CTL_AMPDU; 1917 info->flags &= ~IEEE80211_TX_CTL_AMPDU;
1876 info->flags |= iwl_tx_status_to_mac80211(status); 1918 info->flags |= iwl_tx_status_to_mac80211(status);
@@ -2026,6 +2068,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
2026 int sta_id; 2068 int sta_id;
2027 int freed; 2069 int freed;
2028 u8 *qc = NULL; 2070 u8 *qc = NULL;
2071 unsigned long flags;
2029 2072
2030 if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) { 2073 if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) {
2031 IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d " 2074 IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d "
@@ -2035,7 +2078,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
2035 return; 2078 return;
2036 } 2079 }
2037 2080
2038 info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb[0]); 2081 info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb);
2039 memset(&info->status, 0, sizeof(info->status)); 2082 memset(&info->status, 0, sizeof(info->status));
2040 2083
2041 hdr = iwl_tx_queue_get_hdr(priv, txq_id, index); 2084 hdr = iwl_tx_queue_get_hdr(priv, txq_id, index);
@@ -2050,10 +2093,10 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
2050 return; 2093 return;
2051 } 2094 }
2052 2095
2096 spin_lock_irqsave(&priv->sta_lock, flags);
2053 if (txq->sched_retry) { 2097 if (txq->sched_retry) {
2054 const u32 scd_ssn = iwl4965_get_scd_ssn(tx_resp); 2098 const u32 scd_ssn = iwl4965_get_scd_ssn(tx_resp);
2055 struct iwl_ht_agg *agg = NULL; 2099 struct iwl_ht_agg *agg = NULL;
2056
2057 WARN_ON(!qc); 2100 WARN_ON(!qc);
2058 2101
2059 agg = &priv->stations[sta_id].tid[tid].agg; 2102 agg = &priv->stations[sta_id].tid[tid].agg;
@@ -2110,6 +2153,8 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
2110 iwlagn_txq_check_empty(priv, sta_id, tid, txq_id); 2153 iwlagn_txq_check_empty(priv, sta_id, tid, txq_id);
2111 2154
2112 iwl_check_abort_status(priv, tx_resp->frame_count, status); 2155 iwl_check_abort_status(priv, tx_resp->frame_count, status);
2156
2157 spin_unlock_irqrestore(&priv->sta_lock, flags);
2113} 2158}
2114 2159
2115static int iwl4965_calc_rssi(struct iwl_priv *priv, 2160static int iwl4965_calc_rssi(struct iwl_priv *priv,
@@ -2235,11 +2280,14 @@ static struct iwl_lib_ops iwl4965_lib = {
2235 .set_ct_kill = iwl4965_set_ct_threshold, 2280 .set_ct_kill = iwl4965_set_ct_threshold,
2236 }, 2281 },
2237 .manage_ibss_station = iwlagn_manage_ibss_station, 2282 .manage_ibss_station = iwlagn_manage_ibss_station,
2283 .update_bcast_station = iwl_update_bcast_station,
2238 .debugfs_ops = { 2284 .debugfs_ops = {
2239 .rx_stats_read = iwl_ucode_rx_stats_read, 2285 .rx_stats_read = iwl_ucode_rx_stats_read,
2240 .tx_stats_read = iwl_ucode_tx_stats_read, 2286 .tx_stats_read = iwl_ucode_tx_stats_read,
2241 .general_stats_read = iwl_ucode_general_stats_read, 2287 .general_stats_read = iwl_ucode_general_stats_read,
2288 .bt_stats_read = iwl_ucode_bt_stats_read,
2242 }, 2289 },
2290 .recover_from_tx_stall = iwl_bg_monitor_recover,
2243 .check_plcp_health = iwl_good_plcp_health, 2291 .check_plcp_health = iwl_good_plcp_health,
2244}; 2292};
2245 2293
@@ -2285,7 +2333,7 @@ struct iwl_cfg iwl4965_agn_cfg = {
2285 * Force use of chains B and C for scan RX on 5 GHz band 2333 * Force use of chains B and C for scan RX on 5 GHz band
2286 * because the device has off-channel reception on chain A. 2334 * because the device has off-channel reception on chain A.
2287 */ 2335 */
2288 .scan_antennas[IEEE80211_BAND_5GHZ] = ANT_BC, 2336 .scan_rx_antennas[IEEE80211_BAND_5GHZ] = ANT_BC,
2289}; 2337};
2290 2338
2291/* Module firmware */ 2339/* Module firmware */