forked from Minki/linux
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
This commit is contained in:
commit
b5e4156743
@ -642,31 +642,13 @@ static void __init omap3pandora_init_irq(void)
|
||||
omap_gpio_init();
|
||||
}
|
||||
|
||||
static void pandora_wl1251_set_power(bool enable)
|
||||
{
|
||||
/*
|
||||
* Keep power always on until wl1251_sdio driver learns to re-init
|
||||
* the chip after powering it down and back up.
|
||||
*/
|
||||
}
|
||||
|
||||
static struct wl12xx_platform_data pandora_wl1251_pdata = {
|
||||
.set_power = pandora_wl1251_set_power,
|
||||
.use_eeprom = true,
|
||||
};
|
||||
|
||||
static struct platform_device pandora_wl1251_data = {
|
||||
.name = "wl1251_data",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.platform_data = &pandora_wl1251_pdata,
|
||||
},
|
||||
};
|
||||
|
||||
static void pandora_wl1251_init(void)
|
||||
static void __init pandora_wl1251_init(void)
|
||||
{
|
||||
struct wl12xx_platform_data pandora_wl1251_pdata;
|
||||
int ret;
|
||||
|
||||
memset(&pandora_wl1251_pdata, 0, sizeof(pandora_wl1251_pdata));
|
||||
|
||||
ret = gpio_request(PANDORA_WIFI_IRQ_GPIO, "wl1251 irq");
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
@ -679,6 +661,11 @@ static void pandora_wl1251_init(void)
|
||||
if (pandora_wl1251_pdata.irq < 0)
|
||||
goto fail_irq;
|
||||
|
||||
pandora_wl1251_pdata.use_eeprom = true;
|
||||
ret = wl12xx_set_platform_data(&pandora_wl1251_pdata);
|
||||
if (ret < 0)
|
||||
goto fail_irq;
|
||||
|
||||
return;
|
||||
|
||||
fail_irq:
|
||||
@ -691,7 +678,6 @@ static struct platform_device *omap3pandora_devices[] __initdata = {
|
||||
&pandora_leds_gpio,
|
||||
&pandora_keys_gpio,
|
||||
&pandora_dss_device,
|
||||
&pandora_wl1251_data,
|
||||
&pandora_vwlan_device,
|
||||
};
|
||||
|
||||
|
@ -566,8 +566,8 @@ static void ath_do_set_opmode(struct ath5k_softc *sc)
|
||||
sc->opmode, ath_opmode_to_string(sc->opmode));
|
||||
}
|
||||
|
||||
void ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc,
|
||||
struct ieee80211_vif *vif)
|
||||
static void ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ath_common *common = ath5k_hw_common(sc->ah);
|
||||
struct ath_vif_iter_data iter_data;
|
||||
@ -3206,14 +3206,32 @@ static int ath5k_get_survey(struct ieee80211_hw *hw, int idx,
|
||||
{
|
||||
struct ath5k_softc *sc = hw->priv;
|
||||
struct ieee80211_conf *conf = &hw->conf;
|
||||
struct ath_common *common = ath5k_hw_common(sc->ah);
|
||||
struct ath_cycle_counters *cc = &common->cc_survey;
|
||||
unsigned int div = common->clockrate * 1000;
|
||||
|
||||
if (idx != 0)
|
||||
if (idx != 0)
|
||||
return -ENOENT;
|
||||
|
||||
survey->channel = conf->channel;
|
||||
survey->filled = SURVEY_INFO_NOISE_DBM;
|
||||
survey->noise = sc->ah->ah_noise_floor;
|
||||
|
||||
spin_lock_bh(&common->cc_lock);
|
||||
ath_hw_cycle_counters_update(common);
|
||||
if (cc->cycles > 0) {
|
||||
survey->filled |= SURVEY_INFO_CHANNEL_TIME |
|
||||
SURVEY_INFO_CHANNEL_TIME_BUSY |
|
||||
SURVEY_INFO_CHANNEL_TIME_RX |
|
||||
SURVEY_INFO_CHANNEL_TIME_TX;
|
||||
survey->channel_time += cc->cycles / div;
|
||||
survey->channel_time_busy += cc->rx_busy / div;
|
||||
survey->channel_time_rx += cc->rx_frame / div;
|
||||
survey->channel_time_tx += cc->tx_frame / div;
|
||||
}
|
||||
memset(cc, 0, sizeof(*cc));
|
||||
spin_unlock_bh(&common->cc_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -554,63 +554,63 @@ static ssize_t read_file_frameerrors(struct file *file, char __user *user_buf,
|
||||
|
||||
len += snprintf(buf+len, sizeof(buf)-len,
|
||||
"RX\n---------------------\n");
|
||||
len += snprintf(buf+len, sizeof(buf)-len, "CRC\t%d\t(%d%%)\n",
|
||||
len += snprintf(buf+len, sizeof(buf)-len, "CRC\t%u\t(%u%%)\n",
|
||||
st->rxerr_crc,
|
||||
st->rx_all_count > 0 ?
|
||||
st->rxerr_crc*100/st->rx_all_count : 0);
|
||||
len += snprintf(buf+len, sizeof(buf)-len, "PHY\t%d\t(%d%%)\n",
|
||||
len += snprintf(buf+len, sizeof(buf)-len, "PHY\t%u\t(%u%%)\n",
|
||||
st->rxerr_phy,
|
||||
st->rx_all_count > 0 ?
|
||||
st->rxerr_phy*100/st->rx_all_count : 0);
|
||||
for (i = 0; i < 32; i++) {
|
||||
if (st->rxerr_phy_code[i])
|
||||
len += snprintf(buf+len, sizeof(buf)-len,
|
||||
" phy_err[%d]\t%d\n",
|
||||
" phy_err[%u]\t%u\n",
|
||||
i, st->rxerr_phy_code[i]);
|
||||
}
|
||||
|
||||
len += snprintf(buf+len, sizeof(buf)-len, "FIFO\t%d\t(%d%%)\n",
|
||||
len += snprintf(buf+len, sizeof(buf)-len, "FIFO\t%u\t(%u%%)\n",
|
||||
st->rxerr_fifo,
|
||||
st->rx_all_count > 0 ?
|
||||
st->rxerr_fifo*100/st->rx_all_count : 0);
|
||||
len += snprintf(buf+len, sizeof(buf)-len, "decrypt\t%d\t(%d%%)\n",
|
||||
len += snprintf(buf+len, sizeof(buf)-len, "decrypt\t%u\t(%u%%)\n",
|
||||
st->rxerr_decrypt,
|
||||
st->rx_all_count > 0 ?
|
||||
st->rxerr_decrypt*100/st->rx_all_count : 0);
|
||||
len += snprintf(buf+len, sizeof(buf)-len, "MIC\t%d\t(%d%%)\n",
|
||||
len += snprintf(buf+len, sizeof(buf)-len, "MIC\t%u\t(%u%%)\n",
|
||||
st->rxerr_mic,
|
||||
st->rx_all_count > 0 ?
|
||||
st->rxerr_mic*100/st->rx_all_count : 0);
|
||||
len += snprintf(buf+len, sizeof(buf)-len, "process\t%d\t(%d%%)\n",
|
||||
len += snprintf(buf+len, sizeof(buf)-len, "process\t%u\t(%u%%)\n",
|
||||
st->rxerr_proc,
|
||||
st->rx_all_count > 0 ?
|
||||
st->rxerr_proc*100/st->rx_all_count : 0);
|
||||
len += snprintf(buf+len, sizeof(buf)-len, "jumbo\t%d\t(%d%%)\n",
|
||||
len += snprintf(buf+len, sizeof(buf)-len, "jumbo\t%u\t(%u%%)\n",
|
||||
st->rxerr_jumbo,
|
||||
st->rx_all_count > 0 ?
|
||||
st->rxerr_jumbo*100/st->rx_all_count : 0);
|
||||
len += snprintf(buf+len, sizeof(buf)-len, "[RX all\t%d]\n",
|
||||
len += snprintf(buf+len, sizeof(buf)-len, "[RX all\t%u]\n",
|
||||
st->rx_all_count);
|
||||
len += snprintf(buf+len, sizeof(buf)-len, "RX-all-bytes\t%d\n",
|
||||
len += snprintf(buf+len, sizeof(buf)-len, "RX-all-bytes\t%u\n",
|
||||
st->rx_bytes_count);
|
||||
|
||||
len += snprintf(buf+len, sizeof(buf)-len,
|
||||
"\nTX\n---------------------\n");
|
||||
len += snprintf(buf+len, sizeof(buf)-len, "retry\t%d\t(%d%%)\n",
|
||||
len += snprintf(buf+len, sizeof(buf)-len, "retry\t%u\t(%u%%)\n",
|
||||
st->txerr_retry,
|
||||
st->tx_all_count > 0 ?
|
||||
st->txerr_retry*100/st->tx_all_count : 0);
|
||||
len += snprintf(buf+len, sizeof(buf)-len, "FIFO\t%d\t(%d%%)\n",
|
||||
len += snprintf(buf+len, sizeof(buf)-len, "FIFO\t%u\t(%u%%)\n",
|
||||
st->txerr_fifo,
|
||||
st->tx_all_count > 0 ?
|
||||
st->txerr_fifo*100/st->tx_all_count : 0);
|
||||
len += snprintf(buf+len, sizeof(buf)-len, "filter\t%d\t(%d%%)\n",
|
||||
len += snprintf(buf+len, sizeof(buf)-len, "filter\t%u\t(%u%%)\n",
|
||||
st->txerr_filt,
|
||||
st->tx_all_count > 0 ?
|
||||
st->txerr_filt*100/st->tx_all_count : 0);
|
||||
len += snprintf(buf+len, sizeof(buf)-len, "[TX all\t%d]\n",
|
||||
len += snprintf(buf+len, sizeof(buf)-len, "[TX all\t%u]\n",
|
||||
st->tx_all_count);
|
||||
len += snprintf(buf+len, sizeof(buf)-len, "TX-all-bytes\t%d\n",
|
||||
len += snprintf(buf+len, sizeof(buf)-len, "TX-all-bytes\t%u\n",
|
||||
st->tx_bytes_count);
|
||||
|
||||
if (len > sizeof(buf))
|
||||
|
@ -26,7 +26,7 @@
|
||||
struct ath5k_hw_rx_ctl {
|
||||
u32 rx_control_0; /* RX control word 0 */
|
||||
u32 rx_control_1; /* RX control word 1 */
|
||||
} __packed;
|
||||
} __packed __aligned(4);
|
||||
|
||||
/* RX control word 1 fields/flags */
|
||||
#define AR5K_DESC_RX_CTL1_BUF_LEN 0x00000fff /* data buffer length */
|
||||
@ -39,7 +39,7 @@ struct ath5k_hw_rx_ctl {
|
||||
struct ath5k_hw_rx_status {
|
||||
u32 rx_status_0; /* RX status word 0 */
|
||||
u32 rx_status_1; /* RX status word 1 */
|
||||
} __packed;
|
||||
} __packed __aligned(4);
|
||||
|
||||
/* 5210/5211 */
|
||||
/* RX status word 0 fields/flags */
|
||||
@ -129,7 +129,7 @@ enum ath5k_phy_error_code {
|
||||
struct ath5k_hw_2w_tx_ctl {
|
||||
u32 tx_control_0; /* TX control word 0 */
|
||||
u32 tx_control_1; /* TX control word 1 */
|
||||
} __packed;
|
||||
} __packed __aligned(4);
|
||||
|
||||
/* TX control word 0 fields/flags */
|
||||
#define AR5K_2W_TX_DESC_CTL0_FRAME_LEN 0x00000fff /* frame length */
|
||||
@ -185,7 +185,7 @@ struct ath5k_hw_4w_tx_ctl {
|
||||
u32 tx_control_1; /* TX control word 1 */
|
||||
u32 tx_control_2; /* TX control word 2 */
|
||||
u32 tx_control_3; /* TX control word 3 */
|
||||
} __packed;
|
||||
} __packed __aligned(4);
|
||||
|
||||
/* TX control word 0 fields/flags */
|
||||
#define AR5K_4W_TX_DESC_CTL0_FRAME_LEN 0x00000fff /* frame length */
|
||||
@ -244,7 +244,7 @@ struct ath5k_hw_4w_tx_ctl {
|
||||
struct ath5k_hw_tx_status {
|
||||
u32 tx_status_0; /* TX status word 0 */
|
||||
u32 tx_status_1; /* TX status word 1 */
|
||||
} __packed;
|
||||
} __packed __aligned(4);
|
||||
|
||||
/* TX status word 0 fields/flags */
|
||||
#define AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK 0x00000001 /* TX success */
|
||||
@ -282,7 +282,7 @@ struct ath5k_hw_tx_status {
|
||||
struct ath5k_hw_5210_tx_desc {
|
||||
struct ath5k_hw_2w_tx_ctl tx_ctl;
|
||||
struct ath5k_hw_tx_status tx_stat;
|
||||
} __packed;
|
||||
} __packed __aligned(4);
|
||||
|
||||
/*
|
||||
* 5212 hardware TX descriptor
|
||||
@ -290,7 +290,7 @@ struct ath5k_hw_5210_tx_desc {
|
||||
struct ath5k_hw_5212_tx_desc {
|
||||
struct ath5k_hw_4w_tx_ctl tx_ctl;
|
||||
struct ath5k_hw_tx_status tx_stat;
|
||||
} __packed;
|
||||
} __packed __aligned(4);
|
||||
|
||||
/*
|
||||
* Common hardware RX descriptor
|
||||
@ -298,7 +298,7 @@ struct ath5k_hw_5212_tx_desc {
|
||||
struct ath5k_hw_all_rx_desc {
|
||||
struct ath5k_hw_rx_ctl rx_ctl;
|
||||
struct ath5k_hw_rx_status rx_stat;
|
||||
} __packed;
|
||||
} __packed __aligned(4);
|
||||
|
||||
/*
|
||||
* Atheros hardware DMA descriptor
|
||||
@ -313,7 +313,7 @@ struct ath5k_desc {
|
||||
struct ath5k_hw_5212_tx_desc ds_tx5212;
|
||||
struct ath5k_hw_all_rx_desc ds_rx;
|
||||
} ud;
|
||||
} __packed;
|
||||
} __packed __aligned(4);
|
||||
|
||||
#define AR5K_RXDESC_INTREQ 0x0020
|
||||
|
||||
|
@ -1102,18 +1102,12 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel)
|
||||
PHY calibration
|
||||
\*****************/
|
||||
|
||||
static int sign_extend(int val, const int nbits)
|
||||
{
|
||||
int order = BIT(nbits-1);
|
||||
return (val ^ order) - order;
|
||||
}
|
||||
|
||||
static s32 ath5k_hw_read_measured_noise_floor(struct ath5k_hw *ah)
|
||||
{
|
||||
s32 val;
|
||||
|
||||
val = ath5k_hw_reg_read(ah, AR5K_PHY_NF);
|
||||
return sign_extend(AR5K_REG_MS(val, AR5K_PHY_NF_MINCCA_PWR), 9);
|
||||
return sign_extend32(AR5K_REG_MS(val, AR5K_PHY_NF_MINCCA_PWR), 8);
|
||||
}
|
||||
|
||||
void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah)
|
||||
|
@ -873,7 +873,7 @@ static int ar5008_hw_process_ini(struct ath_hw *ah,
|
||||
channel->max_antenna_gain * 2,
|
||||
channel->max_power * 2,
|
||||
min((u32) MAX_RATE_POWER,
|
||||
(u32) regulatory->power_limit));
|
||||
(u32) regulatory->power_limit), false);
|
||||
|
||||
/* Write analog registers */
|
||||
if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) {
|
||||
@ -1490,25 +1490,25 @@ static void ar5008_hw_do_getnf(struct ath_hw *ah,
|
||||
int16_t nf;
|
||||
|
||||
nf = MS(REG_READ(ah, AR_PHY_CCA), AR_PHY_MINCCA_PWR);
|
||||
nfarray[0] = sign_extend(nf, 9);
|
||||
nfarray[0] = sign_extend32(nf, 8);
|
||||
|
||||
nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), AR_PHY_CH1_MINCCA_PWR);
|
||||
nfarray[1] = sign_extend(nf, 9);
|
||||
nfarray[1] = sign_extend32(nf, 8);
|
||||
|
||||
nf = MS(REG_READ(ah, AR_PHY_CH2_CCA), AR_PHY_CH2_MINCCA_PWR);
|
||||
nfarray[2] = sign_extend(nf, 9);
|
||||
nfarray[2] = sign_extend32(nf, 8);
|
||||
|
||||
if (!IS_CHAN_HT40(ah->curchan))
|
||||
return;
|
||||
|
||||
nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), AR_PHY_EXT_MINCCA_PWR);
|
||||
nfarray[3] = sign_extend(nf, 9);
|
||||
nfarray[3] = sign_extend32(nf, 8);
|
||||
|
||||
nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), AR_PHY_CH1_EXT_MINCCA_PWR);
|
||||
nfarray[4] = sign_extend(nf, 9);
|
||||
nfarray[4] = sign_extend32(nf, 8);
|
||||
|
||||
nf = MS(REG_READ(ah, AR_PHY_CH2_EXT_CCA), AR_PHY_CH2_EXT_MINCCA_PWR);
|
||||
nfarray[5] = sign_extend(nf, 9);
|
||||
nfarray[5] = sign_extend32(nf, 8);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -90,13 +90,10 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
|
||||
|
||||
*masked = isr & ATH9K_INT_COMMON;
|
||||
|
||||
if (ah->config.rx_intr_mitigation) {
|
||||
if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM))
|
||||
*masked |= ATH9K_INT_RX;
|
||||
}
|
||||
|
||||
if (isr & (AR_ISR_RXOK | AR_ISR_RXERR))
|
||||
if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM |
|
||||
AR_ISR_RXOK | AR_ISR_RXERR))
|
||||
*masked |= ATH9K_INT_RX;
|
||||
|
||||
if (isr &
|
||||
(AR_ISR_TXOK | AR_ISR_TXDESC | AR_ISR_TXERR |
|
||||
AR_ISR_TXEOL)) {
|
||||
@ -118,14 +115,6 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
|
||||
"receive FIFO overrun interrupt\n");
|
||||
}
|
||||
|
||||
if (!AR_SREV_9100(ah)) {
|
||||
if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
|
||||
u32 isr5 = REG_READ(ah, AR_ISR_S5_S);
|
||||
if (isr5 & AR_ISR_S5_TIM_TIMER)
|
||||
*masked |= ATH9K_INT_TIM_TIMER;
|
||||
}
|
||||
}
|
||||
|
||||
*masked |= mask2;
|
||||
}
|
||||
|
||||
@ -136,17 +125,18 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
|
||||
u32 s5_s;
|
||||
|
||||
s5_s = REG_READ(ah, AR_ISR_S5_S);
|
||||
if (isr & AR_ISR_GENTMR) {
|
||||
ah->intr_gen_timer_trigger =
|
||||
ah->intr_gen_timer_trigger =
|
||||
MS(s5_s, AR_ISR_S5_GENTIMER_TRIG);
|
||||
|
||||
ah->intr_gen_timer_thresh =
|
||||
MS(s5_s, AR_ISR_S5_GENTIMER_THRESH);
|
||||
ah->intr_gen_timer_thresh =
|
||||
MS(s5_s, AR_ISR_S5_GENTIMER_THRESH);
|
||||
|
||||
if (ah->intr_gen_timer_trigger)
|
||||
*masked |= ATH9K_INT_GENTIMER;
|
||||
if (ah->intr_gen_timer_trigger)
|
||||
*masked |= ATH9K_INT_GENTIMER;
|
||||
|
||||
}
|
||||
if ((s5_s & AR_ISR_S5_TIM_TIMER) &&
|
||||
!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
|
||||
*masked |= ATH9K_INT_TIM_TIMER;
|
||||
}
|
||||
|
||||
if (sync_cause) {
|
||||
@ -218,77 +208,70 @@ static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds,
|
||||
struct ath_tx_status *ts)
|
||||
{
|
||||
struct ar5416_desc *ads = AR5416DESC(ds);
|
||||
u32 status;
|
||||
|
||||
if ((ads->ds_txstatus9 & AR_TxDone) == 0)
|
||||
status = ACCESS_ONCE(ads->ds_txstatus9);
|
||||
if ((status & AR_TxDone) == 0)
|
||||
return -EINPROGRESS;
|
||||
|
||||
ts->ts_seqnum = MS(ads->ds_txstatus9, AR_SeqNum);
|
||||
ts->ts_tstamp = ads->AR_SendTimestamp;
|
||||
ts->ts_status = 0;
|
||||
ts->ts_flags = 0;
|
||||
|
||||
if (ads->ds_txstatus1 & AR_FrmXmitOK)
|
||||
ts->ts_status |= ATH9K_TX_ACKED;
|
||||
if (ads->ds_txstatus1 & AR_ExcessiveRetries)
|
||||
ts->ts_status |= ATH9K_TXERR_XRETRY;
|
||||
if (ads->ds_txstatus1 & AR_Filtered)
|
||||
ts->ts_status |= ATH9K_TXERR_FILT;
|
||||
if (ads->ds_txstatus1 & AR_FIFOUnderrun) {
|
||||
ts->ts_status |= ATH9K_TXERR_FIFO;
|
||||
ath9k_hw_updatetxtriglevel(ah, true);
|
||||
}
|
||||
if (ads->ds_txstatus9 & AR_TxOpExceeded)
|
||||
if (status & AR_TxOpExceeded)
|
||||
ts->ts_status |= ATH9K_TXERR_XTXOP;
|
||||
if (ads->ds_txstatus1 & AR_TxTimerExpired)
|
||||
ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED;
|
||||
ts->tid = MS(status, AR_TxTid);
|
||||
ts->ts_rateindex = MS(status, AR_FinalTxIdx);
|
||||
ts->ts_seqnum = MS(status, AR_SeqNum);
|
||||
|
||||
if (ads->ds_txstatus1 & AR_DescCfgErr)
|
||||
ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR;
|
||||
if (ads->ds_txstatus1 & AR_TxDataUnderrun) {
|
||||
ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN;
|
||||
ath9k_hw_updatetxtriglevel(ah, true);
|
||||
}
|
||||
if (ads->ds_txstatus1 & AR_TxDelimUnderrun) {
|
||||
ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN;
|
||||
ath9k_hw_updatetxtriglevel(ah, true);
|
||||
}
|
||||
if (ads->ds_txstatus0 & AR_TxBaStatus) {
|
||||
status = ACCESS_ONCE(ads->ds_txstatus0);
|
||||
ts->ts_rssi_ctl0 = MS(status, AR_TxRSSIAnt00);
|
||||
ts->ts_rssi_ctl1 = MS(status, AR_TxRSSIAnt01);
|
||||
ts->ts_rssi_ctl2 = MS(status, AR_TxRSSIAnt02);
|
||||
if (status & AR_TxBaStatus) {
|
||||
ts->ts_flags |= ATH9K_TX_BA;
|
||||
ts->ba_low = ads->AR_BaBitmapLow;
|
||||
ts->ba_high = ads->AR_BaBitmapHigh;
|
||||
}
|
||||
|
||||
ts->ts_rateindex = MS(ads->ds_txstatus9, AR_FinalTxIdx);
|
||||
switch (ts->ts_rateindex) {
|
||||
case 0:
|
||||
ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate0);
|
||||
break;
|
||||
case 1:
|
||||
ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate1);
|
||||
break;
|
||||
case 2:
|
||||
ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate2);
|
||||
break;
|
||||
case 3:
|
||||
ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate3);
|
||||
break;
|
||||
status = ACCESS_ONCE(ads->ds_txstatus1);
|
||||
if (status & AR_FrmXmitOK)
|
||||
ts->ts_status |= ATH9K_TX_ACKED;
|
||||
else {
|
||||
if (status & AR_ExcessiveRetries)
|
||||
ts->ts_status |= ATH9K_TXERR_XRETRY;
|
||||
if (status & AR_Filtered)
|
||||
ts->ts_status |= ATH9K_TXERR_FILT;
|
||||
if (status & AR_FIFOUnderrun) {
|
||||
ts->ts_status |= ATH9K_TXERR_FIFO;
|
||||
ath9k_hw_updatetxtriglevel(ah, true);
|
||||
}
|
||||
}
|
||||
if (status & AR_TxTimerExpired)
|
||||
ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED;
|
||||
if (status & AR_DescCfgErr)
|
||||
ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR;
|
||||
if (status & AR_TxDataUnderrun) {
|
||||
ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN;
|
||||
ath9k_hw_updatetxtriglevel(ah, true);
|
||||
}
|
||||
if (status & AR_TxDelimUnderrun) {
|
||||
ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN;
|
||||
ath9k_hw_updatetxtriglevel(ah, true);
|
||||
}
|
||||
ts->ts_shortretry = MS(status, AR_RTSFailCnt);
|
||||
ts->ts_longretry = MS(status, AR_DataFailCnt);
|
||||
ts->ts_virtcol = MS(status, AR_VirtRetryCnt);
|
||||
|
||||
status = ACCESS_ONCE(ads->ds_txstatus5);
|
||||
ts->ts_rssi = MS(status, AR_TxRSSICombined);
|
||||
ts->ts_rssi_ext0 = MS(status, AR_TxRSSIAnt10);
|
||||
ts->ts_rssi_ext1 = MS(status, AR_TxRSSIAnt11);
|
||||
ts->ts_rssi_ext2 = MS(status, AR_TxRSSIAnt12);
|
||||
|
||||
ts->ts_rssi = MS(ads->ds_txstatus5, AR_TxRSSICombined);
|
||||
ts->ts_rssi_ctl0 = MS(ads->ds_txstatus0, AR_TxRSSIAnt00);
|
||||
ts->ts_rssi_ctl1 = MS(ads->ds_txstatus0, AR_TxRSSIAnt01);
|
||||
ts->ts_rssi_ctl2 = MS(ads->ds_txstatus0, AR_TxRSSIAnt02);
|
||||
ts->ts_rssi_ext0 = MS(ads->ds_txstatus5, AR_TxRSSIAnt10);
|
||||
ts->ts_rssi_ext1 = MS(ads->ds_txstatus5, AR_TxRSSIAnt11);
|
||||
ts->ts_rssi_ext2 = MS(ads->ds_txstatus5, AR_TxRSSIAnt12);
|
||||
ts->evm0 = ads->AR_TxEVM0;
|
||||
ts->evm1 = ads->AR_TxEVM1;
|
||||
ts->evm2 = ads->AR_TxEVM2;
|
||||
ts->ts_shortretry = MS(ads->ds_txstatus1, AR_RTSFailCnt);
|
||||
ts->ts_longretry = MS(ads->ds_txstatus1, AR_DataFailCnt);
|
||||
ts->ts_virtcol = MS(ads->ds_txstatus1, AR_VirtRetryCnt);
|
||||
ts->tid = MS(ads->ds_txstatus9, AR_TxTid);
|
||||
ts->ts_antenna = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -473,21 +473,21 @@ static void ar9002_hw_do_getnf(struct ath_hw *ah,
|
||||
int16_t nf;
|
||||
|
||||
nf = MS(REG_READ(ah, AR_PHY_CCA), AR9280_PHY_MINCCA_PWR);
|
||||
nfarray[0] = sign_extend(nf, 9);
|
||||
nfarray[0] = sign_extend32(nf, 8);
|
||||
|
||||
nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), AR9280_PHY_EXT_MINCCA_PWR);
|
||||
if (IS_CHAN_HT40(ah->curchan))
|
||||
nfarray[3] = sign_extend(nf, 9);
|
||||
nfarray[3] = sign_extend32(nf, 8);
|
||||
|
||||
if (AR_SREV_9285(ah) || AR_SREV_9271(ah))
|
||||
return;
|
||||
|
||||
nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), AR9280_PHY_CH1_MINCCA_PWR);
|
||||
nfarray[1] = sign_extend(nf, 9);
|
||||
nfarray[1] = sign_extend32(nf, 8);
|
||||
|
||||
nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), AR9280_PHY_CH1_EXT_MINCCA_PWR);
|
||||
if (IS_CHAN_HT40(ah->curchan))
|
||||
nfarray[4] = sign_extend(nf, 9);
|
||||
nfarray[4] = sign_extend32(nf, 8);
|
||||
}
|
||||
|
||||
static void ar9002_hw_set_nf_limits(struct ath_hw *ah)
|
||||
|
@ -2131,8 +2131,9 @@ static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan, u16 cfgCtl,
|
||||
u8 twiceAntennaReduction,
|
||||
u8 twiceMaxRegulatoryPower,
|
||||
u8 powerLimit)
|
||||
u8 powerLimit, bool test)
|
||||
{
|
||||
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
u8 targetPowerValT2[ar9300RateSize];
|
||||
unsigned int i = 0;
|
||||
@ -2144,7 +2145,16 @@ static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
|
||||
twiceMaxRegulatoryPower,
|
||||
powerLimit);
|
||||
|
||||
while (i < ar9300RateSize) {
|
||||
regulatory->max_power_level = 0;
|
||||
for (i = 0; i < ar9300RateSize; i++) {
|
||||
if (targetPowerValT2[i] > regulatory->max_power_level)
|
||||
regulatory->max_power_level = targetPowerValT2[i];
|
||||
}
|
||||
|
||||
if (test)
|
||||
return;
|
||||
|
||||
for (i = 0; i < ar9300RateSize; i++) {
|
||||
ath_print(common, ATH_DBG_EEPROM,
|
||||
"TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
|
||||
i++;
|
||||
@ -2159,9 +2169,6 @@ static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
|
||||
i++;
|
||||
}
|
||||
|
||||
/* Write target power array to registers */
|
||||
ar9003_hw_tx_power_regwrite(ah, targetPowerValT2);
|
||||
|
||||
/*
|
||||
* This is the TX power we send back to driver core,
|
||||
* and it can use to pass to userspace to display our
|
||||
@ -2180,7 +2187,10 @@ static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
|
||||
i = ALL_TARGET_HT20_0_8_16; /* ht20 */
|
||||
|
||||
ah->txpower_limit = targetPowerValT2[i];
|
||||
regulatory->max_power_level = targetPowerValT2[i];
|
||||
|
||||
/* Write target power array to registers */
|
||||
ar9003_hw_tx_power_regwrite(ah, targetPowerValT2);
|
||||
ar9003_hw_calibration_apply(ah, chan->channel);
|
||||
}
|
||||
|
||||
|
@ -237,10 +237,12 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
|
||||
struct ath_tx_status *ts)
|
||||
{
|
||||
struct ar9003_txs *ads;
|
||||
u32 status;
|
||||
|
||||
ads = &ah->ts_ring[ah->ts_tail];
|
||||
|
||||
if ((ads->status8 & AR_TxDone) == 0)
|
||||
status = ACCESS_ONCE(ads->status8);
|
||||
if ((status & AR_TxDone) == 0)
|
||||
return -EINPROGRESS;
|
||||
|
||||
ah->ts_tail = (ah->ts_tail + 1) % ah->ts_size;
|
||||
@ -253,57 +255,58 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (status & AR_TxOpExceeded)
|
||||
ts->ts_status |= ATH9K_TXERR_XTXOP;
|
||||
ts->ts_rateindex = MS(status, AR_FinalTxIdx);
|
||||
ts->ts_seqnum = MS(status, AR_SeqNum);
|
||||
ts->tid = MS(status, AR_TxTid);
|
||||
|
||||
ts->qid = MS(ads->ds_info, AR_TxQcuNum);
|
||||
ts->desc_id = MS(ads->status1, AR_TxDescId);
|
||||
ts->ts_seqnum = MS(ads->status8, AR_SeqNum);
|
||||
ts->ts_tstamp = ads->status4;
|
||||
ts->ts_status = 0;
|
||||
ts->ts_flags = 0;
|
||||
|
||||
if (ads->status3 & AR_ExcessiveRetries)
|
||||
ts->ts_status |= ATH9K_TXERR_XRETRY;
|
||||
if (ads->status3 & AR_Filtered)
|
||||
ts->ts_status |= ATH9K_TXERR_FILT;
|
||||
if (ads->status3 & AR_FIFOUnderrun) {
|
||||
ts->ts_status |= ATH9K_TXERR_FIFO;
|
||||
ath9k_hw_updatetxtriglevel(ah, true);
|
||||
}
|
||||
if (ads->status8 & AR_TxOpExceeded)
|
||||
ts->ts_status |= ATH9K_TXERR_XTXOP;
|
||||
if (ads->status3 & AR_TxTimerExpired)
|
||||
ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED;
|
||||
|
||||
if (ads->status3 & AR_DescCfgErr)
|
||||
ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR;
|
||||
if (ads->status3 & AR_TxDataUnderrun) {
|
||||
ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN;
|
||||
ath9k_hw_updatetxtriglevel(ah, true);
|
||||
}
|
||||
if (ads->status3 & AR_TxDelimUnderrun) {
|
||||
ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN;
|
||||
ath9k_hw_updatetxtriglevel(ah, true);
|
||||
}
|
||||
if (ads->status2 & AR_TxBaStatus) {
|
||||
status = ACCESS_ONCE(ads->status2);
|
||||
ts->ts_rssi_ctl0 = MS(status, AR_TxRSSIAnt00);
|
||||
ts->ts_rssi_ctl1 = MS(status, AR_TxRSSIAnt01);
|
||||
ts->ts_rssi_ctl2 = MS(status, AR_TxRSSIAnt02);
|
||||
if (status & AR_TxBaStatus) {
|
||||
ts->ts_flags |= ATH9K_TX_BA;
|
||||
ts->ba_low = ads->status5;
|
||||
ts->ba_high = ads->status6;
|
||||
}
|
||||
|
||||
ts->ts_rateindex = MS(ads->status8, AR_FinalTxIdx);
|
||||
status = ACCESS_ONCE(ads->status3);
|
||||
if (status & AR_ExcessiveRetries)
|
||||
ts->ts_status |= ATH9K_TXERR_XRETRY;
|
||||
if (status & AR_Filtered)
|
||||
ts->ts_status |= ATH9K_TXERR_FILT;
|
||||
if (status & AR_FIFOUnderrun) {
|
||||
ts->ts_status |= ATH9K_TXERR_FIFO;
|
||||
ath9k_hw_updatetxtriglevel(ah, true);
|
||||
}
|
||||
if (status & AR_TxTimerExpired)
|
||||
ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED;
|
||||
if (status & AR_DescCfgErr)
|
||||
ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR;
|
||||
if (status & AR_TxDataUnderrun) {
|
||||
ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN;
|
||||
ath9k_hw_updatetxtriglevel(ah, true);
|
||||
}
|
||||
if (status & AR_TxDelimUnderrun) {
|
||||
ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN;
|
||||
ath9k_hw_updatetxtriglevel(ah, true);
|
||||
}
|
||||
ts->ts_shortretry = MS(status, AR_RTSFailCnt);
|
||||
ts->ts_longretry = MS(status, AR_DataFailCnt);
|
||||
ts->ts_virtcol = MS(status, AR_VirtRetryCnt);
|
||||
|
||||
ts->ts_rssi = MS(ads->status7, AR_TxRSSICombined);
|
||||
ts->ts_rssi_ctl0 = MS(ads->status2, AR_TxRSSIAnt00);
|
||||
ts->ts_rssi_ctl1 = MS(ads->status2, AR_TxRSSIAnt01);
|
||||
ts->ts_rssi_ctl2 = MS(ads->status2, AR_TxRSSIAnt02);
|
||||
ts->ts_rssi_ext0 = MS(ads->status7, AR_TxRSSIAnt10);
|
||||
ts->ts_rssi_ext1 = MS(ads->status7, AR_TxRSSIAnt11);
|
||||
ts->ts_rssi_ext2 = MS(ads->status7, AR_TxRSSIAnt12);
|
||||
ts->ts_shortretry = MS(ads->status3, AR_RTSFailCnt);
|
||||
ts->ts_longretry = MS(ads->status3, AR_DataFailCnt);
|
||||
ts->ts_virtcol = MS(ads->status3, AR_VirtRetryCnt);
|
||||
ts->ts_antenna = 0;
|
||||
|
||||
ts->tid = MS(ads->status8, AR_TxTid);
|
||||
status = ACCESS_ONCE(ads->status7);
|
||||
ts->ts_rssi = MS(status, AR_TxRSSICombined);
|
||||
ts->ts_rssi_ext0 = MS(status, AR_TxRSSIAnt10);
|
||||
ts->ts_rssi_ext1 = MS(status, AR_TxRSSIAnt11);
|
||||
ts->ts_rssi_ext2 = MS(status, AR_TxRSSIAnt12);
|
||||
|
||||
memset(ads, 0, sizeof(*ads));
|
||||
|
||||
|
@ -65,7 +65,7 @@ struct ar9003_rxs {
|
||||
u32 status9;
|
||||
u32 status10;
|
||||
u32 status11;
|
||||
} __packed;
|
||||
} __packed __aligned(4);
|
||||
|
||||
/* Transmit Control Descriptor */
|
||||
struct ar9003_txc {
|
||||
@ -93,7 +93,7 @@ struct ar9003_txc {
|
||||
u32 ctl21; /* DMA control 21 */
|
||||
u32 ctl22; /* DMA control 22 */
|
||||
u32 pad[9]; /* pad to cache line (128 bytes/32 dwords) */
|
||||
} __packed;
|
||||
} __packed __aligned(4);
|
||||
|
||||
struct ar9003_txs {
|
||||
u32 ds_info;
|
||||
@ -105,7 +105,7 @@ struct ar9003_txs {
|
||||
u32 status6;
|
||||
u32 status7;
|
||||
u32 status8;
|
||||
} __packed;
|
||||
} __packed __aligned(4);
|
||||
|
||||
void ar9003_hw_attach_mac_ops(struct ath_hw *hw);
|
||||
void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size);
|
||||
|
@ -614,7 +614,7 @@ static int ar9003_hw_process_ini(struct ath_hw *ah,
|
||||
channel->max_antenna_gain * 2,
|
||||
channel->max_power * 2,
|
||||
min((u32) MAX_RATE_POWER,
|
||||
(u32) regulatory->power_limit));
|
||||
(u32) regulatory->power_limit), false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1023,25 +1023,25 @@ static void ar9003_hw_do_getnf(struct ath_hw *ah,
|
||||
int16_t nf;
|
||||
|
||||
nf = MS(REG_READ(ah, AR_PHY_CCA_0), AR_PHY_MINCCA_PWR);
|
||||
nfarray[0] = sign_extend(nf, 9);
|
||||
nfarray[0] = sign_extend32(nf, 8);
|
||||
|
||||
nf = MS(REG_READ(ah, AR_PHY_CCA_1), AR_PHY_CH1_MINCCA_PWR);
|
||||
nfarray[1] = sign_extend(nf, 9);
|
||||
nfarray[1] = sign_extend32(nf, 8);
|
||||
|
||||
nf = MS(REG_READ(ah, AR_PHY_CCA_2), AR_PHY_CH2_MINCCA_PWR);
|
||||
nfarray[2] = sign_extend(nf, 9);
|
||||
nfarray[2] = sign_extend32(nf, 8);
|
||||
|
||||
if (!IS_CHAN_HT40(ah->curchan))
|
||||
return;
|
||||
|
||||
nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), AR_PHY_EXT_MINCCA_PWR);
|
||||
nfarray[3] = sign_extend(nf, 9);
|
||||
nfarray[3] = sign_extend32(nf, 8);
|
||||
|
||||
nf = MS(REG_READ(ah, AR_PHY_EXT_CCA_1), AR_PHY_CH1_EXT_MINCCA_PWR);
|
||||
nfarray[4] = sign_extend(nf, 9);
|
||||
nfarray[4] = sign_extend32(nf, 8);
|
||||
|
||||
nf = MS(REG_READ(ah, AR_PHY_EXT_CCA_2), AR_PHY_CH2_EXT_MINCCA_PWR);
|
||||
nfarray[5] = sign_extend(nf, 9);
|
||||
nfarray[5] = sign_extend32(nf, 8);
|
||||
}
|
||||
|
||||
static void ar9003_hw_set_nf_limits(struct ath_hw *ah)
|
||||
|
@ -195,7 +195,6 @@ enum ATH_AGGR_STATUS {
|
||||
|
||||
#define ATH_TXFIFO_DEPTH 8
|
||||
struct ath_txq {
|
||||
int axq_class;
|
||||
u32 axq_qnum;
|
||||
u32 *axq_link;
|
||||
struct list_head axq_q;
|
||||
@ -208,11 +207,12 @@ struct ath_txq {
|
||||
struct list_head txq_fifo_pending;
|
||||
u8 txq_headidx;
|
||||
u8 txq_tailidx;
|
||||
int pending_frames;
|
||||
};
|
||||
|
||||
struct ath_atx_ac {
|
||||
struct ath_txq *txq;
|
||||
int sched;
|
||||
int qnum;
|
||||
struct list_head list;
|
||||
struct list_head tid_q;
|
||||
};
|
||||
@ -270,7 +270,6 @@ struct ath_node {
|
||||
struct ath_atx_ac ac[WME_NUM_AC];
|
||||
u16 maxampdu;
|
||||
u8 mpdudensity;
|
||||
int last_rssi;
|
||||
};
|
||||
|
||||
#define AGGR_CLEANUP BIT(1)
|
||||
@ -291,12 +290,11 @@ struct ath_tx_control {
|
||||
struct ath_tx {
|
||||
u16 seq_no;
|
||||
u32 txqsetup;
|
||||
int hwq_map[WME_NUM_AC];
|
||||
spinlock_t txbuflock;
|
||||
struct list_head txbuf;
|
||||
struct ath_txq txq[ATH9K_NUM_TX_QUEUES];
|
||||
struct ath_descdma txdma;
|
||||
int pending_frames[WME_NUM_AC];
|
||||
struct ath_txq *txq_map[WME_NUM_AC];
|
||||
};
|
||||
|
||||
struct ath_rx_edma {
|
||||
@ -310,7 +308,6 @@ struct ath_rx {
|
||||
u8 rxotherant;
|
||||
u32 *rxlink;
|
||||
unsigned int rxfilter;
|
||||
spinlock_t pcu_lock;
|
||||
spinlock_t rxbuflock;
|
||||
struct list_head rxbuf;
|
||||
struct ath_descdma rxdma;
|
||||
@ -327,7 +324,6 @@ void ath_rx_cleanup(struct ath_softc *sc);
|
||||
int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp);
|
||||
struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype);
|
||||
void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq);
|
||||
int ath_tx_setup(struct ath_softc *sc, int haltype);
|
||||
void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx);
|
||||
void ath_draintxq(struct ath_softc *sc,
|
||||
struct ath_txq *txq, bool retry_tx);
|
||||
@ -600,9 +596,9 @@ struct ath_softc {
|
||||
struct ath_hw *sc_ah;
|
||||
void __iomem *mem;
|
||||
int irq;
|
||||
spinlock_t sc_resetlock;
|
||||
spinlock_t sc_serial_rw;
|
||||
spinlock_t sc_pm_lock;
|
||||
spinlock_t sc_pcu_lock;
|
||||
struct mutex mutex;
|
||||
struct work_struct paprd_work;
|
||||
struct work_struct hw_check_work;
|
||||
@ -662,11 +658,11 @@ struct ath_wiphy {
|
||||
bool idle;
|
||||
int chan_idx;
|
||||
int chan_is_ht;
|
||||
int last_rssi;
|
||||
};
|
||||
|
||||
void ath9k_tasklet(unsigned long data);
|
||||
int ath_reset(struct ath_softc *sc, bool retry_tx);
|
||||
int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc);
|
||||
int ath_cabq_update(struct ath_softc *);
|
||||
|
||||
static inline void ath_read_cachesize(struct ath_common *common, int *csz)
|
||||
|
@ -28,7 +28,7 @@ int ath_beaconq_config(struct ath_softc *sc)
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ath9k_tx_queue_info qi, qi_be;
|
||||
int qnum;
|
||||
struct ath_txq *txq;
|
||||
|
||||
ath9k_hw_get_txq_props(ah, sc->beacon.beaconq, &qi);
|
||||
if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) {
|
||||
@ -38,8 +38,8 @@ int ath_beaconq_config(struct ath_softc *sc)
|
||||
qi.tqi_cwmax = 0;
|
||||
} else {
|
||||
/* Adhoc mode; important thing is to use 2x cwmin. */
|
||||
qnum = sc->tx.hwq_map[WME_AC_BE];
|
||||
ath9k_hw_get_txq_props(ah, qnum, &qi_be);
|
||||
txq = sc->tx.txq_map[WME_AC_BE];
|
||||
ath9k_hw_get_txq_props(ah, txq->axq_qnum, &qi_be);
|
||||
qi.tqi_aifs = qi_be.tqi_aifs;
|
||||
qi.tqi_cwmin = 4*qi_be.tqi_cwmin;
|
||||
qi.tqi_cwmax = qi_be.tqi_cwmax;
|
||||
@ -503,7 +503,7 @@ static void ath_beacon_config_ap(struct ath_softc *sc,
|
||||
|
||||
/* Set the computed AP beacon timers */
|
||||
|
||||
ath9k_hw_set_interrupts(ah, 0);
|
||||
ath9k_hw_disable_interrupts(ah);
|
||||
ath9k_beacon_init(sc, nexttbtt, intval);
|
||||
sc->beacon.bmisscnt = 0;
|
||||
ath9k_hw_set_interrupts(ah, ah->imask);
|
||||
@ -638,7 +638,7 @@ static void ath_beacon_config_sta(struct ath_softc *sc,
|
||||
|
||||
/* Set the computed STA beacon timers */
|
||||
|
||||
ath9k_hw_set_interrupts(ah, 0);
|
||||
ath9k_hw_disable_interrupts(ah);
|
||||
ath9k_hw_set_sta_beacon_timers(ah, &bs);
|
||||
ah->imask |= ATH9K_INT_BMISS;
|
||||
ath9k_hw_set_interrupts(ah, ah->imask);
|
||||
@ -686,7 +686,7 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc,
|
||||
|
||||
/* Set the computed ADHOC beacon timers */
|
||||
|
||||
ath9k_hw_set_interrupts(ah, 0);
|
||||
ath9k_hw_disable_interrupts(ah);
|
||||
ath9k_beacon_init(sc, nexttbtt, intval);
|
||||
sc->beacon.bmisscnt = 0;
|
||||
ath9k_hw_set_interrupts(ah, ah->imask);
|
||||
|
@ -107,12 +107,10 @@ static u32 ath9k_get_extchanmode(struct ieee80211_channel *chan,
|
||||
/*
|
||||
* Update internal channel flags.
|
||||
*/
|
||||
void ath9k_cmn_update_ichannel(struct ieee80211_hw *hw,
|
||||
struct ath9k_channel *ichan)
|
||||
void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan,
|
||||
struct ieee80211_channel *chan,
|
||||
enum nl80211_channel_type channel_type)
|
||||
{
|
||||
struct ieee80211_channel *chan = hw->conf.channel;
|
||||
struct ieee80211_conf *conf = &hw->conf;
|
||||
|
||||
ichan->channel = chan->center_freq;
|
||||
ichan->chan = chan;
|
||||
|
||||
@ -124,9 +122,8 @@ void ath9k_cmn_update_ichannel(struct ieee80211_hw *hw,
|
||||
ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM;
|
||||
}
|
||||
|
||||
if (conf_is_ht(conf))
|
||||
ichan->chanmode = ath9k_get_extchanmode(chan,
|
||||
conf->channel_type);
|
||||
if (channel_type != NL80211_CHAN_NO_HT)
|
||||
ichan->chanmode = ath9k_get_extchanmode(chan, channel_type);
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_cmn_update_ichannel);
|
||||
|
||||
@ -142,7 +139,7 @@ struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw,
|
||||
|
||||
chan_idx = curchan->hw_value;
|
||||
channel = &ah->channels[chan_idx];
|
||||
ath9k_cmn_update_ichannel(hw, channel);
|
||||
ath9k_cmn_update_ichannel(channel, curchan, hw->conf.channel_type);
|
||||
|
||||
return channel;
|
||||
}
|
||||
|
@ -31,10 +31,11 @@
|
||||
#define WME_MAX_BA WME_BA_BMP_SIZE
|
||||
#define ATH_TID_MAX_BUFS (2 * WME_MAX_BA)
|
||||
|
||||
#define WME_AC_BE 0
|
||||
#define WME_AC_BK 1
|
||||
#define WME_AC_VI 2
|
||||
#define WME_AC_VO 3
|
||||
/* These must match mac80211 skb queue mapping numbers */
|
||||
#define WME_AC_VO 0
|
||||
#define WME_AC_VI 1
|
||||
#define WME_AC_BE 2
|
||||
#define WME_AC_BK 3
|
||||
#define WME_NUM_AC 4
|
||||
|
||||
#define ATH_RSSI_DUMMY_MARKER 0x127
|
||||
@ -62,8 +63,9 @@ enum ath_stomp_type {
|
||||
|
||||
int ath9k_cmn_padpos(__le16 frame_control);
|
||||
int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb);
|
||||
void ath9k_cmn_update_ichannel(struct ieee80211_hw *hw,
|
||||
struct ath9k_channel *ichan);
|
||||
void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan,
|
||||
struct ieee80211_channel *chan,
|
||||
enum nl80211_channel_type channel_type);
|
||||
struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw,
|
||||
struct ath_hw *ah);
|
||||
int ath9k_cmn_count_streams(unsigned int chainmask, int max);
|
||||
|
@ -461,16 +461,16 @@ static ssize_t read_file_wiphy(struct file *file, char __user *user_buf,
|
||||
|
||||
/* Put variable-length stuff down here, and check for overflows. */
|
||||
for (i = 0; i < sc->num_sec_wiphy; i++) {
|
||||
struct ath_wiphy *aphy = sc->sec_wiphy[i];
|
||||
if (aphy == NULL)
|
||||
struct ath_wiphy *aphy_tmp = sc->sec_wiphy[i];
|
||||
if (aphy_tmp == NULL)
|
||||
continue;
|
||||
chan = aphy->hw->conf.channel;
|
||||
chan = aphy_tmp->hw->conf.channel;
|
||||
len += snprintf(buf + len, sizeof(buf) - len,
|
||||
"secondary: %s (%s chan=%d ht=%d)\n",
|
||||
wiphy_name(aphy->hw->wiphy),
|
||||
ath_wiphy_state_str(aphy->state),
|
||||
wiphy_name(aphy_tmp->hw->wiphy),
|
||||
ath_wiphy_state_str(aphy_tmp->state),
|
||||
ieee80211_frequency_to_channel(chan->center_freq),
|
||||
aphy->chan_is_ht);
|
||||
aphy_tmp->chan_is_ht);
|
||||
}
|
||||
if (len > sizeof(buf))
|
||||
len = sizeof(buf);
|
||||
@ -585,10 +585,10 @@ static const struct file_operations fops_wiphy = {
|
||||
do { \
|
||||
len += snprintf(buf + len, size - len, \
|
||||
"%s%13u%11u%10u%10u\n", str, \
|
||||
sc->debug.stats.txstats[sc->tx.hwq_map[WME_AC_BE]].elem, \
|
||||
sc->debug.stats.txstats[sc->tx.hwq_map[WME_AC_BK]].elem, \
|
||||
sc->debug.stats.txstats[sc->tx.hwq_map[WME_AC_VI]].elem, \
|
||||
sc->debug.stats.txstats[sc->tx.hwq_map[WME_AC_VO]].elem); \
|
||||
sc->debug.stats.txstats[WME_AC_BE].elem, \
|
||||
sc->debug.stats.txstats[WME_AC_BK].elem, \
|
||||
sc->debug.stats.txstats[WME_AC_VI].elem, \
|
||||
sc->debug.stats.txstats[WME_AC_VO].elem); \
|
||||
} while(0)
|
||||
|
||||
static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
|
||||
@ -630,33 +630,35 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
|
||||
return retval;
|
||||
}
|
||||
|
||||
void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq,
|
||||
struct ath_buf *bf, struct ath_tx_status *ts)
|
||||
void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
|
||||
struct ath_tx_status *ts)
|
||||
{
|
||||
TX_STAT_INC(txq->axq_qnum, tx_pkts_all);
|
||||
sc->debug.stats.txstats[txq->axq_qnum].tx_bytes_all += bf->bf_mpdu->len;
|
||||
int qnum = skb_get_queue_mapping(bf->bf_mpdu);
|
||||
|
||||
TX_STAT_INC(qnum, tx_pkts_all);
|
||||
sc->debug.stats.txstats[qnum].tx_bytes_all += bf->bf_mpdu->len;
|
||||
|
||||
if (bf_isampdu(bf)) {
|
||||
if (bf_isxretried(bf))
|
||||
TX_STAT_INC(txq->axq_qnum, a_xretries);
|
||||
TX_STAT_INC(qnum, a_xretries);
|
||||
else
|
||||
TX_STAT_INC(txq->axq_qnum, a_completed);
|
||||
TX_STAT_INC(qnum, a_completed);
|
||||
} else {
|
||||
TX_STAT_INC(txq->axq_qnum, completed);
|
||||
TX_STAT_INC(qnum, completed);
|
||||
}
|
||||
|
||||
if (ts->ts_status & ATH9K_TXERR_FIFO)
|
||||
TX_STAT_INC(txq->axq_qnum, fifo_underrun);
|
||||
TX_STAT_INC(qnum, fifo_underrun);
|
||||
if (ts->ts_status & ATH9K_TXERR_XTXOP)
|
||||
TX_STAT_INC(txq->axq_qnum, xtxop);
|
||||
TX_STAT_INC(qnum, xtxop);
|
||||
if (ts->ts_status & ATH9K_TXERR_TIMER_EXPIRED)
|
||||
TX_STAT_INC(txq->axq_qnum, timer_exp);
|
||||
TX_STAT_INC(qnum, timer_exp);
|
||||
if (ts->ts_flags & ATH9K_TX_DESC_CFG_ERR)
|
||||
TX_STAT_INC(txq->axq_qnum, desc_cfg_err);
|
||||
TX_STAT_INC(qnum, desc_cfg_err);
|
||||
if (ts->ts_flags & ATH9K_TX_DATA_UNDERRUN)
|
||||
TX_STAT_INC(txq->axq_qnum, data_underrun);
|
||||
TX_STAT_INC(qnum, data_underrun);
|
||||
if (ts->ts_flags & ATH9K_TX_DELIM_UNDERRUN)
|
||||
TX_STAT_INC(txq->axq_qnum, delim_underrun);
|
||||
TX_STAT_INC(qnum, delim_underrun);
|
||||
}
|
||||
|
||||
static const struct file_operations fops_xmit = {
|
||||
|
@ -169,8 +169,8 @@ void ath9k_exit_debug(struct ath_hw *ah);
|
||||
int ath9k_debug_create_root(void);
|
||||
void ath9k_debug_remove_root(void);
|
||||
void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status);
|
||||
void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq,
|
||||
struct ath_buf *bf, struct ath_tx_status *ts);
|
||||
void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
|
||||
struct ath_tx_status *ts);
|
||||
void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs);
|
||||
|
||||
#else
|
||||
@ -199,7 +199,6 @@ static inline void ath_debug_stat_interrupt(struct ath_softc *sc,
|
||||
}
|
||||
|
||||
static inline void ath_debug_stat_tx(struct ath_softc *sc,
|
||||
struct ath_txq *txq,
|
||||
struct ath_buf *bf,
|
||||
struct ath_tx_status *ts)
|
||||
{
|
||||
|
@ -680,7 +680,8 @@ struct eeprom_ops {
|
||||
void (*set_addac)(struct ath_hw *hw, struct ath9k_channel *chan);
|
||||
void (*set_txpower)(struct ath_hw *hw, struct ath9k_channel *chan,
|
||||
u16 cfgCtl, u8 twiceAntennaReduction,
|
||||
u8 twiceMaxRegulatoryPower, u8 powerLimit);
|
||||
u8 twiceMaxRegulatoryPower, u8 powerLimit,
|
||||
bool test);
|
||||
u16 (*get_spur_channel)(struct ath_hw *ah, u16 i, bool is2GHz);
|
||||
};
|
||||
|
||||
|
@ -726,7 +726,7 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
|
||||
u16 cfgCtl,
|
||||
u8 twiceAntennaReduction,
|
||||
u8 twiceMaxRegulatoryPower,
|
||||
u8 powerLimit)
|
||||
u8 powerLimit, bool test)
|
||||
{
|
||||
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
|
||||
struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
|
||||
@ -751,15 +751,20 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
|
||||
|
||||
ath9k_hw_set_4k_power_cal_table(ah, chan, &txPowerIndexOffset);
|
||||
|
||||
regulatory->max_power_level = 0;
|
||||
for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
|
||||
ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
|
||||
if (ratesArray[i] > AR5416_MAX_RATE_POWER)
|
||||
ratesArray[i] = AR5416_MAX_RATE_POWER;
|
||||
|
||||
if (ratesArray[i] > regulatory->max_power_level)
|
||||
regulatory->max_power_level = ratesArray[i];
|
||||
}
|
||||
|
||||
if (test)
|
||||
return;
|
||||
|
||||
/* Update regulatory */
|
||||
|
||||
i = rate6mb;
|
||||
if (IS_CHAN_HT40(chan))
|
||||
i = rateHt40_0;
|
||||
|
@ -853,7 +853,7 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan, u16 cfgCtl,
|
||||
u8 twiceAntennaReduction,
|
||||
u8 twiceMaxRegulatoryPower,
|
||||
u8 powerLimit)
|
||||
u8 powerLimit, bool test)
|
||||
{
|
||||
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
|
||||
struct ar9287_eeprom *pEepData = &ah->eeprom.map9287;
|
||||
@ -877,12 +877,26 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah,
|
||||
|
||||
ath9k_hw_set_ar9287_power_cal_table(ah, chan, &txPowerIndexOffset);
|
||||
|
||||
regulatory->max_power_level = 0;
|
||||
for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
|
||||
ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
|
||||
if (ratesArray[i] > AR9287_MAX_RATE_POWER)
|
||||
ratesArray[i] = AR9287_MAX_RATE_POWER;
|
||||
|
||||
if (ratesArray[i] > regulatory->max_power_level)
|
||||
regulatory->max_power_level = ratesArray[i];
|
||||
}
|
||||
|
||||
if (test)
|
||||
return;
|
||||
|
||||
if (IS_CHAN_2GHZ(chan))
|
||||
i = rate1l;
|
||||
else
|
||||
i = rate6mb;
|
||||
|
||||
regulatory->max_power_level = ratesArray[i];
|
||||
|
||||
if (AR_SREV_9280_20_OR_LATER(ah)) {
|
||||
for (i = 0; i < Ar5416RateSize; i++)
|
||||
ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2;
|
||||
@ -971,17 +985,6 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah,
|
||||
| ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
|
||||
| ATH9K_POW_SM(ratesArray[rateDupCck], 0));
|
||||
}
|
||||
|
||||
if (IS_CHAN_2GHZ(chan))
|
||||
i = rate1l;
|
||||
else
|
||||
i = rate6mb;
|
||||
|
||||
if (AR_SREV_9280_20_OR_LATER(ah))
|
||||
regulatory->max_power_level =
|
||||
ratesArray[i] + AR9287_PWR_TABLE_OFFSET_DB * 2;
|
||||
else
|
||||
regulatory->max_power_level = ratesArray[i];
|
||||
}
|
||||
|
||||
static void ath9k_hw_ar9287_set_addac(struct ath_hw *ah,
|
||||
|
@ -1258,7 +1258,7 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
|
||||
u16 cfgCtl,
|
||||
u8 twiceAntennaReduction,
|
||||
u8 twiceMaxRegulatoryPower,
|
||||
u8 powerLimit)
|
||||
u8 powerLimit, bool test)
|
||||
{
|
||||
#define RT_AR_DELTA(x) (ratesArray[x] - cck_ofdm_delta)
|
||||
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
|
||||
@ -1285,12 +1285,44 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
|
||||
|
||||
ath9k_hw_set_def_power_cal_table(ah, chan, &txPowerIndexOffset);
|
||||
|
||||
regulatory->max_power_level = 0;
|
||||
for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
|
||||
ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
|
||||
if (ratesArray[i] > AR5416_MAX_RATE_POWER)
|
||||
ratesArray[i] = AR5416_MAX_RATE_POWER;
|
||||
if (ratesArray[i] > regulatory->max_power_level)
|
||||
regulatory->max_power_level = ratesArray[i];
|
||||
}
|
||||
|
||||
if (!test) {
|
||||
i = rate6mb;
|
||||
|
||||
if (IS_CHAN_HT40(chan))
|
||||
i = rateHt40_0;
|
||||
else if (IS_CHAN_HT20(chan))
|
||||
i = rateHt20_0;
|
||||
|
||||
regulatory->max_power_level = ratesArray[i];
|
||||
}
|
||||
|
||||
switch(ar5416_get_ntxchains(ah->txchainmask)) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
regulatory->max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN;
|
||||
break;
|
||||
case 3:
|
||||
regulatory->max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN;
|
||||
break;
|
||||
default:
|
||||
ath_print(ath9k_hw_common(ah), ATH_DBG_EEPROM,
|
||||
"Invalid chainmask configuration\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (test)
|
||||
return;
|
||||
|
||||
if (AR_SREV_9280_20_OR_LATER(ah)) {
|
||||
for (i = 0; i < Ar5416RateSize; i++) {
|
||||
int8_t pwr_table_offset;
|
||||
@ -1387,34 +1419,6 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
|
||||
REG_WRITE(ah, AR_PHY_POWER_TX_SUB,
|
||||
ATH9K_POW_SM(pModal->pwrDecreaseFor3Chain, 6)
|
||||
| ATH9K_POW_SM(pModal->pwrDecreaseFor2Chain, 0));
|
||||
|
||||
i = rate6mb;
|
||||
|
||||
if (IS_CHAN_HT40(chan))
|
||||
i = rateHt40_0;
|
||||
else if (IS_CHAN_HT20(chan))
|
||||
i = rateHt20_0;
|
||||
|
||||
if (AR_SREV_9280_20_OR_LATER(ah))
|
||||
regulatory->max_power_level =
|
||||
ratesArray[i] + AR5416_PWR_TABLE_OFFSET_DB * 2;
|
||||
else
|
||||
regulatory->max_power_level = ratesArray[i];
|
||||
|
||||
switch(ar5416_get_ntxchains(ah->txchainmask)) {
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
regulatory->max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN;
|
||||
break;
|
||||
case 3:
|
||||
regulatory->max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN;
|
||||
break;
|
||||
default:
|
||||
ath_print(ath9k_hw_common(ah), ATH_DBG_EEPROM,
|
||||
"Invalid chainmask configuration\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static u8 ath9k_hw_def_get_num_ant_config(struct ath_hw *ah,
|
||||
|
@ -259,7 +259,7 @@ static void ath9k_gen_timer_start(struct ath_hw *ah,
|
||||
ath9k_hw_gen_timer_start(ah, timer, timer_next, timer_period);
|
||||
|
||||
if ((ah->imask & ATH9K_INT_GENTIMER) == 0) {
|
||||
ath9k_hw_set_interrupts(ah, 0);
|
||||
ath9k_hw_disable_interrupts(ah);
|
||||
ah->imask |= ATH9K_INT_GENTIMER;
|
||||
ath9k_hw_set_interrupts(ah, ah->imask);
|
||||
}
|
||||
@ -273,7 +273,7 @@ static void ath9k_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer)
|
||||
|
||||
/* if no timer is enabled, turn off interrupt mask */
|
||||
if (timer_table->timer_mask.val == 0) {
|
||||
ath9k_hw_set_interrupts(ah, 0);
|
||||
ath9k_hw_disable_interrupts(ah);
|
||||
ah->imask &= ~ATH9K_INT_GENTIMER;
|
||||
ath9k_hw_set_interrupts(ah, ah->imask);
|
||||
}
|
||||
@ -310,10 +310,8 @@ static void ath_btcoex_period_timer(unsigned long data)
|
||||
|
||||
timer_period = is_btscan ? btcoex->btscan_no_stomp :
|
||||
btcoex->btcoex_no_stomp;
|
||||
ath9k_gen_timer_start(ah,
|
||||
btcoex->no_stomp_timer,
|
||||
(ath9k_hw_gettsf32(ah) +
|
||||
timer_period), timer_period * 10);
|
||||
ath9k_gen_timer_start(ah, btcoex->no_stomp_timer, 0,
|
||||
timer_period * 10);
|
||||
btcoex->hw_timer_enabled = true;
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,7 @@ static void ath_update_txpow(struct ath9k_htc_priv *priv)
|
||||
struct ath_hw *ah = priv->ah;
|
||||
|
||||
if (priv->curtxpow != priv->txpowlimit) {
|
||||
ath9k_hw_set_txpowerlimit(ah, priv->txpowlimit);
|
||||
ath9k_hw_set_txpowerlimit(ah, priv->txpowlimit, false);
|
||||
/* read back in case value is clamped */
|
||||
priv->curtxpow = ath9k_hw_regulatory(ah)->power_limit;
|
||||
}
|
||||
@ -184,47 +184,6 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath9k_htc_add_monitor_interface(struct ath9k_htc_priv *priv)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(priv->ah);
|
||||
struct ath9k_htc_target_vif hvif;
|
||||
int ret = 0;
|
||||
u8 cmd_rsp;
|
||||
|
||||
if (priv->nvifs > 0)
|
||||
return -ENOBUFS;
|
||||
|
||||
memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif));
|
||||
memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN);
|
||||
|
||||
hvif.opmode = cpu_to_be32(HTC_M_MONITOR);
|
||||
priv->ah->opmode = NL80211_IFTYPE_MONITOR;
|
||||
hvif.index = priv->nvifs;
|
||||
|
||||
WMI_CMD_BUF(WMI_VAP_CREATE_CMDID, &hvif);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
priv->nvifs++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath9k_htc_remove_monitor_interface(struct ath9k_htc_priv *priv)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(priv->ah);
|
||||
struct ath9k_htc_target_vif hvif;
|
||||
int ret = 0;
|
||||
u8 cmd_rsp;
|
||||
|
||||
memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif));
|
||||
memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN);
|
||||
hvif.index = 0; /* Should do for now */
|
||||
WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif);
|
||||
priv->nvifs--;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath9k_htc_add_station(struct ath9k_htc_priv *priv,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta)
|
||||
@ -1240,16 +1199,6 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw)
|
||||
WMI_CMD(WMI_STOP_RECV_CMDID);
|
||||
skb_queue_purge(&priv->tx_queue);
|
||||
|
||||
/* Remove monitor interface here */
|
||||
if (ah->opmode == NL80211_IFTYPE_MONITOR) {
|
||||
if (ath9k_htc_remove_monitor_interface(priv))
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Unable to remove monitor interface\n");
|
||||
else
|
||||
ath_print(common, ATH_DBG_CONFIG,
|
||||
"Monitor interface removed\n");
|
||||
}
|
||||
|
||||
if (ah->btcoex_hw.enabled) {
|
||||
ath9k_hw_btcoex_disable(ah);
|
||||
if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
|
||||
@ -1400,7 +1349,9 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
|
||||
ath_print(common, ATH_DBG_CONFIG, "Set channel: %d MHz\n",
|
||||
curchan->center_freq);
|
||||
|
||||
ath9k_cmn_update_ichannel(hw, &priv->ah->channels[pos]);
|
||||
ath9k_cmn_update_ichannel(&priv->ah->channels[pos],
|
||||
hw->conf.channel,
|
||||
hw->conf.channel_type);
|
||||
|
||||
if (ath9k_htc_set_channel(priv, hw, &priv->ah->channels[pos]) < 0) {
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
@ -1421,16 +1372,13 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
|
||||
}
|
||||
}
|
||||
|
||||
if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
|
||||
if (changed & IEEE80211_CONF_CHANGE_MONITOR)
|
||||
if (conf->flags & IEEE80211_CONF_MONITOR) {
|
||||
if (ath9k_htc_add_monitor_interface(priv))
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Failed to set monitor mode\n");
|
||||
else
|
||||
ath_print(common, ATH_DBG_CONFIG,
|
||||
"HW opmode set to Monitor mode\n");
|
||||
ath_print(common, ATH_DBG_CONFIG,
|
||||
"HW opmode set to Monitor mode\n");
|
||||
priv->ah->opmode = NL80211_IFTYPE_MONITOR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (changed & IEEE80211_CONF_CHANGE_IDLE) {
|
||||
mutex_lock(&priv->htc_pm_lock);
|
||||
|
@ -20,8 +20,15 @@
|
||||
/* TX */
|
||||
/******/
|
||||
|
||||
static const int subtype_txq_to_hwq[] = {
|
||||
[WME_AC_BE] = ATH_TXQ_AC_BE,
|
||||
[WME_AC_BK] = ATH_TXQ_AC_BK,
|
||||
[WME_AC_VI] = ATH_TXQ_AC_VI,
|
||||
[WME_AC_VO] = ATH_TXQ_AC_VO,
|
||||
};
|
||||
|
||||
#define ATH9K_HTC_INIT_TXQ(subtype) do { \
|
||||
qi.tqi_subtype = subtype; \
|
||||
qi.tqi_subtype = subtype_txq_to_hwq[subtype]; \
|
||||
qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT; \
|
||||
qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT; \
|
||||
qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT; \
|
||||
|
@ -1170,7 +1170,7 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
|
||||
channel->max_antenna_gain * 2,
|
||||
channel->max_power * 2,
|
||||
min((u32) MAX_RATE_POWER,
|
||||
(u32) regulatory->power_limit));
|
||||
(u32) regulatory->power_limit), false);
|
||||
|
||||
ath9k_hw_rfbus_done(ah);
|
||||
|
||||
@ -2176,7 +2176,7 @@ bool ath9k_hw_disable(struct ath_hw *ah)
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_disable);
|
||||
|
||||
void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit)
|
||||
void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test)
|
||||
{
|
||||
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
|
||||
struct ath9k_channel *chan = ah->curchan;
|
||||
@ -2189,7 +2189,7 @@ void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit)
|
||||
channel->max_antenna_gain * 2,
|
||||
channel->max_power * 2,
|
||||
min((u32) MAX_RATE_POWER,
|
||||
(u32) regulatory->power_limit));
|
||||
(u32) regulatory->power_limit), test);
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_set_txpowerlimit);
|
||||
|
||||
@ -2323,11 +2323,10 @@ static u32 rightmost_index(struct ath_gen_timer_table *timer_table, u32 *mask)
|
||||
return timer_table->gen_timer_index[b];
|
||||
}
|
||||
|
||||
u32 ath9k_hw_gettsf32(struct ath_hw *ah)
|
||||
static u32 ath9k_hw_gettsf32(struct ath_hw *ah)
|
||||
{
|
||||
return REG_READ(ah, AR_TSF_L32);
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_gettsf32);
|
||||
|
||||
struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah,
|
||||
void (*trigger)(void *),
|
||||
|
@ -157,6 +157,13 @@
|
||||
#define PAPRD_GAIN_TABLE_ENTRIES 32
|
||||
#define PAPRD_TABLE_SZ 24
|
||||
|
||||
enum ath_hw_txq_subtype {
|
||||
ATH_TXQ_AC_BE = 0,
|
||||
ATH_TXQ_AC_BK = 1,
|
||||
ATH_TXQ_AC_VI = 2,
|
||||
ATH_TXQ_AC_VO = 3,
|
||||
};
|
||||
|
||||
enum ath_ini_subsys {
|
||||
ATH_INI_PRE = 0,
|
||||
ATH_INI_CORE,
|
||||
@ -819,12 +826,6 @@ static inline struct ath_hw_ops *ath9k_hw_ops(struct ath_hw *ah)
|
||||
return &ah->ops;
|
||||
}
|
||||
|
||||
static inline int sign_extend(int val, const int nbits)
|
||||
{
|
||||
int order = BIT(nbits-1);
|
||||
return (val ^ order) - order;
|
||||
}
|
||||
|
||||
/* Initialization, Detach, Reset */
|
||||
const char *ath9k_hw_probe(u16 vendorid, u16 devid);
|
||||
void ath9k_hw_deinit(struct ath_hw *ah);
|
||||
@ -861,7 +862,7 @@ u32 ath9k_hw_getrxfilter(struct ath_hw *ah);
|
||||
void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits);
|
||||
bool ath9k_hw_phy_disable(struct ath_hw *ah);
|
||||
bool ath9k_hw_disable(struct ath_hw *ah);
|
||||
void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit);
|
||||
void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test);
|
||||
void ath9k_hw_setopmode(struct ath_hw *ah);
|
||||
void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1);
|
||||
void ath9k_hw_setbssidmask(struct ath_hw *ah);
|
||||
@ -893,7 +894,6 @@ void ath9k_hw_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer);
|
||||
|
||||
void ath_gen_timer_free(struct ath_hw *ah, struct ath_gen_timer *timer);
|
||||
void ath_gen_timer_isr(struct ath_hw *hw);
|
||||
u32 ath9k_hw_gettsf32(struct ath_hw *ah);
|
||||
|
||||
void ath9k_hw_name(struct ath_hw *ah, char *hw_name, size_t len);
|
||||
|
||||
|
@ -398,7 +398,8 @@ static void ath9k_init_crypto(struct ath_softc *sc)
|
||||
|
||||
static int ath9k_init_btcoex(struct ath_softc *sc)
|
||||
{
|
||||
int r, qnum;
|
||||
struct ath_txq *txq;
|
||||
int r;
|
||||
|
||||
switch (sc->sc_ah->btcoex_hw.scheme) {
|
||||
case ATH_BTCOEX_CFG_NONE:
|
||||
@ -411,8 +412,8 @@ static int ath9k_init_btcoex(struct ath_softc *sc)
|
||||
r = ath_init_btcoex_timer(sc);
|
||||
if (r)
|
||||
return -1;
|
||||
qnum = sc->tx.hwq_map[WME_AC_BE];
|
||||
ath9k_hw_init_btcoex_hw(sc->sc_ah, qnum);
|
||||
txq = sc->tx.txq_map[WME_AC_BE];
|
||||
ath9k_hw_init_btcoex_hw(sc->sc_ah, txq->axq_qnum);
|
||||
sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW;
|
||||
break;
|
||||
default:
|
||||
@ -425,59 +426,18 @@ static int ath9k_init_btcoex(struct ath_softc *sc)
|
||||
|
||||
static int ath9k_init_queues(struct ath_softc *sc)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(sc->tx.hwq_map); i++)
|
||||
sc->tx.hwq_map[i] = -1;
|
||||
|
||||
sc->beacon.beaconq = ath9k_hw_beaconq_setup(sc->sc_ah);
|
||||
if (sc->beacon.beaconq == -1) {
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Unable to setup a beacon xmit queue\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0);
|
||||
if (sc->beacon.cabq == NULL) {
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Unable to setup CAB xmit queue\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
sc->config.cabqReadytime = ATH_CABQ_READY_TIME;
|
||||
ath_cabq_update(sc);
|
||||
|
||||
if (!ath_tx_setup(sc, WME_AC_BK)) {
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Unable to setup xmit queue for BK traffic\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!ath_tx_setup(sc, WME_AC_BE)) {
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Unable to setup xmit queue for BE traffic\n");
|
||||
goto err;
|
||||
}
|
||||
if (!ath_tx_setup(sc, WME_AC_VI)) {
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Unable to setup xmit queue for VI traffic\n");
|
||||
goto err;
|
||||
}
|
||||
if (!ath_tx_setup(sc, WME_AC_VO)) {
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Unable to setup xmit queue for VO traffic\n");
|
||||
goto err;
|
||||
}
|
||||
for (i = 0; i < WME_NUM_AC; i++)
|
||||
sc->tx.txq_map[i] = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, i);
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
|
||||
if (ATH_TXQ_SETUP(sc, i))
|
||||
ath_tx_cleanupq(sc, &sc->tx.txq[i]);
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static int ath9k_init_channels_rates(struct ath_softc *sc)
|
||||
@ -583,7 +543,6 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,
|
||||
spin_lock_init(&common->cc_lock);
|
||||
|
||||
spin_lock_init(&sc->wiphy_lock);
|
||||
spin_lock_init(&sc->sc_resetlock);
|
||||
spin_lock_init(&sc->sc_serial_rw);
|
||||
spin_lock_init(&sc->sc_pm_lock);
|
||||
mutex_init(&sc->mutex);
|
||||
@ -645,6 +604,37 @@ err_hw:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ath9k_init_band_txpower(struct ath_softc *sc, int band)
|
||||
{
|
||||
struct ieee80211_supported_band *sband;
|
||||
struct ieee80211_channel *chan;
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
|
||||
int i;
|
||||
|
||||
sband = &sc->sbands[band];
|
||||
for (i = 0; i < sband->n_channels; i++) {
|
||||
chan = &sband->channels[i];
|
||||
ah->curchan = &ah->channels[chan->hw_value];
|
||||
ath9k_cmn_update_ichannel(ah->curchan, chan, NL80211_CHAN_HT20);
|
||||
ath9k_hw_set_txpowerlimit(ah, MAX_RATE_POWER, true);
|
||||
chan->max_power = reg->max_power_level / 2;
|
||||
}
|
||||
}
|
||||
|
||||
static void ath9k_init_txpower_limits(struct ath_softc *sc)
|
||||
{
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath9k_channel *curchan = ah->curchan;
|
||||
|
||||
if (ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
|
||||
ath9k_init_band_txpower(sc, IEEE80211_BAND_2GHZ);
|
||||
if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
|
||||
ath9k_init_band_txpower(sc, IEEE80211_BAND_5GHZ);
|
||||
|
||||
ah->curchan = curchan;
|
||||
}
|
||||
|
||||
void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
@ -706,6 +696,7 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,
|
||||
const struct ath_bus_ops *bus_ops)
|
||||
{
|
||||
struct ieee80211_hw *hw = sc->hw;
|
||||
struct ath_wiphy *aphy = hw->priv;
|
||||
struct ath_common *common;
|
||||
struct ath_hw *ah;
|
||||
int error = 0;
|
||||
@ -738,6 +729,8 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,
|
||||
if (error != 0)
|
||||
goto error_rx;
|
||||
|
||||
ath9k_init_txpower_limits(sc);
|
||||
|
||||
/* Register with mac80211 */
|
||||
error = ieee80211_register_hw(hw);
|
||||
if (error)
|
||||
@ -755,6 +748,7 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,
|
||||
INIT_WORK(&sc->chan_work, ath9k_wiphy_chan_work);
|
||||
INIT_DELAYED_WORK(&sc->wiphy_work, ath9k_wiphy_work);
|
||||
sc->wiphy_scheduler_int = msecs_to_jiffies(500);
|
||||
aphy->last_rssi = ATH_RSSI_DUMMY_MARKER;
|
||||
|
||||
ath_init_leds(sc);
|
||||
ath_start_rfkill_poll(sc);
|
||||
|
@ -117,12 +117,11 @@ EXPORT_SYMBOL(ath9k_hw_numtxpending);
|
||||
bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel)
|
||||
{
|
||||
u32 txcfg, curLevel, newLevel;
|
||||
enum ath9k_int omask;
|
||||
|
||||
if (ah->tx_trig_level >= ah->config.max_txtrig_level)
|
||||
return false;
|
||||
|
||||
omask = ath9k_hw_set_interrupts(ah, ah->imask & ~ATH9K_INT_GLOBAL);
|
||||
ath9k_hw_disable_interrupts(ah);
|
||||
|
||||
txcfg = REG_READ(ah, AR_TXCFG);
|
||||
curLevel = MS(txcfg, AR_FTRIG);
|
||||
@ -136,7 +135,7 @@ bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel)
|
||||
REG_WRITE(ah, AR_TXCFG,
|
||||
(txcfg & ~AR_FTRIG) | SM(newLevel, AR_FTRIG));
|
||||
|
||||
ath9k_hw_set_interrupts(ah, omask);
|
||||
ath9k_hw_enable_interrupts(ah);
|
||||
|
||||
ah->tx_trig_level = newLevel;
|
||||
|
||||
@ -849,29 +848,60 @@ bool ath9k_hw_intrpend(struct ath_hw *ah)
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_intrpend);
|
||||
|
||||
enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah,
|
||||
enum ath9k_int ints)
|
||||
void ath9k_hw_disable_interrupts(struct ath_hw *ah)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
|
||||
ath_print(common, ATH_DBG_INTERRUPT, "disable IER\n");
|
||||
REG_WRITE(ah, AR_IER, AR_IER_DISABLE);
|
||||
(void) REG_READ(ah, AR_IER);
|
||||
if (!AR_SREV_9100(ah)) {
|
||||
REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0);
|
||||
(void) REG_READ(ah, AR_INTR_ASYNC_ENABLE);
|
||||
|
||||
REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0);
|
||||
(void) REG_READ(ah, AR_INTR_SYNC_ENABLE);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_disable_interrupts);
|
||||
|
||||
void ath9k_hw_enable_interrupts(struct ath_hw *ah)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
|
||||
if (!(ah->imask & ATH9K_INT_GLOBAL))
|
||||
return;
|
||||
|
||||
ath_print(common, ATH_DBG_INTERRUPT, "enable IER\n");
|
||||
REG_WRITE(ah, AR_IER, AR_IER_ENABLE);
|
||||
if (!AR_SREV_9100(ah)) {
|
||||
REG_WRITE(ah, AR_INTR_ASYNC_ENABLE,
|
||||
AR_INTR_MAC_IRQ);
|
||||
REG_WRITE(ah, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ);
|
||||
|
||||
|
||||
REG_WRITE(ah, AR_INTR_SYNC_ENABLE,
|
||||
AR_INTR_SYNC_DEFAULT);
|
||||
REG_WRITE(ah, AR_INTR_SYNC_MASK,
|
||||
AR_INTR_SYNC_DEFAULT);
|
||||
}
|
||||
ath_print(common, ATH_DBG_INTERRUPT, "AR_IMR 0x%x IER 0x%x\n",
|
||||
REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER));
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_enable_interrupts);
|
||||
|
||||
void ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints)
|
||||
{
|
||||
enum ath9k_int omask = ah->imask;
|
||||
u32 mask, mask2;
|
||||
struct ath9k_hw_capabilities *pCap = &ah->caps;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
|
||||
if (!(ints & ATH9K_INT_GLOBAL))
|
||||
ath9k_hw_enable_interrupts(ah);
|
||||
|
||||
ath_print(common, ATH_DBG_INTERRUPT, "0x%x => 0x%x\n", omask, ints);
|
||||
|
||||
if (omask & ATH9K_INT_GLOBAL) {
|
||||
ath_print(common, ATH_DBG_INTERRUPT, "disable IER\n");
|
||||
REG_WRITE(ah, AR_IER, AR_IER_DISABLE);
|
||||
(void) REG_READ(ah, AR_IER);
|
||||
if (!AR_SREV_9100(ah)) {
|
||||
REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0);
|
||||
(void) REG_READ(ah, AR_INTR_ASYNC_ENABLE);
|
||||
|
||||
REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0);
|
||||
(void) REG_READ(ah, AR_INTR_SYNC_ENABLE);
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: global int Ref count */
|
||||
mask = ints & ATH9K_INT_COMMON;
|
||||
mask2 = 0;
|
||||
@ -946,24 +976,8 @@ enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah,
|
||||
REG_CLR_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER);
|
||||
}
|
||||
|
||||
if (ints & ATH9K_INT_GLOBAL) {
|
||||
ath_print(common, ATH_DBG_INTERRUPT, "enable IER\n");
|
||||
REG_WRITE(ah, AR_IER, AR_IER_ENABLE);
|
||||
if (!AR_SREV_9100(ah)) {
|
||||
REG_WRITE(ah, AR_INTR_ASYNC_ENABLE,
|
||||
AR_INTR_MAC_IRQ);
|
||||
REG_WRITE(ah, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ);
|
||||
ath9k_hw_enable_interrupts(ah);
|
||||
|
||||
|
||||
REG_WRITE(ah, AR_INTR_SYNC_ENABLE,
|
||||
AR_INTR_SYNC_DEFAULT);
|
||||
REG_WRITE(ah, AR_INTR_SYNC_MASK,
|
||||
AR_INTR_SYNC_DEFAULT);
|
||||
}
|
||||
ath_print(common, ATH_DBG_INTERRUPT, "AR_IMR 0x%x IER 0x%x\n",
|
||||
REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER));
|
||||
}
|
||||
|
||||
return omask;
|
||||
return;
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_set_interrupts);
|
||||
|
@ -104,13 +104,11 @@ struct ath_tx_status {
|
||||
u32 ts_tstamp;
|
||||
u16 ts_seqnum;
|
||||
u8 ts_status;
|
||||
u8 ts_ratecode;
|
||||
u8 ts_rateindex;
|
||||
int8_t ts_rssi;
|
||||
u8 ts_shortretry;
|
||||
u8 ts_longretry;
|
||||
u8 ts_virtcol;
|
||||
u8 ts_antenna;
|
||||
u8 ts_flags;
|
||||
int8_t ts_rssi_ctl0;
|
||||
int8_t ts_rssi_ctl1;
|
||||
@ -121,7 +119,6 @@ struct ath_tx_status {
|
||||
u8 qid;
|
||||
u16 desc_id;
|
||||
u8 tid;
|
||||
u8 pad[2];
|
||||
u32 ba_low;
|
||||
u32 ba_high;
|
||||
u32 evm0;
|
||||
@ -240,7 +237,7 @@ struct ath_desc {
|
||||
u32 ds_ctl1;
|
||||
u32 ds_hw[20];
|
||||
void *ds_vdata;
|
||||
} __packed;
|
||||
} __packed __aligned(4);
|
||||
|
||||
#define ATH9K_TXDESC_CLRDMASK 0x0001
|
||||
#define ATH9K_TXDESC_NOACK 0x0002
|
||||
@ -310,7 +307,7 @@ struct ar5416_desc {
|
||||
u32 status8;
|
||||
} rx;
|
||||
} u;
|
||||
} __packed;
|
||||
} __packed __aligned(4);
|
||||
|
||||
#define AR5416DESC(_ds) ((struct ar5416_desc *)(_ds))
|
||||
#define AR5416DESC_CONST(_ds) ((const struct ar5416_desc *)(_ds))
|
||||
@ -669,6 +666,7 @@ enum ath9k_key_type {
|
||||
|
||||
struct ath_hw;
|
||||
struct ath9k_channel;
|
||||
enum ath9k_int;
|
||||
|
||||
u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q);
|
||||
void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp);
|
||||
@ -700,8 +698,9 @@ int ath9k_hw_beaconq_setup(struct ath_hw *ah);
|
||||
|
||||
/* Interrupt Handling */
|
||||
bool ath9k_hw_intrpend(struct ath_hw *ah);
|
||||
enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah,
|
||||
enum ath9k_int ints);
|
||||
void ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints);
|
||||
void ath9k_hw_enable_interrupts(struct ath_hw *ah);
|
||||
void ath9k_hw_disable_interrupts(struct ath_hw *ah);
|
||||
|
||||
void ar9002_hw_attach_mac_ops(struct ath_hw *ah);
|
||||
|
||||
|
@ -24,7 +24,7 @@ static void ath_update_txpow(struct ath_softc *sc)
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
|
||||
if (sc->curtxpow != sc->config.txpowlimit) {
|
||||
ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit);
|
||||
ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit, false);
|
||||
/* read back in case value is clamped */
|
||||
sc->curtxpow = ath9k_hw_regulatory(ah)->power_limit;
|
||||
}
|
||||
@ -235,6 +235,8 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
|
||||
|
||||
ath9k_ps_wakeup(sc);
|
||||
|
||||
spin_lock_bh(&sc->sc_pcu_lock);
|
||||
|
||||
/*
|
||||
* This is only performed if the channel settings have
|
||||
* actually changed.
|
||||
@ -244,11 +246,9 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
|
||||
* hardware at the new frequency, and then re-enable
|
||||
* the relevant bits of the h/w.
|
||||
*/
|
||||
ath9k_hw_set_interrupts(ah, 0);
|
||||
ath9k_hw_disable_interrupts(ah);
|
||||
ath_drain_all_txq(sc, false);
|
||||
|
||||
spin_lock_bh(&sc->rx.pcu_lock);
|
||||
|
||||
stopped = ath_stoprecv(sc);
|
||||
|
||||
/* XXX: do not flush receive queue here. We don't want
|
||||
@ -267,30 +267,22 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
|
||||
channel->center_freq, conf_is_ht40(conf),
|
||||
fastcc);
|
||||
|
||||
spin_lock_bh(&sc->sc_resetlock);
|
||||
|
||||
r = ath9k_hw_reset(ah, hchan, caldata, fastcc);
|
||||
if (r) {
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Unable to reset channel (%u MHz), "
|
||||
"reset status %d\n",
|
||||
channel->center_freq, r);
|
||||
spin_unlock_bh(&sc->sc_resetlock);
|
||||
spin_unlock_bh(&sc->rx.pcu_lock);
|
||||
goto ps_restore;
|
||||
}
|
||||
spin_unlock_bh(&sc->sc_resetlock);
|
||||
|
||||
if (ath_startrecv(sc) != 0) {
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Unable to restart recv logic\n");
|
||||
r = -EIO;
|
||||
spin_unlock_bh(&sc->rx.pcu_lock);
|
||||
goto ps_restore;
|
||||
}
|
||||
|
||||
spin_unlock_bh(&sc->rx.pcu_lock);
|
||||
|
||||
ath_update_txpow(sc);
|
||||
ath9k_hw_set_interrupts(ah, ah->imask);
|
||||
|
||||
@ -301,6 +293,8 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
|
||||
}
|
||||
|
||||
ps_restore:
|
||||
spin_unlock_bh(&sc->sc_pcu_lock);
|
||||
|
||||
ath9k_ps_restore(sc);
|
||||
return r;
|
||||
}
|
||||
@ -341,7 +335,7 @@ void ath_paprd_calibrate(struct work_struct *work)
|
||||
struct ath_tx_control txctl;
|
||||
struct ath9k_hw_cal_data *caldata = ah->caldata;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
int qnum, ftype;
|
||||
int ftype;
|
||||
int chain_ok = 0;
|
||||
int chain;
|
||||
int len = 1800;
|
||||
@ -368,8 +362,7 @@ void ath_paprd_calibrate(struct work_struct *work)
|
||||
memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN);
|
||||
|
||||
memset(&txctl, 0, sizeof(txctl));
|
||||
qnum = sc->tx.hwq_map[WME_AC_BE];
|
||||
txctl.txq = &sc->tx.txq[qnum];
|
||||
txctl.txq = sc->tx.txq_map[WME_AC_BE];
|
||||
|
||||
ath9k_ps_wakeup(sc);
|
||||
ar9003_paprd_init_table(ah);
|
||||
@ -567,7 +560,6 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta)
|
||||
an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
|
||||
sta->ht_cap.ampdu_factor);
|
||||
an->mpdudensity = parse_mpdudensity(sta->ht_cap.ampdu_density);
|
||||
an->last_rssi = ATH_RSSI_DUMMY_MARKER;
|
||||
}
|
||||
}
|
||||
|
||||
@ -615,6 +607,8 @@ void ath9k_tasklet(unsigned long data)
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock_bh(&sc->sc_pcu_lock);
|
||||
|
||||
if (!ath9k_hw_check_alive(ah))
|
||||
ieee80211_queue_work(sc->hw, &sc->hw_check_work);
|
||||
|
||||
@ -625,15 +619,12 @@ void ath9k_tasklet(unsigned long data)
|
||||
rxmask = (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
|
||||
|
||||
if (status & rxmask) {
|
||||
spin_lock_bh(&sc->rx.pcu_lock);
|
||||
|
||||
/* Check for high priority Rx first */
|
||||
if ((ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
|
||||
(status & ATH9K_INT_RXHP))
|
||||
ath_rx_tasklet(sc, 0, true);
|
||||
|
||||
ath_rx_tasklet(sc, 0, false);
|
||||
spin_unlock_bh(&sc->rx.pcu_lock);
|
||||
}
|
||||
|
||||
if (status & ATH9K_INT_TX) {
|
||||
@ -658,7 +649,9 @@ void ath9k_tasklet(unsigned long data)
|
||||
ath_gen_timer_isr(sc->sc_ah);
|
||||
|
||||
/* re-enable hardware interrupt */
|
||||
ath9k_hw_set_interrupts(ah, ah->imask);
|
||||
ath9k_hw_enable_interrupts(ah);
|
||||
|
||||
spin_unlock_bh(&sc->sc_pcu_lock);
|
||||
ath9k_ps_restore(sc);
|
||||
}
|
||||
|
||||
@ -757,7 +750,7 @@ irqreturn_t ath_isr(int irq, void *dev)
|
||||
* interrupt; otherwise it will continue to
|
||||
* fire.
|
||||
*/
|
||||
ath9k_hw_set_interrupts(ah, 0);
|
||||
ath9k_hw_disable_interrupts(ah);
|
||||
/*
|
||||
* Let the hal handle the event. We assume
|
||||
* it will clear whatever condition caused
|
||||
@ -766,7 +759,7 @@ irqreturn_t ath_isr(int irq, void *dev)
|
||||
spin_lock(&common->cc_lock);
|
||||
ath9k_hw_proc_mib_event(ah);
|
||||
spin_unlock(&common->cc_lock);
|
||||
ath9k_hw_set_interrupts(ah, ah->imask);
|
||||
ath9k_hw_enable_interrupts(ah);
|
||||
}
|
||||
|
||||
if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
|
||||
@ -783,8 +776,8 @@ chip_reset:
|
||||
ath_debug_stat_interrupt(sc, status);
|
||||
|
||||
if (sched) {
|
||||
/* turn off every interrupt except SWBA */
|
||||
ath9k_hw_set_interrupts(ah, (ah->imask & ATH9K_INT_SWBA));
|
||||
/* turn off every interrupt */
|
||||
ath9k_hw_disable_interrupts(ah);
|
||||
tasklet_schedule(&sc->intr_tq);
|
||||
}
|
||||
|
||||
@ -836,9 +829,11 @@ static u32 ath_get_extchanmode(struct ath_softc *sc,
|
||||
}
|
||||
|
||||
static void ath9k_bss_assoc_info(struct ath_softc *sc,
|
||||
struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *bss_conf)
|
||||
{
|
||||
struct ath_wiphy *aphy = hw->priv;
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
|
||||
@ -862,6 +857,7 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc,
|
||||
ath_beacon_config(sc, vif);
|
||||
|
||||
/* Reset rssi stats */
|
||||
aphy->last_rssi = ATH_RSSI_DUMMY_MARKER;
|
||||
sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
|
||||
|
||||
sc->sc_flags |= SC_OP_ANI_RUN;
|
||||
@ -883,13 +879,13 @@ void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw)
|
||||
int r;
|
||||
|
||||
ath9k_ps_wakeup(sc);
|
||||
spin_lock_bh(&sc->sc_pcu_lock);
|
||||
|
||||
ath9k_hw_configpcipowersave(ah, 0, 0);
|
||||
|
||||
if (!ah->curchan)
|
||||
ah->curchan = ath_get_curchannel(sc, sc->hw);
|
||||
|
||||
spin_lock_bh(&sc->rx.pcu_lock);
|
||||
spin_lock_bh(&sc->sc_resetlock);
|
||||
r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
|
||||
if (r) {
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
@ -897,17 +893,14 @@ void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw)
|
||||
"reset status %d\n",
|
||||
channel->center_freq, r);
|
||||
}
|
||||
spin_unlock_bh(&sc->sc_resetlock);
|
||||
|
||||
ath_update_txpow(sc);
|
||||
if (ath_startrecv(sc) != 0) {
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Unable to restart recv logic\n");
|
||||
spin_unlock_bh(&sc->rx.pcu_lock);
|
||||
spin_unlock_bh(&sc->sc_pcu_lock);
|
||||
return;
|
||||
}
|
||||
spin_unlock_bh(&sc->rx.pcu_lock);
|
||||
|
||||
if (sc->sc_flags & SC_OP_BEACONS)
|
||||
ath_beacon_config(sc, NULL); /* restart beacons */
|
||||
|
||||
@ -920,6 +913,8 @@ void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw)
|
||||
ath9k_hw_set_gpio(ah, ah->led_pin, 0);
|
||||
|
||||
ieee80211_wake_queues(hw);
|
||||
spin_unlock_bh(&sc->sc_pcu_lock);
|
||||
|
||||
ath9k_ps_restore(sc);
|
||||
}
|
||||
|
||||
@ -930,6 +925,8 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw)
|
||||
int r;
|
||||
|
||||
ath9k_ps_wakeup(sc);
|
||||
spin_lock_bh(&sc->sc_pcu_lock);
|
||||
|
||||
ieee80211_stop_queues(hw);
|
||||
|
||||
/*
|
||||
@ -942,19 +939,16 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw)
|
||||
}
|
||||
|
||||
/* Disable interrupts */
|
||||
ath9k_hw_set_interrupts(ah, 0);
|
||||
ath9k_hw_disable_interrupts(ah);
|
||||
|
||||
ath_drain_all_txq(sc, false); /* clear pending tx frames */
|
||||
|
||||
spin_lock_bh(&sc->rx.pcu_lock);
|
||||
|
||||
ath_stoprecv(sc); /* turn off frame recv */
|
||||
ath_flushrecv(sc); /* flush recv queue */
|
||||
|
||||
if (!ah->curchan)
|
||||
ah->curchan = ath_get_curchannel(sc, hw);
|
||||
|
||||
spin_lock_bh(&sc->sc_resetlock);
|
||||
r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
|
||||
if (r) {
|
||||
ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL,
|
||||
@ -962,14 +956,14 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw)
|
||||
"reset status %d\n",
|
||||
channel->center_freq, r);
|
||||
}
|
||||
spin_unlock_bh(&sc->sc_resetlock);
|
||||
|
||||
ath9k_hw_phy_disable(ah);
|
||||
|
||||
spin_unlock_bh(&sc->rx.pcu_lock);
|
||||
|
||||
ath9k_hw_configpcipowersave(ah, 1, 1);
|
||||
|
||||
spin_unlock_bh(&sc->sc_pcu_lock);
|
||||
ath9k_ps_restore(sc);
|
||||
|
||||
ath9k_setpower(sc, ATH9K_PM_FULL_SLEEP);
|
||||
}
|
||||
|
||||
@ -983,29 +977,25 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)
|
||||
/* Stop ANI */
|
||||
del_timer_sync(&common->ani.timer);
|
||||
|
||||
spin_lock_bh(&sc->sc_pcu_lock);
|
||||
|
||||
ieee80211_stop_queues(hw);
|
||||
|
||||
ath9k_hw_set_interrupts(ah, 0);
|
||||
ath9k_hw_disable_interrupts(ah);
|
||||
ath_drain_all_txq(sc, retry_tx);
|
||||
|
||||
spin_lock_bh(&sc->rx.pcu_lock);
|
||||
|
||||
ath_stoprecv(sc);
|
||||
ath_flushrecv(sc);
|
||||
|
||||
spin_lock_bh(&sc->sc_resetlock);
|
||||
r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false);
|
||||
if (r)
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Unable to reset hardware; reset status %d\n", r);
|
||||
spin_unlock_bh(&sc->sc_resetlock);
|
||||
|
||||
if (ath_startrecv(sc) != 0)
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Unable to start recv logic\n");
|
||||
|
||||
spin_unlock_bh(&sc->rx.pcu_lock);
|
||||
|
||||
/*
|
||||
* We may be doing a reset in response to a request
|
||||
* that changes the channel so update any state that
|
||||
@ -1030,6 +1020,7 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)
|
||||
}
|
||||
|
||||
ieee80211_wake_queues(hw);
|
||||
spin_unlock_bh(&sc->sc_pcu_lock);
|
||||
|
||||
/* Start ANI */
|
||||
ath_start_ani(common);
|
||||
@ -1037,56 +1028,6 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)
|
||||
return r;
|
||||
}
|
||||
|
||||
static int ath_get_hal_qnum(u16 queue, struct ath_softc *sc)
|
||||
{
|
||||
int qnum;
|
||||
|
||||
switch (queue) {
|
||||
case 0:
|
||||
qnum = sc->tx.hwq_map[WME_AC_VO];
|
||||
break;
|
||||
case 1:
|
||||
qnum = sc->tx.hwq_map[WME_AC_VI];
|
||||
break;
|
||||
case 2:
|
||||
qnum = sc->tx.hwq_map[WME_AC_BE];
|
||||
break;
|
||||
case 3:
|
||||
qnum = sc->tx.hwq_map[WME_AC_BK];
|
||||
break;
|
||||
default:
|
||||
qnum = sc->tx.hwq_map[WME_AC_BE];
|
||||
break;
|
||||
}
|
||||
|
||||
return qnum;
|
||||
}
|
||||
|
||||
int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc)
|
||||
{
|
||||
int qnum;
|
||||
|
||||
switch (queue) {
|
||||
case WME_AC_VO:
|
||||
qnum = 0;
|
||||
break;
|
||||
case WME_AC_VI:
|
||||
qnum = 1;
|
||||
break;
|
||||
case WME_AC_BE:
|
||||
qnum = 2;
|
||||
break;
|
||||
case WME_AC_BK:
|
||||
qnum = 3;
|
||||
break;
|
||||
default:
|
||||
qnum = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
return qnum;
|
||||
}
|
||||
|
||||
/* XXX: Remove me once we don't depend on ath9k_channel for all
|
||||
* this redundant data */
|
||||
void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw,
|
||||
@ -1168,19 +1109,16 @@ static int ath9k_start(struct ieee80211_hw *hw)
|
||||
* be followed by initialization of the appropriate bits
|
||||
* and then setup of the interrupt mask.
|
||||
*/
|
||||
spin_lock_bh(&sc->rx.pcu_lock);
|
||||
spin_lock_bh(&sc->sc_resetlock);
|
||||
spin_lock_bh(&sc->sc_pcu_lock);
|
||||
r = ath9k_hw_reset(ah, init_channel, ah->caldata, false);
|
||||
if (r) {
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Unable to reset hardware; reset status %d "
|
||||
"(freq %u MHz)\n", r,
|
||||
curchan->center_freq);
|
||||
spin_unlock_bh(&sc->sc_resetlock);
|
||||
spin_unlock_bh(&sc->rx.pcu_lock);
|
||||
spin_unlock_bh(&sc->sc_pcu_lock);
|
||||
goto mutex_unlock;
|
||||
}
|
||||
spin_unlock_bh(&sc->sc_resetlock);
|
||||
|
||||
/*
|
||||
* This is needed only to setup initial state
|
||||
@ -1199,10 +1137,10 @@ static int ath9k_start(struct ieee80211_hw *hw)
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Unable to start recv logic\n");
|
||||
r = -EIO;
|
||||
spin_unlock_bh(&sc->rx.pcu_lock);
|
||||
spin_unlock_bh(&sc->sc_pcu_lock);
|
||||
goto mutex_unlock;
|
||||
}
|
||||
spin_unlock_bh(&sc->rx.pcu_lock);
|
||||
spin_unlock_bh(&sc->sc_pcu_lock);
|
||||
|
||||
/* Setup our intr mask. */
|
||||
ah->imask = ATH9K_INT_TX | ATH9K_INT_RXEOL |
|
||||
@ -1262,7 +1200,6 @@ static int ath9k_tx(struct ieee80211_hw *hw,
|
||||
struct ath_tx_control txctl;
|
||||
int padpos, padsize;
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
|
||||
int qnum;
|
||||
|
||||
if (aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN) {
|
||||
ath_print(common, ATH_DBG_XMIT,
|
||||
@ -1335,8 +1272,7 @@ static int ath9k_tx(struct ieee80211_hw *hw,
|
||||
memmove(skb->data, skb->data + padsize, padpos);
|
||||
}
|
||||
|
||||
qnum = ath_get_hal_qnum(skb_get_queue_mapping(skb), sc);
|
||||
txctl.txq = &sc->tx.txq[qnum];
|
||||
txctl.txq = sc->tx.txq_map[skb_get_queue_mapping(skb)];
|
||||
|
||||
ath_print(common, ATH_DBG_XMIT, "transmitting packet, skb: %p\n", skb);
|
||||
|
||||
@ -1400,22 +1336,25 @@ static void ath9k_stop(struct ieee80211_hw *hw)
|
||||
ath9k_btcoex_timer_pause(sc);
|
||||
}
|
||||
|
||||
spin_lock_bh(&sc->sc_pcu_lock);
|
||||
|
||||
/* make sure h/w will not generate any interrupt
|
||||
* before setting the invalid flag. */
|
||||
ath9k_hw_set_interrupts(ah, 0);
|
||||
ath9k_hw_disable_interrupts(ah);
|
||||
|
||||
spin_lock_bh(&sc->rx.pcu_lock);
|
||||
if (!(sc->sc_flags & SC_OP_INVALID)) {
|
||||
ath_drain_all_txq(sc, false);
|
||||
ath_stoprecv(sc);
|
||||
ath9k_hw_phy_disable(ah);
|
||||
} else
|
||||
sc->rx.rxlink = NULL;
|
||||
spin_unlock_bh(&sc->rx.pcu_lock);
|
||||
|
||||
/* disable HAL and put h/w to sleep */
|
||||
ath9k_hw_disable(ah);
|
||||
ath9k_hw_configpcipowersave(ah, 1, 1);
|
||||
|
||||
spin_unlock_bh(&sc->sc_pcu_lock);
|
||||
|
||||
ath9k_ps_restore(sc);
|
||||
|
||||
/* Finally, put the chip in FULL SLEEP mode */
|
||||
@ -1822,12 +1761,15 @@ static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue,
|
||||
struct ath_wiphy *aphy = hw->priv;
|
||||
struct ath_softc *sc = aphy->sc;
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
struct ath_txq *txq;
|
||||
struct ath9k_tx_queue_info qi;
|
||||
int ret = 0, qnum;
|
||||
int ret = 0;
|
||||
|
||||
if (queue >= WME_NUM_AC)
|
||||
return 0;
|
||||
|
||||
txq = sc->tx.txq_map[queue];
|
||||
|
||||
mutex_lock(&sc->mutex);
|
||||
|
||||
memset(&qi, 0, sizeof(struct ath9k_tx_queue_info));
|
||||
@ -1836,20 +1778,19 @@ static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue,
|
||||
qi.tqi_cwmin = params->cw_min;
|
||||
qi.tqi_cwmax = params->cw_max;
|
||||
qi.tqi_burstTime = params->txop;
|
||||
qnum = ath_get_hal_qnum(queue, sc);
|
||||
|
||||
ath_print(common, ATH_DBG_CONFIG,
|
||||
"Configure tx [queue/halq] [%d/%d], "
|
||||
"aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n",
|
||||
queue, qnum, params->aifs, params->cw_min,
|
||||
queue, txq->axq_qnum, params->aifs, params->cw_min,
|
||||
params->cw_max, params->txop);
|
||||
|
||||
ret = ath_txq_update(sc, qnum, &qi);
|
||||
ret = ath_txq_update(sc, txq->axq_qnum, &qi);
|
||||
if (ret)
|
||||
ath_print(common, ATH_DBG_FATAL, "TXQ Update failed\n");
|
||||
|
||||
if (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC)
|
||||
if ((qnum == sc->tx.hwq_map[WME_AC_BE]) && !ret)
|
||||
if (queue == WME_AC_BE && !ret)
|
||||
ath_beaconq_config(sc);
|
||||
|
||||
mutex_unlock(&sc->mutex);
|
||||
@ -2011,7 +1952,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
|
||||
if (changed & BSS_CHANGED_ASSOC) {
|
||||
ath_print(common, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n",
|
||||
bss_conf->assoc);
|
||||
ath9k_bss_assoc_info(sc, vif, bss_conf);
|
||||
ath9k_bss_assoc_info(sc, hw, vif, bss_conf);
|
||||
}
|
||||
|
||||
mutex_unlock(&sc->mutex);
|
||||
|
@ -247,34 +247,25 @@ static void ath_pci_remove(struct pci_dev *pdev)
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
static int ath_pci_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||
static int ath_pci_suspend(struct device *device)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(device);
|
||||
struct ieee80211_hw *hw = pci_get_drvdata(pdev);
|
||||
struct ath_wiphy *aphy = hw->priv;
|
||||
struct ath_softc *sc = aphy->sc;
|
||||
|
||||
ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1);
|
||||
|
||||
pci_save_state(pdev);
|
||||
pci_disable_device(pdev);
|
||||
pci_set_power_state(pdev, PCI_D3hot);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath_pci_resume(struct pci_dev *pdev)
|
||||
static int ath_pci_resume(struct device *device)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(device);
|
||||
struct ieee80211_hw *hw = pci_get_drvdata(pdev);
|
||||
struct ath_wiphy *aphy = hw->priv;
|
||||
struct ath_softc *sc = aphy->sc;
|
||||
u32 val;
|
||||
int err;
|
||||
|
||||
pci_restore_state(pdev);
|
||||
|
||||
err = pci_enable_device(pdev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/*
|
||||
* Suspend/Resume resets the PCI configuration space, so we have to
|
||||
@ -293,7 +284,23 @@ static int ath_pci_resume(struct pci_dev *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_PM */
|
||||
static const struct dev_pm_ops ath9k_pm_ops = {
|
||||
.suspend = ath_pci_suspend,
|
||||
.resume = ath_pci_resume,
|
||||
.freeze = ath_pci_suspend,
|
||||
.thaw = ath_pci_resume,
|
||||
.poweroff = ath_pci_suspend,
|
||||
.restore = ath_pci_resume,
|
||||
};
|
||||
|
||||
#define ATH9K_PM_OPS (&ath9k_pm_ops)
|
||||
|
||||
#else /* !CONFIG_PM */
|
||||
|
||||
#define ATH9K_PM_OPS NULL
|
||||
|
||||
#endif /* !CONFIG_PM */
|
||||
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, ath_pci_id_table);
|
||||
|
||||
@ -302,10 +309,7 @@ static struct pci_driver ath_pci_driver = {
|
||||
.id_table = ath_pci_id_table,
|
||||
.probe = ath_pci_probe,
|
||||
.remove = ath_pci_remove,
|
||||
#ifdef CONFIG_PM
|
||||
.suspend = ath_pci_suspend,
|
||||
.resume = ath_pci_resume,
|
||||
#endif /* CONFIG_PM */
|
||||
.driver.pm = ATH9K_PM_OPS,
|
||||
};
|
||||
|
||||
int ath_pci_init(void)
|
||||
|
@ -381,25 +381,6 @@ static const struct ath_rate_table ar5416_11g_ratetable = {
|
||||
static int ath_rc_get_rateindex(const struct ath_rate_table *rate_table,
|
||||
struct ieee80211_tx_rate *rate);
|
||||
|
||||
static inline int8_t median(int8_t a, int8_t b, int8_t c)
|
||||
{
|
||||
if (a >= b) {
|
||||
if (b >= c)
|
||||
return b;
|
||||
else if (a > c)
|
||||
return c;
|
||||
else
|
||||
return a;
|
||||
} else {
|
||||
if (a >= c)
|
||||
return a;
|
||||
else if (b >= c)
|
||||
return c;
|
||||
else
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
static void ath_rc_sort_validrates(const struct ath_rate_table *rate_table,
|
||||
struct ath_rate_priv *ath_rc_priv)
|
||||
{
|
||||
@ -1444,12 +1425,12 @@ static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband,
|
||||
ath_rc_priv->neg_ht_rates.rs_nrates = j;
|
||||
}
|
||||
|
||||
is_cw40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40;
|
||||
is_cw40 = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40);
|
||||
|
||||
if (is_cw40)
|
||||
is_sgi = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40;
|
||||
is_sgi = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40);
|
||||
else if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_SGI_20)
|
||||
is_sgi = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20;
|
||||
is_sgi = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20);
|
||||
|
||||
/* Choose rate table first */
|
||||
|
||||
@ -1468,10 +1449,8 @@ static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband,
|
||||
struct ath_rate_priv *ath_rc_priv = priv_sta;
|
||||
const struct ath_rate_table *rate_table = NULL;
|
||||
bool oper_cw40 = false, oper_sgi;
|
||||
bool local_cw40 = (ath_rc_priv->ht_cap & WLAN_RC_40_FLAG) ?
|
||||
true : false;
|
||||
bool local_sgi = (ath_rc_priv->ht_cap & WLAN_RC_SGI_FLAG) ?
|
||||
true : false;
|
||||
bool local_cw40 = !!(ath_rc_priv->ht_cap & WLAN_RC_40_FLAG);
|
||||
bool local_sgi = !!(ath_rc_priv->ht_cap & WLAN_RC_SGI_FLAG);
|
||||
|
||||
/* FIXME: Handle AP mode later when we support CWM */
|
||||
|
||||
|
@ -317,7 +317,7 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
|
||||
struct ath_buf *bf;
|
||||
int error = 0;
|
||||
|
||||
spin_lock_init(&sc->rx.pcu_lock);
|
||||
spin_lock_init(&sc->sc_pcu_lock);
|
||||
sc->sc_flags &= ~SC_OP_RXFLUSH;
|
||||
spin_lock_init(&sc->rx.rxbuflock);
|
||||
|
||||
@ -528,6 +528,8 @@ bool ath_stoprecv(struct ath_softc *sc)
|
||||
sc->rx.rxlink = NULL;
|
||||
spin_unlock_bh(&sc->rx.rxbuflock);
|
||||
|
||||
ATH_DBG_WARN(!stopped, "Could not stop RX, we could be "
|
||||
"confusing the DMA engine when we start RX up\n");
|
||||
return stopped;
|
||||
}
|
||||
|
||||
@ -962,36 +964,23 @@ static void ath9k_process_rssi(struct ath_common *common,
|
||||
struct ieee80211_hdr *hdr,
|
||||
struct ath_rx_status *rx_stats)
|
||||
{
|
||||
struct ath_wiphy *aphy = hw->priv;
|
||||
struct ath_hw *ah = common->ah;
|
||||
struct ieee80211_sta *sta;
|
||||
struct ath_node *an;
|
||||
int last_rssi = ATH_RSSI_DUMMY_MARKER;
|
||||
int last_rssi;
|
||||
__le16 fc;
|
||||
|
||||
if (ah->opmode != NL80211_IFTYPE_STATION)
|
||||
return;
|
||||
|
||||
fc = hdr->frame_control;
|
||||
if (!ieee80211_is_beacon(fc) ||
|
||||
compare_ether_addr(hdr->addr3, common->curbssid))
|
||||
return;
|
||||
|
||||
rcu_read_lock();
|
||||
/*
|
||||
* XXX: use ieee80211_find_sta! This requires quite a bit of work
|
||||
* under the current ath9k virtual wiphy implementation as we have
|
||||
* no way of tying a vif to wiphy. Typically vifs are attached to
|
||||
* at least one sdata of a wiphy on mac80211 but with ath9k virtual
|
||||
* wiphy you'd have to iterate over every wiphy and each sdata.
|
||||
*/
|
||||
if (is_multicast_ether_addr(hdr->addr1))
|
||||
sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr2, NULL);
|
||||
else
|
||||
sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr2, hdr->addr1);
|
||||
|
||||
if (sta) {
|
||||
an = (struct ath_node *) sta->drv_priv;
|
||||
if (rx_stats->rs_rssi != ATH9K_RSSI_BAD &&
|
||||
!rx_stats->rs_moreaggr)
|
||||
ATH_RSSI_LPF(an->last_rssi, rx_stats->rs_rssi);
|
||||
last_rssi = an->last_rssi;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
if (rx_stats->rs_rssi != ATH9K_RSSI_BAD && !rx_stats->rs_moreaggr)
|
||||
ATH_RSSI_LPF(aphy->last_rssi, rx_stats->rs_rssi);
|
||||
|
||||
last_rssi = aphy->last_rssi;
|
||||
if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
|
||||
rx_stats->rs_rssi = ATH_EP_RND(last_rssi,
|
||||
ATH_RSSI_EP_MULTIPLIER);
|
||||
@ -999,8 +988,7 @@ static void ath9k_process_rssi(struct ath_common *common,
|
||||
rx_stats->rs_rssi = 0;
|
||||
|
||||
/* Update Beacon RSSI, this is used by ANI. */
|
||||
if (ieee80211_is_beacon(fc))
|
||||
ah->stats.avgbrssi = rx_stats->rs_rssi;
|
||||
ah->stats.avgbrssi = rx_stats->rs_rssi;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -107,6 +107,7 @@ int ath9k_wiphy_add(struct ath_softc *sc)
|
||||
aphy->sc = sc;
|
||||
aphy->hw = hw;
|
||||
sc->sec_wiphy[i] = aphy;
|
||||
aphy->last_rssi = ATH_RSSI_DUMMY_MARKER;
|
||||
spin_unlock_bh(&sc->wiphy_lock);
|
||||
|
||||
memcpy(addr, common->macaddr, ETH_ALEN);
|
||||
@ -186,7 +187,7 @@ static int ath9k_send_nullfunc(struct ath_wiphy *aphy,
|
||||
info->control.rates[1].idx = -1;
|
||||
|
||||
memset(&txctl, 0, sizeof(struct ath_tx_control));
|
||||
txctl.txq = &sc->tx.txq[sc->tx.hwq_map[WME_AC_VO]];
|
||||
txctl.txq = sc->tx.txq_map[WME_AC_VO];
|
||||
txctl.frame_type = ps ? ATH9K_IFT_PAUSE : ATH9K_IFT_UNPAUSE;
|
||||
|
||||
if (ath_tx_start(aphy->hw, skb, &txctl) != 0)
|
||||
|
@ -124,7 +124,7 @@ static void ath_tx_queue_tid(struct ath_txq *txq, struct ath_atx_tid *tid)
|
||||
|
||||
static void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
|
||||
{
|
||||
struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum];
|
||||
struct ath_txq *txq = tid->ac->txq;
|
||||
|
||||
WARN_ON(!tid->paused);
|
||||
|
||||
@ -142,7 +142,7 @@ unlock:
|
||||
|
||||
static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
|
||||
{
|
||||
struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum];
|
||||
struct ath_txq *txq = tid->ac->txq;
|
||||
struct ath_buf *bf;
|
||||
struct list_head bf_head;
|
||||
struct ath_tx_status ts;
|
||||
@ -817,7 +817,7 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
|
||||
{
|
||||
struct ath_node *an = (struct ath_node *)sta->drv_priv;
|
||||
struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid);
|
||||
struct ath_txq *txq = &sc->tx.txq[txtid->ac->qnum];
|
||||
struct ath_txq *txq = txtid->ac->txq;
|
||||
|
||||
if (txtid->state & AGGR_CLEANUP)
|
||||
return;
|
||||
@ -888,10 +888,16 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ath9k_tx_queue_info qi;
|
||||
static const int subtype_txq_to_hwq[] = {
|
||||
[WME_AC_BE] = ATH_TXQ_AC_BE,
|
||||
[WME_AC_BK] = ATH_TXQ_AC_BK,
|
||||
[WME_AC_VI] = ATH_TXQ_AC_VI,
|
||||
[WME_AC_VO] = ATH_TXQ_AC_VO,
|
||||
};
|
||||
int qnum, i;
|
||||
|
||||
memset(&qi, 0, sizeof(qi));
|
||||
qi.tqi_subtype = subtype;
|
||||
qi.tqi_subtype = subtype_txq_to_hwq[subtype];
|
||||
qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT;
|
||||
qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT;
|
||||
qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT;
|
||||
@ -940,7 +946,6 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
|
||||
if (!ATH_TXQ_SETUP(sc, qnum)) {
|
||||
struct ath_txq *txq = &sc->tx.txq[qnum];
|
||||
|
||||
txq->axq_class = subtype;
|
||||
txq->axq_qnum = qnum;
|
||||
txq->axq_link = NULL;
|
||||
INIT_LIST_HEAD(&txq->axq_q);
|
||||
@ -1148,13 +1153,11 @@ void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Failed to stop TX DMA. Resetting hardware!\n");
|
||||
|
||||
spin_lock_bh(&sc->sc_resetlock);
|
||||
r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false);
|
||||
if (r)
|
||||
ath_print(common, ATH_DBG_FATAL,
|
||||
"Unable to reset hardware; reset status %d\n",
|
||||
r);
|
||||
spin_unlock_bh(&sc->sc_resetlock);
|
||||
}
|
||||
|
||||
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
|
||||
@ -1212,24 +1215,6 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
|
||||
}
|
||||
}
|
||||
|
||||
int ath_tx_setup(struct ath_softc *sc, int haltype)
|
||||
{
|
||||
struct ath_txq *txq;
|
||||
|
||||
if (haltype >= ARRAY_SIZE(sc->tx.hwq_map)) {
|
||||
ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL,
|
||||
"HAL AC %u out of range, max %zu!\n",
|
||||
haltype, ARRAY_SIZE(sc->tx.hwq_map));
|
||||
return 0;
|
||||
}
|
||||
txq = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, haltype);
|
||||
if (txq != NULL) {
|
||||
sc->tx.hwq_map[haltype] = txq->axq_qnum;
|
||||
return 1;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***********/
|
||||
/* TX, DMA */
|
||||
/***********/
|
||||
@ -1710,6 +1695,7 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf,
|
||||
goto tx_done;
|
||||
}
|
||||
|
||||
WARN_ON(tid->ac->txq != txctl->txq);
|
||||
if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
|
||||
/*
|
||||
* Try aggregation if it's a unicast data frame
|
||||
@ -1749,6 +1735,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
return -1;
|
||||
}
|
||||
|
||||
q = skb_get_queue_mapping(skb);
|
||||
r = ath_tx_setup_buffer(hw, bf, skb, txctl);
|
||||
if (unlikely(r)) {
|
||||
ath_print(common, ATH_DBG_FATAL, "TX mem alloc failure\n");
|
||||
@ -1758,8 +1745,9 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
* we will at least have to run TX completionon one buffer
|
||||
* on the queue */
|
||||
spin_lock_bh(&txq->axq_lock);
|
||||
if (!txq->stopped && txq->axq_depth > 1) {
|
||||
ath_mac80211_stop_queue(sc, skb_get_queue_mapping(skb));
|
||||
if (txq == sc->tx.txq_map[q] && !txq->stopped &&
|
||||
txq->axq_depth > 1) {
|
||||
ath_mac80211_stop_queue(sc, q);
|
||||
txq->stopped = 1;
|
||||
}
|
||||
spin_unlock_bh(&txq->axq_lock);
|
||||
@ -1769,13 +1757,10 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
|
||||
return r;
|
||||
}
|
||||
|
||||
q = skb_get_queue_mapping(skb);
|
||||
if (q >= 4)
|
||||
q = 0;
|
||||
|
||||
spin_lock_bh(&txq->axq_lock);
|
||||
if (++sc->tx.pending_frames[q] > ATH_MAX_QDEPTH && !txq->stopped) {
|
||||
ath_mac80211_stop_queue(sc, skb_get_queue_mapping(skb));
|
||||
if (txq == sc->tx.txq_map[q] &&
|
||||
++txq->pending_frames > ATH_MAX_QDEPTH && !txq->stopped) {
|
||||
ath_mac80211_stop_queue(sc, q);
|
||||
txq->stopped = 1;
|
||||
}
|
||||
spin_unlock_bh(&txq->axq_lock);
|
||||
@ -1843,7 +1828,8 @@ exit:
|
||||
/*****************/
|
||||
|
||||
static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
|
||||
struct ath_wiphy *aphy, int tx_flags)
|
||||
struct ath_wiphy *aphy, int tx_flags,
|
||||
struct ath_txq *txq)
|
||||
{
|
||||
struct ieee80211_hw *hw = sc->hw;
|
||||
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
|
||||
@ -1890,11 +1876,12 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
|
||||
ath9k_tx_status(hw, skb);
|
||||
else {
|
||||
q = skb_get_queue_mapping(skb);
|
||||
if (q >= 4)
|
||||
q = 0;
|
||||
|
||||
if (--sc->tx.pending_frames[q] < 0)
|
||||
sc->tx.pending_frames[q] = 0;
|
||||
if (txq == sc->tx.txq_map[q]) {
|
||||
spin_lock_bh(&txq->axq_lock);
|
||||
if (WARN_ON(--txq->pending_frames < 0))
|
||||
txq->pending_frames = 0;
|
||||
spin_unlock_bh(&txq->axq_lock);
|
||||
}
|
||||
|
||||
ieee80211_tx_status(hw, skb);
|
||||
}
|
||||
@ -1929,8 +1916,8 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
|
||||
else
|
||||
complete(&sc->paprd_complete);
|
||||
} else {
|
||||
ath_debug_stat_tx(sc, txq, bf, ts);
|
||||
ath_tx_complete(sc, skb, bf->aphy, tx_flags);
|
||||
ath_debug_stat_tx(sc, bf, ts);
|
||||
ath_tx_complete(sc, skb, bf->aphy, tx_flags, txq);
|
||||
}
|
||||
/* At this point, skb (bf->bf_mpdu) is consumed...make sure we don't
|
||||
* accidentally reference it later.
|
||||
@ -2020,16 +2007,13 @@ static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts,
|
||||
tx_info->status.rates[tx_rateindex].count = ts->ts_longretry + 1;
|
||||
}
|
||||
|
||||
static void ath_wake_mac80211_queue(struct ath_softc *sc, struct ath_txq *txq)
|
||||
static void ath_wake_mac80211_queue(struct ath_softc *sc, int qnum)
|
||||
{
|
||||
int qnum;
|
||||
|
||||
qnum = ath_get_mac80211_qnum(txq->axq_class, sc);
|
||||
if (qnum == -1)
|
||||
return;
|
||||
struct ath_txq *txq;
|
||||
|
||||
txq = sc->tx.txq_map[qnum];
|
||||
spin_lock_bh(&txq->axq_lock);
|
||||
if (txq->stopped && sc->tx.pending_frames[qnum] < ATH_MAX_QDEPTH) {
|
||||
if (txq->stopped && txq->pending_frames < ATH_MAX_QDEPTH) {
|
||||
if (ath_mac80211_start_queue(sc, qnum))
|
||||
txq->stopped = 0;
|
||||
}
|
||||
@ -2046,6 +2030,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
|
||||
struct ath_tx_status ts;
|
||||
int txok;
|
||||
int status;
|
||||
int qnum;
|
||||
|
||||
ath_print(common, ATH_DBG_QUEUE, "tx queue %d (%x), link %p\n",
|
||||
txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum),
|
||||
@ -2121,12 +2106,15 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
|
||||
ath_tx_rc_status(bf, &ts, txok ? 0 : 1, txok, true);
|
||||
}
|
||||
|
||||
qnum = skb_get_queue_mapping(bf->bf_mpdu);
|
||||
|
||||
if (bf_isampdu(bf))
|
||||
ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, txok);
|
||||
else
|
||||
ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, txok, 0);
|
||||
|
||||
ath_wake_mac80211_queue(sc, txq);
|
||||
if (txq == sc->tx.txq_map[qnum])
|
||||
ath_wake_mac80211_queue(sc, qnum);
|
||||
|
||||
spin_lock_bh(&txq->axq_lock);
|
||||
if (sc->sc_flags & SC_OP_TXAGGR)
|
||||
@ -2196,6 +2184,7 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
|
||||
struct list_head bf_head;
|
||||
int status;
|
||||
int txok;
|
||||
int qnum;
|
||||
|
||||
for (;;) {
|
||||
status = ath9k_hw_txprocdesc(ah, NULL, (void *)&txs);
|
||||
@ -2239,13 +2228,16 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
|
||||
ath_tx_rc_status(bf, &txs, txok ? 0 : 1, txok, true);
|
||||
}
|
||||
|
||||
qnum = skb_get_queue_mapping(bf->bf_mpdu);
|
||||
|
||||
if (bf_isampdu(bf))
|
||||
ath_tx_complete_aggr(sc, txq, bf, &bf_head, &txs, txok);
|
||||
else
|
||||
ath_tx_complete_buf(sc, bf, txq, &bf_head,
|
||||
&txs, txok, 0);
|
||||
|
||||
ath_wake_mac80211_queue(sc, txq);
|
||||
if (txq == sc->tx.txq_map[qnum])
|
||||
ath_wake_mac80211_queue(sc, qnum);
|
||||
|
||||
spin_lock_bh(&txq->axq_lock);
|
||||
if (!list_empty(&txq->txq_fifo_pending)) {
|
||||
@ -2377,7 +2369,7 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
|
||||
for (acno = 0, ac = &an->ac[acno];
|
||||
acno < WME_NUM_AC; acno++, ac++) {
|
||||
ac->sched = false;
|
||||
ac->qnum = sc->tx.hwq_map[acno];
|
||||
ac->txq = sc->tx.txq_map[acno];
|
||||
INIT_LIST_HEAD(&ac->tid_q);
|
||||
}
|
||||
}
|
||||
@ -2387,17 +2379,13 @@ void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an)
|
||||
struct ath_atx_ac *ac;
|
||||
struct ath_atx_tid *tid;
|
||||
struct ath_txq *txq;
|
||||
int i, tidno;
|
||||
int tidno;
|
||||
|
||||
for (tidno = 0, tid = &an->tid[tidno];
|
||||
tidno < WME_NUM_TID; tidno++, tid++) {
|
||||
i = tid->ac->qnum;
|
||||
|
||||
if (!ATH_TXQ_SETUP(sc, i))
|
||||
continue;
|
||||
|
||||
txq = &sc->tx.txq[i];
|
||||
ac = tid->ac;
|
||||
txq = ac->txq;
|
||||
|
||||
spin_lock_bh(&txq->axq_lock);
|
||||
|
||||
|
@ -48,7 +48,7 @@
|
||||
#include <linux/usb.h>
|
||||
#ifdef CONFIG_CARL9170_LEDS
|
||||
#include <linux/leds.h>
|
||||
#endif /* CONFIG_CARL170_LEDS */
|
||||
#endif /* CONFIG_CARL9170_LEDS */
|
||||
#ifdef CONFIG_CARL9170_WPC
|
||||
#include <linux/input.h>
|
||||
#endif /* CONFIG_CARL9170_WPC */
|
||||
@ -215,7 +215,7 @@ enum carl9170_restart_reasons {
|
||||
CARL9170_RR_TOO_MANY_FIRMWARE_ERRORS,
|
||||
CARL9170_RR_WATCHDOG,
|
||||
CARL9170_RR_STUCK_TX,
|
||||
CARL9170_RR_SLOW_SYSTEM,
|
||||
CARL9170_RR_UNRESPONSIVE_DEVICE,
|
||||
CARL9170_RR_COMMAND_TIMEOUT,
|
||||
CARL9170_RR_TOO_MANY_PHY_ERRORS,
|
||||
CARL9170_RR_LOST_RSP,
|
||||
@ -287,6 +287,7 @@ struct ar9170 {
|
||||
|
||||
/* reset / stuck frames/queue detection */
|
||||
struct work_struct restart_work;
|
||||
struct work_struct ping_work;
|
||||
unsigned int restart_counter;
|
||||
unsigned long queue_stop_timeout[__AR9170_NUM_TXQ];
|
||||
unsigned long max_queue_stop_timeout[__AR9170_NUM_TXQ];
|
||||
|
@ -97,13 +97,13 @@ struct carl9170_set_key_cmd {
|
||||
__le16 type;
|
||||
u8 macAddr[6];
|
||||
u32 key[4];
|
||||
} __packed;
|
||||
} __packed __aligned(4);
|
||||
#define CARL9170_SET_KEY_CMD_SIZE 28
|
||||
|
||||
struct carl9170_disable_key_cmd {
|
||||
__le16 user;
|
||||
__le16 padding;
|
||||
} __packed;
|
||||
} __packed __aligned(4);
|
||||
#define CARL9170_DISABLE_KEY_CMD_SIZE 4
|
||||
|
||||
struct carl9170_u32_list {
|
||||
@ -206,7 +206,7 @@ struct carl9170_cmd {
|
||||
struct carl9170_rx_filter_cmd rx_filter;
|
||||
u8 data[CARL9170_MAX_CMD_PAYLOAD_LEN];
|
||||
} __packed;
|
||||
} __packed;
|
||||
} __packed __aligned(4);
|
||||
|
||||
#define CARL9170_TX_STATUS_QUEUE 3
|
||||
#define CARL9170_TX_STATUS_QUEUE_S 0
|
||||
@ -216,6 +216,7 @@ struct carl9170_cmd {
|
||||
#define CARL9170_TX_STATUS_TRIES (7 << CARL9170_TX_STATUS_TRIES_S)
|
||||
#define CARL9170_TX_STATUS_SUCCESS 0x80
|
||||
|
||||
#ifdef __CARL9170FW__
|
||||
/*
|
||||
* NOTE:
|
||||
* Both structs [carl9170_tx_status and _carl9170_tx_status]
|
||||
@ -232,6 +233,8 @@ struct carl9170_tx_status {
|
||||
u8 tries:3;
|
||||
u8 success:1;
|
||||
} __packed;
|
||||
#endif /* __CARL9170FW__ */
|
||||
|
||||
struct _carl9170_tx_status {
|
||||
/*
|
||||
* This version should be immune to all alignment bugs.
|
||||
@ -272,13 +275,15 @@ struct carl9170_rsp {
|
||||
struct carl9170_rf_init_result rf_init_res;
|
||||
struct carl9170_u32_list rreg_res;
|
||||
struct carl9170_u32_list echo;
|
||||
#ifdef __CARL9170FW__
|
||||
struct carl9170_tx_status tx_status[0];
|
||||
#endif /* __CARL9170FW__ */
|
||||
struct _carl9170_tx_status _tx_status[0];
|
||||
struct carl9170_gpio gpio;
|
||||
struct carl9170_tsf_rsp tsf;
|
||||
struct carl9170_psm psm;
|
||||
u8 data[CARL9170_MAX_CMD_PAYLOAD_LEN];
|
||||
} __packed;
|
||||
} __packed;
|
||||
} __packed __aligned(4);
|
||||
|
||||
#endif /* __CARL9170_SHARED_FWCMD_H */
|
||||
|
@ -712,7 +712,8 @@ struct ar9170_stream {
|
||||
__le16 tag;
|
||||
|
||||
u8 payload[0];
|
||||
};
|
||||
} __packed __aligned(4);
|
||||
#define AR9170_STREAM_LEN 4
|
||||
|
||||
#define AR9170_MAX_ACKTABLE_ENTRIES 8
|
||||
#define AR9170_MAX_VIRTUAL_MAC 7
|
||||
@ -736,4 +737,8 @@ struct ar9170_stream {
|
||||
|
||||
#define MOD_VAL(reg, value, newvalue) \
|
||||
(((value) & ~reg) | (((newvalue) << reg##_S) & reg))
|
||||
|
||||
#define GET_VAL(reg, value) \
|
||||
(((value) & reg) >> reg##_S)
|
||||
|
||||
#endif /* __CARL9170_SHARED_HW_H */
|
||||
|
@ -205,8 +205,8 @@ int carl9170_init_mac(struct ar9170 *ar)
|
||||
carl9170_regwrite(AR9170_MAC_REG_BACKOFF_PROTECT, 0x105);
|
||||
|
||||
/* Aggregation MAX number and timeout */
|
||||
carl9170_regwrite(AR9170_MAC_REG_AMPDU_FACTOR, 0xa);
|
||||
carl9170_regwrite(AR9170_MAC_REG_AMPDU_DENSITY, 0x140a00);
|
||||
carl9170_regwrite(AR9170_MAC_REG_AMPDU_FACTOR, 0x8000a);
|
||||
carl9170_regwrite(AR9170_MAC_REG_AMPDU_DENSITY, 0x140a07);
|
||||
|
||||
carl9170_regwrite(AR9170_MAC_REG_FRAMETYPE_FILTER,
|
||||
AR9170_MAC_FTF_DEFAULTS);
|
||||
@ -457,8 +457,9 @@ int carl9170_set_beacon_timers(struct ar9170 *ar)
|
||||
|
||||
int carl9170_update_beacon(struct ar9170 *ar, const bool submit)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct sk_buff *skb = NULL;
|
||||
struct carl9170_vif_info *cvif;
|
||||
struct ieee80211_tx_info *txinfo;
|
||||
__le32 *data, *old = NULL;
|
||||
u32 word, off, addr, len;
|
||||
int i = 0, err = 0;
|
||||
@ -487,7 +488,13 @@ found:
|
||||
|
||||
if (!skb) {
|
||||
err = -ENOMEM;
|
||||
goto out_unlock;
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
txinfo = IEEE80211_SKB_CB(skb);
|
||||
if (txinfo->control.rates[0].flags & IEEE80211_TX_RC_MCS) {
|
||||
err = -EINVAL;
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
spin_lock_bh(&ar->beacon_lock);
|
||||
@ -504,11 +511,8 @@ found:
|
||||
wiphy_err(ar->hw->wiphy, "beacon does not "
|
||||
"fit into device memory!\n");
|
||||
}
|
||||
|
||||
spin_unlock_bh(&ar->beacon_lock);
|
||||
dev_kfree_skb_any(skb);
|
||||
err = -EINVAL;
|
||||
goto out_unlock;
|
||||
goto err_unlock;
|
||||
}
|
||||
|
||||
if (len > AR9170_MAC_BCN_LENGTH_MAX) {
|
||||
@ -518,22 +522,22 @@ found:
|
||||
AR9170_MAC_BCN_LENGTH_MAX, len);
|
||||
}
|
||||
|
||||
spin_unlock_bh(&ar->beacon_lock);
|
||||
dev_kfree_skb_any(skb);
|
||||
err = -EMSGSIZE;
|
||||
goto out_unlock;
|
||||
goto err_unlock;
|
||||
}
|
||||
|
||||
i = txinfo->control.rates[0].idx;
|
||||
if (txinfo->band != IEEE80211_BAND_2GHZ)
|
||||
i += 4;
|
||||
|
||||
word = __carl9170_ratetable[i].hw_value & 0xf;
|
||||
if (i < 4)
|
||||
word |= ((skb->len + FCS_LEN) << (3 + 16)) + 0x0400;
|
||||
else
|
||||
word |= ((skb->len + FCS_LEN) << 16) + 0x0010;
|
||||
|
||||
carl9170_async_regwrite_begin(ar);
|
||||
|
||||
/* XXX: use skb->cb info */
|
||||
if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) {
|
||||
carl9170_async_regwrite(AR9170_MAC_REG_BCN_PLCP,
|
||||
((skb->len + FCS_LEN) << (3 + 16)) + 0x0400);
|
||||
} else {
|
||||
carl9170_async_regwrite(AR9170_MAC_REG_BCN_PLCP,
|
||||
((skb->len + FCS_LEN) << 16) + 0x001b);
|
||||
}
|
||||
carl9170_async_regwrite(AR9170_MAC_REG_BCN_PLCP, word);
|
||||
|
||||
for (i = 0; i < DIV_ROUND_UP(skb->len, 4); i++) {
|
||||
/*
|
||||
@ -557,7 +561,7 @@ found:
|
||||
cvif->beacon = skb;
|
||||
spin_unlock_bh(&ar->beacon_lock);
|
||||
if (err)
|
||||
goto out_unlock;
|
||||
goto err_free;
|
||||
|
||||
if (submit) {
|
||||
err = carl9170_bcn_ctrl(ar, cvif->id,
|
||||
@ -565,10 +569,18 @@ found:
|
||||
addr, skb->len + FCS_LEN);
|
||||
|
||||
if (err)
|
||||
goto out_unlock;
|
||||
goto err_free;
|
||||
}
|
||||
out_unlock:
|
||||
rcu_read_unlock();
|
||||
return 0;
|
||||
|
||||
err_unlock:
|
||||
spin_unlock_bh(&ar->beacon_lock);
|
||||
|
||||
err_free:
|
||||
rcu_read_unlock();
|
||||
dev_kfree_skb_any(skb);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -428,6 +428,7 @@ static void carl9170_cancel_worker(struct ar9170 *ar)
|
||||
cancel_delayed_work_sync(&ar->led_work);
|
||||
#endif /* CONFIG_CARL9170_LEDS */
|
||||
cancel_work_sync(&ar->ps_work);
|
||||
cancel_work_sync(&ar->ping_work);
|
||||
cancel_work_sync(&ar->ampdu_work);
|
||||
}
|
||||
|
||||
@ -533,6 +534,21 @@ void carl9170_restart(struct ar9170 *ar, const enum carl9170_restart_reasons r)
|
||||
*/
|
||||
}
|
||||
|
||||
static void carl9170_ping_work(struct work_struct *work)
|
||||
{
|
||||
struct ar9170 *ar = container_of(work, struct ar9170, ping_work);
|
||||
int err;
|
||||
|
||||
if (!IS_STARTED(ar))
|
||||
return;
|
||||
|
||||
mutex_lock(&ar->mutex);
|
||||
err = carl9170_echo_test(ar, 0xdeadbeef);
|
||||
if (err)
|
||||
carl9170_restart(ar, CARL9170_RR_UNRESPONSIVE_DEVICE);
|
||||
mutex_unlock(&ar->mutex);
|
||||
}
|
||||
|
||||
static int carl9170_init_interface(struct ar9170 *ar,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
@ -1614,6 +1630,7 @@ void *carl9170_alloc(size_t priv_size)
|
||||
skb_queue_head_init(&ar->tx_pending[i]);
|
||||
}
|
||||
INIT_WORK(&ar->ps_work, carl9170_ps_work);
|
||||
INIT_WORK(&ar->ping_work, carl9170_ping_work);
|
||||
INIT_WORK(&ar->restart_work, carl9170_restart_work);
|
||||
INIT_WORK(&ar->ampdu_work, carl9170_ampdu_work);
|
||||
INIT_DELAYED_WORK(&ar->tx_janitor, carl9170_tx_janitor);
|
||||
@ -1828,7 +1845,7 @@ int carl9170_register(struct ar9170 *ar)
|
||||
err = carl9170_led_register(ar);
|
||||
if (err)
|
||||
goto err_unreg;
|
||||
#endif /* CONFIG_CAR9L170_LEDS */
|
||||
#endif /* CONFIG_CARL9170_LEDS */
|
||||
|
||||
#ifdef CONFIG_CARL9170_WPC
|
||||
err = carl9170_register_wps_button(ar);
|
||||
|
@ -1554,15 +1554,6 @@ static int carl9170_set_power_cal(struct ar9170 *ar, u32 freq,
|
||||
return carl9170_regwrite_result();
|
||||
}
|
||||
|
||||
/* TODO: replace this with sign_extend32(noise, 8) */
|
||||
static int carl9170_calc_noise_dbm(u32 raw_noise)
|
||||
{
|
||||
if (raw_noise & 0x100)
|
||||
return ~0x1ff | raw_noise;
|
||||
else
|
||||
return raw_noise;
|
||||
}
|
||||
|
||||
int carl9170_get_noisefloor(struct ar9170 *ar)
|
||||
{
|
||||
static const u32 phy_regs[] = {
|
||||
@ -1578,11 +1569,11 @@ int carl9170_get_noisefloor(struct ar9170 *ar)
|
||||
return err;
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
ar->noise[i] = carl9170_calc_noise_dbm(
|
||||
(phy_res[i] >> 19) & 0x1ff);
|
||||
ar->noise[i] = sign_extend32(GET_VAL(
|
||||
AR9170_PHY_CCA_MIN_PWR, phy_res[i]), 8);
|
||||
|
||||
ar->noise[i + 2] = carl9170_calc_noise_dbm(
|
||||
(phy_res[i + 2] >> 23) & 0x1ff);
|
||||
ar->noise[i + 2] = sign_extend32(GET_VAL(
|
||||
AR9170_PHY_EXT_CCA_MIN_PWR, phy_res[i + 2]), 8);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -139,8 +139,8 @@
|
||||
#define AR9170_PHY_AGC_CONTROL_NO_UPDATE_NF 0x00020000
|
||||
|
||||
#define AR9170_PHY_REG_CCA (AR9170_PHY_REG_BASE + 0x0064)
|
||||
#define AR9170_PHY_CCA_MINCCA_PWR 0x0ff80000
|
||||
#define AR9170_PHY_CCA_MINCCA_PWR_S 19
|
||||
#define AR9170_PHY_CCA_MIN_PWR 0x0ff80000
|
||||
#define AR9170_PHY_CCA_MIN_PWR_S 19
|
||||
#define AR9170_PHY_CCA_THRESH62 0x0007f000
|
||||
#define AR9170_PHY_CCA_THRESH62_S 12
|
||||
|
||||
@ -338,8 +338,8 @@
|
||||
#define AR9170_PHY_EXT_CCA_CYCPWR_THR1_S 9
|
||||
#define AR9170_PHY_EXT_CCA_THRESH62 0x007f0000
|
||||
#define AR9170_PHY_EXT_CCA_THRESH62_S 16
|
||||
#define AR9170_PHY_EXT_MINCCA_PWR 0xff800000
|
||||
#define AR9170_PHY_EXT_MINCCA_PWR_S 23
|
||||
#define AR9170_PHY_EXT_CCA_MIN_PWR 0xff800000
|
||||
#define AR9170_PHY_EXT_CCA_MIN_PWR_S 23
|
||||
|
||||
#define AR9170_PHY_REG_SFCORR_EXT (AR9170_PHY_REG_BASE + 0x01c0)
|
||||
#define AR9170_PHY_SFCORR_EXT_M1_THRESH 0x0000007f
|
||||
@ -546,19 +546,19 @@
|
||||
#define AR9170_PHY_FORCE_XPA_CFG_S 0
|
||||
|
||||
#define AR9170_PHY_REG_CH1_CCA (AR9170_PHY_REG_BASE + 0x1064)
|
||||
#define AR9170_PHY_CH1_MINCCA_PWR 0x0ff80000
|
||||
#define AR9170_PHY_CH1_MINCCA_PWR_S 19
|
||||
#define AR9170_PHY_CH1_CCA_MIN_PWR 0x0ff80000
|
||||
#define AR9170_PHY_CH1_CCA_MIN_PWR_S 19
|
||||
|
||||
#define AR9170_PHY_REG_CH2_CCA (AR9170_PHY_REG_BASE + 0x2064)
|
||||
#define AR9170_PHY_CH2_MINCCA_PWR 0x0ff80000
|
||||
#define AR9170_PHY_CH2_MINCCA_PWR_S 19
|
||||
#define AR9170_PHY_CH2_CCA_MIN_PWR 0x0ff80000
|
||||
#define AR9170_PHY_CH2_CCA_MIN_PWR_S 19
|
||||
|
||||
#define AR9170_PHY_REG_CH1_EXT_CCA (AR9170_PHY_REG_BASE + 0x11bc)
|
||||
#define AR9170_PHY_CH1_EXT_MINCCA_PWR 0xff800000
|
||||
#define AR9170_PHY_CH1_EXT_MINCCA_PWR_S 23
|
||||
#define AR9170_PHY_CH1_EXT_CCA_MIN_PWR 0xff800000
|
||||
#define AR9170_PHY_CH1_EXT_CCA_MIN_PWR_S 23
|
||||
|
||||
#define AR9170_PHY_REG_CH2_EXT_CCA (AR9170_PHY_REG_BASE + 0x21bc)
|
||||
#define AR9170_PHY_CH2_EXT_MINCCA_PWR 0xff800000
|
||||
#define AR9170_PHY_CH2_EXT_MINCCA_PWR_S 23
|
||||
#define AR9170_PHY_CH2_EXT_CCA_MIN_PWR 0xff800000
|
||||
#define AR9170_PHY_CH2_EXT_CCA_MIN_PWR_S 23
|
||||
|
||||
#endif /* __CARL9170_SHARED_PHY_H */
|
||||
|
@ -242,9 +242,11 @@ static void carl9170_tx_release(struct kref *ref)
|
||||
ar->tx_ampdu_schedule = true;
|
||||
|
||||
if (txinfo->flags & IEEE80211_TX_STAT_AMPDU) {
|
||||
txinfo->status.ampdu_len = txinfo->pad[0];
|
||||
txinfo->status.ampdu_ack_len = txinfo->pad[1];
|
||||
txinfo->pad[0] = txinfo->pad[1] = 0;
|
||||
struct _carl9170_tx_superframe *super;
|
||||
|
||||
super = (void *)skb->data;
|
||||
txinfo->status.ampdu_len = super->s.rix;
|
||||
txinfo->status.ampdu_ack_len = super->s.cnt;
|
||||
} else if (txinfo->flags & IEEE80211_TX_STAT_ACK) {
|
||||
/*
|
||||
* drop redundant tx_status reports:
|
||||
@ -337,7 +339,8 @@ static void carl9170_tx_status_process_ampdu(struct ar9170 *ar,
|
||||
u8 tid;
|
||||
|
||||
if (!(txinfo->flags & IEEE80211_TX_CTL_AMPDU) ||
|
||||
txinfo->flags & IEEE80211_TX_CTL_INJECTED)
|
||||
txinfo->flags & IEEE80211_TX_CTL_INJECTED ||
|
||||
(!(super->f.mac_control & cpu_to_le16(AR9170_TX_MAC_AGGR))))
|
||||
return;
|
||||
|
||||
tx_info = IEEE80211_SKB_CB(skb);
|
||||
@ -389,8 +392,8 @@ static void carl9170_tx_status_process_ampdu(struct ar9170 *ar,
|
||||
sta_info->stats[tid].ampdu_ack_len++;
|
||||
|
||||
if (super->f.mac_control & cpu_to_le16(AR9170_TX_MAC_IMM_BA)) {
|
||||
txinfo->pad[0] = sta_info->stats[tid].ampdu_len;
|
||||
txinfo->pad[1] = sta_info->stats[tid].ampdu_ack_len;
|
||||
super->s.rix = sta_info->stats[tid].ampdu_len;
|
||||
super->s.cnt = sta_info->stats[tid].ampdu_ack_len;
|
||||
txinfo->flags |= IEEE80211_TX_STAT_AMPDU;
|
||||
sta_info->stats[tid].clear = true;
|
||||
}
|
||||
@ -524,6 +527,59 @@ next:
|
||||
}
|
||||
}
|
||||
|
||||
static void carl9170_tx_ampdu_timeout(struct ar9170 *ar)
|
||||
{
|
||||
struct carl9170_sta_tid *iter;
|
||||
struct sk_buff *skb;
|
||||
struct ieee80211_tx_info *txinfo;
|
||||
struct carl9170_tx_info *arinfo;
|
||||
struct _carl9170_tx_superframe *super;
|
||||
struct ieee80211_sta *sta;
|
||||
struct ieee80211_vif *vif;
|
||||
struct ieee80211_hdr *hdr;
|
||||
unsigned int vif_id;
|
||||
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(iter, &ar->tx_ampdu_list, list) {
|
||||
if (iter->state < CARL9170_TID_STATE_IDLE)
|
||||
continue;
|
||||
|
||||
spin_lock_bh(&iter->lock);
|
||||
skb = skb_peek(&iter->queue);
|
||||
if (!skb)
|
||||
goto unlock;
|
||||
|
||||
txinfo = IEEE80211_SKB_CB(skb);
|
||||
arinfo = (void *)txinfo->rate_driver_data;
|
||||
if (time_is_after_jiffies(arinfo->timeout +
|
||||
msecs_to_jiffies(CARL9170_QUEUE_TIMEOUT)))
|
||||
goto unlock;
|
||||
|
||||
super = (void *) skb->data;
|
||||
hdr = (void *) super->frame_data;
|
||||
|
||||
vif_id = (super->s.misc & CARL9170_TX_SUPER_MISC_VIF_ID) >>
|
||||
CARL9170_TX_SUPER_MISC_VIF_ID_S;
|
||||
|
||||
if (WARN_ON(vif_id >= AR9170_MAX_VIRTUAL_MAC))
|
||||
goto unlock;
|
||||
|
||||
vif = rcu_dereference(ar->vif_priv[vif_id].vif);
|
||||
if (WARN_ON(!vif))
|
||||
goto unlock;
|
||||
|
||||
sta = ieee80211_find_sta(vif, hdr->addr1);
|
||||
if (WARN_ON(!sta))
|
||||
goto unlock;
|
||||
|
||||
ieee80211_stop_tx_ba_session(sta, iter->tid);
|
||||
unlock:
|
||||
spin_unlock_bh(&iter->lock);
|
||||
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
void carl9170_tx_janitor(struct work_struct *work)
|
||||
{
|
||||
struct ar9170 *ar = container_of(work, struct ar9170,
|
||||
@ -534,6 +590,7 @@ void carl9170_tx_janitor(struct work_struct *work)
|
||||
ar->tx_janitor_last_run = jiffies;
|
||||
|
||||
carl9170_check_queue_stop_timeout(ar);
|
||||
carl9170_tx_ampdu_timeout(ar);
|
||||
|
||||
if (!atomic_read(&ar->tx_total_queued))
|
||||
return;
|
||||
@ -842,10 +899,8 @@ static int carl9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb)
|
||||
if (unlikely(!sta || !cvif))
|
||||
goto err_out;
|
||||
|
||||
factor = min_t(unsigned int, 1u,
|
||||
info->control.sta->ht_cap.ampdu_factor);
|
||||
|
||||
density = info->control.sta->ht_cap.ampdu_density;
|
||||
factor = min_t(unsigned int, 1u, sta->ht_cap.ampdu_factor);
|
||||
density = sta->ht_cap.ampdu_density;
|
||||
|
||||
if (density) {
|
||||
/*
|
||||
@ -1206,6 +1261,7 @@ static void carl9170_tx(struct ar9170 *ar)
|
||||
static bool carl9170_tx_ampdu_queue(struct ar9170 *ar,
|
||||
struct ieee80211_sta *sta, struct sk_buff *skb)
|
||||
{
|
||||
struct _carl9170_tx_superframe *super = (void *) super;
|
||||
struct carl9170_sta_info *sta_info;
|
||||
struct carl9170_sta_tid *agg;
|
||||
struct sk_buff *iter;
|
||||
@ -1274,6 +1330,7 @@ err_unlock:
|
||||
|
||||
err_unlock_rcu:
|
||||
rcu_read_unlock();
|
||||
super->f.mac_control &= ~cpu_to_le16(AR9170_TX_MAC_AGGR);
|
||||
carl9170_tx_status(ar, skb, false);
|
||||
ar->tx_dropped++;
|
||||
return false;
|
||||
@ -1302,9 +1359,6 @@ int carl9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
*/
|
||||
|
||||
if (info->flags & IEEE80211_TX_CTL_AMPDU) {
|
||||
if (WARN_ON_ONCE(!sta))
|
||||
goto err_free;
|
||||
|
||||
run = carl9170_tx_ampdu_queue(ar, sta, skb);
|
||||
if (run)
|
||||
carl9170_tx_ampdu(ar);
|
||||
|
@ -433,7 +433,7 @@ static void carl9170_usb_rx_complete(struct urb *urb)
|
||||
* device.
|
||||
*/
|
||||
|
||||
carl9170_restart(ar, CARL9170_RR_SLOW_SYSTEM);
|
||||
ieee80211_queue_work(ar->hw, &ar->ping_work);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
|
@ -1,7 +1,7 @@
|
||||
#ifndef __CARL9170_SHARED_VERSION_H
|
||||
#define __CARL9170_SHARED_VERSION_H
|
||||
#define CARL9170FW_VERSION_YEAR 10
|
||||
#define CARL9170FW_VERSION_MONTH 9
|
||||
#define CARL9170FW_VERSION_DAY 28
|
||||
#define CARL9170FW_VERSION_GIT "1.8.8.3"
|
||||
#define CARL9170FW_VERSION_MONTH 10
|
||||
#define CARL9170FW_VERSION_DAY 29
|
||||
#define CARL9170FW_VERSION_GIT "1.9.0"
|
||||
#endif /* __CARL9170_SHARED_VERSION_H */
|
||||
|
@ -70,11 +70,13 @@ enum ATH_DEBUG {
|
||||
#ifdef CONFIG_ATH_DEBUG
|
||||
void ath_print(struct ath_common *common, int dbg_mask, const char *fmt, ...)
|
||||
__attribute__ ((format (printf, 3, 4)));
|
||||
#define ATH_DBG_WARN(foo, arg...) WARN(foo, arg)
|
||||
#else
|
||||
static inline void __attribute__ ((format (printf, 3, 4)))
|
||||
ath_print(struct ath_common *common, int dbg_mask, const char *fmt, ...)
|
||||
{
|
||||
}
|
||||
#define ATH_DBG_WARN(foo, arg)
|
||||
#endif /* CONFIG_ATH_DEBUG */
|
||||
|
||||
/** Returns string describing opmode, or NULL if unknown mode. */
|
||||
|
@ -67,7 +67,8 @@ bool ath_hw_keyreset(struct ath_common *common, u16 entry)
|
||||
}
|
||||
EXPORT_SYMBOL(ath_hw_keyreset);
|
||||
|
||||
bool ath_hw_keysetmac(struct ath_common *common, u16 entry, const u8 *mac)
|
||||
static bool ath_hw_keysetmac(struct ath_common *common,
|
||||
u16 entry, const u8 *mac)
|
||||
{
|
||||
u32 macHi, macLo;
|
||||
u32 unicast_flag = AR_KEYTABLE_VALID;
|
||||
@ -107,9 +108,9 @@ bool ath_hw_keysetmac(struct ath_common *common, u16 entry, const u8 *mac)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ath_hw_set_keycache_entry(struct ath_common *common, u16 entry,
|
||||
const struct ath_keyval *k,
|
||||
const u8 *mac)
|
||||
static bool ath_hw_set_keycache_entry(struct ath_common *common, u16 entry,
|
||||
const struct ath_keyval *k,
|
||||
const u8 *mac)
|
||||
{
|
||||
void *ah = common->ah;
|
||||
u32 key0, key1, key2, key3, key4;
|
||||
|
@ -153,6 +153,19 @@
|
||||
#define B43_BFH_FEM_BT 0x0040 /* has FEM and switch to share antenna
|
||||
* with bluetooth */
|
||||
|
||||
/* SPROM boardflags2_lo values */
|
||||
#define B43_BFL2_RXBB_INT_REG_DIS 0x0001 /* external RX BB regulator present */
|
||||
#define B43_BFL2_APLL_WAR 0x0002 /* alternative A-band PLL settings implemented */
|
||||
#define B43_BFL2_TXPWRCTRL_EN 0x0004 /* permits enabling TX Power Control */
|
||||
#define B43_BFL2_2X4_DIV 0x0008 /* 2x4 diversity switch */
|
||||
#define B43_BFL2_5G_PWRGAIN 0x0010 /* supports 5G band power gain */
|
||||
#define B43_BFL2_PCIEWAR_OVR 0x0020 /* overrides ASPM and Clkreq settings */
|
||||
#define B43_BFL2_CAESERS_BRD 0x0040 /* is Caesers board (unused) */
|
||||
#define B43_BFL2_BTC3WIRE 0x0080 /* used 3-wire bluetooth coexist */
|
||||
#define B43_BFL2_SKWRKFEM_BRD 0x0100 /* 4321mcm93 uses Skyworks FEM */
|
||||
#define B43_BFL2_SPUR_WAR 0x0200 /* has a workaround for clock-harmonic spurs */
|
||||
#define B43_BFL2_GPLL_WAR 0x0400 /* altenative G-band PLL settings implemented */
|
||||
|
||||
/* GPIO register offset, in both ChipCommon and PCI core. */
|
||||
#define B43_GPIO_CONTROL 0x6c
|
||||
|
||||
|
@ -415,11 +415,6 @@ static int alloc_ringmemory(struct b43_dmaring *ring)
|
||||
|
||||
static void free_ringmemory(struct b43_dmaring *ring)
|
||||
{
|
||||
gfp_t flags = GFP_KERNEL;
|
||||
|
||||
if (ring->type == B43_DMA_64BIT)
|
||||
flags |= GFP_DMA;
|
||||
|
||||
dma_free_coherent(ring->dev->dev->dma_dev, B43_DMA_RINGMEMSIZE,
|
||||
ring->descbase, ring->dmabase);
|
||||
}
|
||||
|
@ -191,7 +191,8 @@ static void b43_radio_init2055_post(struct b43_wldev *dev)
|
||||
binfo->type != 0x46D ||
|
||||
binfo->rev < 0x41);
|
||||
else
|
||||
workaround = ((sprom->boardflags_hi & B43_BFH_NOPA) == 0);
|
||||
workaround =
|
||||
!(sprom->boardflags2_lo & B43_BFL2_RXBB_INT_REG_DIS);
|
||||
|
||||
b43_radio_mask(dev, B2055_MASTER1, 0xFFF3);
|
||||
if (workaround) {
|
||||
@ -240,10 +241,13 @@ static void b43_radio_init2055_post(struct b43_wldev *dev)
|
||||
static void b43_radio_init2055(struct b43_wldev *dev)
|
||||
{
|
||||
b43_radio_init2055_pre(dev);
|
||||
if (b43_status(dev) < B43_STAT_INITIALIZED)
|
||||
b2055_upload_inittab(dev, 0, 1);
|
||||
else
|
||||
b2055_upload_inittab(dev, 0/*FIXME on 5ghz band*/, 0);
|
||||
if (b43_status(dev) < B43_STAT_INITIALIZED) {
|
||||
/* Follow wl, not specs. Do not force uploading all regs */
|
||||
b2055_upload_inittab(dev, 0, 0);
|
||||
} else {
|
||||
bool ghz5 = b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ;
|
||||
b2055_upload_inittab(dev, ghz5, 0);
|
||||
}
|
||||
b43_radio_init2055_post(dev);
|
||||
}
|
||||
|
||||
|
@ -244,7 +244,7 @@ static const struct b2055_inittab_entry b2055_inittab [] = {
|
||||
[0xCB] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
|
||||
[0xCC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
|
||||
[B2055_C1_LNA_GAINBST] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
|
||||
[0xCE] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
|
||||
[0xCE] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
|
||||
[0xCF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
|
||||
[0xD0] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
|
||||
[0xD1] = { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
|
||||
@ -256,7 +256,7 @@ static const struct b2055_inittab_entry b2055_inittab [] = {
|
||||
[0xD7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
|
||||
[0xD8] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
|
||||
[B2055_C2_LNA_GAINBST] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
|
||||
[0xDA] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
|
||||
[0xDA] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
|
||||
[0xDB] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
|
||||
[0xDC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
|
||||
[0xDD] = { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
|
||||
@ -1299,7 +1299,7 @@ void b2055_upload_inittab(struct b43_wldev *dev,
|
||||
bool ghz5, bool ignore_uploadflag)
|
||||
{
|
||||
const struct b2055_inittab_entry *e;
|
||||
unsigned int i;
|
||||
unsigned int i, writes = 0;
|
||||
u16 value;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(b2055_inittab); i++) {
|
||||
@ -1312,6 +1312,8 @@ void b2055_upload_inittab(struct b43_wldev *dev,
|
||||
else
|
||||
value = e->ghz2;
|
||||
b43_radio_write16(dev, i, value);
|
||||
if (++writes % 4 == 0)
|
||||
b43_read32(dev, B43_MMIO_MACCTL); /* flush */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,9 +24,60 @@
|
||||
#include "radio_2056.h"
|
||||
#include "phy_common.h"
|
||||
|
||||
#define RADIOREGS3(r00, r01, r02, r03, r04, r05, r06, r07, r08, r09, \
|
||||
r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, \
|
||||
r20, r21, r22, r23, r24, r25, r26, r27, r28, r29, \
|
||||
r30, r31, r32, r33, r34, r35, r36) \
|
||||
.radio_syn_pll_vcocal1 = r00, \
|
||||
.radio_syn_pll_vcocal2 = r01, \
|
||||
.radio_syn_pll_refdiv = r02, \
|
||||
.radio_syn_pll_mmd2 = r03, \
|
||||
.radio_syn_pll_mmd1 = r04, \
|
||||
.radio_syn_pll_loopfilter1 = r05, \
|
||||
.radio_syn_pll_loopfilter2 = r06, \
|
||||
.radio_syn_pll_loopfilter3 = r07, \
|
||||
.radio_syn_pll_loopfilter4 = r08, \
|
||||
.radio_syn_pll_loopfilter5 = r09, \
|
||||
.radio_syn_reserved_addr27 = r10, \
|
||||
.radio_syn_reserved_addr28 = r11, \
|
||||
.radio_syn_reserved_addr29 = r12, \
|
||||
.radio_syn_logen_vcobuf1 = r13, \
|
||||
.radio_syn_logen_mixer2 = r14, \
|
||||
.radio_syn_logen_buf3 = r15, \
|
||||
.radio_syn_logen_buf4 = r16, \
|
||||
.radio_rx0_lnaa_tune = r17, \
|
||||
.radio_rx0_lnag_tune = r18, \
|
||||
.radio_tx0_intpaa_boost_tune = r19, \
|
||||
.radio_tx0_intpag_boost_tune = r20, \
|
||||
.radio_tx0_pada_boost_tune = r21, \
|
||||
.radio_tx0_padg_boost_tune = r22, \
|
||||
.radio_tx0_pgaa_boost_tune = r23, \
|
||||
.radio_tx0_pgag_boost_tune = r24, \
|
||||
.radio_tx0_mixa_boost_tune = r25, \
|
||||
.radio_tx0_mixg_boost_tune = r26, \
|
||||
.radio_rx1_lnaa_tune = r27, \
|
||||
.radio_rx1_lnag_tune = r28, \
|
||||
.radio_tx1_intpaa_boost_tune = r29, \
|
||||
.radio_tx1_intpag_boost_tune = r30, \
|
||||
.radio_tx1_pada_boost_tune = r31, \
|
||||
.radio_tx1_padg_boost_tune = r32, \
|
||||
.radio_tx1_pgaa_boost_tune = r33, \
|
||||
.radio_tx1_pgag_boost_tune = r34, \
|
||||
.radio_tx1_mixa_boost_tune = r35, \
|
||||
.radio_tx1_mixg_boost_tune = r36
|
||||
|
||||
#define PHYREGS(r0, r1, r2, r3, r4, r5) \
|
||||
.phy_regs.phy_bw1a = r0, \
|
||||
.phy_regs.phy_bw2 = r1, \
|
||||
.phy_regs.phy_bw3 = r2, \
|
||||
.phy_regs.phy_bw4 = r3, \
|
||||
.phy_regs.phy_bw5 = r4, \
|
||||
.phy_regs.phy_bw6 = r5
|
||||
|
||||
static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_rev3[] = {
|
||||
};
|
||||
|
||||
/* TODO: add support for rev4+ devices by searching in rev4+ tables */
|
||||
const struct b43_nphy_channeltab_entry_rev3 *
|
||||
b43_nphy_get_chantabent_rev3(struct b43_wldev *dev, u16 freq)
|
||||
{
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -29,7 +29,7 @@
|
||||
/* Returns TRUE, if the radio is enabled in hardware. */
|
||||
bool b43legacy_is_hw_radio_enabled(struct b43legacy_wldev *dev)
|
||||
{
|
||||
if (dev->phy.rev >= 3) {
|
||||
if (dev->dev->id.revision >= 3) {
|
||||
if (!(b43legacy_read32(dev, B43legacy_MMIO_RADIO_HWENABLED_HI)
|
||||
& B43legacy_MMIO_RADIO_HWENABLED_HI_MASK))
|
||||
return 1;
|
||||
|
@ -106,6 +106,9 @@ config IWL5000
|
||||
Intel WiFi Link 1000BGN
|
||||
Intel Wireless WiFi 5150AGN
|
||||
Intel Wireless WiFi 5100AGN, 5300AGN, and 5350AGN
|
||||
Intel 6000 Gen 2 Series Wi-Fi Adapters (6000G2A and 6000G2B)
|
||||
Intel WIreless WiFi Link 6050BGN Gen 2 Adapter
|
||||
Intel 100 Series Wi-Fi Adapters (100BGN and 130BGN)
|
||||
|
||||
config IWL3945
|
||||
tristate "Intel PRO/Wireless 3945ABG/BG Network Connection (iwl3945)"
|
||||
|
@ -2,6 +2,8 @@ obj-$(CONFIG_IWLWIFI) += iwlcore.o
|
||||
iwlcore-objs := iwl-core.o iwl-eeprom.o iwl-hcmd.o iwl-power.o
|
||||
iwlcore-objs += iwl-rx.o iwl-tx.o iwl-sta.o
|
||||
iwlcore-objs += iwl-scan.o iwl-led.o
|
||||
iwlcore-$(CONFIG_IWL3945) += iwl-legacy.o
|
||||
iwlcore-$(CONFIG_IWL4965) += iwl-legacy.o
|
||||
iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o
|
||||
iwlcore-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o
|
||||
|
||||
@ -9,13 +11,14 @@ CFLAGS_iwl-devtrace.o := -I$(src)
|
||||
|
||||
# AGN
|
||||
obj-$(CONFIG_IWLAGN) += iwlagn.o
|
||||
iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o iwl-agn-ict.o
|
||||
iwlagn-objs += iwl-agn-ucode.o iwl-agn-hcmd.o iwl-agn-tx.o
|
||||
iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o
|
||||
iwlagn-objs += iwl-agn-ucode.o iwl-agn-tx.o
|
||||
iwlagn-objs += iwl-agn-lib.o iwl-agn-rx.o iwl-agn-calib.o
|
||||
iwlagn-objs += iwl-agn-tt.o iwl-agn-sta.o iwl-agn-eeprom.o
|
||||
iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-agn-debugfs.o
|
||||
|
||||
iwlagn-$(CONFIG_IWL4965) += iwl-4965.o
|
||||
iwlagn-$(CONFIG_IWL5000) += iwl-agn-rxon.o iwl-agn-hcmd.o iwl-agn-ict.o
|
||||
iwlagn-$(CONFIG_IWL5000) += iwl-5000.o
|
||||
iwlagn-$(CONFIG_IWL5000) += iwl-6000.o
|
||||
iwlagn-$(CONFIG_IWL5000) += iwl-1000.o
|
||||
|
@ -211,14 +211,16 @@ static struct iwl_lib_ops iwl1000_lib = {
|
||||
.calib_version = iwlagn_eeprom_calib_version,
|
||||
.query_addr = iwlagn_eeprom_query_addr,
|
||||
},
|
||||
.post_associate = iwl_post_associate,
|
||||
.isr = iwl_isr_ict,
|
||||
.config_ap = iwl_config_ap,
|
||||
.isr_ops = {
|
||||
.isr = iwl_isr_ict,
|
||||
.free = iwl_free_isr_ict,
|
||||
.alloc = iwl_alloc_isr_ict,
|
||||
.reset = iwl_reset_ict,
|
||||
.disable = iwl_disable_ict,
|
||||
},
|
||||
.temp_ops = {
|
||||
.temperature = iwlagn_temperature,
|
||||
},
|
||||
.manage_ibss_station = iwlagn_manage_ibss_station,
|
||||
.update_bcast_stations = iwl_update_bcast_stations,
|
||||
.debugfs_ops = {
|
||||
.rx_stats_read = iwl_ucode_rx_stats_read,
|
||||
.tx_stats_read = iwl_ucode_tx_stats_read,
|
||||
@ -243,6 +245,7 @@ static const struct iwl_ops iwl1000_ops = {
|
||||
.hcmd = &iwlagn_hcmd,
|
||||
.utils = &iwlagn_hcmd_utils,
|
||||
.led = &iwlagn_led_ops,
|
||||
.ieee80211_ops = &iwlagn_hw_ops,
|
||||
};
|
||||
|
||||
static struct iwl_base_params iwl1000_base_params = {
|
||||
|
@ -51,6 +51,7 @@
|
||||
#include "iwl-led.h"
|
||||
#include "iwl-3945-led.h"
|
||||
#include "iwl-3945-debugfs.h"
|
||||
#include "iwl-legacy.h"
|
||||
|
||||
#define IWL_DECLARE_RATE_INFO(r, ip, in, rp, rn, pp, np) \
|
||||
[IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP, \
|
||||
@ -1451,6 +1452,10 @@ static int iwl3945_send_tx_power(struct iwl_priv *priv)
|
||||
};
|
||||
u16 chan;
|
||||
|
||||
if (WARN_ONCE(test_bit(STATUS_SCAN_HW, &priv->status),
|
||||
"TX Power requested while scanning!\n"))
|
||||
return -EAGAIN;
|
||||
|
||||
chan = le16_to_cpu(priv->contexts[IWL_RXON_CTX_BSS].active.channel);
|
||||
|
||||
txpower.band = (priv->band == IEEE80211_BAND_5GHZ) ? 0 : 1;
|
||||
@ -2722,10 +2727,9 @@ static struct iwl_lib_ops iwl3945_lib = {
|
||||
},
|
||||
.send_tx_power = iwl3945_send_tx_power,
|
||||
.is_valid_rtc_data_addr = iwl3945_hw_valid_rtc_data_addr,
|
||||
.post_associate = iwl3945_post_associate,
|
||||
.isr = iwl_isr_legacy,
|
||||
.config_ap = iwl3945_config_ap,
|
||||
.manage_ibss_station = iwl3945_manage_ibss_station,
|
||||
.isr_ops = {
|
||||
.isr = iwl_isr_legacy,
|
||||
},
|
||||
.recover_from_tx_stall = iwl_bg_monitor_recover,
|
||||
.check_plcp_health = iwl3945_good_plcp_health,
|
||||
|
||||
@ -2736,10 +2740,16 @@ static struct iwl_lib_ops iwl3945_lib = {
|
||||
},
|
||||
};
|
||||
|
||||
static const struct iwl_legacy_ops iwl3945_legacy_ops = {
|
||||
.post_associate = iwl3945_post_associate,
|
||||
.config_ap = iwl3945_config_ap,
|
||||
.manage_ibss_station = iwl3945_manage_ibss_station,
|
||||
};
|
||||
|
||||
static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = {
|
||||
.get_hcmd_size = iwl3945_get_hcmd_size,
|
||||
.build_addsta_hcmd = iwl3945_build_addsta_hcmd,
|
||||
.tx_cmd_protection = iwlcore_tx_cmd_protection,
|
||||
.tx_cmd_protection = iwl_legacy_tx_cmd_protection,
|
||||
.request_scan = iwl3945_request_scan,
|
||||
.post_scan = iwl3945_post_scan,
|
||||
};
|
||||
@ -2749,6 +2759,8 @@ static const struct iwl_ops iwl3945_ops = {
|
||||
.hcmd = &iwl3945_hcmd,
|
||||
.utils = &iwl3945_hcmd_utils,
|
||||
.led = &iwl3945_led_ops,
|
||||
.legacy = &iwl3945_legacy_ops,
|
||||
.ieee80211_ops = &iwl3945_hw_ops,
|
||||
};
|
||||
|
||||
static struct iwl_base_params iwl3945_base_params = {
|
||||
|
@ -264,10 +264,8 @@ void iwl3945_reply_statistics(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb);
|
||||
extern void iwl3945_disable_events(struct iwl_priv *priv);
|
||||
extern int iwl4965_get_temperature(const struct iwl_priv *priv);
|
||||
extern void iwl3945_post_associate(struct iwl_priv *priv,
|
||||
struct ieee80211_vif *vif);
|
||||
extern void iwl3945_config_ap(struct iwl_priv *priv,
|
||||
struct ieee80211_vif *vif);
|
||||
extern void iwl3945_post_associate(struct iwl_priv *priv);
|
||||
extern void iwl3945_config_ap(struct iwl_priv *priv);
|
||||
|
||||
extern int iwl3945_commit_rxon(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx);
|
||||
@ -282,6 +280,8 @@ extern int iwl3945_commit_rxon(struct iwl_priv *priv,
|
||||
*/
|
||||
extern u8 iwl3945_hw_find_station(struct iwl_priv *priv, const u8 *bssid);
|
||||
|
||||
extern struct ieee80211_ops iwl3945_hw_ops;
|
||||
|
||||
/*
|
||||
* Forward declare iwl-3945.c functions for iwl-base.c
|
||||
*/
|
||||
|
@ -48,6 +48,7 @@
|
||||
#include "iwl-agn-led.h"
|
||||
#include "iwl-agn.h"
|
||||
#include "iwl-agn-debugfs.h"
|
||||
#include "iwl-legacy.h"
|
||||
|
||||
static int iwl4965_send_tx_power(struct iwl_priv *priv);
|
||||
static int iwl4965_hw_get_temperature(struct iwl_priv *priv);
|
||||
@ -1377,13 +1378,9 @@ static int iwl4965_send_tx_power(struct iwl_priv *priv)
|
||||
u8 ctrl_chan_high = 0;
|
||||
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
|
||||
|
||||
if (test_bit(STATUS_SCANNING, &priv->status)) {
|
||||
/* If this gets hit a lot, switch it to a BUG() and catch
|
||||
* the stack trace to find out who is calling this during
|
||||
* a scan. */
|
||||
IWL_WARN(priv, "TX Power requested while scanning!\n");
|
||||
if (WARN_ONCE(test_bit(STATUS_SCAN_HW, &priv->status),
|
||||
"TX Power requested while scanning!\n"))
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
band = priv->band == IEEE80211_BAND_2GHZ;
|
||||
|
||||
@ -1447,6 +1444,142 @@ static int iwl4965_send_rxon_assoc(struct iwl_priv *priv,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int iwl4965_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
|
||||
{
|
||||
/* cast away the const for active_rxon in this function */
|
||||
struct iwl_rxon_cmd *active_rxon = (void *)&ctx->active;
|
||||
int ret;
|
||||
bool new_assoc =
|
||||
!!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK);
|
||||
|
||||
if (!iwl_is_alive(priv))
|
||||
return -EBUSY;
|
||||
|
||||
if (!ctx->is_active)
|
||||
return 0;
|
||||
|
||||
/* always get timestamp with Rx frame */
|
||||
ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK;
|
||||
|
||||
ret = iwl_check_rxon_cmd(priv, ctx);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Invalid RXON configuration. Not committing.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* receive commit_rxon request
|
||||
* abort any previous channel switch if still in process
|
||||
*/
|
||||
if (priv->switch_rxon.switch_in_progress &&
|
||||
(priv->switch_rxon.channel != ctx->staging.channel)) {
|
||||
IWL_DEBUG_11H(priv, "abort channel switch on %d\n",
|
||||
le16_to_cpu(priv->switch_rxon.channel));
|
||||
iwl_chswitch_done(priv, false);
|
||||
}
|
||||
|
||||
/* If we don't need to send a full RXON, we can use
|
||||
* iwl_rxon_assoc_cmd which is used to reconfigure filter
|
||||
* and other flags for the current radio configuration. */
|
||||
if (!iwl_full_rxon_required(priv, ctx)) {
|
||||
ret = iwl_send_rxon_assoc(priv, ctx);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Error setting RXON_ASSOC (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
|
||||
iwl_print_rx_config_cmd(priv, ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If we are currently associated and the new config requires
|
||||
* an RXON_ASSOC and the new config wants the associated mask enabled,
|
||||
* we must clear the associated from the active configuration
|
||||
* before we apply the new config */
|
||||
if (iwl_is_associated_ctx(ctx) && new_assoc) {
|
||||
IWL_DEBUG_INFO(priv, "Toggling associated bit on current RXON\n");
|
||||
active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
|
||||
|
||||
ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd,
|
||||
sizeof(struct iwl_rxon_cmd),
|
||||
active_rxon);
|
||||
|
||||
/* If the mask clearing failed then we set
|
||||
* active_rxon back to what it was previously */
|
||||
if (ret) {
|
||||
active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK;
|
||||
IWL_ERR(priv, "Error clearing ASSOC_MSK (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
iwl_clear_ucode_stations(priv, ctx);
|
||||
iwl_restore_stations(priv, ctx);
|
||||
ret = iwl_restore_default_wep_keys(priv, ctx);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
IWL_DEBUG_INFO(priv, "Sending RXON\n"
|
||||
"* with%s RXON_FILTER_ASSOC_MSK\n"
|
||||
"* channel = %d\n"
|
||||
"* bssid = %pM\n",
|
||||
(new_assoc ? "" : "out"),
|
||||
le16_to_cpu(ctx->staging.channel),
|
||||
ctx->staging.bssid_addr);
|
||||
|
||||
iwl_set_rxon_hwcrypto(priv, ctx, !priv->cfg->mod_params->sw_crypto);
|
||||
|
||||
/* Apply the new configuration
|
||||
* RXON unassoc clears the station table in uCode so restoration of
|
||||
* stations is needed after it (the RXON command) completes
|
||||
*/
|
||||
if (!new_assoc) {
|
||||
ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd,
|
||||
sizeof(struct iwl_rxon_cmd), &ctx->staging);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
IWL_DEBUG_INFO(priv, "Return from !new_assoc RXON.\n");
|
||||
memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
|
||||
iwl_clear_ucode_stations(priv, ctx);
|
||||
iwl_restore_stations(priv, ctx);
|
||||
ret = iwl_restore_default_wep_keys(priv, ctx);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
if (new_assoc) {
|
||||
priv->start_calib = 0;
|
||||
/* Apply the new configuration
|
||||
* RXON assoc doesn't clear the station table in uCode,
|
||||
*/
|
||||
ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd,
|
||||
sizeof(struct iwl_rxon_cmd), &ctx->staging);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
|
||||
}
|
||||
iwl_print_rx_config_cmd(priv, ctx);
|
||||
|
||||
iwl_init_sensitivity(priv);
|
||||
|
||||
/* If we issue a new RXON command which required a tune then we must
|
||||
* send a new TXPOWER command or we won't be able to Tx any frames */
|
||||
ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Error sending TX power (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwl4965_hw_channel_switch(struct iwl_priv *priv,
|
||||
struct ieee80211_channel_switch *ch_switch)
|
||||
{
|
||||
@ -1553,22 +1686,6 @@ static void iwl4965_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
|
||||
tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent;
|
||||
}
|
||||
|
||||
/**
|
||||
* sign_extend - Sign extend a value using specified bit as sign-bit
|
||||
*
|
||||
* Example: sign_extend(9, 3) would return -7 as bit3 of 1001b is 1
|
||||
* and bit0..2 is 001b which when sign extended to 1111111111111001b is -7.
|
||||
*
|
||||
* @param oper value to sign extend
|
||||
* @param index 0 based bit index (0<=index<32) to sign bit
|
||||
*/
|
||||
static s32 sign_extend(u32 oper, int index)
|
||||
{
|
||||
u8 shift = 31 - index;
|
||||
|
||||
return (s32)(oper << shift) >> shift;
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl4965_hw_get_temperature - return the calibrated temperature (in Kelvin)
|
||||
* @statistics: Provides the temperature reading from the uCode
|
||||
@ -1606,9 +1723,9 @@ static int iwl4965_hw_get_temperature(struct iwl_priv *priv)
|
||||
* "initialize" ALIVE response.
|
||||
*/
|
||||
if (!test_bit(STATUS_TEMPERATURE, &priv->status))
|
||||
vt = sign_extend(R4, 23);
|
||||
vt = sign_extend32(R4, 23);
|
||||
else
|
||||
vt = sign_extend(le32_to_cpu(priv->_agn.statistics.
|
||||
vt = sign_extend32(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);
|
||||
@ -2216,7 +2333,7 @@ static void iwl4965_cancel_deferred_work(struct iwl_priv *priv)
|
||||
|
||||
static struct iwl_hcmd_ops iwl4965_hcmd = {
|
||||
.rxon_assoc = iwl4965_send_rxon_assoc,
|
||||
.commit_rxon = iwlagn_commit_rxon,
|
||||
.commit_rxon = iwl4965_commit_rxon,
|
||||
.set_rxon_chain = iwlagn_set_rxon_chain,
|
||||
.send_bt_config = iwl_send_bt_config,
|
||||
};
|
||||
@ -2233,12 +2350,155 @@ static void iwl4965_post_scan(struct iwl_priv *priv)
|
||||
iwlcore_commit_rxon(priv, ctx);
|
||||
}
|
||||
|
||||
static void iwl4965_post_associate(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
|
||||
struct ieee80211_vif *vif = ctx->vif;
|
||||
struct ieee80211_conf *conf = NULL;
|
||||
int ret = 0;
|
||||
|
||||
if (!vif || !priv->is_open)
|
||||
return;
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_AP) {
|
||||
IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||
return;
|
||||
|
||||
iwl_scan_cancel_timeout(priv, 200);
|
||||
|
||||
conf = ieee80211_get_hw_conf(priv->hw);
|
||||
|
||||
ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
|
||||
iwlcore_commit_rxon(priv, ctx);
|
||||
|
||||
ret = iwl_send_rxon_timing(priv, ctx);
|
||||
if (ret)
|
||||
IWL_WARN(priv, "RXON timing - "
|
||||
"Attempting to continue.\n");
|
||||
|
||||
ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
|
||||
|
||||
iwl_set_rxon_ht(priv, &priv->current_ht_config);
|
||||
|
||||
if (priv->cfg->ops->hcmd->set_rxon_chain)
|
||||
priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
|
||||
|
||||
ctx->staging.assoc_id = cpu_to_le16(vif->bss_conf.aid);
|
||||
|
||||
IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n",
|
||||
vif->bss_conf.aid, vif->bss_conf.beacon_int);
|
||||
|
||||
if (vif->bss_conf.use_short_preamble)
|
||||
ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
|
||||
else
|
||||
ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
|
||||
|
||||
if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
|
||||
if (vif->bss_conf.use_short_slot)
|
||||
ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
|
||||
else
|
||||
ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
|
||||
}
|
||||
|
||||
iwlcore_commit_rxon(priv, ctx);
|
||||
|
||||
IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n",
|
||||
vif->bss_conf.aid, ctx->active.bssid_addr);
|
||||
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
break;
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
iwlagn_send_beacon_cmd(priv);
|
||||
break;
|
||||
default:
|
||||
IWL_ERR(priv, "%s Should not be called in %d mode\n",
|
||||
__func__, vif->type);
|
||||
break;
|
||||
}
|
||||
|
||||
/* the chain noise calibration will enabled PM upon completion
|
||||
* If chain noise has already been run, then we need to enable
|
||||
* power management here */
|
||||
if (priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE)
|
||||
iwl_power_update_mode(priv, false);
|
||||
|
||||
/* Enable Rx differential gain and sensitivity calibrations */
|
||||
iwl_chain_noise_reset(priv);
|
||||
priv->start_calib = 1;
|
||||
}
|
||||
|
||||
static void iwl4965_config_ap(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
|
||||
struct ieee80211_vif *vif = ctx->vif;
|
||||
int ret = 0;
|
||||
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||
return;
|
||||
|
||||
/* The following should be done only at AP bring up */
|
||||
if (!iwl_is_associated_ctx(ctx)) {
|
||||
|
||||
/* RXON - unassoc (to set timing command) */
|
||||
ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
|
||||
iwlcore_commit_rxon(priv, ctx);
|
||||
|
||||
/* RXON Timing */
|
||||
ret = iwl_send_rxon_timing(priv, ctx);
|
||||
if (ret)
|
||||
IWL_WARN(priv, "RXON timing failed - "
|
||||
"Attempting to continue.\n");
|
||||
|
||||
/* AP has all antennas */
|
||||
priv->chain_noise_data.active_chains =
|
||||
priv->hw_params.valid_rx_ant;
|
||||
iwl_set_rxon_ht(priv, &priv->current_ht_config);
|
||||
if (priv->cfg->ops->hcmd->set_rxon_chain)
|
||||
priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
|
||||
|
||||
ctx->staging.assoc_id = 0;
|
||||
|
||||
if (vif->bss_conf.use_short_preamble)
|
||||
ctx->staging.flags |=
|
||||
RXON_FLG_SHORT_PREAMBLE_MSK;
|
||||
else
|
||||
ctx->staging.flags &=
|
||||
~RXON_FLG_SHORT_PREAMBLE_MSK;
|
||||
|
||||
if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
|
||||
if (vif->bss_conf.use_short_slot)
|
||||
ctx->staging.flags |=
|
||||
RXON_FLG_SHORT_SLOT_MSK;
|
||||
else
|
||||
ctx->staging.flags &=
|
||||
~RXON_FLG_SHORT_SLOT_MSK;
|
||||
}
|
||||
/* need to send beacon cmd before committing assoc RXON! */
|
||||
iwlagn_send_beacon_cmd(priv);
|
||||
/* restore RXON assoc */
|
||||
ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
|
||||
iwlcore_commit_rxon(priv, ctx);
|
||||
}
|
||||
iwlagn_send_beacon_cmd(priv);
|
||||
|
||||
/* FIXME - we need to add code here to detect a totally new
|
||||
* configuration, reset the AP, unassoc, rxon timing, assoc,
|
||||
* clear sta table, add BCAST sta... */
|
||||
}
|
||||
|
||||
static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = {
|
||||
.get_hcmd_size = iwl4965_get_hcmd_size,
|
||||
.build_addsta_hcmd = iwl4965_build_addsta_hcmd,
|
||||
.chain_noise_reset = iwl4965_chain_noise_reset,
|
||||
.gain_computation = iwl4965_gain_computation,
|
||||
.tx_cmd_protection = iwlcore_tx_cmd_protection,
|
||||
.tx_cmd_protection = iwl_legacy_tx_cmd_protection,
|
||||
.calc_rssi = iwl4965_calc_rssi,
|
||||
.request_scan = iwlagn_request_scan,
|
||||
.post_scan = iwl4965_post_scan,
|
||||
@ -2285,14 +2545,12 @@ static struct iwl_lib_ops iwl4965_lib = {
|
||||
},
|
||||
.send_tx_power = iwl4965_send_tx_power,
|
||||
.update_chain_flags = iwl_update_chain_flags,
|
||||
.post_associate = iwl_post_associate,
|
||||
.config_ap = iwl_config_ap,
|
||||
.isr = iwl_isr_legacy,
|
||||
.isr_ops = {
|
||||
.isr = iwl_isr_legacy,
|
||||
},
|
||||
.temp_ops = {
|
||||
.temperature = iwl4965_temperature_calib,
|
||||
},
|
||||
.manage_ibss_station = iwlagn_manage_ibss_station,
|
||||
.update_bcast_stations = iwl_update_bcast_stations,
|
||||
.debugfs_ops = {
|
||||
.rx_stats_read = iwl_ucode_rx_stats_read,
|
||||
.tx_stats_read = iwl_ucode_tx_stats_read,
|
||||
@ -2304,11 +2562,43 @@ static struct iwl_lib_ops iwl4965_lib = {
|
||||
.check_plcp_health = iwl_good_plcp_health,
|
||||
};
|
||||
|
||||
static const struct iwl_legacy_ops iwl4965_legacy_ops = {
|
||||
.post_associate = iwl4965_post_associate,
|
||||
.config_ap = iwl4965_config_ap,
|
||||
.manage_ibss_station = iwlagn_manage_ibss_station,
|
||||
.update_bcast_stations = iwl_update_bcast_stations,
|
||||
};
|
||||
|
||||
struct ieee80211_ops iwl4965_hw_ops = {
|
||||
.tx = iwlagn_mac_tx,
|
||||
.start = iwlagn_mac_start,
|
||||
.stop = iwlagn_mac_stop,
|
||||
.add_interface = iwl_mac_add_interface,
|
||||
.remove_interface = iwl_mac_remove_interface,
|
||||
.change_interface = iwl_mac_change_interface,
|
||||
.config = iwl_legacy_mac_config,
|
||||
.configure_filter = iwlagn_configure_filter,
|
||||
.set_key = iwlagn_mac_set_key,
|
||||
.update_tkip_key = iwlagn_mac_update_tkip_key,
|
||||
.conf_tx = iwl_mac_conf_tx,
|
||||
.reset_tsf = iwl_legacy_mac_reset_tsf,
|
||||
.bss_info_changed = iwl_legacy_mac_bss_info_changed,
|
||||
.ampdu_action = iwlagn_mac_ampdu_action,
|
||||
.hw_scan = iwl_mac_hw_scan,
|
||||
.sta_add = iwlagn_mac_sta_add,
|
||||
.sta_remove = iwl_mac_sta_remove,
|
||||
.channel_switch = iwlagn_mac_channel_switch,
|
||||
.flush = iwlagn_mac_flush,
|
||||
.tx_last_beacon = iwl_mac_tx_last_beacon,
|
||||
};
|
||||
|
||||
static const struct iwl_ops iwl4965_ops = {
|
||||
.lib = &iwl4965_lib,
|
||||
.hcmd = &iwl4965_hcmd,
|
||||
.utils = &iwl4965_hcmd_utils,
|
||||
.led = &iwlagn_led_ops,
|
||||
.legacy = &iwl4965_legacy_ops,
|
||||
.ieee80211_ops = &iwl4965_hw_ops,
|
||||
};
|
||||
|
||||
static struct iwl_base_params iwl4965_base_params = {
|
||||
|
@ -385,14 +385,16 @@ static struct iwl_lib_ops iwl5000_lib = {
|
||||
.calib_version = iwlagn_eeprom_calib_version,
|
||||
.query_addr = iwlagn_eeprom_query_addr,
|
||||
},
|
||||
.post_associate = iwl_post_associate,
|
||||
.isr = iwl_isr_ict,
|
||||
.config_ap = iwl_config_ap,
|
||||
.isr_ops = {
|
||||
.isr = iwl_isr_ict,
|
||||
.free = iwl_free_isr_ict,
|
||||
.alloc = iwl_alloc_isr_ict,
|
||||
.reset = iwl_reset_ict,
|
||||
.disable = iwl_disable_ict,
|
||||
},
|
||||
.temp_ops = {
|
||||
.temperature = iwlagn_temperature,
|
||||
},
|
||||
.manage_ibss_station = iwlagn_manage_ibss_station,
|
||||
.update_bcast_stations = iwl_update_bcast_stations,
|
||||
.debugfs_ops = {
|
||||
.rx_stats_read = iwl_ucode_rx_stats_read,
|
||||
.tx_stats_read = iwl_ucode_tx_stats_read,
|
||||
@ -453,14 +455,16 @@ static struct iwl_lib_ops iwl5150_lib = {
|
||||
.calib_version = iwlagn_eeprom_calib_version,
|
||||
.query_addr = iwlagn_eeprom_query_addr,
|
||||
},
|
||||
.post_associate = iwl_post_associate,
|
||||
.isr = iwl_isr_ict,
|
||||
.config_ap = iwl_config_ap,
|
||||
.isr_ops = {
|
||||
.isr = iwl_isr_ict,
|
||||
.free = iwl_free_isr_ict,
|
||||
.alloc = iwl_alloc_isr_ict,
|
||||
.reset = iwl_reset_ict,
|
||||
.disable = iwl_disable_ict,
|
||||
},
|
||||
.temp_ops = {
|
||||
.temperature = iwl5150_temperature,
|
||||
},
|
||||
.manage_ibss_station = iwlagn_manage_ibss_station,
|
||||
.update_bcast_stations = iwl_update_bcast_stations,
|
||||
.debugfs_ops = {
|
||||
.rx_stats_read = iwl_ucode_rx_stats_read,
|
||||
.tx_stats_read = iwl_ucode_tx_stats_read,
|
||||
@ -485,6 +489,7 @@ static const struct iwl_ops iwl5000_ops = {
|
||||
.hcmd = &iwlagn_hcmd,
|
||||
.utils = &iwlagn_hcmd_utils,
|
||||
.led = &iwlagn_led_ops,
|
||||
.ieee80211_ops = &iwlagn_hw_ops,
|
||||
};
|
||||
|
||||
static const struct iwl_ops iwl5150_ops = {
|
||||
@ -492,6 +497,7 @@ static const struct iwl_ops iwl5150_ops = {
|
||||
.hcmd = &iwlagn_hcmd,
|
||||
.utils = &iwlagn_hcmd_utils,
|
||||
.led = &iwlagn_led_ops,
|
||||
.ieee80211_ops = &iwlagn_hw_ops,
|
||||
};
|
||||
|
||||
static struct iwl_base_params iwl5000_base_params = {
|
||||
|
@ -53,13 +53,11 @@
|
||||
#define IWL6000_UCODE_API_MAX 4
|
||||
#define IWL6050_UCODE_API_MAX 5
|
||||
#define IWL6000G2_UCODE_API_MAX 5
|
||||
#define IWL130_UCODE_API_MAX 5
|
||||
|
||||
/* Lowest firmware API version supported */
|
||||
#define IWL6000_UCODE_API_MIN 4
|
||||
#define IWL6050_UCODE_API_MIN 4
|
||||
#define IWL6000G2_UCODE_API_MIN 4
|
||||
#define IWL130_UCODE_API_MIN 5
|
||||
|
||||
#define IWL6000_FW_PRE "iwlwifi-6000-"
|
||||
#define _IWL6000_MODULE_FIRMWARE(api) IWL6000_FW_PRE #api ".ucode"
|
||||
@ -77,10 +75,6 @@
|
||||
#define _IWL6000G2B_MODULE_FIRMWARE(api) IWL6000G2B_FW_PRE #api ".ucode"
|
||||
#define IWL6000G2B_MODULE_FIRMWARE(api) _IWL6000G2B_MODULE_FIRMWARE(api)
|
||||
|
||||
#define IWL130_FW_PRE "iwlwifi-130-"
|
||||
#define _IWL130_MODULE_FIRMWARE(api) IWL130_FW_PRE #api ".ucode"
|
||||
#define IWL130_MODULE_FIRMWARE(api) _IWL130_MODULE_FIRMWARE(api)
|
||||
|
||||
static void iwl6000_set_ct_threshold(struct iwl_priv *priv)
|
||||
{
|
||||
/* want Celsius */
|
||||
@ -328,14 +322,16 @@ static struct iwl_lib_ops iwl6000_lib = {
|
||||
.query_addr = iwlagn_eeprom_query_addr,
|
||||
.update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower,
|
||||
},
|
||||
.post_associate = iwl_post_associate,
|
||||
.isr = iwl_isr_ict,
|
||||
.config_ap = iwl_config_ap,
|
||||
.isr_ops = {
|
||||
.isr = iwl_isr_ict,
|
||||
.free = iwl_free_isr_ict,
|
||||
.alloc = iwl_alloc_isr_ict,
|
||||
.reset = iwl_reset_ict,
|
||||
.disable = iwl_disable_ict,
|
||||
},
|
||||
.temp_ops = {
|
||||
.temperature = iwlagn_temperature,
|
||||
},
|
||||
.manage_ibss_station = iwlagn_manage_ibss_station,
|
||||
.update_bcast_stations = iwl_update_bcast_stations,
|
||||
.debugfs_ops = {
|
||||
.rx_stats_read = iwl_ucode_rx_stats_read,
|
||||
.tx_stats_read = iwl_ucode_tx_stats_read,
|
||||
@ -399,14 +395,16 @@ static struct iwl_lib_ops iwl6000g2b_lib = {
|
||||
.query_addr = iwlagn_eeprom_query_addr,
|
||||
.update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower,
|
||||
},
|
||||
.post_associate = iwl_post_associate,
|
||||
.isr = iwl_isr_ict,
|
||||
.config_ap = iwl_config_ap,
|
||||
.isr_ops = {
|
||||
.isr = iwl_isr_ict,
|
||||
.free = iwl_free_isr_ict,
|
||||
.alloc = iwl_alloc_isr_ict,
|
||||
.reset = iwl_reset_ict,
|
||||
.disable = iwl_disable_ict,
|
||||
},
|
||||
.temp_ops = {
|
||||
.temperature = iwlagn_temperature,
|
||||
},
|
||||
.manage_ibss_station = iwlagn_manage_ibss_station,
|
||||
.update_bcast_stations = iwl_update_bcast_stations,
|
||||
.debugfs_ops = {
|
||||
.rx_stats_read = iwl_ucode_rx_stats_read,
|
||||
.tx_stats_read = iwl_ucode_tx_stats_read,
|
||||
@ -439,6 +437,7 @@ static const struct iwl_ops iwl6000_ops = {
|
||||
.hcmd = &iwlagn_hcmd,
|
||||
.utils = &iwlagn_hcmd_utils,
|
||||
.led = &iwlagn_led_ops,
|
||||
.ieee80211_ops = &iwlagn_hw_ops,
|
||||
};
|
||||
|
||||
static const struct iwl_ops iwl6050_ops = {
|
||||
@ -447,6 +446,7 @@ static const struct iwl_ops iwl6050_ops = {
|
||||
.utils = &iwlagn_hcmd_utils,
|
||||
.led = &iwlagn_led_ops,
|
||||
.nic = &iwl6050_nic_ops,
|
||||
.ieee80211_ops = &iwlagn_hw_ops,
|
||||
};
|
||||
|
||||
static const struct iwl_ops iwl6050g2_ops = {
|
||||
@ -455,6 +455,7 @@ static const struct iwl_ops iwl6050g2_ops = {
|
||||
.utils = &iwlagn_hcmd_utils,
|
||||
.led = &iwlagn_led_ops,
|
||||
.nic = &iwl6050g2_nic_ops,
|
||||
.ieee80211_ops = &iwlagn_hw_ops,
|
||||
};
|
||||
|
||||
static const struct iwl_ops iwl6000g2b_ops = {
|
||||
@ -462,6 +463,7 @@ static const struct iwl_ops iwl6000g2b_ops = {
|
||||
.hcmd = &iwlagn_bt_hcmd,
|
||||
.utils = &iwlagn_hcmd_utils,
|
||||
.led = &iwlagn_led_ops,
|
||||
.ieee80211_ops = &iwlagn_hw_ops,
|
||||
};
|
||||
|
||||
static struct iwl_base_params iwl6000_base_params = {
|
||||
@ -485,6 +487,7 @@ static struct iwl_base_params iwl6000_base_params = {
|
||||
.ucode_tracing = true,
|
||||
.sensitivity_calib_by_driver = true,
|
||||
.chain_noise_calib_by_driver = true,
|
||||
.shadow_reg_enable = true,
|
||||
};
|
||||
|
||||
static struct iwl_base_params iwl6050_base_params = {
|
||||
@ -508,6 +511,7 @@ static struct iwl_base_params iwl6050_base_params = {
|
||||
.ucode_tracing = true,
|
||||
.sensitivity_calib_by_driver = true,
|
||||
.chain_noise_calib_by_driver = true,
|
||||
.shadow_reg_enable = true,
|
||||
};
|
||||
static struct iwl_base_params iwl6000_coex_base_params = {
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
@ -530,6 +534,7 @@ static struct iwl_base_params iwl6000_coex_base_params = {
|
||||
.ucode_tracing = true,
|
||||
.sensitivity_calib_by_driver = true,
|
||||
.chain_noise_calib_by_driver = true,
|
||||
.shadow_reg_enable = true,
|
||||
};
|
||||
|
||||
static struct iwl_ht_params iwl6000_ht_params = {
|
||||
@ -842,8 +847,8 @@ struct iwl_cfg iwl6000_3agn_cfg = {
|
||||
struct iwl_cfg iwl130_bgn_cfg = {
|
||||
.name = "Intel(R) 130 Series 1x1 BGN",
|
||||
.fw_name_pre = IWL6000G2B_FW_PRE,
|
||||
.ucode_api_max = IWL130_UCODE_API_MAX,
|
||||
.ucode_api_min = IWL130_UCODE_API_MIN,
|
||||
.ucode_api_max = IWL6000G2_UCODE_API_MAX,
|
||||
.ucode_api_min = IWL6000G2_UCODE_API_MIN,
|
||||
.sku = IWL_SKU_G|IWL_SKU_N,
|
||||
.valid_tx_ant = ANT_A,
|
||||
.valid_rx_ant = ANT_A,
|
||||
@ -862,8 +867,8 @@ struct iwl_cfg iwl130_bgn_cfg = {
|
||||
struct iwl_cfg iwl130_bg_cfg = {
|
||||
.name = "Intel(R) 130 Series 1x2 BG",
|
||||
.fw_name_pre = IWL6000G2B_FW_PRE,
|
||||
.ucode_api_max = IWL130_UCODE_API_MAX,
|
||||
.ucode_api_min = IWL130_UCODE_API_MIN,
|
||||
.ucode_api_max = IWL6000G2_UCODE_API_MAX,
|
||||
.ucode_api_min = IWL6000G2_UCODE_API_MIN,
|
||||
.sku = IWL_SKU_G,
|
||||
.valid_tx_ant = ANT_A,
|
||||
.valid_rx_ant = ANT_A,
|
||||
@ -882,4 +887,3 @@ MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL6050_MODULE_FIRMWARE(IWL6050_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL6000G2A_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL6000G2B_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX));
|
||||
MODULE_FIRMWARE(IWL130_MODULE_FIRMWARE(IWL130_UCODE_API_MAX));
|
||||
|
@ -732,8 +732,122 @@ static inline u8 find_first_chain(u8 mask)
|
||||
return CHAIN_C;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run disconnected antenna algorithm to find out which antennas are
|
||||
* disconnected.
|
||||
*/
|
||||
static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig,
|
||||
struct iwl_chain_noise_data *data)
|
||||
{
|
||||
u32 active_chains = 0;
|
||||
u32 max_average_sig;
|
||||
u16 max_average_sig_antenna_i;
|
||||
u8 num_tx_chains;
|
||||
u8 first_chain;
|
||||
u16 i = 0;
|
||||
|
||||
average_sig[0] = data->chain_signal_a /
|
||||
priv->cfg->base_params->chain_noise_num_beacons;
|
||||
average_sig[1] = data->chain_signal_b /
|
||||
priv->cfg->base_params->chain_noise_num_beacons;
|
||||
average_sig[2] = data->chain_signal_c /
|
||||
priv->cfg->base_params->chain_noise_num_beacons;
|
||||
|
||||
if (average_sig[0] >= average_sig[1]) {
|
||||
max_average_sig = average_sig[0];
|
||||
max_average_sig_antenna_i = 0;
|
||||
active_chains = (1 << max_average_sig_antenna_i);
|
||||
} else {
|
||||
max_average_sig = average_sig[1];
|
||||
max_average_sig_antenna_i = 1;
|
||||
active_chains = (1 << max_average_sig_antenna_i);
|
||||
}
|
||||
|
||||
if (average_sig[2] >= max_average_sig) {
|
||||
max_average_sig = average_sig[2];
|
||||
max_average_sig_antenna_i = 2;
|
||||
active_chains = (1 << max_average_sig_antenna_i);
|
||||
}
|
||||
|
||||
IWL_DEBUG_CALIB(priv, "average_sig: a %d b %d c %d\n",
|
||||
average_sig[0], average_sig[1], average_sig[2]);
|
||||
IWL_DEBUG_CALIB(priv, "max_average_sig = %d, antenna %d\n",
|
||||
max_average_sig, max_average_sig_antenna_i);
|
||||
|
||||
/* Compare signal strengths for all 3 receivers. */
|
||||
for (i = 0; i < NUM_RX_CHAINS; i++) {
|
||||
if (i != max_average_sig_antenna_i) {
|
||||
s32 rssi_delta = (max_average_sig - average_sig[i]);
|
||||
|
||||
/* If signal is very weak, compared with
|
||||
* strongest, mark it as disconnected. */
|
||||
if (rssi_delta > MAXIMUM_ALLOWED_PATHLOSS)
|
||||
data->disconn_array[i] = 1;
|
||||
else
|
||||
active_chains |= (1 << i);
|
||||
IWL_DEBUG_CALIB(priv, "i = %d rssiDelta = %d "
|
||||
"disconn_array[i] = %d\n",
|
||||
i, rssi_delta, data->disconn_array[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The above algorithm sometimes fails when the ucode
|
||||
* reports 0 for all chains. It's not clear why that
|
||||
* happens to start with, but it is then causing trouble
|
||||
* because this can make us enable more chains than the
|
||||
* hardware really has.
|
||||
*
|
||||
* To be safe, simply mask out any chains that we know
|
||||
* are not on the device.
|
||||
*/
|
||||
active_chains &= priv->hw_params.valid_rx_ant;
|
||||
|
||||
num_tx_chains = 0;
|
||||
for (i = 0; i < NUM_RX_CHAINS; i++) {
|
||||
/* loops on all the bits of
|
||||
* priv->hw_setting.valid_tx_ant */
|
||||
u8 ant_msk = (1 << i);
|
||||
if (!(priv->hw_params.valid_tx_ant & ant_msk))
|
||||
continue;
|
||||
|
||||
num_tx_chains++;
|
||||
if (data->disconn_array[i] == 0)
|
||||
/* there is a Tx antenna connected */
|
||||
break;
|
||||
if (num_tx_chains == priv->hw_params.tx_chains_num &&
|
||||
data->disconn_array[i]) {
|
||||
/*
|
||||
* If all chains are disconnected
|
||||
* connect the first valid tx chain
|
||||
*/
|
||||
first_chain =
|
||||
find_first_chain(priv->cfg->valid_tx_ant);
|
||||
data->disconn_array[first_chain] = 0;
|
||||
active_chains |= BIT(first_chain);
|
||||
IWL_DEBUG_CALIB(priv, "All Tx chains are disconnected \
|
||||
W/A - declare %d as connected\n",
|
||||
first_chain);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (active_chains != priv->hw_params.valid_rx_ant &&
|
||||
active_chains != priv->chain_noise_data.active_chains)
|
||||
IWL_DEBUG_CALIB(priv,
|
||||
"Detected that not all antennas are connected! "
|
||||
"Connected: %#x, valid: %#x.\n",
|
||||
active_chains, priv->hw_params.valid_rx_ant);
|
||||
|
||||
/* Save for use within RXON, TX, SCAN commands, etc. */
|
||||
data->active_chains = active_chains;
|
||||
IWL_DEBUG_CALIB(priv, "active_chains (bitwise) = 0x%x\n",
|
||||
active_chains);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Accumulate 20 beacons of signal and noise statistics for each of
|
||||
* Accumulate 16 beacons of signal and noise statistics for each of
|
||||
* 3 receivers/antennas/rx-chains, then figure out:
|
||||
* 1) Which antennas are connected.
|
||||
* 2) Differential rx gain settings to balance the 3 receivers.
|
||||
@ -750,8 +864,6 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp)
|
||||
u32 chain_sig_c;
|
||||
u32 average_sig[NUM_RX_CHAINS] = {INITIALIZATION_VALUE};
|
||||
u32 average_noise[NUM_RX_CHAINS] = {INITIALIZATION_VALUE};
|
||||
u32 max_average_sig;
|
||||
u16 max_average_sig_antenna_i;
|
||||
u32 min_average_noise = MIN_AVERAGE_NOISE_MAX_VALUE;
|
||||
u16 min_average_noise_antenna_i = INITIALIZATION_VALUE;
|
||||
u16 i = 0;
|
||||
@ -759,11 +871,9 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp)
|
||||
u16 stat_chnum = INITIALIZATION_VALUE;
|
||||
u8 rxon_band24;
|
||||
u8 stat_band24;
|
||||
u32 active_chains = 0;
|
||||
u8 num_tx_chains;
|
||||
unsigned long flags;
|
||||
struct statistics_rx_non_phy *rx_info;
|
||||
u8 first_chain;
|
||||
|
||||
/*
|
||||
* MULTI-FIXME:
|
||||
* When we support multiple interfaces on different channels,
|
||||
@ -869,108 +979,16 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp)
|
||||
return;
|
||||
|
||||
/* Analyze signal for disconnected antenna */
|
||||
average_sig[0] = data->chain_signal_a /
|
||||
priv->cfg->base_params->chain_noise_num_beacons;
|
||||
average_sig[1] = data->chain_signal_b /
|
||||
priv->cfg->base_params->chain_noise_num_beacons;
|
||||
average_sig[2] = data->chain_signal_c /
|
||||
priv->cfg->base_params->chain_noise_num_beacons;
|
||||
|
||||
if (average_sig[0] >= average_sig[1]) {
|
||||
max_average_sig = average_sig[0];
|
||||
max_average_sig_antenna_i = 0;
|
||||
active_chains = (1 << max_average_sig_antenna_i);
|
||||
} else {
|
||||
max_average_sig = average_sig[1];
|
||||
max_average_sig_antenna_i = 1;
|
||||
active_chains = (1 << max_average_sig_antenna_i);
|
||||
}
|
||||
|
||||
if (average_sig[2] >= max_average_sig) {
|
||||
max_average_sig = average_sig[2];
|
||||
max_average_sig_antenna_i = 2;
|
||||
active_chains = (1 << max_average_sig_antenna_i);
|
||||
}
|
||||
|
||||
IWL_DEBUG_CALIB(priv, "average_sig: a %d b %d c %d\n",
|
||||
average_sig[0], average_sig[1], average_sig[2]);
|
||||
IWL_DEBUG_CALIB(priv, "max_average_sig = %d, antenna %d\n",
|
||||
max_average_sig, max_average_sig_antenna_i);
|
||||
|
||||
/* Compare signal strengths for all 3 receivers. */
|
||||
for (i = 0; i < NUM_RX_CHAINS; i++) {
|
||||
if (i != max_average_sig_antenna_i) {
|
||||
s32 rssi_delta = (max_average_sig - average_sig[i]);
|
||||
|
||||
/* If signal is very weak, compared with
|
||||
* strongest, mark it as disconnected. */
|
||||
if (rssi_delta > MAXIMUM_ALLOWED_PATHLOSS)
|
||||
data->disconn_array[i] = 1;
|
||||
else
|
||||
active_chains |= (1 << i);
|
||||
IWL_DEBUG_CALIB(priv, "i = %d rssiDelta = %d "
|
||||
"disconn_array[i] = %d\n",
|
||||
i, rssi_delta, data->disconn_array[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The above algorithm sometimes fails when the ucode
|
||||
* reports 0 for all chains. It's not clear why that
|
||||
* happens to start with, but it is then causing trouble
|
||||
* because this can make us enable more chains than the
|
||||
* hardware really has.
|
||||
*
|
||||
* To be safe, simply mask out any chains that we know
|
||||
* are not on the device.
|
||||
*/
|
||||
if (priv->cfg->bt_params &&
|
||||
priv->cfg->bt_params->advanced_bt_coexist &&
|
||||
priv->bt_full_concurrent) {
|
||||
/* operated as 1x1 in full concurrency mode */
|
||||
active_chains &= first_antenna(priv->hw_params.valid_rx_ant);
|
||||
priv->cfg->bt_params->advanced_bt_coexist) {
|
||||
/* Disable disconnected antenna algorithm for advanced
|
||||
bt coex, assuming valid antennas are connected */
|
||||
data->active_chains = priv->hw_params.valid_rx_ant;
|
||||
for (i = 0; i < NUM_RX_CHAINS; i++)
|
||||
if (!(data->active_chains & (1<<i)))
|
||||
data->disconn_array[i] = 1;
|
||||
} else
|
||||
active_chains &= priv->hw_params.valid_rx_ant;
|
||||
|
||||
num_tx_chains = 0;
|
||||
for (i = 0; i < NUM_RX_CHAINS; i++) {
|
||||
/* loops on all the bits of
|
||||
* priv->hw_setting.valid_tx_ant */
|
||||
u8 ant_msk = (1 << i);
|
||||
if (!(priv->hw_params.valid_tx_ant & ant_msk))
|
||||
continue;
|
||||
|
||||
num_tx_chains++;
|
||||
if (data->disconn_array[i] == 0)
|
||||
/* there is a Tx antenna connected */
|
||||
break;
|
||||
if (num_tx_chains == priv->hw_params.tx_chains_num &&
|
||||
data->disconn_array[i]) {
|
||||
/*
|
||||
* If all chains are disconnected
|
||||
* connect the first valid tx chain
|
||||
*/
|
||||
first_chain =
|
||||
find_first_chain(priv->cfg->valid_tx_ant);
|
||||
data->disconn_array[first_chain] = 0;
|
||||
active_chains |= BIT(first_chain);
|
||||
IWL_DEBUG_CALIB(priv, "All Tx chains are disconnected W/A - declare %d as connected\n",
|
||||
first_chain);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (active_chains != priv->hw_params.valid_rx_ant &&
|
||||
active_chains != priv->chain_noise_data.active_chains)
|
||||
IWL_DEBUG_CALIB(priv,
|
||||
"Detected that not all antennas are connected! "
|
||||
"Connected: %#x, valid: %#x.\n",
|
||||
active_chains, priv->hw_params.valid_rx_ant);
|
||||
|
||||
/* Save for use within RXON, TX, SCAN commands, etc. */
|
||||
priv->chain_noise_data.active_chains = active_chains;
|
||||
IWL_DEBUG_CALIB(priv, "active_chains (bitwise) = 0x%x\n",
|
||||
active_chains);
|
||||
iwl_find_disconn_antenna(priv, average_sig, data);
|
||||
|
||||
/* Analyze noise for rx balance */
|
||||
average_noise[0] = data->chain_noise_a /
|
||||
|
@ -496,6 +496,10 @@ int iwlagn_send_tx_power(struct iwl_priv *priv)
|
||||
struct iwlagn_tx_power_dbm_cmd tx_power_cmd;
|
||||
u8 tx_ant_cfg_cmd;
|
||||
|
||||
if (WARN_ONCE(test_bit(STATUS_SCAN_HW, &priv->status),
|
||||
"TX Power requested while scanning!\n"))
|
||||
return -EAGAIN;
|
||||
|
||||
/* half dBm need to multiply */
|
||||
tx_power_cmd.global_lmt = (s8)(2 * priv->tx_power_user_lmt);
|
||||
|
||||
@ -522,9 +526,8 @@ int iwlagn_send_tx_power(struct iwl_priv *priv)
|
||||
else
|
||||
tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD;
|
||||
|
||||
return iwl_send_cmd_pdu_async(priv, tx_ant_cfg_cmd,
|
||||
sizeof(tx_power_cmd), &tx_power_cmd,
|
||||
NULL);
|
||||
return iwl_send_cmd_pdu(priv, tx_ant_cfg_cmd, sizeof(tx_power_cmd),
|
||||
&tx_power_cmd);
|
||||
}
|
||||
|
||||
void iwlagn_temperature(struct iwl_priv *priv)
|
||||
@ -750,6 +753,12 @@ int iwlagn_hw_nic_init(struct iwl_priv *priv)
|
||||
} else
|
||||
iwlagn_txq_ctx_reset(priv);
|
||||
|
||||
if (priv->cfg->base_params->shadow_reg_enable) {
|
||||
/* enable shadow regs in HW */
|
||||
iwl_set_bit(priv, CSR_MAC_SHADOW_REG_CTRL,
|
||||
0x800FFFFF);
|
||||
}
|
||||
|
||||
set_bit(STATUS_INIT, &priv->status);
|
||||
|
||||
return 0;
|
||||
@ -1584,22 +1593,6 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void iwlagn_post_scan(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_rxon_context *ctx;
|
||||
|
||||
/*
|
||||
* Since setting the RXON may have been deferred while
|
||||
* performing the scan, fire one off if needed
|
||||
*/
|
||||
for_each_context(priv, ctx)
|
||||
if (memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging)))
|
||||
iwlagn_commit_rxon(priv, ctx);
|
||||
|
||||
if (priv->cfg->ops->hcmd->set_pan_params)
|
||||
priv->cfg->ops->hcmd->set_pan_params(priv);
|
||||
}
|
||||
|
||||
int iwlagn_manage_ibss_station(struct iwl_priv *priv,
|
||||
struct ieee80211_vif *vif, bool add)
|
||||
{
|
||||
@ -1884,12 +1877,20 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work)
|
||||
struct iwl_rxon_context *ctx;
|
||||
int smps_request = -1;
|
||||
|
||||
/*
|
||||
* Note: bt_traffic_load can be overridden by scan complete and
|
||||
* coex profile notifications. Ignore that since only bad consequence
|
||||
* can be not matching debug print with actual state.
|
||||
*/
|
||||
IWL_DEBUG_INFO(priv, "BT traffic load changes: %d\n",
|
||||
priv->bt_traffic_load);
|
||||
|
||||
switch (priv->bt_traffic_load) {
|
||||
case IWL_BT_COEX_TRAFFIC_LOAD_NONE:
|
||||
smps_request = IEEE80211_SMPS_AUTOMATIC;
|
||||
if (priv->bt_status)
|
||||
smps_request = IEEE80211_SMPS_DYNAMIC;
|
||||
else
|
||||
smps_request = IEEE80211_SMPS_AUTOMATIC;
|
||||
break;
|
||||
case IWL_BT_COEX_TRAFFIC_LOAD_LOW:
|
||||
smps_request = IEEE80211_SMPS_DYNAMIC;
|
||||
@ -1906,6 +1907,16 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work)
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
/*
|
||||
* We can not send command to firmware while scanning. When the scan
|
||||
* complete we will schedule this work again. We do check with mutex
|
||||
* locked to prevent new scan request to arrive. We do not check
|
||||
* STATUS_SCANNING to avoid race when queue_work two times from
|
||||
* different notifications, but quit and not perform any work at all.
|
||||
*/
|
||||
if (test_bit(STATUS_SCAN_HW, &priv->status))
|
||||
goto out;
|
||||
|
||||
if (priv->cfg->ops->lib->update_chain_flags)
|
||||
priv->cfg->ops->lib->update_chain_flags(priv);
|
||||
|
||||
@ -1915,7 +1926,7 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work)
|
||||
ieee80211_request_smps(ctx->vif, smps_request);
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
mutex_unlock(&priv->mutex);
|
||||
}
|
||||
|
||||
|
619
drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
Normal file
619
drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
Normal file
@ -0,0 +1,619 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution in the
|
||||
* file called LICENSE.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#include "iwl-dev.h"
|
||||
#include "iwl-agn.h"
|
||||
#include "iwl-sta.h"
|
||||
#include "iwl-core.h"
|
||||
#include "iwl-agn-calib.h"
|
||||
|
||||
static int iwlagn_disable_bss(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx,
|
||||
struct iwl_rxon_cmd *send)
|
||||
{
|
||||
__le32 old_filter = send->filter_flags;
|
||||
int ret;
|
||||
|
||||
send->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
|
||||
ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, sizeof(*send), send);
|
||||
|
||||
send->filter_flags = old_filter;
|
||||
|
||||
if (ret)
|
||||
IWL_ERR(priv, "Error clearing ASSOC_MSK on BSS (%d)\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int iwlagn_disable_pan(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx,
|
||||
struct iwl_rxon_cmd *send)
|
||||
{
|
||||
__le32 old_filter = send->filter_flags;
|
||||
u8 old_dev_type = send->dev_type;
|
||||
int ret;
|
||||
|
||||
send->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
|
||||
send->dev_type = RXON_DEV_TYPE_P2P;
|
||||
ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, sizeof(*send), send);
|
||||
|
||||
send->filter_flags = old_filter;
|
||||
send->dev_type = old_dev_type;
|
||||
|
||||
if (ret)
|
||||
IWL_ERR(priv, "Error disabling PAN (%d)\n", ret);
|
||||
|
||||
/* FIXME: WAIT FOR PAN DISABLE */
|
||||
msleep(300);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int iwlagn_update_beacon(struct iwl_priv *priv,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
dev_kfree_skb(priv->beacon_skb);
|
||||
priv->beacon_skb = ieee80211_beacon_get(priv->hw, vif);
|
||||
if (!priv->beacon_skb)
|
||||
return -ENOMEM;
|
||||
return iwlagn_send_beacon_cmd(priv);
|
||||
}
|
||||
|
||||
/**
|
||||
* iwlagn_commit_rxon - commit staging_rxon to hardware
|
||||
*
|
||||
* The RXON command in staging_rxon is committed to the hardware and
|
||||
* the active_rxon structure is updated with the new data. This
|
||||
* function correctly transitions out of the RXON_ASSOC_MSK state if
|
||||
* a HW tune is required based on the RXON structure changes.
|
||||
*/
|
||||
int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
|
||||
{
|
||||
/* cast away the const for active_rxon in this function */
|
||||
struct iwl_rxon_cmd *active = (void *)&ctx->active;
|
||||
bool new_assoc = !!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK);
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
if (!iwl_is_alive(priv))
|
||||
return -EBUSY;
|
||||
|
||||
/* This function hardcodes a bunch of dual-mode assumptions */
|
||||
BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
|
||||
|
||||
if (!ctx->is_active)
|
||||
return 0;
|
||||
|
||||
/* always get timestamp with Rx frame */
|
||||
ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK;
|
||||
|
||||
if ((ctx->vif && ctx->vif->bss_conf.use_short_slot) ||
|
||||
!(ctx->staging.flags & RXON_FLG_BAND_24G_MSK))
|
||||
ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
|
||||
else
|
||||
ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
|
||||
|
||||
ret = iwl_check_rxon_cmd(priv, ctx);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Invalid RXON configuration. Not committing.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* receive commit_rxon request
|
||||
* abort any previous channel switch if still in process
|
||||
*/
|
||||
if (priv->switch_rxon.switch_in_progress &&
|
||||
(priv->switch_rxon.channel != ctx->staging.channel)) {
|
||||
IWL_DEBUG_11H(priv, "abort channel switch on %d\n",
|
||||
le16_to_cpu(priv->switch_rxon.channel));
|
||||
iwl_chswitch_done(priv, false);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we don't need to send a full RXON, we can use
|
||||
* iwl_rxon_assoc_cmd which is used to reconfigure filter
|
||||
* and other flags for the current radio configuration.
|
||||
*/
|
||||
if (!iwl_full_rxon_required(priv, ctx)) {
|
||||
ret = iwl_send_rxon_assoc(priv, ctx);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Error setting RXON_ASSOC (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
memcpy(active, &ctx->staging, sizeof(*active));
|
||||
iwl_print_rx_config_cmd(priv, ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (priv->cfg->ops->hcmd->set_pan_params) {
|
||||
ret = priv->cfg->ops->hcmd->set_pan_params(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
iwl_set_rxon_hwcrypto(priv, ctx, !priv->cfg->mod_params->sw_crypto);
|
||||
|
||||
IWL_DEBUG_INFO(priv,
|
||||
"Going to commit RXON\n"
|
||||
" * with%s RXON_FILTER_ASSOC_MSK\n"
|
||||
" * channel = %d\n"
|
||||
" * bssid = %pM\n",
|
||||
(new_assoc ? "" : "out"),
|
||||
le16_to_cpu(ctx->staging.channel),
|
||||
ctx->staging.bssid_addr);
|
||||
|
||||
/*
|
||||
* Always clear associated first, but with the correct config.
|
||||
* This is required as for example station addition for the
|
||||
* AP station must be done after the BSSID is set to correctly
|
||||
* set up filters in the device.
|
||||
*/
|
||||
if (ctx->ctxid == IWL_RXON_CTX_BSS)
|
||||
ret = iwlagn_disable_bss(priv, ctx, &ctx->staging);
|
||||
else
|
||||
ret = iwlagn_disable_pan(priv, ctx, &ctx->staging);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
memcpy(active, &ctx->staging, sizeof(*active));
|
||||
|
||||
/*
|
||||
* Un-assoc RXON clears the station table and WEP
|
||||
* keys, so we have to restore those afterwards.
|
||||
*/
|
||||
iwl_clear_ucode_stations(priv, ctx);
|
||||
iwl_restore_stations(priv, ctx);
|
||||
ret = iwl_restore_default_wep_keys(priv, ctx);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* RXON timing must be before associated RXON */
|
||||
ret = iwl_send_rxon_timing(priv, ctx);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Failed to send timing (%d)!\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (new_assoc) {
|
||||
/*
|
||||
* We'll run into this code path when beaconing is
|
||||
* enabled, but then we also need to send the beacon
|
||||
* to the device.
|
||||
*/
|
||||
if (ctx->vif && (ctx->vif->type == NL80211_IFTYPE_AP)) {
|
||||
ret = iwlagn_update_beacon(priv, ctx->vif);
|
||||
if (ret) {
|
||||
IWL_ERR(priv,
|
||||
"Error sending required beacon (%d)!\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
priv->start_calib = 0;
|
||||
/*
|
||||
* Apply the new configuration.
|
||||
*
|
||||
* Associated RXON doesn't clear the station table in uCode,
|
||||
* so we don't need to restore stations etc. after this.
|
||||
*/
|
||||
ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd,
|
||||
sizeof(struct iwl_rxon_cmd), &ctx->staging);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
memcpy(active, &ctx->staging, sizeof(*active));
|
||||
|
||||
/* IBSS beacon needs to be sent after setting assoc */
|
||||
if (ctx->vif && (ctx->vif->type == NL80211_IFTYPE_ADHOC))
|
||||
if (iwlagn_update_beacon(priv, ctx->vif))
|
||||
IWL_ERR(priv, "Error sending IBSS beacon\n");
|
||||
}
|
||||
|
||||
iwl_print_rx_config_cmd(priv, ctx);
|
||||
|
||||
iwl_init_sensitivity(priv);
|
||||
|
||||
/*
|
||||
* If we issue a new RXON command which required a tune then we must
|
||||
* send a new TXPOWER command or we won't be able to Tx any frames.
|
||||
*
|
||||
* FIXME: which RXON requires a tune? Can we optimise this out in
|
||||
* some cases?
|
||||
*/
|
||||
ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Error sending TX power (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void iwlagn_update_qos(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!ctx->is_active)
|
||||
return;
|
||||
|
||||
ctx->qos_data.def_qos_parm.qos_flags = 0;
|
||||
|
||||
if (ctx->qos_data.qos_active)
|
||||
ctx->qos_data.def_qos_parm.qos_flags |=
|
||||
QOS_PARAM_FLG_UPDATE_EDCA_MSK;
|
||||
|
||||
if (ctx->ht.enabled)
|
||||
ctx->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK;
|
||||
|
||||
IWL_DEBUG_QOS(priv, "send QoS cmd with Qos active=%d FLAGS=0x%X\n",
|
||||
ctx->qos_data.qos_active,
|
||||
ctx->qos_data.def_qos_parm.qos_flags);
|
||||
|
||||
ret = iwl_send_cmd_pdu(priv, ctx->qos_cmd,
|
||||
sizeof(struct iwl_qosparam_cmd),
|
||||
&ctx->qos_data.def_qos_parm);
|
||||
if (ret)
|
||||
IWL_ERR(priv, "Failed to update QoS\n");
|
||||
}
|
||||
|
||||
int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
|
||||
{
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
struct iwl_rxon_context *ctx;
|
||||
struct ieee80211_conf *conf = &hw->conf;
|
||||
struct ieee80211_channel *channel = conf->channel;
|
||||
const struct iwl_channel_info *ch_info;
|
||||
int ret = 0;
|
||||
bool ht_changed[NUM_IWL_RXON_CTX] = {};
|
||||
|
||||
IWL_DEBUG_MAC80211(priv, "changed %#x", changed);
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
if (unlikely(test_bit(STATUS_SCANNING, &priv->status))) {
|
||||
IWL_DEBUG_MAC80211(priv, "leave - scanning\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!iwl_is_ready(priv)) {
|
||||
IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (changed & (IEEE80211_CONF_CHANGE_SMPS |
|
||||
IEEE80211_CONF_CHANGE_CHANNEL)) {
|
||||
/* mac80211 uses static for non-HT which is what we want */
|
||||
priv->current_ht_config.smps = conf->smps_mode;
|
||||
|
||||
/*
|
||||
* Recalculate chain counts.
|
||||
*
|
||||
* If monitor mode is enabled then mac80211 will
|
||||
* set up the SM PS mode to OFF if an HT channel is
|
||||
* configured.
|
||||
*/
|
||||
if (priv->cfg->ops->hcmd->set_rxon_chain)
|
||||
for_each_context(priv, ctx)
|
||||
priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
|
||||
}
|
||||
|
||||
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
|
||||
unsigned long flags;
|
||||
|
||||
ch_info = iwl_get_channel_info(priv, channel->band,
|
||||
channel->hw_value);
|
||||
if (!is_channel_valid(ch_info)) {
|
||||
IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
|
||||
for_each_context(priv, ctx) {
|
||||
/* Configure HT40 channels */
|
||||
if (ctx->ht.enabled != conf_is_ht(conf)) {
|
||||
ctx->ht.enabled = conf_is_ht(conf);
|
||||
ht_changed[ctx->ctxid] = true;
|
||||
}
|
||||
|
||||
if (ctx->ht.enabled) {
|
||||
if (conf_is_ht40_minus(conf)) {
|
||||
ctx->ht.extension_chan_offset =
|
||||
IEEE80211_HT_PARAM_CHA_SEC_BELOW;
|
||||
ctx->ht.is_40mhz = true;
|
||||
} else if (conf_is_ht40_plus(conf)) {
|
||||
ctx->ht.extension_chan_offset =
|
||||
IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
|
||||
ctx->ht.is_40mhz = true;
|
||||
} else {
|
||||
ctx->ht.extension_chan_offset =
|
||||
IEEE80211_HT_PARAM_CHA_SEC_NONE;
|
||||
ctx->ht.is_40mhz = false;
|
||||
}
|
||||
} else
|
||||
ctx->ht.is_40mhz = false;
|
||||
|
||||
/*
|
||||
* Default to no protection. Protection mode will
|
||||
* later be set from BSS config in iwl_ht_conf
|
||||
*/
|
||||
ctx->ht.protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE;
|
||||
|
||||
/* if we are switching from ht to 2.4 clear flags
|
||||
* from any ht related info since 2.4 does not
|
||||
* support ht */
|
||||
if (le16_to_cpu(ctx->staging.channel) !=
|
||||
channel->hw_value)
|
||||
ctx->staging.flags = 0;
|
||||
|
||||
iwl_set_rxon_channel(priv, channel, ctx);
|
||||
iwl_set_rxon_ht(priv, &priv->current_ht_config);
|
||||
|
||||
iwl_set_flags_for_band(priv, ctx, channel->band,
|
||||
ctx->vif);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
iwl_update_bcast_stations(priv);
|
||||
|
||||
/*
|
||||
* The list of supported rates and rate mask can be different
|
||||
* for each band; since the band may have changed, reset
|
||||
* the rate mask to what mac80211 lists.
|
||||
*/
|
||||
iwl_set_rate(priv);
|
||||
}
|
||||
|
||||
if (changed & (IEEE80211_CONF_CHANGE_PS |
|
||||
IEEE80211_CONF_CHANGE_IDLE)) {
|
||||
ret = iwl_power_update_mode(priv, false);
|
||||
if (ret)
|
||||
IWL_DEBUG_MAC80211(priv, "Error setting sleep level\n");
|
||||
}
|
||||
|
||||
if (changed & IEEE80211_CONF_CHANGE_POWER) {
|
||||
IWL_DEBUG_MAC80211(priv, "TX Power old=%d new=%d\n",
|
||||
priv->tx_power_user_lmt, conf->power_level);
|
||||
|
||||
iwl_set_tx_power(priv, conf->power_level, false);
|
||||
}
|
||||
|
||||
for_each_context(priv, ctx) {
|
||||
if (!memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging)))
|
||||
continue;
|
||||
iwlagn_commit_rxon(priv, ctx);
|
||||
if (ht_changed[ctx->ctxid])
|
||||
iwlagn_update_qos(priv, ctx);
|
||||
}
|
||||
out:
|
||||
mutex_unlock(&priv->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void iwlagn_check_needed_chains(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx,
|
||||
struct ieee80211_bss_conf *bss_conf)
|
||||
{
|
||||
struct ieee80211_vif *vif = ctx->vif;
|
||||
struct iwl_rxon_context *tmp;
|
||||
struct ieee80211_sta *sta;
|
||||
struct iwl_ht_config *ht_conf = &priv->current_ht_config;
|
||||
bool need_multiple;
|
||||
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
rcu_read_lock();
|
||||
sta = ieee80211_find_sta(vif, bss_conf->bssid);
|
||||
if (sta) {
|
||||
struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
|
||||
int maxstreams;
|
||||
|
||||
maxstreams = (ht_cap->mcs.tx_params &
|
||||
IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK)
|
||||
>> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT;
|
||||
maxstreams += 1;
|
||||
|
||||
need_multiple = true;
|
||||
|
||||
if ((ht_cap->mcs.rx_mask[1] == 0) &&
|
||||
(ht_cap->mcs.rx_mask[2] == 0))
|
||||
need_multiple = false;
|
||||
if (maxstreams <= 1)
|
||||
need_multiple = false;
|
||||
} else {
|
||||
/*
|
||||
* If at all, this can only happen through a race
|
||||
* when the AP disconnects us while we're still
|
||||
* setting up the connection, in that case mac80211
|
||||
* will soon tell us about that.
|
||||
*/
|
||||
need_multiple = false;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
break;
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
/* currently */
|
||||
need_multiple = false;
|
||||
break;
|
||||
default:
|
||||
/* only AP really */
|
||||
need_multiple = true;
|
||||
break;
|
||||
}
|
||||
|
||||
ctx->ht_need_multiple_chains = need_multiple;
|
||||
|
||||
if (!need_multiple) {
|
||||
/* check all contexts */
|
||||
for_each_context(priv, tmp) {
|
||||
if (!tmp->vif)
|
||||
continue;
|
||||
if (tmp->ht_need_multiple_chains) {
|
||||
need_multiple = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ht_conf->single_chain_sufficient = !need_multiple;
|
||||
}
|
||||
|
||||
void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *bss_conf,
|
||||
u32 changes)
|
||||
{
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
|
||||
int ret;
|
||||
bool force = false;
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
if (changes & BSS_CHANGED_BEACON_INT)
|
||||
force = true;
|
||||
|
||||
if (changes & BSS_CHANGED_QOS) {
|
||||
ctx->qos_data.qos_active = bss_conf->qos;
|
||||
iwlagn_update_qos(priv, ctx);
|
||||
}
|
||||
|
||||
ctx->staging.assoc_id = cpu_to_le16(vif->bss_conf.aid);
|
||||
if (vif->bss_conf.use_short_preamble)
|
||||
ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
|
||||
else
|
||||
ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
|
||||
|
||||
if (changes & BSS_CHANGED_ASSOC) {
|
||||
if (bss_conf->assoc) {
|
||||
iwl_led_associate(priv);
|
||||
priv->timestamp = bss_conf->timestamp;
|
||||
ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
|
||||
} else {
|
||||
ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
|
||||
iwl_led_disassociate(priv);
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->ht.enabled) {
|
||||
ctx->ht.protection = bss_conf->ht_operation_mode &
|
||||
IEEE80211_HT_OP_MODE_PROTECTION;
|
||||
ctx->ht.non_gf_sta_present = !!(bss_conf->ht_operation_mode &
|
||||
IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
|
||||
iwlagn_check_needed_chains(priv, ctx, bss_conf);
|
||||
iwl_set_rxon_ht(priv, &priv->current_ht_config);
|
||||
}
|
||||
|
||||
if (priv->cfg->ops->hcmd->set_rxon_chain)
|
||||
priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
|
||||
|
||||
if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ))
|
||||
ctx->staging.flags |= RXON_FLG_TGG_PROTECT_MSK;
|
||||
else
|
||||
ctx->staging.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
|
||||
|
||||
if (bss_conf->use_cts_prot)
|
||||
ctx->staging.flags |= RXON_FLG_SELF_CTS_EN;
|
||||
else
|
||||
ctx->staging.flags &= ~RXON_FLG_SELF_CTS_EN;
|
||||
|
||||
memcpy(ctx->staging.bssid_addr, bss_conf->bssid, ETH_ALEN);
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_AP ||
|
||||
vif->type == NL80211_IFTYPE_ADHOC) {
|
||||
if (vif->bss_conf.enable_beacon) {
|
||||
ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
|
||||
priv->beacon_ctx = ctx;
|
||||
} else {
|
||||
ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
|
||||
priv->beacon_ctx = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (force || memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging)))
|
||||
iwlagn_commit_rxon(priv, ctx);
|
||||
|
||||
if (changes & BSS_CHANGED_ASSOC && bss_conf->assoc) {
|
||||
/*
|
||||
* The chain noise calibration will enable PM upon
|
||||
* completion. If calibration has already been run
|
||||
* then we need to enable power management here.
|
||||
*/
|
||||
if (priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE)
|
||||
iwl_power_update_mode(priv, false);
|
||||
|
||||
/* Enable RX differential gain and sensitivity calibrations */
|
||||
iwl_chain_noise_reset(priv);
|
||||
priv->start_calib = 1;
|
||||
}
|
||||
|
||||
if (changes & BSS_CHANGED_IBSS) {
|
||||
ret = iwlagn_manage_ibss_station(priv, vif,
|
||||
bss_conf->ibss_joined);
|
||||
if (ret)
|
||||
IWL_ERR(priv, "failed to %s IBSS station %pM\n",
|
||||
bss_conf->ibss_joined ? "add" : "remove",
|
||||
bss_conf->bssid);
|
||||
}
|
||||
|
||||
if (changes & BSS_CHANGED_BEACON && vif->type == NL80211_IFTYPE_ADHOC &&
|
||||
priv->beacon_ctx) {
|
||||
if (iwlagn_update_beacon(priv, vif))
|
||||
IWL_ERR(priv, "Error sending IBSS beacon\n");
|
||||
}
|
||||
|
||||
mutex_unlock(&priv->mutex);
|
||||
}
|
||||
|
||||
void iwlagn_post_scan(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_rxon_context *ctx;
|
||||
|
||||
/*
|
||||
* Since setting the RXON may have been deferred while
|
||||
* performing the scan, fire one off if needed
|
||||
*/
|
||||
for_each_context(priv, ctx)
|
||||
if (memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging)))
|
||||
iwlagn_commit_rxon(priv, ctx);
|
||||
|
||||
if (priv->cfg->ops->hcmd->set_pan_params)
|
||||
priv->cfg->ops->hcmd->set_pan_params(priv);
|
||||
}
|
@ -684,7 +684,7 @@ int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
|
||||
return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
|
||||
}
|
||||
|
||||
void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id)
|
||||
static void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
@ -714,3 +714,33 @@ void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt)
|
||||
spin_unlock_irqrestore(&priv->sta_lock, flags);
|
||||
|
||||
}
|
||||
|
||||
void iwlagn_mac_sta_notify(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
enum sta_notify_cmd cmd,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
|
||||
int sta_id;
|
||||
|
||||
switch (cmd) {
|
||||
case STA_NOTIFY_SLEEP:
|
||||
WARN_ON(!sta_priv->client);
|
||||
sta_priv->asleep = true;
|
||||
if (atomic_read(&sta_priv->pending_frames) > 0)
|
||||
ieee80211_sta_block_awake(hw, sta, true);
|
||||
break;
|
||||
case STA_NOTIFY_AWAKE:
|
||||
WARN_ON(!sta_priv->client);
|
||||
if (!sta_priv->asleep)
|
||||
break;
|
||||
sta_priv->asleep = false;
|
||||
sta_id = iwl_sta_id(sta);
|
||||
if (sta_id != IWL_INVALID_STATION)
|
||||
iwl_sta_modify_ps_wake(priv, sta_id);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -90,170 +90,6 @@ MODULE_ALIAS("iwl4965");
|
||||
static int iwlagn_ant_coupling;
|
||||
static bool iwlagn_bt_ch_announce = 1;
|
||||
|
||||
/**
|
||||
* iwlagn_commit_rxon - commit staging_rxon to hardware
|
||||
*
|
||||
* The RXON command in staging_rxon is committed to the hardware and
|
||||
* the active_rxon structure is updated with the new data. This
|
||||
* function correctly transitions out of the RXON_ASSOC_MSK state if
|
||||
* a HW tune is required based on the RXON structure changes.
|
||||
*/
|
||||
int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
|
||||
{
|
||||
/* cast away the const for active_rxon in this function */
|
||||
struct iwl_rxon_cmd *active_rxon = (void *)&ctx->active;
|
||||
int ret;
|
||||
bool new_assoc =
|
||||
!!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK);
|
||||
bool old_assoc = !!(ctx->active.filter_flags & RXON_FILTER_ASSOC_MSK);
|
||||
|
||||
if (!iwl_is_alive(priv))
|
||||
return -EBUSY;
|
||||
|
||||
if (!ctx->is_active)
|
||||
return 0;
|
||||
|
||||
/* always get timestamp with Rx frame */
|
||||
ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK;
|
||||
|
||||
ret = iwl_check_rxon_cmd(priv, ctx);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Invalid RXON configuration. Not committing.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* receive commit_rxon request
|
||||
* abort any previous channel switch if still in process
|
||||
*/
|
||||
if (priv->switch_rxon.switch_in_progress &&
|
||||
(priv->switch_rxon.channel != ctx->staging.channel)) {
|
||||
IWL_DEBUG_11H(priv, "abort channel switch on %d\n",
|
||||
le16_to_cpu(priv->switch_rxon.channel));
|
||||
iwl_chswitch_done(priv, false);
|
||||
}
|
||||
|
||||
/* If we don't need to send a full RXON, we can use
|
||||
* iwl_rxon_assoc_cmd which is used to reconfigure filter
|
||||
* and other flags for the current radio configuration. */
|
||||
if (!iwl_full_rxon_required(priv, ctx)) {
|
||||
ret = iwl_send_rxon_assoc(priv, ctx);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Error setting RXON_ASSOC (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
|
||||
iwl_print_rx_config_cmd(priv, ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If we are currently associated and the new config requires
|
||||
* an RXON_ASSOC and the new config wants the associated mask enabled,
|
||||
* we must clear the associated from the active configuration
|
||||
* before we apply the new config */
|
||||
if (iwl_is_associated_ctx(ctx) && new_assoc) {
|
||||
IWL_DEBUG_INFO(priv, "Toggling associated bit on current RXON\n");
|
||||
active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
|
||||
|
||||
ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd,
|
||||
sizeof(struct iwl_rxon_cmd),
|
||||
active_rxon);
|
||||
|
||||
/* If the mask clearing failed then we set
|
||||
* active_rxon back to what it was previously */
|
||||
if (ret) {
|
||||
active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK;
|
||||
IWL_ERR(priv, "Error clearing ASSOC_MSK (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
iwl_clear_ucode_stations(priv, ctx);
|
||||
iwl_restore_stations(priv, ctx);
|
||||
ret = iwl_restore_default_wep_keys(priv, ctx);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
IWL_DEBUG_INFO(priv, "Sending RXON\n"
|
||||
"* with%s RXON_FILTER_ASSOC_MSK\n"
|
||||
"* channel = %d\n"
|
||||
"* bssid = %pM\n",
|
||||
(new_assoc ? "" : "out"),
|
||||
le16_to_cpu(ctx->staging.channel),
|
||||
ctx->staging.bssid_addr);
|
||||
|
||||
iwl_set_rxon_hwcrypto(priv, ctx, !priv->cfg->mod_params->sw_crypto);
|
||||
|
||||
if (!old_assoc) {
|
||||
/*
|
||||
* First of all, before setting associated, we need to
|
||||
* send RXON timing so the device knows about the DTIM
|
||||
* period and other timing values
|
||||
*/
|
||||
ret = iwl_send_rxon_timing(priv, ctx);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Error setting RXON timing!\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (priv->cfg->ops->hcmd->set_pan_params) {
|
||||
ret = priv->cfg->ops->hcmd->set_pan_params(priv);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Apply the new configuration
|
||||
* RXON unassoc clears the station table in uCode so restoration of
|
||||
* stations is needed after it (the RXON command) completes
|
||||
*/
|
||||
if (!new_assoc) {
|
||||
ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd,
|
||||
sizeof(struct iwl_rxon_cmd), &ctx->staging);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
IWL_DEBUG_INFO(priv, "Return from !new_assoc RXON.\n");
|
||||
memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
|
||||
iwl_clear_ucode_stations(priv, ctx);
|
||||
iwl_restore_stations(priv, ctx);
|
||||
ret = iwl_restore_default_wep_keys(priv, ctx);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
if (new_assoc) {
|
||||
priv->start_calib = 0;
|
||||
/* Apply the new configuration
|
||||
* RXON assoc doesn't clear the station table in uCode,
|
||||
*/
|
||||
ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd,
|
||||
sizeof(struct iwl_rxon_cmd), &ctx->staging);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
|
||||
}
|
||||
iwl_print_rx_config_cmd(priv, ctx);
|
||||
|
||||
iwl_init_sensitivity(priv);
|
||||
|
||||
/* If we issue a new RXON command which required a tune then we must
|
||||
* send a new TXPOWER command or we won't be able to Tx any frames */
|
||||
ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Error sending TX power (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void iwl_update_chain_flags(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_rxon_context *ctx;
|
||||
@ -411,7 +247,8 @@ static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv,
|
||||
|
||||
return sizeof(*tx_beacon_cmd) + frame_size;
|
||||
}
|
||||
static int iwl_send_beacon_cmd(struct iwl_priv *priv)
|
||||
|
||||
int iwlagn_send_beacon_cmd(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_frame *frame;
|
||||
unsigned int frame_size;
|
||||
@ -661,7 +498,7 @@ static void iwl_bg_beacon_update(struct work_struct *work)
|
||||
|
||||
priv->beacon_skb = beacon;
|
||||
|
||||
iwl_send_beacon_cmd(priv);
|
||||
iwlagn_send_beacon_cmd(priv);
|
||||
out:
|
||||
mutex_unlock(&priv->mutex);
|
||||
}
|
||||
@ -2978,7 +2815,8 @@ static void __iwl_down(struct iwl_priv *priv)
|
||||
STATUS_EXIT_PENDING;
|
||||
|
||||
/* device going down, Stop using ICT table */
|
||||
iwl_disable_ict(priv);
|
||||
if (priv->cfg->ops->lib->isr_ops.disable)
|
||||
priv->cfg->ops->lib->isr_ops.disable(priv);
|
||||
|
||||
iwlagn_txq_ctx_stop(priv);
|
||||
iwlagn_rxq_stop(priv);
|
||||
@ -3201,7 +3039,8 @@ static void iwl_bg_alive_start(struct work_struct *data)
|
||||
return;
|
||||
|
||||
/* enable dram interrupt */
|
||||
iwl_reset_ict(priv);
|
||||
if (priv->cfg->ops->lib->isr_ops.reset)
|
||||
priv->cfg->ops->lib->isr_ops.reset(priv);
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
iwl_alive_start(priv);
|
||||
@ -3309,92 +3148,6 @@ static void iwl_bg_rx_replenish(struct work_struct *data)
|
||||
mutex_unlock(&priv->mutex);
|
||||
}
|
||||
|
||||
#define IWL_DELAY_NEXT_SCAN (HZ*2)
|
||||
|
||||
void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_rxon_context *ctx;
|
||||
struct ieee80211_conf *conf = NULL;
|
||||
int ret = 0;
|
||||
|
||||
if (!vif || !priv->is_open)
|
||||
return;
|
||||
|
||||
ctx = iwl_rxon_ctx_from_vif(vif);
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_AP) {
|
||||
IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||
return;
|
||||
|
||||
iwl_scan_cancel_timeout(priv, 200);
|
||||
|
||||
conf = ieee80211_get_hw_conf(priv->hw);
|
||||
|
||||
ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
|
||||
iwlcore_commit_rxon(priv, ctx);
|
||||
|
||||
ret = iwl_send_rxon_timing(priv, ctx);
|
||||
if (ret)
|
||||
IWL_WARN(priv, "RXON timing - "
|
||||
"Attempting to continue.\n");
|
||||
|
||||
ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
|
||||
|
||||
iwl_set_rxon_ht(priv, &priv->current_ht_config);
|
||||
|
||||
if (priv->cfg->ops->hcmd->set_rxon_chain)
|
||||
priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
|
||||
|
||||
ctx->staging.assoc_id = cpu_to_le16(vif->bss_conf.aid);
|
||||
|
||||
IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n",
|
||||
vif->bss_conf.aid, vif->bss_conf.beacon_int);
|
||||
|
||||
if (vif->bss_conf.use_short_preamble)
|
||||
ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
|
||||
else
|
||||
ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
|
||||
|
||||
if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
|
||||
if (vif->bss_conf.use_short_slot)
|
||||
ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
|
||||
else
|
||||
ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
|
||||
}
|
||||
|
||||
iwlcore_commit_rxon(priv, ctx);
|
||||
|
||||
IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n",
|
||||
vif->bss_conf.aid, ctx->active.bssid_addr);
|
||||
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
break;
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
iwl_send_beacon_cmd(priv);
|
||||
break;
|
||||
default:
|
||||
IWL_ERR(priv, "%s Should not be called in %d mode\n",
|
||||
__func__, vif->type);
|
||||
break;
|
||||
}
|
||||
|
||||
/* the chain noise calibration will enabled PM upon completion
|
||||
* If chain noise has already been run, then we need to enable
|
||||
* power management here */
|
||||
if (priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE)
|
||||
iwl_power_update_mode(priv, false);
|
||||
|
||||
/* Enable Rx differential gain and sensitivity calibrations */
|
||||
iwl_chain_noise_reset(priv);
|
||||
priv->start_calib = 1;
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* mac80211 entry point functions
|
||||
@ -3474,7 +3227,7 @@ static int iwl_mac_setup_register(struct iwl_priv *priv,
|
||||
}
|
||||
|
||||
|
||||
static int iwl_mac_start(struct ieee80211_hw *hw)
|
||||
int iwlagn_mac_start(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
int ret;
|
||||
@ -3515,7 +3268,7 @@ out:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void iwl_mac_stop(struct ieee80211_hw *hw)
|
||||
void iwlagn_mac_stop(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
|
||||
@ -3537,7 +3290,7 @@ static void iwl_mac_stop(struct ieee80211_hw *hw)
|
||||
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||
}
|
||||
|
||||
static int iwl_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
int iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
{
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
|
||||
@ -3553,73 +3306,12 @@ static int iwl_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
||||
void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_key_conf *keyconf,
|
||||
struct ieee80211_sta *sta,
|
||||
u32 iv32, u16 *phase1key)
|
||||
{
|
||||
struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
|
||||
int ret = 0;
|
||||
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||
return;
|
||||
|
||||
/* The following should be done only at AP bring up */
|
||||
if (!iwl_is_associated_ctx(ctx)) {
|
||||
|
||||
/* RXON - unassoc (to set timing command) */
|
||||
ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
|
||||
iwlcore_commit_rxon(priv, ctx);
|
||||
|
||||
/* RXON Timing */
|
||||
ret = iwl_send_rxon_timing(priv, ctx);
|
||||
if (ret)
|
||||
IWL_WARN(priv, "RXON timing failed - "
|
||||
"Attempting to continue.\n");
|
||||
|
||||
/* AP has all antennas */
|
||||
priv->chain_noise_data.active_chains =
|
||||
priv->hw_params.valid_rx_ant;
|
||||
iwl_set_rxon_ht(priv, &priv->current_ht_config);
|
||||
if (priv->cfg->ops->hcmd->set_rxon_chain)
|
||||
priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
|
||||
|
||||
ctx->staging.assoc_id = 0;
|
||||
|
||||
if (vif->bss_conf.use_short_preamble)
|
||||
ctx->staging.flags |=
|
||||
RXON_FLG_SHORT_PREAMBLE_MSK;
|
||||
else
|
||||
ctx->staging.flags &=
|
||||
~RXON_FLG_SHORT_PREAMBLE_MSK;
|
||||
|
||||
if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
|
||||
if (vif->bss_conf.use_short_slot)
|
||||
ctx->staging.flags |=
|
||||
RXON_FLG_SHORT_SLOT_MSK;
|
||||
else
|
||||
ctx->staging.flags &=
|
||||
~RXON_FLG_SHORT_SLOT_MSK;
|
||||
}
|
||||
/* need to send beacon cmd before committing assoc RXON! */
|
||||
iwl_send_beacon_cmd(priv);
|
||||
/* restore RXON assoc */
|
||||
ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
|
||||
iwlcore_commit_rxon(priv, ctx);
|
||||
}
|
||||
iwl_send_beacon_cmd(priv);
|
||||
|
||||
/* FIXME - we need to add code here to detect a totally new
|
||||
* configuration, reset the AP, unassoc, rxon timing, assoc,
|
||||
* clear sta table, add BCAST sta... */
|
||||
}
|
||||
|
||||
static void iwl_mac_update_tkip_key(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_key_conf *keyconf,
|
||||
struct ieee80211_sta *sta,
|
||||
u32 iv32, u16 *phase1key)
|
||||
{
|
||||
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
|
||||
|
||||
@ -3631,10 +3323,9 @@ static void iwl_mac_update_tkip_key(struct ieee80211_hw *hw,
|
||||
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||
}
|
||||
|
||||
static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *key)
|
||||
int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
struct ieee80211_vif *vif, struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *key)
|
||||
{
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
|
||||
@ -3701,10 +3392,10 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
enum ieee80211_ampdu_mlme_action action,
|
||||
struct ieee80211_sta *sta, u16 tid, u16 *ssn)
|
||||
int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
enum ieee80211_ampdu_mlme_action action,
|
||||
struct ieee80211_sta *sta, u16 tid, u16 *ssn)
|
||||
{
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
int ret = -EINVAL;
|
||||
@ -3785,39 +3476,9 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void iwl_mac_sta_notify(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
enum sta_notify_cmd cmd,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
|
||||
int sta_id;
|
||||
|
||||
switch (cmd) {
|
||||
case STA_NOTIFY_SLEEP:
|
||||
WARN_ON(!sta_priv->client);
|
||||
sta_priv->asleep = true;
|
||||
if (atomic_read(&sta_priv->pending_frames) > 0)
|
||||
ieee80211_sta_block_awake(hw, sta, true);
|
||||
break;
|
||||
case STA_NOTIFY_AWAKE:
|
||||
WARN_ON(!sta_priv->client);
|
||||
if (!sta_priv->asleep)
|
||||
break;
|
||||
sta_priv->asleep = false;
|
||||
sta_id = iwl_sta_id(sta);
|
||||
if (sta_id != IWL_INVALID_STATION)
|
||||
iwl_sta_modify_ps_wake(priv, sta_id);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta)
|
||||
int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
|
||||
@ -3858,8 +3519,8 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void iwl_mac_channel_switch(struct ieee80211_hw *hw,
|
||||
struct ieee80211_channel_switch *ch_switch)
|
||||
void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
|
||||
struct ieee80211_channel_switch *ch_switch)
|
||||
{
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
const struct iwl_channel_info *ch_info;
|
||||
@ -3956,10 +3617,10 @@ out_exit:
|
||||
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||
}
|
||||
|
||||
static void iwlagn_configure_filter(struct ieee80211_hw *hw,
|
||||
unsigned int changed_flags,
|
||||
unsigned int *total_flags,
|
||||
u64 multicast)
|
||||
void iwlagn_configure_filter(struct ieee80211_hw *hw,
|
||||
unsigned int changed_flags,
|
||||
unsigned int *total_flags,
|
||||
u64 multicast)
|
||||
{
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
__le32 filter_or = 0, filter_nand = 0;
|
||||
@ -3986,7 +3647,11 @@ static void iwlagn_configure_filter(struct ieee80211_hw *hw,
|
||||
for_each_context(priv, ctx) {
|
||||
ctx->staging.filter_flags &= ~filter_nand;
|
||||
ctx->staging.filter_flags |= filter_or;
|
||||
iwlcore_commit_rxon(priv, ctx);
|
||||
|
||||
/*
|
||||
* Not committing directly because hardware can perform a scan,
|
||||
* but we'll eventually commit the filter flags change anyway.
|
||||
*/
|
||||
}
|
||||
|
||||
mutex_unlock(&priv->mutex);
|
||||
@ -4001,7 +3666,7 @@ static void iwlagn_configure_filter(struct ieee80211_hw *hw,
|
||||
FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;
|
||||
}
|
||||
|
||||
static void iwl_mac_flush(struct ieee80211_hw *hw, bool drop)
|
||||
void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop)
|
||||
{
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
|
||||
@ -4179,6 +3844,7 @@ static int iwl_init_drv(struct iwl_priv *priv)
|
||||
* this value will get overwritten by channel max power avg
|
||||
* from eeprom */
|
||||
priv->tx_power_user_lmt = IWLAGN_TX_POWER_TARGET_POWER_MIN;
|
||||
priv->tx_power_next = IWLAGN_TX_POWER_TARGET_POWER_MIN;
|
||||
|
||||
ret = iwl_init_channel_map(priv);
|
||||
if (ret) {
|
||||
@ -4209,28 +3875,30 @@ static void iwl_uninit_drv(struct iwl_priv *priv)
|
||||
kfree(priv->scan_cmd);
|
||||
}
|
||||
|
||||
static struct ieee80211_ops iwl_hw_ops = {
|
||||
.tx = iwl_mac_tx,
|
||||
.start = iwl_mac_start,
|
||||
.stop = iwl_mac_stop,
|
||||
#ifdef CONFIG_IWL5000
|
||||
struct ieee80211_ops iwlagn_hw_ops = {
|
||||
.tx = iwlagn_mac_tx,
|
||||
.start = iwlagn_mac_start,
|
||||
.stop = iwlagn_mac_stop,
|
||||
.add_interface = iwl_mac_add_interface,
|
||||
.remove_interface = iwl_mac_remove_interface,
|
||||
.config = iwl_mac_config,
|
||||
.change_interface = iwl_mac_change_interface,
|
||||
.config = iwlagn_mac_config,
|
||||
.configure_filter = iwlagn_configure_filter,
|
||||
.set_key = iwl_mac_set_key,
|
||||
.update_tkip_key = iwl_mac_update_tkip_key,
|
||||
.set_key = iwlagn_mac_set_key,
|
||||
.update_tkip_key = iwlagn_mac_update_tkip_key,
|
||||
.conf_tx = iwl_mac_conf_tx,
|
||||
.reset_tsf = iwl_mac_reset_tsf,
|
||||
.bss_info_changed = iwl_bss_info_changed,
|
||||
.ampdu_action = iwl_mac_ampdu_action,
|
||||
.bss_info_changed = iwlagn_bss_info_changed,
|
||||
.ampdu_action = iwlagn_mac_ampdu_action,
|
||||
.hw_scan = iwl_mac_hw_scan,
|
||||
.sta_notify = iwl_mac_sta_notify,
|
||||
.sta_notify = iwlagn_mac_sta_notify,
|
||||
.sta_add = iwlagn_mac_sta_add,
|
||||
.sta_remove = iwl_mac_sta_remove,
|
||||
.channel_switch = iwl_mac_channel_switch,
|
||||
.flush = iwl_mac_flush,
|
||||
.channel_switch = iwlagn_mac_channel_switch,
|
||||
.flush = iwlagn_mac_flush,
|
||||
.tx_last_beacon = iwl_mac_tx_last_beacon,
|
||||
};
|
||||
#endif
|
||||
|
||||
static void iwl_hw_detect(struct iwl_priv *priv)
|
||||
{
|
||||
@ -4298,10 +3966,15 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
if (cfg->mod_params->disable_hw_scan) {
|
||||
dev_printk(KERN_DEBUG, &(pdev->dev),
|
||||
"sw scan support is deprecated\n");
|
||||
iwl_hw_ops.hw_scan = NULL;
|
||||
#ifdef CONFIG_IWL5000
|
||||
iwlagn_hw_ops.hw_scan = NULL;
|
||||
#endif
|
||||
#ifdef CONFIG_IWL4965
|
||||
iwl4965_hw_ops.hw_scan = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
hw = iwl_alloc_all(cfg, &iwl_hw_ops);
|
||||
hw = iwl_alloc_all(cfg);
|
||||
if (!hw) {
|
||||
err = -ENOMEM;
|
||||
goto out;
|
||||
@ -4333,6 +4006,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
BIT(NL80211_IFTYPE_ADHOC);
|
||||
priv->contexts[IWL_RXON_CTX_BSS].interface_modes =
|
||||
BIT(NL80211_IFTYPE_STATION);
|
||||
priv->contexts[IWL_RXON_CTX_BSS].ap_devtype = RXON_DEV_TYPE_AP;
|
||||
priv->contexts[IWL_RXON_CTX_BSS].ibss_devtype = RXON_DEV_TYPE_IBSS;
|
||||
priv->contexts[IWL_RXON_CTX_BSS].station_devtype = RXON_DEV_TYPE_ESS;
|
||||
priv->contexts[IWL_RXON_CTX_BSS].unused_devtype = RXON_DEV_TYPE_ESS;
|
||||
@ -4500,8 +4174,10 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
|
||||
pci_enable_msi(priv->pci_dev);
|
||||
|
||||
iwl_alloc_isr_ict(priv);
|
||||
err = request_irq(priv->pci_dev->irq, priv->cfg->ops->lib->isr,
|
||||
if (priv->cfg->ops->lib->isr_ops.alloc)
|
||||
priv->cfg->ops->lib->isr_ops.alloc(priv);
|
||||
|
||||
err = request_irq(priv->pci_dev->irq, priv->cfg->ops->lib->isr_ops.isr,
|
||||
IRQF_SHARED, DRV_NAME, priv);
|
||||
if (err) {
|
||||
IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq);
|
||||
@ -4548,7 +4224,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
destroy_workqueue(priv->workqueue);
|
||||
priv->workqueue = NULL;
|
||||
free_irq(priv->pci_dev->irq, priv);
|
||||
iwl_free_isr_ict(priv);
|
||||
if (priv->cfg->ops->lib->isr_ops.free)
|
||||
priv->cfg->ops->lib->isr_ops.free(priv);
|
||||
out_disable_msi:
|
||||
pci_disable_msi(priv->pci_dev);
|
||||
iwl_uninit_drv(priv);
|
||||
@ -4643,7 +4320,8 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
|
||||
|
||||
iwl_uninit_drv(priv);
|
||||
|
||||
iwl_free_isr_ict(priv);
|
||||
if (priv->cfg->ops->lib->isr_ops.free)
|
||||
priv->cfg->ops->lib->isr_ops.free(priv);
|
||||
|
||||
dev_kfree_skb(priv->beacon_skb);
|
||||
|
||||
@ -4735,13 +4413,6 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
|
||||
{IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_2abg_cfg)},
|
||||
|
||||
/* 6x00 Series Gen2a */
|
||||
{IWL_PCI_DEVICE(0x0082, 0x1201, iwl6000g2a_2agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0085, 0x1211, iwl6000g2a_2agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0082, 0x1221, iwl6000g2a_2agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0082, 0x1206, iwl6000g2a_2abg_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0085, 0x1216, iwl6000g2a_2abg_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0082, 0x1226, iwl6000g2a_2abg_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0082, 0x1207, iwl6000g2a_2bg_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0082, 0x1301, iwl6000g2a_2agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0082, 0x1306, iwl6000g2a_2abg_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0082, 0x1307, iwl6000g2a_2bg_cfg)},
|
||||
@ -4751,24 +4422,12 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
|
||||
{IWL_PCI_DEVICE(0x0085, 0x1316, iwl6000g2a_2abg_cfg)},
|
||||
|
||||
/* 6x00 Series Gen2b */
|
||||
{IWL_PCI_DEVICE(0x008F, 0x5105, iwl6000g2b_bgn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0090, 0x5115, iwl6000g2b_bgn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x008F, 0x5125, iwl6000g2b_bgn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x008F, 0x5107, iwl6000g2b_bg_cfg)},
|
||||
{IWL_PCI_DEVICE(0x008F, 0x5201, iwl6000g2b_2agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0090, 0x5211, iwl6000g2b_2agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x008F, 0x5221, iwl6000g2b_2agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x008F, 0x5206, iwl6000g2b_2abg_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0090, 0x5216, iwl6000g2b_2abg_cfg)},
|
||||
{IWL_PCI_DEVICE(0x008F, 0x5226, iwl6000g2b_2abg_cfg)},
|
||||
{IWL_PCI_DEVICE(0x008F, 0x5207, iwl6000g2b_2bg_cfg)},
|
||||
{IWL_PCI_DEVICE(0x008A, 0x5301, iwl6000g2b_bgn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x008A, 0x5305, iwl6000g2b_bgn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x008A, 0x5307, iwl6000g2b_bg_cfg)},
|
||||
{IWL_PCI_DEVICE(0x008A, 0x5321, iwl6000g2b_bgn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x008A, 0x5325, iwl6000g2b_bgn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x008B, 0x5311, iwl6000g2b_bgn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x008A, 0x5327, iwl6000g2b_bg_cfg)},
|
||||
{IWL_PCI_DEVICE(0x008B, 0x5315, iwl6000g2b_bgn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x008B, 0x5317, iwl6000g2b_bg_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0090, 0x5211, iwl6000g2b_2agn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0090, 0x5215, iwl6000g2b_2bgn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x0090, 0x5216, iwl6000g2b_2abg_cfg)},
|
||||
@ -4812,10 +4471,11 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
|
||||
|
||||
/* 100 Series WiFi */
|
||||
{IWL_PCI_DEVICE(0x08AE, 0x1005, iwl100_bgn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08AF, 0x1015, iwl100_bgn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08AE, 0x1025, iwl100_bgn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08AE, 0x1007, iwl100_bg_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08AE, 0x1017, iwl100_bg_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08AF, 0x1015, iwl100_bgn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08AF, 0x1017, iwl100_bg_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08AE, 0x1025, iwl100_bgn_cfg)},
|
||||
{IWL_PCI_DEVICE(0x08AE, 0x1027, iwl100_bg_cfg)},
|
||||
|
||||
/* 130 Series WiFi */
|
||||
{IWL_PCI_DEVICE(0x0896, 0x5005, iwl130_bgn_cfg)},
|
||||
@ -4836,10 +4496,7 @@ static struct pci_driver iwl_driver = {
|
||||
.id_table = iwl_hw_card_ids,
|
||||
.probe = iwl_pci_probe,
|
||||
.remove = __devexit_p(iwl_pci_remove),
|
||||
#ifdef CONFIG_PM
|
||||
.suspend = iwl_pci_suspend,
|
||||
.resume = iwl_pci_resume,
|
||||
#endif
|
||||
.driver.pm = IWL_PM_OPS,
|
||||
};
|
||||
|
||||
static int __init iwl_init(void)
|
||||
|
@ -102,6 +102,9 @@ extern struct iwl_hcmd_ops iwlagn_hcmd;
|
||||
extern struct iwl_hcmd_ops iwlagn_bt_hcmd;
|
||||
extern struct iwl_hcmd_utils_ops iwlagn_hcmd_utils;
|
||||
|
||||
extern struct ieee80211_ops iwlagn_hw_ops;
|
||||
extern struct ieee80211_ops iwl4965_hw_ops;
|
||||
|
||||
int iwl_reset_ict(struct iwl_priv *priv);
|
||||
void iwl_disable_ict(struct iwl_priv *priv);
|
||||
int iwl_alloc_isr_ict(struct iwl_priv *priv);
|
||||
@ -132,6 +135,11 @@ void iwl_free_tfds_in_queue(struct iwl_priv *priv,
|
||||
/* RXON */
|
||||
int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
|
||||
void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
|
||||
int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed);
|
||||
void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *bss_conf,
|
||||
u32 changes);
|
||||
|
||||
/* uCode */
|
||||
int iwlagn_load_ucode(struct iwl_priv *priv);
|
||||
@ -249,6 +257,7 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv,
|
||||
int iwlagn_send_rxon_assoc(struct iwl_priv *priv,
|
||||
struct iwl_rxon_context *ctx);
|
||||
int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant);
|
||||
int iwlagn_send_beacon_cmd(struct iwl_priv *priv);
|
||||
|
||||
/* bt coex */
|
||||
void iwlagn_send_advance_bt_config(struct iwl_priv *priv);
|
||||
@ -292,9 +301,12 @@ int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta,
|
||||
int tid, u16 ssn);
|
||||
int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
|
||||
int tid);
|
||||
void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id);
|
||||
void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt);
|
||||
int iwl_update_bcast_stations(struct iwl_priv *priv);
|
||||
void iwlagn_mac_sta_notify(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
enum sta_notify_cmd cmd,
|
||||
struct ieee80211_sta *sta);
|
||||
|
||||
/* rate */
|
||||
static inline u32 iwl_ant_idx_to_flags(u8 ant_idx)
|
||||
@ -318,4 +330,31 @@ void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac);
|
||||
int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv);
|
||||
void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv);
|
||||
|
||||
/* mac80211 handlers (for 4965) */
|
||||
int iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
|
||||
int iwlagn_mac_start(struct ieee80211_hw *hw);
|
||||
void iwlagn_mac_stop(struct ieee80211_hw *hw);
|
||||
void iwlagn_configure_filter(struct ieee80211_hw *hw,
|
||||
unsigned int changed_flags,
|
||||
unsigned int *total_flags,
|
||||
u64 multicast);
|
||||
int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
struct ieee80211_vif *vif, struct ieee80211_sta *sta,
|
||||
struct ieee80211_key_conf *key);
|
||||
void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_key_conf *keyconf,
|
||||
struct ieee80211_sta *sta,
|
||||
u32 iv32, u16 *phase1key);
|
||||
int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
enum ieee80211_ampdu_mlme_action action,
|
||||
struct ieee80211_sta *sta, u16 tid, u16 *ssn);
|
||||
int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta);
|
||||
void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
|
||||
struct ieee80211_channel_switch *ch_switch);
|
||||
void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop);
|
||||
|
||||
#endif /* __iwl_agn_h__ */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -120,6 +120,14 @@ struct iwl_apm_ops {
|
||||
void (*config)(struct iwl_priv *priv);
|
||||
};
|
||||
|
||||
struct iwl_isr_ops {
|
||||
irqreturn_t (*isr) (int irq, void *data);
|
||||
void (*free)(struct iwl_priv *priv);
|
||||
int (*alloc)(struct iwl_priv *priv);
|
||||
int (*reset)(struct iwl_priv *priv);
|
||||
void (*disable)(struct iwl_priv *priv);
|
||||
};
|
||||
|
||||
struct iwl_debugfs_ops {
|
||||
ssize_t (*rx_stats_read)(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos);
|
||||
@ -193,20 +201,15 @@ struct iwl_lib_ops {
|
||||
/* power */
|
||||
int (*send_tx_power) (struct iwl_priv *priv);
|
||||
void (*update_chain_flags)(struct iwl_priv *priv);
|
||||
void (*post_associate)(struct iwl_priv *priv,
|
||||
struct ieee80211_vif *vif);
|
||||
void (*config_ap)(struct iwl_priv *priv, struct ieee80211_vif *vif);
|
||||
irqreturn_t (*isr) (int irq, void *data);
|
||||
|
||||
/* isr */
|
||||
struct iwl_isr_ops isr_ops;
|
||||
|
||||
/* eeprom operations (as defined in iwl-eeprom.h) */
|
||||
struct iwl_eeprom_ops eeprom_ops;
|
||||
|
||||
/* temperature */
|
||||
struct iwl_temp_ops temp_ops;
|
||||
/* station management */
|
||||
int (*manage_ibss_station)(struct iwl_priv *priv,
|
||||
struct ieee80211_vif *vif, bool add);
|
||||
int (*update_bcast_stations)(struct iwl_priv *priv);
|
||||
/* recover from tx queue stall */
|
||||
void (*recover_from_tx_stall)(unsigned long data);
|
||||
/* check for plcp health */
|
||||
@ -235,12 +238,23 @@ struct iwl_nic_ops {
|
||||
void (*additional_nic_config)(struct iwl_priv *priv);
|
||||
};
|
||||
|
||||
struct iwl_legacy_ops {
|
||||
void (*post_associate)(struct iwl_priv *priv);
|
||||
void (*config_ap)(struct iwl_priv *priv);
|
||||
/* station management */
|
||||
int (*update_bcast_stations)(struct iwl_priv *priv);
|
||||
int (*manage_ibss_station)(struct iwl_priv *priv,
|
||||
struct ieee80211_vif *vif, bool add);
|
||||
};
|
||||
|
||||
struct iwl_ops {
|
||||
const struct iwl_lib_ops *lib;
|
||||
const struct iwl_hcmd_ops *hcmd;
|
||||
const struct iwl_hcmd_utils_ops *utils;
|
||||
const struct iwl_led_ops *led;
|
||||
const struct iwl_nic_ops *nic;
|
||||
const struct iwl_legacy_ops *legacy;
|
||||
const struct ieee80211_ops *ieee80211_ops;
|
||||
};
|
||||
|
||||
struct iwl_mod_params {
|
||||
@ -276,6 +290,7 @@ struct iwl_mod_params {
|
||||
* sensitivity calibration operation
|
||||
* @chain_noise_calib_by_driver: driver has the capability to perform
|
||||
* chain noise calibration operation
|
||||
* @shadow_reg_enable: HW shadhow register bit
|
||||
*/
|
||||
struct iwl_base_params {
|
||||
int eeprom_size;
|
||||
@ -306,6 +321,7 @@ struct iwl_base_params {
|
||||
const bool ucode_tracing;
|
||||
const bool sensitivity_calib_by_driver;
|
||||
const bool chain_noise_calib_by_driver;
|
||||
const bool shadow_reg_enable;
|
||||
};
|
||||
/*
|
||||
* @advanced_bt_coexist: support advanced bt coexist
|
||||
@ -396,8 +412,7 @@ struct iwl_cfg {
|
||||
* L i b *
|
||||
***************************/
|
||||
|
||||
struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg,
|
||||
struct ieee80211_ops *hw_ops);
|
||||
struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg);
|
||||
int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
|
||||
const struct ieee80211_tx_queue_params *params);
|
||||
int iwl_mac_tx_last_beacon(struct ieee80211_hw *hw);
|
||||
@ -425,23 +440,16 @@ int iwl_set_decrypted_flag(struct iwl_priv *priv,
|
||||
u32 decrypt_res,
|
||||
struct ieee80211_rx_status *stats);
|
||||
void iwl_irq_handle_error(struct iwl_priv *priv);
|
||||
void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif);
|
||||
void iwl_bss_info_changed(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *bss_conf,
|
||||
u32 changes);
|
||||
int iwl_mac_add_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif);
|
||||
void iwl_mac_remove_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif);
|
||||
int iwl_mac_config(struct ieee80211_hw *hw, u32 changed);
|
||||
void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif);
|
||||
void iwl_mac_reset_tsf(struct ieee80211_hw *hw);
|
||||
int iwl_mac_change_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
enum nl80211_iftype newtype, bool newp2p);
|
||||
int iwl_alloc_txq_mem(struct iwl_priv *priv);
|
||||
void iwl_free_txq_mem(struct iwl_priv *priv);
|
||||
void iwlcore_tx_cmd_protection(struct iwl_priv *priv,
|
||||
struct ieee80211_tx_info *info,
|
||||
__le16 fc, __le32 *tx_flags);
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
int iwl_alloc_traffic_mem(struct iwl_priv *priv);
|
||||
void iwl_free_traffic_mem(struct iwl_priv *priv);
|
||||
@ -598,7 +606,6 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
|
||||
/*****************************************************
|
||||
* PCI *
|
||||
*****************************************************/
|
||||
irqreturn_t iwl_isr_legacy(int irq, void *data);
|
||||
|
||||
static inline u16 iwl_pcie_link_ctl(struct iwl_priv *priv)
|
||||
{
|
||||
@ -615,9 +622,17 @@ __le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base,
|
||||
u32 addon, u32 beacon_interval);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state);
|
||||
int iwl_pci_resume(struct pci_dev *pdev);
|
||||
#endif /* CONFIG_PM */
|
||||
int iwl_pci_suspend(struct device *device);
|
||||
int iwl_pci_resume(struct device *device);
|
||||
extern const struct dev_pm_ops iwl_pm_ops;
|
||||
|
||||
#define IWL_PM_OPS (&iwl_pm_ops)
|
||||
|
||||
#else /* !CONFIG_PM */
|
||||
|
||||
#define IWL_PM_OPS NULL
|
||||
|
||||
#endif /* !CONFIG_PM */
|
||||
|
||||
/*****************************************************
|
||||
* Error Handling Debugging
|
||||
@ -724,11 +739,6 @@ static inline int iwlcore_commit_rxon(struct iwl_priv *priv,
|
||||
{
|
||||
return priv->cfg->ops->hcmd->commit_rxon(priv, ctx);
|
||||
}
|
||||
static inline void iwlcore_config_ap(struct iwl_priv *priv,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
priv->cfg->ops->lib->config_ap(priv, vif);
|
||||
}
|
||||
static inline const struct ieee80211_supported_band *iwl_get_hw_mode(
|
||||
struct iwl_priv *priv, enum ieee80211_band band)
|
||||
{
|
||||
|
@ -132,6 +132,8 @@
|
||||
|
||||
#define CSR_LED_REG (CSR_BASE+0x094)
|
||||
#define CSR_DRAM_INT_TBL_REG (CSR_BASE+0x0A0)
|
||||
#define CSR_MAC_SHADOW_REG_CTRL (CSR_BASE+0x0A8) /* 6000 and up */
|
||||
|
||||
|
||||
/* GIO Chicken Bits (PCI Express bus link power management) */
|
||||
#define CSR_GIO_CHICKEN_BITS (CSR_BASE+0x100)
|
||||
|
@ -1162,6 +1162,8 @@ struct iwl_rxon_context {
|
||||
*/
|
||||
bool always_active, is_active;
|
||||
|
||||
bool ht_need_multiple_chains;
|
||||
|
||||
enum iwl_rxon_context_id ctxid;
|
||||
|
||||
u32 interface_modes, exclusive_interface_modes;
|
||||
@ -1517,6 +1519,7 @@ struct iwl_priv {
|
||||
s8 tx_power_user_lmt;
|
||||
s8 tx_power_device_lmt;
|
||||
s8 tx_power_lmt_in_half_dbm; /* max tx power in half-dBm format */
|
||||
s8 tx_power_next;
|
||||
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
|
@ -134,6 +134,7 @@ int iwl_led_associate(struct iwl_priv *priv)
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_led_associate);
|
||||
|
||||
int iwl_led_disassociate(struct iwl_priv *priv)
|
||||
{
|
||||
@ -141,6 +142,7 @@ int iwl_led_disassociate(struct iwl_priv *priv)
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_led_disassociate);
|
||||
|
||||
/*
|
||||
* calculate blink rate according to last second Tx/Rx activities
|
||||
|
662
drivers/net/wireless/iwlwifi/iwl-legacy.c
Normal file
662
drivers/net/wireless/iwlwifi/iwl-legacy.c
Normal file
@ -0,0 +1,662 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*****************************************************************************/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <net/mac80211.h>
|
||||
|
||||
#include "iwl-dev.h"
|
||||
#include "iwl-core.h"
|
||||
#include "iwl-helpers.h"
|
||||
#include "iwl-legacy.h"
|
||||
|
||||
static void iwl_update_qos(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
|
||||
{
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||
return;
|
||||
|
||||
if (!ctx->is_active)
|
||||
return;
|
||||
|
||||
ctx->qos_data.def_qos_parm.qos_flags = 0;
|
||||
|
||||
if (ctx->qos_data.qos_active)
|
||||
ctx->qos_data.def_qos_parm.qos_flags |=
|
||||
QOS_PARAM_FLG_UPDATE_EDCA_MSK;
|
||||
|
||||
if (ctx->ht.enabled)
|
||||
ctx->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK;
|
||||
|
||||
IWL_DEBUG_QOS(priv, "send QoS cmd with Qos active=%d FLAGS=0x%X\n",
|
||||
ctx->qos_data.qos_active,
|
||||
ctx->qos_data.def_qos_parm.qos_flags);
|
||||
|
||||
iwl_send_cmd_pdu_async(priv, ctx->qos_cmd,
|
||||
sizeof(struct iwl_qosparam_cmd),
|
||||
&ctx->qos_data.def_qos_parm, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl_legacy_mac_config - mac80211 config callback
|
||||
*/
|
||||
int iwl_legacy_mac_config(struct ieee80211_hw *hw, u32 changed)
|
||||
{
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
const struct iwl_channel_info *ch_info;
|
||||
struct ieee80211_conf *conf = &hw->conf;
|
||||
struct ieee80211_channel *channel = conf->channel;
|
||||
struct iwl_ht_config *ht_conf = &priv->current_ht_config;
|
||||
struct iwl_rxon_context *ctx;
|
||||
unsigned long flags = 0;
|
||||
int ret = 0;
|
||||
u16 ch;
|
||||
int scan_active = 0;
|
||||
bool ht_changed[NUM_IWL_RXON_CTX] = {};
|
||||
|
||||
if (WARN_ON(!priv->cfg->ops->legacy))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
IWL_DEBUG_MAC80211(priv, "enter to channel %d changed 0x%X\n",
|
||||
channel->hw_value, changed);
|
||||
|
||||
if (unlikely(!priv->cfg->mod_params->disable_hw_scan &&
|
||||
test_bit(STATUS_SCANNING, &priv->status))) {
|
||||
scan_active = 1;
|
||||
IWL_DEBUG_MAC80211(priv, "leave - scanning\n");
|
||||
}
|
||||
|
||||
if (changed & (IEEE80211_CONF_CHANGE_SMPS |
|
||||
IEEE80211_CONF_CHANGE_CHANNEL)) {
|
||||
/* mac80211 uses static for non-HT which is what we want */
|
||||
priv->current_ht_config.smps = conf->smps_mode;
|
||||
|
||||
/*
|
||||
* Recalculate chain counts.
|
||||
*
|
||||
* If monitor mode is enabled then mac80211 will
|
||||
* set up the SM PS mode to OFF if an HT channel is
|
||||
* configured.
|
||||
*/
|
||||
if (priv->cfg->ops->hcmd->set_rxon_chain)
|
||||
for_each_context(priv, ctx)
|
||||
priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
|
||||
}
|
||||
|
||||
/* during scanning mac80211 will delay channel setting until
|
||||
* scan finish with changed = 0
|
||||
*/
|
||||
if (!changed || (changed & IEEE80211_CONF_CHANGE_CHANNEL)) {
|
||||
if (scan_active)
|
||||
goto set_ch_out;
|
||||
|
||||
ch = channel->hw_value;
|
||||
ch_info = iwl_get_channel_info(priv, channel->band, ch);
|
||||
if (!is_channel_valid(ch_info)) {
|
||||
IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n");
|
||||
ret = -EINVAL;
|
||||
goto set_ch_out;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
|
||||
for_each_context(priv, ctx) {
|
||||
/* Configure HT40 channels */
|
||||
if (ctx->ht.enabled != conf_is_ht(conf)) {
|
||||
ctx->ht.enabled = conf_is_ht(conf);
|
||||
ht_changed[ctx->ctxid] = true;
|
||||
}
|
||||
if (ctx->ht.enabled) {
|
||||
if (conf_is_ht40_minus(conf)) {
|
||||
ctx->ht.extension_chan_offset =
|
||||
IEEE80211_HT_PARAM_CHA_SEC_BELOW;
|
||||
ctx->ht.is_40mhz = true;
|
||||
} else if (conf_is_ht40_plus(conf)) {
|
||||
ctx->ht.extension_chan_offset =
|
||||
IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
|
||||
ctx->ht.is_40mhz = true;
|
||||
} else {
|
||||
ctx->ht.extension_chan_offset =
|
||||
IEEE80211_HT_PARAM_CHA_SEC_NONE;
|
||||
ctx->ht.is_40mhz = false;
|
||||
}
|
||||
} else
|
||||
ctx->ht.is_40mhz = false;
|
||||
|
||||
/*
|
||||
* Default to no protection. Protection mode will
|
||||
* later be set from BSS config in iwl_ht_conf
|
||||
*/
|
||||
ctx->ht.protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE;
|
||||
|
||||
/* if we are switching from ht to 2.4 clear flags
|
||||
* from any ht related info since 2.4 does not
|
||||
* support ht */
|
||||
if ((le16_to_cpu(ctx->staging.channel) != ch))
|
||||
ctx->staging.flags = 0;
|
||||
|
||||
iwl_set_rxon_channel(priv, channel, ctx);
|
||||
iwl_set_rxon_ht(priv, ht_conf);
|
||||
|
||||
iwl_set_flags_for_band(priv, ctx, channel->band,
|
||||
ctx->vif);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
if (priv->cfg->ops->legacy->update_bcast_stations)
|
||||
ret = priv->cfg->ops->legacy->update_bcast_stations(priv);
|
||||
|
||||
set_ch_out:
|
||||
/* The list of supported rates and rate mask can be different
|
||||
* for each band; since the band may have changed, reset
|
||||
* the rate mask to what mac80211 lists */
|
||||
iwl_set_rate(priv);
|
||||
}
|
||||
|
||||
if (changed & (IEEE80211_CONF_CHANGE_PS |
|
||||
IEEE80211_CONF_CHANGE_IDLE)) {
|
||||
ret = iwl_power_update_mode(priv, false);
|
||||
if (ret)
|
||||
IWL_DEBUG_MAC80211(priv, "Error setting sleep level\n");
|
||||
}
|
||||
|
||||
if (changed & IEEE80211_CONF_CHANGE_POWER) {
|
||||
IWL_DEBUG_MAC80211(priv, "TX Power old=%d new=%d\n",
|
||||
priv->tx_power_user_lmt, conf->power_level);
|
||||
|
||||
iwl_set_tx_power(priv, conf->power_level, false);
|
||||
}
|
||||
|
||||
if (!iwl_is_ready(priv)) {
|
||||
IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (scan_active)
|
||||
goto out;
|
||||
|
||||
for_each_context(priv, ctx) {
|
||||
if (memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging)))
|
||||
iwlcore_commit_rxon(priv, ctx);
|
||||
else
|
||||
IWL_DEBUG_INFO(priv,
|
||||
"Not re-sending same RXON configuration.\n");
|
||||
if (ht_changed[ctx->ctxid])
|
||||
iwl_update_qos(priv, ctx);
|
||||
}
|
||||
|
||||
out:
|
||||
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||
mutex_unlock(&priv->mutex);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_legacy_mac_config);
|
||||
|
||||
void iwl_legacy_mac_reset_tsf(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
unsigned long flags;
|
||||
/* IBSS can only be the IWL_RXON_CTX_BSS context */
|
||||
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
|
||||
|
||||
if (WARN_ON(!priv->cfg->ops->legacy))
|
||||
return;
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
IWL_DEBUG_MAC80211(priv, "enter\n");
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_config));
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
|
||||
/* new association get rid of ibss beacon skb */
|
||||
if (priv->beacon_skb)
|
||||
dev_kfree_skb(priv->beacon_skb);
|
||||
|
||||
priv->beacon_skb = NULL;
|
||||
|
||||
priv->timestamp = 0;
|
||||
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
iwl_scan_cancel_timeout(priv, 100);
|
||||
if (!iwl_is_ready_rf(priv)) {
|
||||
IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
|
||||
mutex_unlock(&priv->mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
/* we are restarting association process
|
||||
* clear RXON_FILTER_ASSOC_MSK bit
|
||||
*/
|
||||
ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
|
||||
iwlcore_commit_rxon(priv, ctx);
|
||||
|
||||
iwl_set_rate(priv);
|
||||
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
||||
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_legacy_mac_reset_tsf);
|
||||
|
||||
static void iwl_ht_conf(struct iwl_priv *priv,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_ht_config *ht_conf = &priv->current_ht_config;
|
||||
struct ieee80211_sta *sta;
|
||||
struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
|
||||
struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
|
||||
|
||||
IWL_DEBUG_ASSOC(priv, "enter:\n");
|
||||
|
||||
if (!ctx->ht.enabled)
|
||||
return;
|
||||
|
||||
ctx->ht.protection =
|
||||
bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION;
|
||||
ctx->ht.non_gf_sta_present =
|
||||
!!(bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
|
||||
|
||||
ht_conf->single_chain_sufficient = false;
|
||||
|
||||
switch (vif->type) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
rcu_read_lock();
|
||||
sta = ieee80211_find_sta(vif, bss_conf->bssid);
|
||||
if (sta) {
|
||||
struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
|
||||
int maxstreams;
|
||||
|
||||
maxstreams = (ht_cap->mcs.tx_params &
|
||||
IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK)
|
||||
>> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT;
|
||||
maxstreams += 1;
|
||||
|
||||
if ((ht_cap->mcs.rx_mask[1] == 0) &&
|
||||
(ht_cap->mcs.rx_mask[2] == 0))
|
||||
ht_conf->single_chain_sufficient = true;
|
||||
if (maxstreams <= 1)
|
||||
ht_conf->single_chain_sufficient = true;
|
||||
} else {
|
||||
/*
|
||||
* If at all, this can only happen through a race
|
||||
* when the AP disconnects us while we're still
|
||||
* setting up the connection, in that case mac80211
|
||||
* will soon tell us about that.
|
||||
*/
|
||||
ht_conf->single_chain_sufficient = true;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
break;
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
ht_conf->single_chain_sufficient = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
IWL_DEBUG_ASSOC(priv, "leave\n");
|
||||
}
|
||||
|
||||
static inline void iwl_set_no_assoc(struct iwl_priv *priv,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
|
||||
|
||||
iwl_led_disassociate(priv);
|
||||
/*
|
||||
* inform the ucode that there is no longer an
|
||||
* association and that no more packets should be
|
||||
* sent
|
||||
*/
|
||||
ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
|
||||
ctx->staging.assoc_id = 0;
|
||||
iwlcore_commit_rxon(priv, ctx);
|
||||
}
|
||||
|
||||
static void iwlcore_beacon_update(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
unsigned long flags;
|
||||
__le64 timestamp;
|
||||
struct sk_buff *skb = ieee80211_beacon_get(hw, vif);
|
||||
|
||||
if (!skb)
|
||||
return;
|
||||
|
||||
IWL_DEBUG_MAC80211(priv, "enter\n");
|
||||
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
if (!priv->beacon_ctx) {
|
||||
IWL_ERR(priv, "update beacon but no beacon context!\n");
|
||||
dev_kfree_skb(skb);
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
|
||||
if (priv->beacon_skb)
|
||||
dev_kfree_skb(priv->beacon_skb);
|
||||
|
||||
priv->beacon_skb = 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);
|
||||
|
||||
if (!iwl_is_ready_rf(priv)) {
|
||||
IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
|
||||
return;
|
||||
}
|
||||
|
||||
priv->cfg->ops->legacy->post_associate(priv);
|
||||
}
|
||||
|
||||
void iwl_legacy_mac_bss_info_changed(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *bss_conf,
|
||||
u32 changes)
|
||||
{
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
|
||||
int ret;
|
||||
|
||||
if (WARN_ON(!priv->cfg->ops->legacy))
|
||||
return;
|
||||
|
||||
IWL_DEBUG_MAC80211(priv, "changes = 0x%X\n", changes);
|
||||
|
||||
if (!iwl_is_alive(priv))
|
||||
return;
|
||||
|
||||
mutex_lock(&priv->mutex);
|
||||
|
||||
if (changes & BSS_CHANGED_QOS) {
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
ctx->qos_data.qos_active = bss_conf->qos;
|
||||
iwl_update_qos(priv, ctx);
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
}
|
||||
|
||||
if (changes & BSS_CHANGED_BEACON_ENABLED) {
|
||||
/*
|
||||
* the add_interface code must make sure we only ever
|
||||
* have a single interface that could be beaconing at
|
||||
* any time.
|
||||
*/
|
||||
if (vif->bss_conf.enable_beacon)
|
||||
priv->beacon_ctx = ctx;
|
||||
else
|
||||
priv->beacon_ctx = NULL;
|
||||
}
|
||||
|
||||
if (changes & BSS_CHANGED_BEACON && vif->type == NL80211_IFTYPE_AP) {
|
||||
dev_kfree_skb(priv->beacon_skb);
|
||||
priv->beacon_skb = ieee80211_beacon_get(hw, vif);
|
||||
}
|
||||
|
||||
if (changes & BSS_CHANGED_BEACON_INT && vif->type == NL80211_IFTYPE_AP)
|
||||
iwl_send_rxon_timing(priv, ctx);
|
||||
|
||||
if (changes & BSS_CHANGED_BSSID) {
|
||||
IWL_DEBUG_MAC80211(priv, "BSSID %pM\n", bss_conf->bssid);
|
||||
|
||||
/*
|
||||
* If there is currently a HW scan going on in the
|
||||
* background then we need to cancel it else the RXON
|
||||
* below/in post_associate will fail.
|
||||
*/
|
||||
if (iwl_scan_cancel_timeout(priv, 100)) {
|
||||
IWL_WARN(priv, "Aborted scan still in progress after 100ms\n");
|
||||
IWL_DEBUG_MAC80211(priv, "leaving - scan abort failed.\n");
|
||||
mutex_unlock(&priv->mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
/* mac80211 only sets assoc when in STATION mode */
|
||||
if (vif->type == NL80211_IFTYPE_ADHOC || bss_conf->assoc) {
|
||||
memcpy(ctx->staging.bssid_addr,
|
||||
bss_conf->bssid, ETH_ALEN);
|
||||
|
||||
/* currently needed in a few places */
|
||||
memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN);
|
||||
} else {
|
||||
ctx->staging.filter_flags &=
|
||||
~RXON_FILTER_ASSOC_MSK;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* This needs to be after setting the BSSID in case
|
||||
* mac80211 decides to do both changes at once because
|
||||
* it will invoke post_associate.
|
||||
*/
|
||||
if (vif->type == NL80211_IFTYPE_ADHOC && changes & BSS_CHANGED_BEACON)
|
||||
iwlcore_beacon_update(hw, vif);
|
||||
|
||||
if (changes & BSS_CHANGED_ERP_PREAMBLE) {
|
||||
IWL_DEBUG_MAC80211(priv, "ERP_PREAMBLE %d\n",
|
||||
bss_conf->use_short_preamble);
|
||||
if (bss_conf->use_short_preamble)
|
||||
ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
|
||||
else
|
||||
ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
|
||||
}
|
||||
|
||||
if (changes & BSS_CHANGED_ERP_CTS_PROT) {
|
||||
IWL_DEBUG_MAC80211(priv, "ERP_CTS %d\n", bss_conf->use_cts_prot);
|
||||
if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ))
|
||||
ctx->staging.flags |= RXON_FLG_TGG_PROTECT_MSK;
|
||||
else
|
||||
ctx->staging.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
|
||||
if (bss_conf->use_cts_prot)
|
||||
ctx->staging.flags |= RXON_FLG_SELF_CTS_EN;
|
||||
else
|
||||
ctx->staging.flags &= ~RXON_FLG_SELF_CTS_EN;
|
||||
}
|
||||
|
||||
if (changes & BSS_CHANGED_BASIC_RATES) {
|
||||
/* XXX use this information
|
||||
*
|
||||
* To do that, remove code from iwl_set_rate() and put something
|
||||
* like this here:
|
||||
*
|
||||
if (A-band)
|
||||
ctx->staging.ofdm_basic_rates =
|
||||
bss_conf->basic_rates;
|
||||
else
|
||||
ctx->staging.ofdm_basic_rates =
|
||||
bss_conf->basic_rates >> 4;
|
||||
ctx->staging.cck_basic_rates =
|
||||
bss_conf->basic_rates & 0xF;
|
||||
*/
|
||||
}
|
||||
|
||||
if (changes & BSS_CHANGED_HT) {
|
||||
iwl_ht_conf(priv, vif);
|
||||
|
||||
if (priv->cfg->ops->hcmd->set_rxon_chain)
|
||||
priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
|
||||
}
|
||||
|
||||
if (changes & BSS_CHANGED_ASSOC) {
|
||||
IWL_DEBUG_MAC80211(priv, "ASSOC %d\n", bss_conf->assoc);
|
||||
if (bss_conf->assoc) {
|
||||
priv->timestamp = bss_conf->timestamp;
|
||||
|
||||
iwl_led_associate(priv);
|
||||
|
||||
if (!iwl_is_rfkill(priv))
|
||||
priv->cfg->ops->legacy->post_associate(priv);
|
||||
} else
|
||||
iwl_set_no_assoc(priv, vif);
|
||||
}
|
||||
|
||||
if (changes && iwl_is_associated_ctx(ctx) && bss_conf->aid) {
|
||||
IWL_DEBUG_MAC80211(priv, "Changes (%#x) while associated\n",
|
||||
changes);
|
||||
ret = iwl_send_rxon_assoc(priv, ctx);
|
||||
if (!ret) {
|
||||
/* Sync active_rxon with latest change. */
|
||||
memcpy((void *)&ctx->active,
|
||||
&ctx->staging,
|
||||
sizeof(struct iwl_rxon_cmd));
|
||||
}
|
||||
}
|
||||
|
||||
if (changes & BSS_CHANGED_BEACON_ENABLED) {
|
||||
if (vif->bss_conf.enable_beacon) {
|
||||
memcpy(ctx->staging.bssid_addr,
|
||||
bss_conf->bssid, ETH_ALEN);
|
||||
memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN);
|
||||
iwl_led_associate(priv);
|
||||
priv->cfg->ops->legacy->config_ap(priv);
|
||||
} else
|
||||
iwl_set_no_assoc(priv, vif);
|
||||
}
|
||||
|
||||
if (changes & BSS_CHANGED_IBSS) {
|
||||
ret = priv->cfg->ops->legacy->manage_ibss_station(priv, vif,
|
||||
bss_conf->ibss_joined);
|
||||
if (ret)
|
||||
IWL_ERR(priv, "failed to %s IBSS station %pM\n",
|
||||
bss_conf->ibss_joined ? "add" : "remove",
|
||||
bss_conf->bssid);
|
||||
}
|
||||
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
||||
IWL_DEBUG_MAC80211(priv, "leave\n");
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_legacy_mac_bss_info_changed);
|
||||
|
||||
irqreturn_t iwl_isr_legacy(int irq, void *data)
|
||||
{
|
||||
struct iwl_priv *priv = data;
|
||||
u32 inta, inta_mask;
|
||||
u32 inta_fh;
|
||||
unsigned long flags;
|
||||
if (!priv)
|
||||
return IRQ_NONE;
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
|
||||
/* Disable (but don't clear!) interrupts here to avoid
|
||||
* back-to-back ISRs and sporadic interrupts from our NIC.
|
||||
* If we have something to service, the tasklet will re-enable ints.
|
||||
* If we *don't* have something, we'll re-enable before leaving here. */
|
||||
inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */
|
||||
iwl_write32(priv, CSR_INT_MASK, 0x00000000);
|
||||
|
||||
/* Discover which interrupts are active/pending */
|
||||
inta = iwl_read32(priv, CSR_INT);
|
||||
inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
|
||||
|
||||
/* Ignore interrupt if there's nothing in NIC to service.
|
||||
* This may be due to IRQ shared with another device,
|
||||
* or due to sporadic interrupts thrown from our NIC. */
|
||||
if (!inta && !inta_fh) {
|
||||
IWL_DEBUG_ISR(priv,
|
||||
"Ignore interrupt, inta == 0, inta_fh == 0\n");
|
||||
goto none;
|
||||
}
|
||||
|
||||
if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
|
||||
/* Hardware disappeared. It might have already raised
|
||||
* an interrupt */
|
||||
IWL_WARN(priv, "HARDWARE GONE?? INTA == 0x%08x\n", inta);
|
||||
goto unplugged;
|
||||
}
|
||||
|
||||
IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
|
||||
inta, inta_mask, inta_fh);
|
||||
|
||||
inta &= ~CSR_INT_BIT_SCD;
|
||||
|
||||
/* iwl_irq_tasklet() will service interrupts and re-enable them */
|
||||
if (likely(inta || inta_fh))
|
||||
tasklet_schedule(&priv->irq_tasklet);
|
||||
|
||||
unplugged:
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
return IRQ_HANDLED;
|
||||
|
||||
none:
|
||||
/* re-enable interrupts here since we don't have anything to service. */
|
||||
/* only Re-enable if diabled by irq */
|
||||
if (test_bit(STATUS_INT_ENABLED, &priv->status))
|
||||
iwl_enable_interrupts(priv);
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_isr_legacy);
|
||||
|
||||
/*
|
||||
* iwl_legacy_tx_cmd_protection: Set rts/cts. 3945 and 4965 only share this
|
||||
* function.
|
||||
*/
|
||||
void iwl_legacy_tx_cmd_protection(struct iwl_priv *priv,
|
||||
struct ieee80211_tx_info *info,
|
||||
__le16 fc, __le32 *tx_flags)
|
||||
{
|
||||
if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) {
|
||||
*tx_flags |= TX_CMD_FLG_RTS_MSK;
|
||||
*tx_flags &= ~TX_CMD_FLG_CTS_MSK;
|
||||
*tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK;
|
||||
|
||||
if (!ieee80211_is_mgmt(fc))
|
||||
return;
|
||||
|
||||
switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
|
||||
case cpu_to_le16(IEEE80211_STYPE_AUTH):
|
||||
case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
|
||||
case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ):
|
||||
case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ):
|
||||
*tx_flags &= ~TX_CMD_FLG_RTS_MSK;
|
||||
*tx_flags |= TX_CMD_FLG_CTS_MSK;
|
||||
break;
|
||||
}
|
||||
} else if (info->control.rates[0].flags &
|
||||
IEEE80211_TX_RC_USE_CTS_PROTECT) {
|
||||
*tx_flags &= ~TX_CMD_FLG_RTS_MSK;
|
||||
*tx_flags |= TX_CMD_FLG_CTS_MSK;
|
||||
*tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_legacy_tx_cmd_protection);
|
79
drivers/net/wireless/iwlwifi/iwl-legacy.h
Normal file
79
drivers/net/wireless/iwlwifi/iwl-legacy.h
Normal file
@ -0,0 +1,79 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
|
||||
* USA
|
||||
*
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* Contact Information:
|
||||
* Intel Linux Wireless <ilw@linux.intel.com>
|
||||
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef __iwl_legacy_h__
|
||||
#define __iwl_legacy_h__
|
||||
|
||||
/* mac80211 handlers */
|
||||
int iwl_legacy_mac_config(struct ieee80211_hw *hw, u32 changed);
|
||||
void iwl_legacy_mac_reset_tsf(struct ieee80211_hw *hw);
|
||||
void iwl_legacy_mac_bss_info_changed(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *bss_conf,
|
||||
u32 changes);
|
||||
void iwl_legacy_tx_cmd_protection(struct iwl_priv *priv,
|
||||
struct ieee80211_tx_info *info,
|
||||
__le16 fc, __le32 *tx_flags);
|
||||
|
||||
irqreturn_t iwl_isr_legacy(int irq, void *data);
|
||||
|
||||
#endif /* __iwl_legacy_h__ */
|
@ -263,70 +263,95 @@ static int iwl_set_power(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd)
|
||||
sizeof(struct iwl_powertable_cmd), cmd);
|
||||
}
|
||||
|
||||
/* priv->mutex must be held */
|
||||
int iwl_power_update_mode(struct iwl_priv *priv, bool force)
|
||||
static void iwl_power_build_cmd(struct iwl_priv *priv,
|
||||
struct iwl_powertable_cmd *cmd)
|
||||
{
|
||||
int ret = 0;
|
||||
bool enabled = priv->hw->conf.flags & IEEE80211_CONF_PS;
|
||||
bool update_chains;
|
||||
struct iwl_powertable_cmd cmd;
|
||||
int dtimper;
|
||||
|
||||
dtimper = priv->hw->conf.ps_dtim_period ?: 1;
|
||||
|
||||
if (priv->cfg->base_params->broken_powersave)
|
||||
iwl_power_sleep_cam_cmd(priv, cmd);
|
||||
else if (priv->cfg->base_params->supports_idle &&
|
||||
priv->hw->conf.flags & IEEE80211_CONF_IDLE)
|
||||
iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, 20);
|
||||
else if (priv->cfg->ops->lib->tt_ops.lower_power_detection &&
|
||||
priv->cfg->ops->lib->tt_ops.tt_power_mode &&
|
||||
priv->cfg->ops->lib->tt_ops.lower_power_detection(priv)) {
|
||||
/* in thermal throttling low power state */
|
||||
iwl_static_sleep_cmd(priv, cmd,
|
||||
priv->cfg->ops->lib->tt_ops.tt_power_mode(priv), dtimper);
|
||||
} else if (!enabled)
|
||||
iwl_power_sleep_cam_cmd(priv, cmd);
|
||||
else if (priv->power_data.debug_sleep_level_override >= 0)
|
||||
iwl_static_sleep_cmd(priv, cmd,
|
||||
priv->power_data.debug_sleep_level_override,
|
||||
dtimper);
|
||||
else if (no_sleep_autoadjust)
|
||||
iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_1, dtimper);
|
||||
else
|
||||
iwl_power_fill_sleep_cmd(priv, cmd,
|
||||
priv->hw->conf.dynamic_ps_timeout,
|
||||
priv->hw->conf.max_sleep_period);
|
||||
}
|
||||
|
||||
int iwl_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd,
|
||||
bool force)
|
||||
{
|
||||
int ret;
|
||||
bool update_chains;
|
||||
|
||||
lockdep_assert_held(&priv->mutex);
|
||||
|
||||
/* Don't update the RX chain when chain noise calibration is running */
|
||||
update_chains = priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE ||
|
||||
priv->chain_noise_data.state == IWL_CHAIN_NOISE_ALIVE;
|
||||
|
||||
dtimper = priv->hw->conf.ps_dtim_period ?: 1;
|
||||
if (!memcmp(&priv->power_data.sleep_cmd, cmd, sizeof(*cmd)) && !force)
|
||||
return 0;
|
||||
|
||||
if (priv->cfg->base_params->broken_powersave)
|
||||
iwl_power_sleep_cam_cmd(priv, &cmd);
|
||||
else if (priv->cfg->base_params->supports_idle &&
|
||||
priv->hw->conf.flags & IEEE80211_CONF_IDLE)
|
||||
iwl_static_sleep_cmd(priv, &cmd, IWL_POWER_INDEX_5, 20);
|
||||
else if (priv->cfg->ops->lib->tt_ops.lower_power_detection &&
|
||||
priv->cfg->ops->lib->tt_ops.tt_power_mode &&
|
||||
priv->cfg->ops->lib->tt_ops.lower_power_detection(priv)) {
|
||||
/* in thermal throttling low power state */
|
||||
iwl_static_sleep_cmd(priv, &cmd,
|
||||
priv->cfg->ops->lib->tt_ops.tt_power_mode(priv), dtimper);
|
||||
} else if (!enabled)
|
||||
iwl_power_sleep_cam_cmd(priv, &cmd);
|
||||
else if (priv->power_data.debug_sleep_level_override >= 0)
|
||||
iwl_static_sleep_cmd(priv, &cmd,
|
||||
priv->power_data.debug_sleep_level_override,
|
||||
dtimper);
|
||||
else if (no_sleep_autoadjust)
|
||||
iwl_static_sleep_cmd(priv, &cmd, IWL_POWER_INDEX_1, dtimper);
|
||||
else
|
||||
iwl_power_fill_sleep_cmd(priv, &cmd,
|
||||
priv->hw->conf.dynamic_ps_timeout,
|
||||
priv->hw->conf.max_sleep_period);
|
||||
if (!iwl_is_ready_rf(priv))
|
||||
return -EIO;
|
||||
|
||||
if (iwl_is_ready_rf(priv) &&
|
||||
(memcmp(&priv->power_data.sleep_cmd, &cmd, sizeof(cmd)) || force)) {
|
||||
if (cmd.flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK)
|
||||
set_bit(STATUS_POWER_PMI, &priv->status);
|
||||
/* scan complete use sleep_power_next, need to be updated */
|
||||
memcpy(&priv->power_data.sleep_cmd_next, cmd, sizeof(*cmd));
|
||||
if (test_bit(STATUS_SCANNING, &priv->status) && !force) {
|
||||
IWL_DEBUG_INFO(priv, "Defer power set mode while scanning\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = iwl_set_power(priv, &cmd);
|
||||
if (!ret) {
|
||||
if (!(cmd.flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK))
|
||||
clear_bit(STATUS_POWER_PMI, &priv->status);
|
||||
if (cmd->flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK)
|
||||
set_bit(STATUS_POWER_PMI, &priv->status);
|
||||
|
||||
if (priv->cfg->ops->lib->update_chain_flags &&
|
||||
update_chains)
|
||||
priv->cfg->ops->lib->update_chain_flags(priv);
|
||||
else if (priv->cfg->ops->lib->update_chain_flags)
|
||||
IWL_DEBUG_POWER(priv,
|
||||
ret = iwl_set_power(priv, cmd);
|
||||
if (!ret) {
|
||||
if (!(cmd->flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK))
|
||||
clear_bit(STATUS_POWER_PMI, &priv->status);
|
||||
|
||||
if (priv->cfg->ops->lib->update_chain_flags && update_chains)
|
||||
priv->cfg->ops->lib->update_chain_flags(priv);
|
||||
else if (priv->cfg->ops->lib->update_chain_flags)
|
||||
IWL_DEBUG_POWER(priv,
|
||||
"Cannot update the power, chain noise "
|
||||
"calibration running: %d\n",
|
||||
priv->chain_noise_data.state);
|
||||
memcpy(&priv->power_data.sleep_cmd, &cmd, sizeof(cmd));
|
||||
} else
|
||||
IWL_ERR(priv, "set power fail, ret = %d", ret);
|
||||
}
|
||||
|
||||
memcpy(&priv->power_data.sleep_cmd, cmd, sizeof(*cmd));
|
||||
} else
|
||||
IWL_ERR(priv, "set power fail, ret = %d", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_power_set_mode);
|
||||
|
||||
int iwl_power_update_mode(struct iwl_priv *priv, bool force)
|
||||
{
|
||||
struct iwl_powertable_cmd cmd;
|
||||
|
||||
iwl_power_build_cmd(priv, &cmd);
|
||||
return iwl_power_set_mode(priv, &cmd, force);
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_power_update_mode);
|
||||
|
||||
/* initialize to default */
|
||||
|
@ -41,10 +41,13 @@ enum iwl_power_level {
|
||||
|
||||
struct iwl_power_mgr {
|
||||
struct iwl_powertable_cmd sleep_cmd;
|
||||
struct iwl_powertable_cmd sleep_cmd_next;
|
||||
int debug_sleep_level_override;
|
||||
bool pci_pm;
|
||||
};
|
||||
|
||||
int iwl_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd,
|
||||
bool force);
|
||||
int iwl_power_update_mode(struct iwl_priv *priv, bool force);
|
||||
void iwl_power_initialize(struct iwl_priv *priv);
|
||||
|
||||
|
@ -134,28 +134,37 @@ void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q
|
||||
if (q->need_update == 0)
|
||||
goto exit_unlock;
|
||||
|
||||
/* If power-saving is in use, make sure device is awake */
|
||||
if (test_bit(STATUS_POWER_PMI, &priv->status)) {
|
||||
reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
|
||||
|
||||
if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
|
||||
IWL_DEBUG_INFO(priv, "Rx queue requesting wakeup, GP1 = 0x%x\n",
|
||||
reg);
|
||||
iwl_set_bit(priv, CSR_GP_CNTRL,
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
|
||||
goto exit_unlock;
|
||||
}
|
||||
|
||||
q->write_actual = (q->write & ~0x7);
|
||||
iwl_write_direct32(priv, rx_wrt_ptr_reg, q->write_actual);
|
||||
|
||||
/* Else device is assumed to be awake */
|
||||
} else {
|
||||
if (priv->cfg->base_params->shadow_reg_enable) {
|
||||
/* shadow register enabled */
|
||||
/* Device expects a multiple of 8 */
|
||||
q->write_actual = (q->write & ~0x7);
|
||||
iwl_write_direct32(priv, rx_wrt_ptr_reg, q->write_actual);
|
||||
}
|
||||
iwl_write32(priv, rx_wrt_ptr_reg, q->write_actual);
|
||||
} else {
|
||||
/* If power-saving is in use, make sure device is awake */
|
||||
if (test_bit(STATUS_POWER_PMI, &priv->status)) {
|
||||
reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
|
||||
|
||||
if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
|
||||
IWL_DEBUG_INFO(priv,
|
||||
"Rx queue requesting wakeup,"
|
||||
" GP1 = 0x%x\n", reg);
|
||||
iwl_set_bit(priv, CSR_GP_CNTRL,
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
|
||||
goto exit_unlock;
|
||||
}
|
||||
|
||||
q->write_actual = (q->write & ~0x7);
|
||||
iwl_write_direct32(priv, rx_wrt_ptr_reg,
|
||||
q->write_actual);
|
||||
|
||||
/* Else device is assumed to be awake */
|
||||
} else {
|
||||
/* Device expects a multiple of 8 */
|
||||
q->write_actual = (q->write & ~0x7);
|
||||
iwl_write_direct32(priv, rx_wrt_ptr_reg,
|
||||
q->write_actual);
|
||||
}
|
||||
}
|
||||
q->need_update = 0;
|
||||
|
||||
exit_unlock:
|
||||
|
@ -603,13 +603,16 @@ out_settings:
|
||||
if (!iwl_is_ready_rf(priv))
|
||||
goto out;
|
||||
|
||||
/* Since setting the TXPOWER may have been deferred while
|
||||
* performing the scan, fire one off */
|
||||
iwl_set_tx_power(priv, priv->tx_power_user_lmt, true);
|
||||
/*
|
||||
* We do not commit power settings while scan is pending,
|
||||
* do it now if the settings changed.
|
||||
*/
|
||||
iwl_power_set_mode(priv, &priv->power_data.sleep_cmd_next, false);
|
||||
iwl_set_tx_power(priv, priv->tx_power_next, false);
|
||||
|
||||
priv->cfg->ops->utils->post_scan(priv);
|
||||
|
||||
out:
|
||||
out:
|
||||
mutex_unlock(&priv->mutex);
|
||||
}
|
||||
|
||||
|
@ -49,30 +49,39 @@ void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq)
|
||||
if (txq->need_update == 0)
|
||||
return;
|
||||
|
||||
/* if we're trying to save power */
|
||||
if (test_bit(STATUS_POWER_PMI, &priv->status)) {
|
||||
/* wake up nic if it's powered down ...
|
||||
* uCode will wake up, and interrupt us again, so next
|
||||
* time we'll skip this part. */
|
||||
reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
|
||||
|
||||
if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
|
||||
IWL_DEBUG_INFO(priv, "Tx queue %d requesting wakeup, GP1 = 0x%x\n",
|
||||
txq_id, reg);
|
||||
iwl_set_bit(priv, CSR_GP_CNTRL,
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
|
||||
return;
|
||||
}
|
||||
|
||||
iwl_write_direct32(priv, HBUS_TARG_WRPTR,
|
||||
txq->q.write_ptr | (txq_id << 8));
|
||||
|
||||
/* else not in power-save mode, uCode will never sleep when we're
|
||||
* trying to tx (during RFKILL, we're not trying to tx). */
|
||||
} else
|
||||
if (priv->cfg->base_params->shadow_reg_enable) {
|
||||
/* shadow register enabled */
|
||||
iwl_write32(priv, HBUS_TARG_WRPTR,
|
||||
txq->q.write_ptr | (txq_id << 8));
|
||||
} else {
|
||||
/* if we're trying to save power */
|
||||
if (test_bit(STATUS_POWER_PMI, &priv->status)) {
|
||||
/* wake up nic if it's powered down ...
|
||||
* uCode will wake up, and interrupt us again, so next
|
||||
* time we'll skip this part. */
|
||||
reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
|
||||
|
||||
if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
|
||||
IWL_DEBUG_INFO(priv,
|
||||
"Tx queue %d requesting wakeup,"
|
||||
" GP1 = 0x%x\n", txq_id, reg);
|
||||
iwl_set_bit(priv, CSR_GP_CNTRL,
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
|
||||
return;
|
||||
}
|
||||
|
||||
iwl_write_direct32(priv, HBUS_TARG_WRPTR,
|
||||
txq->q.write_ptr | (txq_id << 8));
|
||||
|
||||
/*
|
||||
* else not in power-save mode,
|
||||
* uCode will never sleep when we're
|
||||
* trying to tx (during RFKILL, we're not trying to tx).
|
||||
*/
|
||||
} else
|
||||
iwl_write32(priv, HBUS_TARG_WRPTR,
|
||||
txq->q.write_ptr | (txq_id << 8));
|
||||
}
|
||||
txq->need_update = 0;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_txq_update_write_ptr);
|
||||
|
@ -61,6 +61,7 @@
|
||||
#include "iwl-helpers.h"
|
||||
#include "iwl-dev.h"
|
||||
#include "iwl-spectrum.h"
|
||||
#include "iwl-legacy.h"
|
||||
|
||||
/*
|
||||
* module name, copyright, version, etc.
|
||||
@ -3057,22 +3058,22 @@ static void iwl3945_bg_rx_replenish(struct work_struct *data)
|
||||
mutex_unlock(&priv->mutex);
|
||||
}
|
||||
|
||||
void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
||||
void iwl3945_post_associate(struct iwl_priv *priv)
|
||||
{
|
||||
int rc = 0;
|
||||
struct ieee80211_conf *conf = NULL;
|
||||
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
|
||||
|
||||
if (!vif || !priv->is_open)
|
||||
if (!ctx->vif || !priv->is_open)
|
||||
return;
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_AP) {
|
||||
if (ctx->vif->type == NL80211_IFTYPE_AP) {
|
||||
IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n",
|
||||
vif->bss_conf.aid, ctx->active.bssid_addr);
|
||||
ctx->vif->bss_conf.aid, ctx->active.bssid_addr);
|
||||
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||
return;
|
||||
@ -3091,18 +3092,18 @@ void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
||||
|
||||
ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
|
||||
|
||||
ctx->staging.assoc_id = cpu_to_le16(vif->bss_conf.aid);
|
||||
ctx->staging.assoc_id = cpu_to_le16(ctx->vif->bss_conf.aid);
|
||||
|
||||
IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n",
|
||||
vif->bss_conf.aid, vif->bss_conf.beacon_int);
|
||||
ctx->vif->bss_conf.aid, ctx->vif->bss_conf.beacon_int);
|
||||
|
||||
if (vif->bss_conf.use_short_preamble)
|
||||
if (ctx->vif->bss_conf.use_short_preamble)
|
||||
ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
|
||||
else
|
||||
ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
|
||||
|
||||
if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
|
||||
if (vif->bss_conf.use_short_slot)
|
||||
if (ctx->vif->bss_conf.use_short_slot)
|
||||
ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
|
||||
else
|
||||
ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
|
||||
@ -3110,7 +3111,7 @@ void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
||||
|
||||
iwl3945_commit_rxon(priv, ctx);
|
||||
|
||||
switch (vif->type) {
|
||||
switch (ctx->vif->type) {
|
||||
case NL80211_IFTYPE_STATION:
|
||||
iwl3945_rate_scale_init(priv->hw, IWL_AP_ID);
|
||||
break;
|
||||
@ -3119,7 +3120,7 @@ void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
||||
break;
|
||||
default:
|
||||
IWL_ERR(priv, "%s Should not be called in %d mode\n",
|
||||
__func__, vif->type);
|
||||
__func__, ctx->vif->type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -3234,9 +3235,10 @@ static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
void iwl3945_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif)
|
||||
void iwl3945_config_ap(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
|
||||
struct ieee80211_vif *vif = ctx->vif;
|
||||
int rc = 0;
|
||||
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||
@ -3407,9 +3409,9 @@ static void iwl3945_configure_filter(struct ieee80211_hw *hw,
|
||||
ctx->staging.filter_flags |= filter_or;
|
||||
|
||||
/*
|
||||
* Committing directly here breaks for some reason,
|
||||
* but we'll eventually commit the filter flags
|
||||
* change anyway.
|
||||
* Not committing directly because hardware can perform a scan,
|
||||
* but even if hw is ready, committing here breaks for some reason,
|
||||
* we'll eventually commit the filter flags change anyway.
|
||||
*/
|
||||
|
||||
mutex_unlock(&priv->mutex);
|
||||
@ -3824,18 +3826,19 @@ static struct attribute_group iwl3945_attribute_group = {
|
||||
.attrs = iwl3945_sysfs_entries,
|
||||
};
|
||||
|
||||
static struct ieee80211_ops iwl3945_hw_ops = {
|
||||
struct ieee80211_ops iwl3945_hw_ops = {
|
||||
.tx = iwl3945_mac_tx,
|
||||
.start = iwl3945_mac_start,
|
||||
.stop = iwl3945_mac_stop,
|
||||
.add_interface = iwl_mac_add_interface,
|
||||
.remove_interface = iwl_mac_remove_interface,
|
||||
.config = iwl_mac_config,
|
||||
.change_interface = iwl_mac_change_interface,
|
||||
.config = iwl_legacy_mac_config,
|
||||
.configure_filter = iwl3945_configure_filter,
|
||||
.set_key = iwl3945_mac_set_key,
|
||||
.conf_tx = iwl_mac_conf_tx,
|
||||
.reset_tsf = iwl_mac_reset_tsf,
|
||||
.bss_info_changed = iwl_bss_info_changed,
|
||||
.reset_tsf = iwl_legacy_mac_reset_tsf,
|
||||
.bss_info_changed = iwl_legacy_mac_bss_info_changed,
|
||||
.hw_scan = iwl_mac_hw_scan,
|
||||
.sta_add = iwl3945_mac_sta_add,
|
||||
.sta_remove = iwl_mac_sta_remove,
|
||||
@ -3866,6 +3869,7 @@ static int iwl3945_init_drv(struct iwl_priv *priv)
|
||||
priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF;
|
||||
|
||||
priv->tx_power_user_lmt = IWL_DEFAULT_TX_POWER;
|
||||
priv->tx_power_next = IWL_DEFAULT_TX_POWER;
|
||||
|
||||
if (eeprom->version < EEPROM_3945_EEPROM_VERSION) {
|
||||
IWL_WARN(priv, "Unsupported EEPROM version: 0x%04X\n",
|
||||
@ -3965,7 +3969,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
|
||||
|
||||
/* mac80211 allocates memory for this device instance, including
|
||||
* space for this driver's private structure */
|
||||
hw = iwl_alloc_all(cfg, &iwl3945_hw_ops);
|
||||
hw = iwl_alloc_all(cfg);
|
||||
if (hw == NULL) {
|
||||
pr_err("Can not allocate network device\n");
|
||||
err = -ENOMEM;
|
||||
@ -4117,7 +4121,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
|
||||
|
||||
pci_enable_msi(priv->pci_dev);
|
||||
|
||||
err = request_irq(priv->pci_dev->irq, priv->cfg->ops->lib->isr,
|
||||
err = request_irq(priv->pci_dev->irq, priv->cfg->ops->lib->isr_ops.isr,
|
||||
IRQF_SHARED, DRV_NAME, priv);
|
||||
if (err) {
|
||||
IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq);
|
||||
@ -4275,10 +4279,7 @@ static struct pci_driver iwl3945_driver = {
|
||||
.id_table = iwl3945_hw_card_ids,
|
||||
.probe = iwl3945_pci_probe,
|
||||
.remove = __devexit_p(iwl3945_pci_remove),
|
||||
#ifdef CONFIG_PM
|
||||
.suspend = iwl_pci_suspend,
|
||||
.resume = iwl_pci_resume,
|
||||
#endif
|
||||
.driver.pm = IWL_PM_OPS,
|
||||
};
|
||||
|
||||
static int __init iwl3945_init(void)
|
||||
|
@ -309,6 +309,8 @@ struct mac80211_hwsim_data {
|
||||
*/
|
||||
u64 group;
|
||||
struct dentry *debugfs_group;
|
||||
|
||||
int power_level;
|
||||
};
|
||||
|
||||
|
||||
@ -497,7 +499,7 @@ static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
|
||||
rx_status.band = data->channel->band;
|
||||
rx_status.rate_idx = info->control.rates[0].idx;
|
||||
/* TODO: simulate real signal strength (and optional packet loss) */
|
||||
rx_status.signal = -50;
|
||||
rx_status.signal = data->power_level - 50;
|
||||
|
||||
if (data->ps != PS_DISABLED)
|
||||
hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
|
||||
@ -698,6 +700,7 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed)
|
||||
data->idle = !!(conf->flags & IEEE80211_CONF_IDLE);
|
||||
|
||||
data->channel = conf->channel;
|
||||
data->power_level = conf->power_level;
|
||||
if (!data->started || !data->beacon_int)
|
||||
del_timer(&data->beacon_timer);
|
||||
else
|
||||
|
@ -1125,10 +1125,12 @@ struct mwl8k_tx_desc {
|
||||
__le32 reserved;
|
||||
__le16 rate_info;
|
||||
__u8 peer_id;
|
||||
__u8 tx_frag_cnt;
|
||||
__u8 xmitcontrol;
|
||||
} __packed;
|
||||
|
||||
#define MWL8K_TX_DESCS 128
|
||||
#define MWL8K_XMITCONTROL_NON_AMPDU 0x04
|
||||
|
||||
|
||||
static int mwl8k_txq_init(struct ieee80211_hw *hw, int index)
|
||||
{
|
||||
@ -1448,6 +1450,9 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
|
||||
tx->peer_id = MWL8K_STA(tx_info->control.sta)->peer_id;
|
||||
else
|
||||
tx->peer_id = 0;
|
||||
|
||||
if (priv->ap_fw)
|
||||
tx->xmitcontrol = MWL8K_XMITCONTROL_NON_AMPDU;
|
||||
wmb();
|
||||
tx->status = cpu_to_le32(MWL8K_TXD_STATUS_FW_OWNED | txstatus);
|
||||
|
||||
|
@ -885,8 +885,7 @@ static void rt2400pci_toggle_rx(struct rt2x00_dev *rt2x00dev,
|
||||
|
||||
rt2x00pci_register_read(rt2x00dev, RXCSR0, ®);
|
||||
rt2x00_set_field32(®, RXCSR0_DISABLE_RX,
|
||||
(state == STATE_RADIO_RX_OFF) ||
|
||||
(state == STATE_RADIO_RX_OFF_LINK));
|
||||
(state == STATE_RADIO_RX_OFF));
|
||||
rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
|
||||
}
|
||||
|
||||
@ -989,9 +988,7 @@ static int rt2400pci_set_device_state(struct rt2x00_dev *rt2x00dev,
|
||||
rt2400pci_disable_radio(rt2x00dev);
|
||||
break;
|
||||
case STATE_RADIO_RX_ON:
|
||||
case STATE_RADIO_RX_ON_LINK:
|
||||
case STATE_RADIO_RX_OFF:
|
||||
case STATE_RADIO_RX_OFF_LINK:
|
||||
rt2400pci_toggle_rx(rt2x00dev, state);
|
||||
break;
|
||||
case STATE_RADIO_IRQ_ON:
|
||||
@ -1612,6 +1609,7 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = {
|
||||
.get_tsf = rt2400pci_get_tsf,
|
||||
.tx_last_beacon = rt2400pci_tx_last_beacon,
|
||||
.rfkill_poll = rt2x00mac_rfkill_poll,
|
||||
.flush = rt2x00mac_flush,
|
||||
};
|
||||
|
||||
static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
|
||||
@ -1640,28 +1638,28 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
|
||||
};
|
||||
|
||||
static const struct data_queue_desc rt2400pci_queue_rx = {
|
||||
.entry_num = RX_ENTRIES,
|
||||
.entry_num = 24,
|
||||
.data_size = DATA_FRAME_SIZE,
|
||||
.desc_size = RXD_DESC_SIZE,
|
||||
.priv_size = sizeof(struct queue_entry_priv_pci),
|
||||
};
|
||||
|
||||
static const struct data_queue_desc rt2400pci_queue_tx = {
|
||||
.entry_num = TX_ENTRIES,
|
||||
.entry_num = 24,
|
||||
.data_size = DATA_FRAME_SIZE,
|
||||
.desc_size = TXD_DESC_SIZE,
|
||||
.priv_size = sizeof(struct queue_entry_priv_pci),
|
||||
};
|
||||
|
||||
static const struct data_queue_desc rt2400pci_queue_bcn = {
|
||||
.entry_num = BEACON_ENTRIES,
|
||||
.entry_num = 1,
|
||||
.data_size = MGMT_FRAME_SIZE,
|
||||
.desc_size = TXD_DESC_SIZE,
|
||||
.priv_size = sizeof(struct queue_entry_priv_pci),
|
||||
};
|
||||
|
||||
static const struct data_queue_desc rt2400pci_queue_atim = {
|
||||
.entry_num = ATIM_ENTRIES,
|
||||
.entry_num = 8,
|
||||
.data_size = DATA_FRAME_SIZE,
|
||||
.desc_size = TXD_DESC_SIZE,
|
||||
.priv_size = sizeof(struct queue_entry_priv_pci),
|
||||
|
@ -809,8 +809,8 @@
|
||||
/*
|
||||
* DMA descriptor defines.
|
||||
*/
|
||||
#define TXD_DESC_SIZE ( 8 * sizeof(__le32) )
|
||||
#define RXD_DESC_SIZE ( 8 * sizeof(__le32) )
|
||||
#define TXD_DESC_SIZE (8 * sizeof(__le32))
|
||||
#define RXD_DESC_SIZE (8 * sizeof(__le32))
|
||||
|
||||
/*
|
||||
* TX descriptor format for TX, PRIO, ATIM and Beacon Ring.
|
||||
@ -948,6 +948,6 @@
|
||||
((__CLAMP_TX(__txpower) - MAX_TXPOWER) + MIN_TXPOWER)
|
||||
|
||||
#define TXPOWER_TO_DEV(__txpower) \
|
||||
MAX_TXPOWER - (__CLAMP_TX(__txpower) - MIN_TXPOWER)
|
||||
(MAX_TXPOWER - (__CLAMP_TX(__txpower) - MIN_TXPOWER))
|
||||
|
||||
#endif /* RT2400PCI_H */
|
||||
|
@ -1040,8 +1040,7 @@ static void rt2500pci_toggle_rx(struct rt2x00_dev *rt2x00dev,
|
||||
|
||||
rt2x00pci_register_read(rt2x00dev, RXCSR0, ®);
|
||||
rt2x00_set_field32(®, RXCSR0_DISABLE_RX,
|
||||
(state == STATE_RADIO_RX_OFF) ||
|
||||
(state == STATE_RADIO_RX_OFF_LINK));
|
||||
(state == STATE_RADIO_RX_OFF));
|
||||
rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
|
||||
}
|
||||
|
||||
@ -1144,9 +1143,7 @@ static int rt2500pci_set_device_state(struct rt2x00_dev *rt2x00dev,
|
||||
rt2500pci_disable_radio(rt2x00dev);
|
||||
break;
|
||||
case STATE_RADIO_RX_ON:
|
||||
case STATE_RADIO_RX_ON_LINK:
|
||||
case STATE_RADIO_RX_OFF:
|
||||
case STATE_RADIO_RX_OFF_LINK:
|
||||
rt2500pci_toggle_rx(rt2x00dev, state);
|
||||
break;
|
||||
case STATE_RADIO_IRQ_ON:
|
||||
@ -1193,9 +1190,9 @@ static void rt2500pci_write_tx_desc(struct queue_entry *entry,
|
||||
|
||||
rt2x00_desc_read(txd, 2, &word);
|
||||
rt2x00_set_field32(&word, TXD_W2_IV_OFFSET, IEEE80211_HEADER);
|
||||
rt2x00_set_field32(&word, TXD_W2_AIFS, txdesc->aifs);
|
||||
rt2x00_set_field32(&word, TXD_W2_CWMIN, txdesc->cw_min);
|
||||
rt2x00_set_field32(&word, TXD_W2_CWMAX, txdesc->cw_max);
|
||||
rt2x00_set_field32(&word, TXD_W2_AIFS, entry->queue->aifs);
|
||||
rt2x00_set_field32(&word, TXD_W2_CWMIN, entry->queue->cw_min);
|
||||
rt2x00_set_field32(&word, TXD_W2_CWMAX, entry->queue->cw_max);
|
||||
rt2x00_desc_write(txd, 2, word);
|
||||
|
||||
rt2x00_desc_read(txd, 3, &word);
|
||||
@ -1909,6 +1906,7 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = {
|
||||
.get_tsf = rt2500pci_get_tsf,
|
||||
.tx_last_beacon = rt2500pci_tx_last_beacon,
|
||||
.rfkill_poll = rt2x00mac_rfkill_poll,
|
||||
.flush = rt2x00mac_flush,
|
||||
};
|
||||
|
||||
static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
|
||||
@ -1937,28 +1935,28 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
|
||||
};
|
||||
|
||||
static const struct data_queue_desc rt2500pci_queue_rx = {
|
||||
.entry_num = RX_ENTRIES,
|
||||
.entry_num = 32,
|
||||
.data_size = DATA_FRAME_SIZE,
|
||||
.desc_size = RXD_DESC_SIZE,
|
||||
.priv_size = sizeof(struct queue_entry_priv_pci),
|
||||
};
|
||||
|
||||
static const struct data_queue_desc rt2500pci_queue_tx = {
|
||||
.entry_num = TX_ENTRIES,
|
||||
.entry_num = 32,
|
||||
.data_size = DATA_FRAME_SIZE,
|
||||
.desc_size = TXD_DESC_SIZE,
|
||||
.priv_size = sizeof(struct queue_entry_priv_pci),
|
||||
};
|
||||
|
||||
static const struct data_queue_desc rt2500pci_queue_bcn = {
|
||||
.entry_num = BEACON_ENTRIES,
|
||||
.entry_num = 1,
|
||||
.data_size = MGMT_FRAME_SIZE,
|
||||
.desc_size = TXD_DESC_SIZE,
|
||||
.priv_size = sizeof(struct queue_entry_priv_pci),
|
||||
};
|
||||
|
||||
static const struct data_queue_desc rt2500pci_queue_atim = {
|
||||
.entry_num = ATIM_ENTRIES,
|
||||
.entry_num = 8,
|
||||
.data_size = DATA_FRAME_SIZE,
|
||||
.desc_size = TXD_DESC_SIZE,
|
||||
.priv_size = sizeof(struct queue_entry_priv_pci),
|
||||
|
@ -1088,8 +1088,8 @@
|
||||
/*
|
||||
* DMA descriptor defines.
|
||||
*/
|
||||
#define TXD_DESC_SIZE ( 11 * sizeof(__le32) )
|
||||
#define RXD_DESC_SIZE ( 11 * sizeof(__le32) )
|
||||
#define TXD_DESC_SIZE (11 * sizeof(__le32))
|
||||
#define RXD_DESC_SIZE (11 * sizeof(__le32))
|
||||
|
||||
/*
|
||||
* TX descriptor format for TX, PRIO, ATIM and Beacon Ring.
|
||||
|
@ -39,7 +39,7 @@
|
||||
/*
|
||||
* Allow hardware encryption to be disabled.
|
||||
*/
|
||||
static int modparam_nohwcrypt = 0;
|
||||
static int modparam_nohwcrypt;
|
||||
module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
|
||||
MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
|
||||
|
||||
@ -938,8 +938,7 @@ static void rt2500usb_toggle_rx(struct rt2x00_dev *rt2x00dev,
|
||||
|
||||
rt2500usb_register_read(rt2x00dev, TXRX_CSR2, ®);
|
||||
rt2x00_set_field16(®, TXRX_CSR2_DISABLE_RX,
|
||||
(state == STATE_RADIO_RX_OFF) ||
|
||||
(state == STATE_RADIO_RX_OFF_LINK));
|
||||
(state == STATE_RADIO_RX_OFF));
|
||||
rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg);
|
||||
}
|
||||
|
||||
@ -1019,9 +1018,7 @@ static int rt2500usb_set_device_state(struct rt2x00_dev *rt2x00dev,
|
||||
rt2500usb_disable_radio(rt2x00dev);
|
||||
break;
|
||||
case STATE_RADIO_RX_ON:
|
||||
case STATE_RADIO_RX_ON_LINK:
|
||||
case STATE_RADIO_RX_OFF:
|
||||
case STATE_RADIO_RX_OFF_LINK:
|
||||
rt2500usb_toggle_rx(rt2x00dev, state);
|
||||
break;
|
||||
case STATE_RADIO_IRQ_ON:
|
||||
@ -1081,9 +1078,9 @@ static void rt2500usb_write_tx_desc(struct queue_entry *entry,
|
||||
|
||||
rt2x00_desc_read(txd, 1, &word);
|
||||
rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, txdesc->iv_offset);
|
||||
rt2x00_set_field32(&word, TXD_W1_AIFS, txdesc->aifs);
|
||||
rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min);
|
||||
rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max);
|
||||
rt2x00_set_field32(&word, TXD_W1_AIFS, entry->queue->aifs);
|
||||
rt2x00_set_field32(&word, TXD_W1_CWMIN, entry->queue->cw_min);
|
||||
rt2x00_set_field32(&word, TXD_W1_CWMAX, entry->queue->cw_max);
|
||||
rt2x00_desc_write(txd, 1, word);
|
||||
|
||||
rt2x00_desc_read(txd, 2, &word);
|
||||
@ -1801,6 +1798,7 @@ static const struct ieee80211_ops rt2500usb_mac80211_ops = {
|
||||
.bss_info_changed = rt2x00mac_bss_info_changed,
|
||||
.conf_tx = rt2x00mac_conf_tx,
|
||||
.rfkill_poll = rt2x00mac_rfkill_poll,
|
||||
.flush = rt2x00mac_flush,
|
||||
};
|
||||
|
||||
static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
|
||||
@ -1829,28 +1827,28 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
|
||||
};
|
||||
|
||||
static const struct data_queue_desc rt2500usb_queue_rx = {
|
||||
.entry_num = RX_ENTRIES,
|
||||
.entry_num = 32,
|
||||
.data_size = DATA_FRAME_SIZE,
|
||||
.desc_size = RXD_DESC_SIZE,
|
||||
.priv_size = sizeof(struct queue_entry_priv_usb),
|
||||
};
|
||||
|
||||
static const struct data_queue_desc rt2500usb_queue_tx = {
|
||||
.entry_num = TX_ENTRIES,
|
||||
.entry_num = 32,
|
||||
.data_size = DATA_FRAME_SIZE,
|
||||
.desc_size = TXD_DESC_SIZE,
|
||||
.priv_size = sizeof(struct queue_entry_priv_usb),
|
||||
};
|
||||
|
||||
static const struct data_queue_desc rt2500usb_queue_bcn = {
|
||||
.entry_num = BEACON_ENTRIES,
|
||||
.entry_num = 1,
|
||||
.data_size = MGMT_FRAME_SIZE,
|
||||
.desc_size = TXD_DESC_SIZE,
|
||||
.priv_size = sizeof(struct queue_entry_priv_usb_bcn),
|
||||
};
|
||||
|
||||
static const struct data_queue_desc rt2500usb_queue_atim = {
|
||||
.entry_num = ATIM_ENTRIES,
|
||||
.entry_num = 8,
|
||||
.data_size = DATA_FRAME_SIZE,
|
||||
.desc_size = TXD_DESC_SIZE,
|
||||
.priv_size = sizeof(struct queue_entry_priv_usb),
|
||||
|
@ -412,10 +412,22 @@
|
||||
#define BCN_OFFSET1_BCN7 FIELD32(0xff000000)
|
||||
|
||||
/*
|
||||
* PBF registers
|
||||
* Most are for debug. Driver doesn't touch PBF register.
|
||||
* TXRXQ_PCNT: PBF register
|
||||
* PCNT_TX0Q: Page count for TX hardware queue 0
|
||||
* PCNT_TX1Q: Page count for TX hardware queue 1
|
||||
* PCNT_TX2Q: Page count for TX hardware queue 2
|
||||
* PCNT_RX0Q: Page count for RX hardware queue
|
||||
*/
|
||||
#define TXRXQ_PCNT 0x0438
|
||||
#define TXRXQ_PCNT_TX0Q FIELD32(0x000000ff)
|
||||
#define TXRXQ_PCNT_TX1Q FIELD32(0x0000ff00)
|
||||
#define TXRXQ_PCNT_TX2Q FIELD32(0x00ff0000)
|
||||
#define TXRXQ_PCNT_RX0Q FIELD32(0xff000000)
|
||||
|
||||
/*
|
||||
* PBF register
|
||||
* Debug. Driver doesn't touch PBF register.
|
||||
*/
|
||||
#define PBF_DBG 0x043c
|
||||
|
||||
/*
|
||||
@ -960,8 +972,31 @@
|
||||
|
||||
/*
|
||||
* TXOP_CTRL_CFG:
|
||||
* TIMEOUT_TRUN_EN: Enable/Disable TXOP timeout truncation
|
||||
* AC_TRUN_EN: Enable/Disable truncation for AC change
|
||||
* TXRATEGRP_TRUN_EN: Enable/Disable truncation for TX rate group change
|
||||
* USER_MODE_TRUN_EN: Enable/Disable truncation for user TXOP mode
|
||||
* MIMO_PS_TRUN_EN: Enable/Disable truncation for MIMO PS RTS/CTS
|
||||
* RESERVED_TRUN_EN: Reserved
|
||||
* LSIG_TXOP_EN: Enable/Disable L-SIG TXOP protection
|
||||
* EXT_CCA_EN: Enable/Disable extension channel CCA reference (Defer 40Mhz
|
||||
* transmissions if extension CCA is clear).
|
||||
* EXT_CCA_DLY: Extension CCA signal delay time (unit: us)
|
||||
* EXT_CWMIN: CwMin for extension channel backoff
|
||||
* 0: Disabled
|
||||
*
|
||||
*/
|
||||
#define TXOP_CTRL_CFG 0x1340
|
||||
#define TXOP_CTRL_CFG_TIMEOUT_TRUN_EN FIELD32(0x00000001)
|
||||
#define TXOP_CTRL_CFG_AC_TRUN_EN FIELD32(0x00000002)
|
||||
#define TXOP_CTRL_CFG_TXRATEGRP_TRUN_EN FIELD32(0x00000004)
|
||||
#define TXOP_CTRL_CFG_USER_MODE_TRUN_EN FIELD32(0x00000008)
|
||||
#define TXOP_CTRL_CFG_MIMO_PS_TRUN_EN FIELD32(0x00000010)
|
||||
#define TXOP_CTRL_CFG_RESERVED_TRUN_EN FIELD32(0x00000020)
|
||||
#define TXOP_CTRL_CFG_LSIG_TXOP_EN FIELD32(0x00000040)
|
||||
#define TXOP_CTRL_CFG_EXT_CCA_EN FIELD32(0x00000080)
|
||||
#define TXOP_CTRL_CFG_EXT_CCA_DLY FIELD32(0x0000ff00)
|
||||
#define TXOP_CTRL_CFG_EXT_CWMIN FIELD32(0x000f0000)
|
||||
|
||||
/*
|
||||
* TX_RTS_CFG:
|
||||
@ -1485,17 +1520,17 @@
|
||||
#define SHARED_KEY_MODE_BASE 0x7000
|
||||
|
||||
#define MAC_WCID_ENTRY(__idx) \
|
||||
( MAC_WCID_BASE + ((__idx) * sizeof(struct mac_wcid_entry)) )
|
||||
(MAC_WCID_BASE + ((__idx) * sizeof(struct mac_wcid_entry)))
|
||||
#define PAIRWISE_KEY_ENTRY(__idx) \
|
||||
( PAIRWISE_KEY_TABLE_BASE + ((__idx) * sizeof(struct hw_key_entry)) )
|
||||
(PAIRWISE_KEY_TABLE_BASE + ((__idx) * sizeof(struct hw_key_entry)))
|
||||
#define MAC_IVEIV_ENTRY(__idx) \
|
||||
( MAC_IVEIV_TABLE_BASE + ((__idx) * sizeof(struct mac_iveiv_entry)) )
|
||||
(MAC_IVEIV_TABLE_BASE + ((__idx) * sizeof(struct mac_iveiv_entry)))
|
||||
#define MAC_WCID_ATTR_ENTRY(__idx) \
|
||||
( MAC_WCID_ATTRIBUTE_BASE + ((__idx) * sizeof(u32)) )
|
||||
(MAC_WCID_ATTRIBUTE_BASE + ((__idx) * sizeof(u32)))
|
||||
#define SHARED_KEY_ENTRY(__idx) \
|
||||
( SHARED_KEY_TABLE_BASE + ((__idx) * sizeof(struct hw_key_entry)) )
|
||||
(SHARED_KEY_TABLE_BASE + ((__idx) * sizeof(struct hw_key_entry)))
|
||||
#define SHARED_KEY_MODE_ENTRY(__idx) \
|
||||
( SHARED_KEY_MODE_BASE + ((__idx) * sizeof(u32)) )
|
||||
(SHARED_KEY_MODE_BASE + ((__idx) * sizeof(u32)))
|
||||
|
||||
struct mac_wcid_entry {
|
||||
u8 mac[6];
|
||||
@ -1635,9 +1670,9 @@ struct mac_iveiv_entry {
|
||||
#define HW_BEACON_BASE7 0x5bc0
|
||||
|
||||
#define HW_BEACON_OFFSET(__index) \
|
||||
( ((__index) < 4) ? ( HW_BEACON_BASE0 + (__index * 0x0200) ) : \
|
||||
(((__index) < 6) ? ( HW_BEACON_BASE4 + ((__index - 4) * 0x0200) ) : \
|
||||
(HW_BEACON_BASE6 - ((__index - 6) * 0x0200))) )
|
||||
(((__index) < 4) ? (HW_BEACON_BASE0 + (__index * 0x0200)) : \
|
||||
(((__index) < 6) ? (HW_BEACON_BASE4 + ((__index - 4) * 0x0200)) : \
|
||||
(HW_BEACON_BASE6 - ((__index - 6) * 0x0200))))
|
||||
|
||||
/*
|
||||
* BBP registers.
|
||||
@ -1987,8 +2022,8 @@ struct mac_iveiv_entry {
|
||||
/*
|
||||
* DMA descriptor defines.
|
||||
*/
|
||||
#define TXWI_DESC_SIZE ( 4 * sizeof(__le32) )
|
||||
#define RXWI_DESC_SIZE ( 4 * sizeof(__le32) )
|
||||
#define TXWI_DESC_SIZE (4 * sizeof(__le32))
|
||||
#define RXWI_DESC_SIZE (4 * sizeof(__le32))
|
||||
|
||||
/*
|
||||
* TX WI structure
|
||||
|
@ -277,13 +277,17 @@ int rt2800_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev)
|
||||
unsigned int i;
|
||||
u32 reg;
|
||||
|
||||
/*
|
||||
* Some devices are really slow to respond here. Wait a whole second
|
||||
* before timing out.
|
||||
*/
|
||||
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
|
||||
rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®);
|
||||
if (!rt2x00_get_field32(reg, WPDMA_GLO_CFG_TX_DMA_BUSY) &&
|
||||
!rt2x00_get_field32(reg, WPDMA_GLO_CFG_RX_DMA_BUSY))
|
||||
return 0;
|
||||
|
||||
msleep(1);
|
||||
msleep(10);
|
||||
}
|
||||
|
||||
ERROR(rt2x00dev, "WPDMA TX/RX busy, aborting.\n");
|
||||
@ -483,7 +487,7 @@ void rt2800_write_tx_data(struct queue_entry *entry,
|
||||
txdesc->key_idx : 0xff);
|
||||
rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT,
|
||||
txdesc->length);
|
||||
rt2x00_set_field32(&word, TXWI_W1_PACKETID_QUEUE, txdesc->qid);
|
||||
rt2x00_set_field32(&word, TXWI_W1_PACKETID_QUEUE, entry->queue->qid);
|
||||
rt2x00_set_field32(&word, TXWI_W1_PACKETID_ENTRY, (entry->entry_idx % 3) + 1);
|
||||
rt2x00_desc_write(txwi, 1, word);
|
||||
|
||||
@ -727,7 +731,7 @@ void rt2800_txdone(struct rt2x00_dev *rt2x00dev)
|
||||
* that the TX_STA_FIFO stack has a size of 16. We stick to our
|
||||
* tx ring size for now.
|
||||
*/
|
||||
for (i = 0; i < TX_ENTRIES; i++) {
|
||||
for (i = 0; i < rt2x00dev->ops->tx->entry_num; i++) {
|
||||
rt2800_register_read(rt2x00dev, TX_STA_FIFO, ®);
|
||||
if (!rt2x00_get_field32(reg, TX_STA_FIFO_VALID))
|
||||
break;
|
||||
@ -824,7 +828,7 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2800_write_beacon);
|
||||
|
||||
static void inline rt2800_clear_beacon(struct rt2x00_dev *rt2x00dev,
|
||||
static inline void rt2800_clear_beacon(struct rt2x00_dev *rt2x00dev,
|
||||
unsigned int beacon_base)
|
||||
{
|
||||
int i;
|
||||
@ -1144,6 +1148,7 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,
|
||||
struct rt2x00intf_conf *conf, const unsigned int flags)
|
||||
{
|
||||
u32 reg;
|
||||
bool update_bssid = false;
|
||||
|
||||
if (flags & CONFIG_UPDATE_TYPE) {
|
||||
/*
|
||||
@ -1173,6 +1178,16 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,
|
||||
}
|
||||
|
||||
if (flags & CONFIG_UPDATE_MAC) {
|
||||
if (flags & CONFIG_UPDATE_TYPE &&
|
||||
conf->sync == TSF_SYNC_AP_NONE) {
|
||||
/*
|
||||
* The BSSID register has to be set to our own mac
|
||||
* address in AP mode.
|
||||
*/
|
||||
memcpy(conf->bssid, conf->mac, sizeof(conf->mac));
|
||||
update_bssid = true;
|
||||
}
|
||||
|
||||
if (!is_zero_ether_addr((const u8 *)conf->mac)) {
|
||||
reg = le32_to_cpu(conf->mac[1]);
|
||||
rt2x00_set_field32(®, MAC_ADDR_DW1_UNICAST_TO_ME_MASK, 0xff);
|
||||
@ -1183,7 +1198,7 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,
|
||||
conf->mac, sizeof(conf->mac));
|
||||
}
|
||||
|
||||
if (flags & CONFIG_UPDATE_BSSID) {
|
||||
if ((flags & CONFIG_UPDATE_BSSID) || update_bssid) {
|
||||
if (!is_zero_ether_addr((const u8 *)conf->bssid)) {
|
||||
reg = le32_to_cpu(conf->bssid[1]);
|
||||
rt2x00_set_field32(®, MAC_BSSID_DW1_BSS_ID_MASK, 3);
|
||||
@ -2097,7 +2112,23 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
|
||||
rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
|
||||
}
|
||||
|
||||
rt2800_register_write(rt2x00dev, TXOP_CTRL_CFG, 0x0000583f);
|
||||
/*
|
||||
* The legacy driver also sets TXOP_CTRL_CFG_RESERVED_TRUN_EN to 1
|
||||
* although it is reserved.
|
||||
*/
|
||||
rt2800_register_read(rt2x00dev, TXOP_CTRL_CFG, ®);
|
||||
rt2x00_set_field32(®, TXOP_CTRL_CFG_TIMEOUT_TRUN_EN, 1);
|
||||
rt2x00_set_field32(®, TXOP_CTRL_CFG_AC_TRUN_EN, 1);
|
||||
rt2x00_set_field32(®, TXOP_CTRL_CFG_TXRATEGRP_TRUN_EN, 1);
|
||||
rt2x00_set_field32(®, TXOP_CTRL_CFG_USER_MODE_TRUN_EN, 1);
|
||||
rt2x00_set_field32(®, TXOP_CTRL_CFG_MIMO_PS_TRUN_EN, 1);
|
||||
rt2x00_set_field32(®, TXOP_CTRL_CFG_RESERVED_TRUN_EN, 1);
|
||||
rt2x00_set_field32(®, TXOP_CTRL_CFG_LSIG_TXOP_EN, 0);
|
||||
rt2x00_set_field32(®, TXOP_CTRL_CFG_EXT_CCA_EN, 0);
|
||||
rt2x00_set_field32(®, TXOP_CTRL_CFG_EXT_CCA_DLY, 88);
|
||||
rt2x00_set_field32(®, TXOP_CTRL_CFG_EXT_CWMIN, 0);
|
||||
rt2800_register_write(rt2x00dev, TXOP_CTRL_CFG, reg);
|
||||
|
||||
rt2800_register_write(rt2x00dev, TXOP_HLDR_ET, 0x00000002);
|
||||
|
||||
rt2800_register_read(rt2x00dev, TX_RTS_CFG, ®);
|
||||
|
@ -328,8 +328,7 @@ static void rt2800pci_toggle_rx(struct rt2x00_dev *rt2x00dev,
|
||||
|
||||
rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®);
|
||||
rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX,
|
||||
(state == STATE_RADIO_RX_ON) ||
|
||||
(state == STATE_RADIO_RX_ON_LINK));
|
||||
(state == STATE_RADIO_RX_ON));
|
||||
rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
|
||||
}
|
||||
|
||||
@ -442,7 +441,7 @@ static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev,
|
||||
* if the device is booting and wasn't asleep it will return
|
||||
* failure when attempting to wakeup.
|
||||
*/
|
||||
rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0, 2);
|
||||
rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0xff, 2);
|
||||
|
||||
if (state == STATE_AWAKE) {
|
||||
rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKUP, 0, 0);
|
||||
@ -477,9 +476,7 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev,
|
||||
rt2800pci_set_state(rt2x00dev, STATE_SLEEP);
|
||||
break;
|
||||
case STATE_RADIO_RX_ON:
|
||||
case STATE_RADIO_RX_ON_LINK:
|
||||
case STATE_RADIO_RX_OFF:
|
||||
case STATE_RADIO_RX_OFF_LINK:
|
||||
rt2800pci_toggle_rx(rt2x00dev, state);
|
||||
break;
|
||||
case STATE_RADIO_IRQ_ON:
|
||||
@ -777,7 +774,7 @@ static void rt2800pci_txstatus_interrupt(struct rt2x00_dev *rt2x00dev)
|
||||
* Since we have only one producer and one consumer we don't
|
||||
* need to lock the kfifo.
|
||||
*/
|
||||
for (i = 0; i < TX_ENTRIES; i++) {
|
||||
for (i = 0; i < rt2x00dev->ops->tx->entry_num; i++) {
|
||||
rt2800_register_read(rt2x00dev, TX_STA_FIFO, &status);
|
||||
|
||||
if (!rt2x00_get_field32(status, TX_STA_FIFO_VALID))
|
||||
@ -943,6 +940,7 @@ static const struct ieee80211_ops rt2800pci_mac80211_ops = {
|
||||
.get_tsf = rt2800_get_tsf,
|
||||
.rfkill_poll = rt2x00mac_rfkill_poll,
|
||||
.ampdu_action = rt2800_ampdu_action,
|
||||
.flush = rt2x00mac_flush,
|
||||
};
|
||||
|
||||
static const struct rt2800_ops rt2800pci_rt2800_ops = {
|
||||
@ -991,21 +989,21 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
|
||||
};
|
||||
|
||||
static const struct data_queue_desc rt2800pci_queue_rx = {
|
||||
.entry_num = RX_ENTRIES,
|
||||
.entry_num = 128,
|
||||
.data_size = AGGREGATION_SIZE,
|
||||
.desc_size = RXD_DESC_SIZE,
|
||||
.priv_size = sizeof(struct queue_entry_priv_pci),
|
||||
};
|
||||
|
||||
static const struct data_queue_desc rt2800pci_queue_tx = {
|
||||
.entry_num = TX_ENTRIES,
|
||||
.entry_num = 64,
|
||||
.data_size = AGGREGATION_SIZE,
|
||||
.desc_size = TXD_DESC_SIZE,
|
||||
.priv_size = sizeof(struct queue_entry_priv_pci),
|
||||
};
|
||||
|
||||
static const struct data_queue_desc rt2800pci_queue_bcn = {
|
||||
.entry_num = 8 * BEACON_ENTRIES,
|
||||
.entry_num = 8,
|
||||
.data_size = 0, /* No DMA required for beacons */
|
||||
.desc_size = TXWI_DESC_SIZE,
|
||||
.priv_size = sizeof(struct queue_entry_priv_pci),
|
||||
|
@ -38,10 +38,10 @@
|
||||
* Queue register offset macros
|
||||
*/
|
||||
#define TX_QUEUE_REG_OFFSET 0x10
|
||||
#define TX_BASE_PTR(__x) TX_BASE_PTR0 + ((__x) * TX_QUEUE_REG_OFFSET)
|
||||
#define TX_MAX_CNT(__x) TX_MAX_CNT0 + ((__x) * TX_QUEUE_REG_OFFSET)
|
||||
#define TX_CTX_IDX(__x) TX_CTX_IDX0 + ((__x) * TX_QUEUE_REG_OFFSET)
|
||||
#define TX_DTX_IDX(__x) TX_DTX_IDX0 + ((__x) * TX_QUEUE_REG_OFFSET)
|
||||
#define TX_BASE_PTR(__x) (TX_BASE_PTR0 + ((__x) * TX_QUEUE_REG_OFFSET))
|
||||
#define TX_MAX_CNT(__x) (TX_MAX_CNT0 + ((__x) * TX_QUEUE_REG_OFFSET))
|
||||
#define TX_CTX_IDX(__x) (TX_CTX_IDX0 + ((__x) * TX_QUEUE_REG_OFFSET))
|
||||
#define TX_DTX_IDX(__x) (TX_DTX_IDX0 + ((__x) * TX_QUEUE_REG_OFFSET))
|
||||
|
||||
/*
|
||||
* 8051 firmware image.
|
||||
@ -52,8 +52,8 @@
|
||||
/*
|
||||
* DMA descriptor defines.
|
||||
*/
|
||||
#define TXD_DESC_SIZE ( 4 * sizeof(__le32) )
|
||||
#define RXD_DESC_SIZE ( 4 * sizeof(__le32) )
|
||||
#define TXD_DESC_SIZE (4 * sizeof(__le32))
|
||||
#define RXD_DESC_SIZE (4 * sizeof(__le32))
|
||||
|
||||
/*
|
||||
* TX descriptor format for TX, PRIO and Beacon Ring.
|
||||
|
@ -45,7 +45,7 @@
|
||||
/*
|
||||
* Allow hardware encryption to be disabled.
|
||||
*/
|
||||
static int modparam_nohwcrypt = 0;
|
||||
static int modparam_nohwcrypt;
|
||||
module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
|
||||
MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
|
||||
|
||||
@ -114,8 +114,7 @@ static void rt2800usb_toggle_rx(struct rt2x00_dev *rt2x00dev,
|
||||
|
||||
rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®);
|
||||
rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX,
|
||||
(state == STATE_RADIO_RX_ON) ||
|
||||
(state == STATE_RADIO_RX_ON_LINK));
|
||||
(state == STATE_RADIO_RX_ON));
|
||||
rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
|
||||
}
|
||||
|
||||
@ -165,7 +164,8 @@ static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev)
|
||||
* this limit so reduce the number to prevent errors.
|
||||
*/
|
||||
rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_LIMIT,
|
||||
((RX_ENTRIES * DATA_FRAME_SIZE) / 1024) - 3);
|
||||
((rt2x00dev->ops->rx->entry_num * DATA_FRAME_SIZE)
|
||||
/ 1024) - 3);
|
||||
rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_EN, 1);
|
||||
rt2x00_set_field32(®, USB_DMA_CFG_TX_BULK_EN, 1);
|
||||
rt2800_register_write(rt2x00dev, USB_DMA_CFG, reg);
|
||||
@ -183,9 +183,9 @@ static int rt2800usb_set_state(struct rt2x00_dev *rt2x00dev,
|
||||
enum dev_state state)
|
||||
{
|
||||
if (state == STATE_AWAKE)
|
||||
rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, 0xff, 0, 0);
|
||||
rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, 0xff, 0, 2);
|
||||
else
|
||||
rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0, 2);
|
||||
rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0xff, 2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -215,9 +215,7 @@ static int rt2800usb_set_device_state(struct rt2x00_dev *rt2x00dev,
|
||||
rt2800usb_set_state(rt2x00dev, STATE_SLEEP);
|
||||
break;
|
||||
case STATE_RADIO_RX_ON:
|
||||
case STATE_RADIO_RX_ON_LINK:
|
||||
case STATE_RADIO_RX_OFF:
|
||||
case STATE_RADIO_RX_OFF_LINK:
|
||||
rt2800usb_toggle_rx(rt2x00dev, state);
|
||||
break;
|
||||
case STATE_RADIO_IRQ_ON:
|
||||
@ -244,6 +242,49 @@ static int rt2800usb_set_device_state(struct rt2x00_dev *rt2x00dev,
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Watchdog handlers
|
||||
*/
|
||||
static void rt2800usb_watchdog(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
unsigned int i;
|
||||
u32 reg;
|
||||
|
||||
rt2800_register_read(rt2x00dev, TXRXQ_PCNT, ®);
|
||||
if (rt2x00_get_field32(reg, TXRXQ_PCNT_TX0Q)) {
|
||||
WARNING(rt2x00dev, "TX HW queue 0 timed out,"
|
||||
" invoke forced kick");
|
||||
|
||||
rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40012);
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
udelay(10);
|
||||
if (!rt2x00_get_field32(reg, TXRXQ_PCNT_TX0Q))
|
||||
break;
|
||||
}
|
||||
|
||||
rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40006);
|
||||
}
|
||||
|
||||
rt2800_register_read(rt2x00dev, TXRXQ_PCNT, ®);
|
||||
if (rt2x00_get_field32(reg, TXRXQ_PCNT_TX1Q)) {
|
||||
WARNING(rt2x00dev, "TX HW queue 1 timed out,"
|
||||
" invoke forced kick");
|
||||
|
||||
rt2800_register_write(rt2x00dev, PBF_CFG, 0xf4000a);
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
udelay(10);
|
||||
if (!rt2x00_get_field32(reg, TXRXQ_PCNT_TX1Q))
|
||||
break;
|
||||
}
|
||||
|
||||
rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40006);
|
||||
}
|
||||
|
||||
rt2x00usb_watchdog(rt2x00dev);
|
||||
}
|
||||
|
||||
/*
|
||||
* TX descriptor initialization
|
||||
*/
|
||||
@ -507,6 +548,7 @@ static const struct ieee80211_ops rt2800usb_mac80211_ops = {
|
||||
.get_tsf = rt2800_get_tsf,
|
||||
.rfkill_poll = rt2x00mac_rfkill_poll,
|
||||
.ampdu_action = rt2800_ampdu_action,
|
||||
.flush = rt2x00mac_flush,
|
||||
};
|
||||
|
||||
static const struct rt2800_ops rt2800usb_rt2800_ops = {
|
||||
@ -535,7 +577,7 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
|
||||
.link_stats = rt2800_link_stats,
|
||||
.reset_tuner = rt2800_reset_tuner,
|
||||
.link_tuner = rt2800_link_tuner,
|
||||
.watchdog = rt2x00usb_watchdog,
|
||||
.watchdog = rt2800usb_watchdog,
|
||||
.write_tx_desc = rt2800usb_write_tx_desc,
|
||||
.write_tx_data = rt2800_write_tx_data,
|
||||
.write_beacon = rt2800_write_beacon,
|
||||
@ -553,21 +595,21 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
|
||||
};
|
||||
|
||||
static const struct data_queue_desc rt2800usb_queue_rx = {
|
||||
.entry_num = RX_ENTRIES,
|
||||
.entry_num = 128,
|
||||
.data_size = AGGREGATION_SIZE,
|
||||
.desc_size = RXINFO_DESC_SIZE + RXWI_DESC_SIZE,
|
||||
.priv_size = sizeof(struct queue_entry_priv_usb),
|
||||
};
|
||||
|
||||
static const struct data_queue_desc rt2800usb_queue_tx = {
|
||||
.entry_num = TX_ENTRIES,
|
||||
.entry_num = 64,
|
||||
.data_size = AGGREGATION_SIZE,
|
||||
.desc_size = TXINFO_DESC_SIZE + TXWI_DESC_SIZE,
|
||||
.priv_size = sizeof(struct queue_entry_priv_usb),
|
||||
};
|
||||
|
||||
static const struct data_queue_desc rt2800usb_queue_bcn = {
|
||||
.entry_num = 8 * BEACON_ENTRIES,
|
||||
.entry_num = 8,
|
||||
.data_size = MGMT_FRAME_SIZE,
|
||||
.desc_size = TXINFO_DESC_SIZE + TXWI_DESC_SIZE,
|
||||
.priv_size = sizeof(struct queue_entry_priv_usb),
|
||||
|
@ -40,8 +40,8 @@
|
||||
/*
|
||||
* DMA descriptor defines.
|
||||
*/
|
||||
#define TXINFO_DESC_SIZE ( 1 * sizeof(__le32) )
|
||||
#define RXINFO_DESC_SIZE ( 1 * sizeof(__le32) )
|
||||
#define TXINFO_DESC_SIZE (1 * sizeof(__le32))
|
||||
#define RXINFO_DESC_SIZE (1 * sizeof(__le32))
|
||||
|
||||
/*
|
||||
* TX Info structure
|
||||
|
@ -1133,6 +1133,7 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
|
||||
int rt2x00mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
|
||||
const struct ieee80211_tx_queue_params *params);
|
||||
void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw);
|
||||
void rt2x00mac_flush(struct ieee80211_hw *hw, bool drop);
|
||||
|
||||
/*
|
||||
* Driver allocation handlers.
|
||||
|
@ -133,7 +133,7 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
|
||||
*/
|
||||
if (!(ant->flags & ANTENNA_RX_DIVERSITY))
|
||||
config.rx = rt2x00lib_config_antenna_check(config.rx, def->rx);
|
||||
else if(config.rx == ANTENNA_SW_DIVERSITY)
|
||||
else if (config.rx == ANTENNA_SW_DIVERSITY)
|
||||
config.rx = active->rx;
|
||||
|
||||
if (!(ant->flags & ANTENNA_TX_DIVERSITY))
|
||||
@ -146,7 +146,8 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
|
||||
* else the changes will be ignored by the device.
|
||||
*/
|
||||
if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
|
||||
rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF_LINK);
|
||||
rt2x00dev->ops->lib->set_device_state(rt2x00dev,
|
||||
STATE_RADIO_RX_OFF);
|
||||
|
||||
/*
|
||||
* Write new antenna setup to device and reset the link tuner.
|
||||
@ -160,7 +161,8 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
|
||||
memcpy(active, &config, sizeof(config));
|
||||
|
||||
if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
|
||||
rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON_LINK);
|
||||
rt2x00dev->ops->lib->set_device_state(rt2x00dev,
|
||||
STATE_RADIO_RX_ON);
|
||||
}
|
||||
|
||||
void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
|
||||
|
@ -162,11 +162,11 @@ void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
|
||||
struct timeval timestamp;
|
||||
u32 data_len;
|
||||
|
||||
do_gettimeofday(×tamp);
|
||||
|
||||
if (!test_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags))
|
||||
if (likely(!test_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags)))
|
||||
return;
|
||||
|
||||
do_gettimeofday(×tamp);
|
||||
|
||||
if (skb_queue_len(&intf->frame_dump_skbqueue) > 20) {
|
||||
DEBUG(rt2x00dev, "txrx dump queue length exceeded.\n");
|
||||
return;
|
||||
@ -342,7 +342,7 @@ static ssize_t rt2x00debug_read_queue_stats(struct file *file,
|
||||
sprintf(data, "qid\tcount\tlimit\tlength\tindex\tdma done\tdone\n");
|
||||
|
||||
queue_for_each(intf->rt2x00dev, queue) {
|
||||
spin_lock_irqsave(&queue->lock, irqflags);
|
||||
spin_lock_irqsave(&queue->index_lock, irqflags);
|
||||
|
||||
temp += sprintf(temp, "%d\t%d\t%d\t%d\t%d\t%d\t%d\n", queue->qid,
|
||||
queue->count, queue->limit, queue->length,
|
||||
@ -350,7 +350,7 @@ static ssize_t rt2x00debug_read_queue_stats(struct file *file,
|
||||
queue->index[Q_INDEX_DMA_DONE],
|
||||
queue->index[Q_INDEX_DONE]);
|
||||
|
||||
spin_unlock_irqrestore(&queue->lock, irqflags);
|
||||
spin_unlock_irqrestore(&queue->index_lock, irqflags);
|
||||
}
|
||||
|
||||
size = strlen(data);
|
||||
|
@ -68,7 +68,8 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev)
|
||||
/*
|
||||
* Enable RX.
|
||||
*/
|
||||
rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON);
|
||||
rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_RX_ON);
|
||||
rt2x00link_start_tuner(rt2x00dev);
|
||||
|
||||
/*
|
||||
* Start watchdog monitoring.
|
||||
@ -102,7 +103,8 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev)
|
||||
/*
|
||||
* Disable RX.
|
||||
*/
|
||||
rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF);
|
||||
rt2x00link_stop_tuner(rt2x00dev);
|
||||
rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_RX_OFF);
|
||||
|
||||
/*
|
||||
* Disable radio.
|
||||
@ -113,23 +115,6 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev)
|
||||
rt2x00leds_led_radio(rt2x00dev, false);
|
||||
}
|
||||
|
||||
void rt2x00lib_toggle_rx(struct rt2x00_dev *rt2x00dev, enum dev_state state)
|
||||
{
|
||||
/*
|
||||
* When we are disabling the RX, we should also stop the link tuner.
|
||||
*/
|
||||
if (state == STATE_RADIO_RX_OFF)
|
||||
rt2x00link_stop_tuner(rt2x00dev);
|
||||
|
||||
rt2x00dev->ops->lib->set_device_state(rt2x00dev, state);
|
||||
|
||||
/*
|
||||
* When we are enabling the RX, we should also start the link tuner.
|
||||
*/
|
||||
if (state == STATE_RADIO_RX_ON)
|
||||
rt2x00link_start_tuner(rt2x00dev);
|
||||
}
|
||||
|
||||
static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
@ -483,6 +468,10 @@ void rt2x00lib_rxdone(struct queue_entry *entry)
|
||||
unsigned int header_length;
|
||||
int rate_idx;
|
||||
|
||||
if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) ||
|
||||
!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
|
||||
goto submit_entry;
|
||||
|
||||
if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags))
|
||||
goto submit_entry;
|
||||
|
||||
@ -567,9 +556,13 @@ void rt2x00lib_rxdone(struct queue_entry *entry)
|
||||
entry->skb = skb;
|
||||
|
||||
submit_entry:
|
||||
rt2x00dev->ops->lib->clear_entry(entry);
|
||||
rt2x00queue_index_inc(entry->queue, Q_INDEX);
|
||||
entry->flags = 0;
|
||||
rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE);
|
||||
if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) &&
|
||||
test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) {
|
||||
rt2x00dev->ops->lib->clear_entry(entry);
|
||||
rt2x00queue_index_inc(entry->queue, Q_INDEX);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2x00lib_rxdone);
|
||||
|
||||
@ -678,7 +671,7 @@ static void rt2x00lib_rate(struct ieee80211_rate *entry,
|
||||
{
|
||||
entry->flags = 0;
|
||||
entry->bitrate = rate->bitrate;
|
||||
entry->hw_value =index;
|
||||
entry->hw_value = index;
|
||||
entry->hw_value_short = index;
|
||||
|
||||
if (rate->flags & DEV_RATE_SHORT_PREAMBLE)
|
||||
|
@ -57,7 +57,7 @@ static inline const struct rt2x00_rate *rt2x00_get_rate(const u16 hw_value)
|
||||
}
|
||||
|
||||
#define RATE_MCS(__mode, __mcs) \
|
||||
( (((__mode) & 0x00ff) << 8) | ((__mcs) & 0x00ff) )
|
||||
((((__mode) & 0x00ff) << 8) | ((__mcs) & 0x00ff))
|
||||
|
||||
static inline int rt2x00_get_rate_mcs(const u16 mcs_value)
|
||||
{
|
||||
@ -69,7 +69,6 @@ static inline int rt2x00_get_rate_mcs(const u16 mcs_value)
|
||||
*/
|
||||
int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev);
|
||||
void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev);
|
||||
void rt2x00lib_toggle_rx(struct rt2x00_dev *rt2x00dev, enum dev_state state);
|
||||
|
||||
/*
|
||||
* Initialization handlers.
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user