diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-4965.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-4965.c | 98 |
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 | ||
431 | static void iwl4965_bg_txpower_work(struct work_struct *work) | 434 | static 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 | ||
1444 | static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel) | 1448 | static 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 | ||
2115 | static int iwl4965_calc_rssi(struct iwl_priv *priv, | 2160 | static 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 */ |