diff options
Diffstat (limited to 'drivers/net/wireless/ralink/rt2x00/rt2800lib.c')
-rw-r--r-- | drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 79 |
1 files changed, 62 insertions, 17 deletions
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c index 4fb79e05078f..5436cdb07937 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c @@ -1418,6 +1418,23 @@ int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev, } EXPORT_SYMBOL_GPL(rt2800_config_pairwise_key); +static void rt2800_set_max_psdu_len(struct rt2x00_dev *rt2x00dev) +{ + u8 i, max_psdu; + u32 reg; + struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; + + for (i = 0; i < 3; i++) + if (drv_data->ampdu_factor_cnt[i] > 0) + break; + + max_psdu = min(drv_data->max_psdu, i); + + rt2800_register_read(rt2x00dev, MAX_LEN_CFG, ®); + rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, max_psdu); + rt2800_register_write(rt2x00dev, MAX_LEN_CFG, reg); +} + int rt2800_sta_add(struct rt2x00_dev *rt2x00dev, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { @@ -1426,6 +1443,17 @@ int rt2800_sta_add(struct rt2x00_dev *rt2x00dev, struct ieee80211_vif *vif, struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; /* + * Limit global maximum TX AMPDU length to smallest value of all + * connected stations. In AP mode this can be suboptimal, but we + * do not have a choice if some connected STA is not capable to + * receive the same amount of data like the others. + */ + if (sta->ht_cap.ht_supported) { + drv_data->ampdu_factor_cnt[sta->ht_cap.ampdu_factor & 3]++; + rt2800_set_max_psdu_len(rt2x00dev); + } + + /* * Search for the first free WCID entry and return the corresponding * index. */ @@ -1457,9 +1485,16 @@ int rt2800_sta_add(struct rt2x00_dev *rt2x00dev, struct ieee80211_vif *vif, } EXPORT_SYMBOL_GPL(rt2800_sta_add); -int rt2800_sta_remove(struct rt2x00_dev *rt2x00dev, int wcid) +int rt2800_sta_remove(struct rt2x00_dev *rt2x00dev, struct ieee80211_sta *sta) { struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; + struct rt2x00_sta *sta_priv = sta_to_rt2x00_sta(sta); + int wcid = sta_priv->wcid; + + if (sta->ht_cap.ht_supported) { + drv_data->ampdu_factor_cnt[sta->ht_cap.ampdu_factor & 3]--; + rt2800_set_max_psdu_len(rt2x00dev); + } if (wcid > WCID_END) return 0; @@ -1904,7 +1939,7 @@ static void rt2800_config_lna_gain(struct rt2x00_dev *rt2x00dev, #define FREQ_OFFSET_BOUND 0x5f -static void rt2800_adjust_freq_offset(struct rt2x00_dev *rt2x00dev) +static void rt2800_freq_cal_mode1(struct rt2x00_dev *rt2x00dev) { u8 freq_offset, prev_freq_offset; u8 rfcsr, prev_rfcsr; @@ -2075,7 +2110,9 @@ static void rt2800_config_channel_rf3xxx(struct rt2x00_dev *rt2x00dev, rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr); rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1); rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); - msleep(1); + + usleep_range(1000, 1500); + rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 0); rt2800_rfcsr_write(rt2x00dev, 30, rfcsr); } @@ -2380,7 +2417,7 @@ static void rt2800_config_channel_rf3053(struct rt2x00_dev *rt2x00dev, } rt2800_rfcsr_write(rt2x00dev, 1, rfcsr); - rt2800_adjust_freq_offset(rt2x00dev); + rt2800_freq_cal_mode1(rt2x00dev); if (conf_is_ht40(conf)) { txrx_agc_fc = rt2x00_get_field8(drv_data->calibration_bw40, @@ -2570,7 +2607,7 @@ static void rt2800_config_channel_rf3290(struct rt2x00_dev *rt2x00dev, rt2x00_set_field8(&rfcsr, RFCSR49_TX, info->default_power1); rt2800_rfcsr_write(rt2x00dev, 49, rfcsr); - rt2800_adjust_freq_offset(rt2x00dev); + rt2800_freq_cal_mode1(rt2x00dev); if (rf->channel <= 14) { if (rf->channel == 6) @@ -2611,7 +2648,7 @@ static void rt2800_config_channel_rf3322(struct rt2x00_dev *rt2x00dev, else rt2800_rfcsr_write(rt2x00dev, 48, info->default_power2); - rt2800_adjust_freq_offset(rt2x00dev); + rt2800_freq_cal_mode1(rt2x00dev); rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr); rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1); @@ -2676,7 +2713,7 @@ static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev, rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1); rt2800_rfcsr_write(rt2x00dev, 1, rfcsr); - rt2800_adjust_freq_offset(rt2x00dev); + rt2800_freq_cal_mode1(rt2x00dev); if (rf->channel <= 14) { int idx = rf->channel-1; @@ -2971,7 +3008,7 @@ static void rt2800_config_channel_rf55xx(struct rt2x00_dev *rt2x00dev, } /* TODO proper frequency adjustment */ - rt2800_adjust_freq_offset(rt2x00dev); + rt2800_freq_cal_mode1(rt2x00dev); /* TODO merge with others */ rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr); @@ -3407,7 +3444,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, } } - msleep(1); + usleep_range(1000, 1500); /* * Clear channel statistic counters @@ -4306,15 +4343,18 @@ void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev) case RF5372: case RF5390: case RF5392: + case RF5592: rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr); rt2x00_set_field8(&rfcsr, RFCSR3_VCOCAL_EN, 1); rt2800_rfcsr_write(rt2x00dev, 3, rfcsr); break; default: + WARN_ONCE(1, "Not supported RF chipet %x for VCO recalibration", + rt2x00dev->chip.rf); return; } - mdelay(1); + usleep_range(1000, 1500); rt2800_register_read(rt2x00dev, TX_PIN_CFG, &tx_pin); if (rt2x00dev->rf_channel <= 14) { @@ -4536,6 +4576,7 @@ EXPORT_SYMBOL_GPL(rt2800_link_tuner); */ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) { + struct rt2800_drv_data *drv_data = rt2x00dev->drv_data; u32 reg; u16 eeprom; unsigned int i; @@ -4704,12 +4745,15 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) rt2x00_set_field32(®, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE); if (rt2x00_rt_rev_gte(rt2x00dev, RT2872, REV_RT2872E) || rt2x00_rt(rt2x00dev, RT2883) || - rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070E)) + rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070E)) { + drv_data->max_psdu = 2; rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 2); - else + } else { + drv_data->max_psdu = 1; rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 1); - rt2x00_set_field32(®, MAX_LEN_CFG_MIN_PSDU, 0); - rt2x00_set_field32(®, MAX_LEN_CFG_MIN_MPDU, 0); + } + rt2x00_set_field32(®, MAX_LEN_CFG_MIN_PSDU, 10); + rt2x00_set_field32(®, MAX_LEN_CFG_MIN_MPDU, 10); rt2800_register_write(rt2x00dev, MAX_LEN_CFG, reg); rt2800_register_read(rt2x00dev, LED_CFG, ®); @@ -6415,7 +6459,7 @@ static void rt2800_init_rfcsr_3593(struct rt2x00_dev *rt2x00dev) rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_EN, 1); rt2800_rfcsr_write(rt2x00dev, 2, rfcsr); - rt2800_adjust_freq_offset(rt2x00dev); + rt2800_freq_cal_mode1(rt2x00dev); rt2800_rfcsr_read(rt2x00dev, 18, &rfcsr); rt2x00_set_field8(&rfcsr, RFCSR18_XO_TUNE_BYPASS, 1); @@ -6641,7 +6685,7 @@ static void rt2800_init_rfcsr_5592(struct rt2x00_dev *rt2x00dev) rt2800_rfcsr_write(rt2x00dev, 2, 0x80); msleep(1); - rt2800_adjust_freq_offset(rt2x00dev); + rt2800_freq_cal_mode1(rt2x00dev); /* Enable DC filter */ if (rt2x00_rt_rev_gte(rt2x00dev, RT5592, REV_RT5592C)) @@ -7593,7 +7637,7 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) spec->ht.cap |= rx_chains << IEEE80211_HT_CAP_RX_STBC_SHIFT; - spec->ht.ampdu_factor = 3; + spec->ht.ampdu_factor = (rx_chains > 1) ? 3 : 2; spec->ht.ampdu_density = 4; spec->ht.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; if (tx_chains != rx_chains) { @@ -7675,6 +7719,7 @@ static int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) case RF5372: case RF5390: case RF5392: + case RF5592: __set_bit(CAPABILITY_VCO_RECALIBRATION, &rt2x00dev->cap_flags); break; } |