Merge branch 'for-davem' of ssh://master.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6

This commit is contained in:
David S. Miller 2010-12-23 10:13:30 -08:00
commit a130883d95
181 changed files with 27762 additions and 3069 deletions

View File

@ -5062,6 +5062,16 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.g
S: Maintained
F: drivers/net/wireless/rtl818x/rtl8187*
RTL8192CE WIRELESS DRIVER
M: Larry Finger <Larry.Finger@lwfinger.net>
M: Chaoming Li <chaoming_li@realsil.com.cn>
L: linux-wireless@vger.kernel.org
W: http://linuxwireless.org/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
S: Maintained
F: drivers/net/wireless/rtlwifi/
F: drivers/net/wireless/rtlwifi/rtl8192ce/
S3 SAVAGE FRAMEBUFFER DRIVER
M: Antonino Daplas <adaplas@gmail.com>
L: linux-fbdev@vger.kernel.org

View File

@ -279,6 +279,7 @@ source "drivers/net/wireless/libertas/Kconfig"
source "drivers/net/wireless/orinoco/Kconfig"
source "drivers/net/wireless/p54/Kconfig"
source "drivers/net/wireless/rt2x00/Kconfig"
source "drivers/net/wireless/rtlwifi/Kconfig"
source "drivers/net/wireless/wl1251/Kconfig"
source "drivers/net/wireless/wl12xx/Kconfig"
source "drivers/net/wireless/zd1211rw/Kconfig"

View File

@ -24,6 +24,7 @@ obj-$(CONFIG_B43LEGACY) += b43legacy/
obj-$(CONFIG_ZD1211RW) += zd1211rw/
obj-$(CONFIG_RTL8180) += rtl818x/
obj-$(CONFIG_RTL8187) += rtl818x/
obj-$(CONFIG_RTL8192CE) += rtlwifi/
# 16-bit wireless PCMCIA client drivers
obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o

View File

@ -2351,6 +2351,10 @@ ath5k_init_softc(struct ath5k_softc *sc, const struct ath_bus_ops *bus_ops)
BIT(NL80211_IFTYPE_ADHOC) |
BIT(NL80211_IFTYPE_MESH_POINT);
/* both antennas can be configured as RX or TX */
hw->wiphy->available_antennas_tx = 0x3;
hw->wiphy->available_antennas_rx = 0x3;
hw->extra_tx_headroom = 2;
hw->channel_change_time = 5000;
@ -2654,6 +2658,7 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan,
bool skip_pcu)
{
struct ath5k_hw *ah = sc->ah;
struct ath_common *common = ath5k_hw_common(ah);
int ret, ani_mode;
ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "resetting\n");
@ -2696,6 +2701,14 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan,
ah->ah_cal_next_nf = jiffies;
ewma_init(&ah->ah_beacon_rssi_avg, 1024, 8);
/* clear survey data and cycle counters */
memset(&sc->survey, 0, sizeof(sc->survey));
spin_lock(&common->cc_lock);
ath_hw_cycle_counters_update(common);
memset(&common->cc_survey, 0, sizeof(common->cc_survey));
memset(&common->cc_ani, 0, sizeof(common->cc_ani));
spin_unlock(&common->cc_lock);
/*
* Change channels and update the h/w rate map if we're switching;
* e.g. 11a to 11b/g.
@ -3362,25 +3375,27 @@ static int ath5k_get_survey(struct ieee80211_hw *hw, int idx,
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;
sc->survey.channel_time += cc->cycles / div;
sc->survey.channel_time_busy += cc->rx_busy / div;
sc->survey.channel_time_rx += cc->rx_frame / div;
sc->survey.channel_time_tx += cc->tx_frame / div;
}
memset(cc, 0, sizeof(*cc));
spin_unlock_bh(&common->cc_lock);
memcpy(survey, &sc->survey, sizeof(*survey));
survey->channel = conf->channel;
survey->noise = sc->ah->ah_noise_floor;
survey->filled = SURVEY_INFO_NOISE_DBM |
SURVEY_INFO_CHANNEL_TIME |
SURVEY_INFO_CHANNEL_TIME_BUSY |
SURVEY_INFO_CHANNEL_TIME_RX |
SURVEY_INFO_CHANNEL_TIME_TX;
return 0;
}

View File

@ -258,6 +258,8 @@ struct ath5k_softc {
struct tasklet_struct ani_tasklet; /* ANI calibration */
struct delayed_work tx_complete_work;
struct survey_info survey; /* collected survey info */
};
#define ath5k_hw_hasbssidmask(_ah) \

View File

@ -961,18 +961,6 @@ static void ar5008_hw_rfbus_done(struct ath_hw *ah)
REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0);
}
static void ar5008_hw_enable_rfkill(struct ath_hw *ah)
{
REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL,
AR_GPIO_INPUT_EN_VAL_RFSILENT_BB);
REG_CLR_BIT(ah, AR_GPIO_INPUT_MUX2,
AR_GPIO_INPUT_MUX2_RFSILENT);
ath9k_hw_cfg_gpio_input(ah, ah->rfkill_gpio);
REG_SET_BIT(ah, AR_PHY_TEST, RFSILENT_BB);
}
static void ar5008_restore_chainmask(struct ath_hw *ah)
{
int rx_chainmask = ah->rxchainmask;
@ -1629,7 +1617,6 @@ void ar5008_hw_attach_phy_ops(struct ath_hw *ah)
priv_ops->set_delta_slope = ar5008_hw_set_delta_slope;
priv_ops->rfbus_req = ar5008_hw_rfbus_req;
priv_ops->rfbus_done = ar5008_hw_rfbus_done;
priv_ops->enable_rfkill = ar5008_hw_enable_rfkill;
priv_ops->restore_chainmask = ar5008_restore_chainmask;
priv_ops->set_diversity = ar5008_set_diversity;
priv_ops->do_getnf = ar5008_hw_do_getnf;

View File

@ -26,24 +26,6 @@ MODULE_PARM_DESC(nohwcrypt, "Force new ANI for AR5008, AR9001, AR9002");
/* General hardware code for the A5008/AR9001/AR9002 hadware families */
static bool ar9002_hw_macversion_supported(u32 macversion)
{
switch (macversion) {
case AR_SREV_VERSION_5416_PCI:
case AR_SREV_VERSION_5416_PCIE:
case AR_SREV_VERSION_9160:
case AR_SREV_VERSION_9100:
case AR_SREV_VERSION_9280:
case AR_SREV_VERSION_9285:
case AR_SREV_VERSION_9287:
case AR_SREV_VERSION_9271:
return true;
default:
break;
}
return false;
}
static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
{
if (AR_SREV_9271(ah)) {
@ -565,7 +547,6 @@ void ar9002_hw_attach_ops(struct ath_hw *ah)
priv_ops->init_mode_regs = ar9002_hw_init_mode_regs;
priv_ops->init_mode_gain_regs = ar9002_hw_init_mode_gain_regs;
priv_ops->macversion_supported = ar9002_hw_macversion_supported;
ops->config_pci_powersave = ar9002_hw_configpcipowersave;

View File

@ -283,7 +283,6 @@ static void ar9002_hw_set11n_txdesc(struct ath_hw *ah, void *ds,
{
struct ar5416_desc *ads = AR5416DESC(ds);
txPower += ah->txpower_indexoffset;
if (txPower > 63)
txPower = 63;

View File

@ -34,9 +34,9 @@ static const u32 ar9300_2p2_radio_postamble[][5] = {
static const u32 ar9300Modes_lowest_ob_db_tx_gain_table_2p2[][5] = {
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
{0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800},
{0x0000a2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000},
{0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000},
{0x0000a2dc, 0x00033800, 0x00033800, 0x00637800, 0x00637800},
{0x0000a2e0, 0x0003c000, 0x0003c000, 0x03838000, 0x03838000},
{0x0000a2e4, 0x03fc0000, 0x03fc0000, 0x03fc0000, 0x03fc0000},
{0x0000a2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
{0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
@ -56,21 +56,21 @@ static const u32 ar9300Modes_lowest_ob_db_tx_gain_table_2p2[][5] = {
{0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24},
{0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640},
{0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660},
{0x0000a544, 0x5302266c, 0x5302266c, 0x3f001861, 0x3f001861},
{0x0000a548, 0x5702286c, 0x5702286c, 0x43001a81, 0x43001a81},
{0x0000a54c, 0x5c02486b, 0x5c02486b, 0x47001a83, 0x47001a83},
{0x0000a550, 0x61024a6c, 0x61024a6c, 0x4a001c84, 0x4a001c84},
{0x0000a554, 0x66026a6c, 0x66026a6c, 0x4e001ce3, 0x4e001ce3},
{0x0000a558, 0x6b026e6c, 0x6b026e6c, 0x52001ce5, 0x52001ce5},
{0x0000a55c, 0x7002708c, 0x7002708c, 0x56001ce9, 0x56001ce9},
{0x0000a560, 0x7302b08a, 0x7302b08a, 0x5a001ceb, 0x5a001ceb},
{0x0000a564, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
{0x0000a568, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
{0x0000a56c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
{0x0000a570, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
{0x0000a574, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
{0x0000a578, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
{0x0000a57c, 0x7702b08c, 0x7702b08c, 0x5d001eec, 0x5d001eec},
{0x0000a544, 0x52022470, 0x52022470, 0x3f001861, 0x3f001861},
{0x0000a548, 0x55022490, 0x55022490, 0x43001a81, 0x43001a81},
{0x0000a54c, 0x59022492, 0x59022492, 0x47001a83, 0x47001a83},
{0x0000a550, 0x5d022692, 0x5d022692, 0x4a001c84, 0x4a001c84},
{0x0000a554, 0x61022892, 0x61022892, 0x4e001ce3, 0x4e001ce3},
{0x0000a558, 0x65024890, 0x65024890, 0x52001ce5, 0x52001ce5},
{0x0000a55c, 0x69024892, 0x69024892, 0x56001ce9, 0x56001ce9},
{0x0000a560, 0x6e024c92, 0x6e024c92, 0x5a001ceb, 0x5a001ceb},
{0x0000a564, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
{0x0000a568, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
{0x0000a56c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
{0x0000a570, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
{0x0000a574, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
{0x0000a578, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
{0x0000a57c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
{0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000},
{0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002},
{0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004},
@ -88,44 +88,44 @@ static const u32 ar9300Modes_lowest_ob_db_tx_gain_table_2p2[][5] = {
{0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24},
{0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640},
{0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660},
{0x0000a5c4, 0x5382266c, 0x5382266c, 0x3f801861, 0x3f801861},
{0x0000a5c8, 0x5782286c, 0x5782286c, 0x43801a81, 0x43801a81},
{0x0000a5cc, 0x5c82486b, 0x5c82486b, 0x47801a83, 0x47801a83},
{0x0000a5d0, 0x61824a6c, 0x61824a6c, 0x4a801c84, 0x4a801c84},
{0x0000a5d4, 0x66826a6c, 0x66826a6c, 0x4e801ce3, 0x4e801ce3},
{0x0000a5d8, 0x6b826e6c, 0x6b826e6c, 0x52801ce5, 0x52801ce5},
{0x0000a5dc, 0x7082708c, 0x7082708c, 0x56801ce9, 0x56801ce9},
{0x0000a5e0, 0x7382b08a, 0x7382b08a, 0x5a801ceb, 0x5a801ceb},
{0x0000a5e4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
{0x0000a5e8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
{0x0000a5ec, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
{0x0000a5f0, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
{0x0000a5f4, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
{0x0000a5f8, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
{0x0000a5fc, 0x7782b08c, 0x7782b08c, 0x5d801eec, 0x5d801eec},
{0x0000a5c4, 0x52822470, 0x52822470, 0x3f801861, 0x3f801861},
{0x0000a5c8, 0x55822490, 0x55822490, 0x43801a81, 0x43801a81},
{0x0000a5cc, 0x59822492, 0x59822492, 0x47801a83, 0x47801a83},
{0x0000a5d0, 0x5d822692, 0x5d822692, 0x4a801c84, 0x4a801c84},
{0x0000a5d4, 0x61822892, 0x61822892, 0x4e801ce3, 0x4e801ce3},
{0x0000a5d8, 0x65824890, 0x65824890, 0x52801ce5, 0x52801ce5},
{0x0000a5dc, 0x69824892, 0x69824892, 0x56801ce9, 0x56801ce9},
{0x0000a5e0, 0x6e824c92, 0x6e824c92, 0x5a801ceb, 0x5a801ceb},
{0x0000a5e4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
{0x0000a5e8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
{0x0000a5ec, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
{0x0000a5f0, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
{0x0000a5f4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
{0x0000a5f8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
{0x0000a5fc, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
{0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a614, 0x01404000, 0x01404000, 0x01404000, 0x01404000},
{0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501},
{0x0000a61c, 0x02008802, 0x02008802, 0x02008501, 0x02008501},
{0x0000a620, 0x0300cc03, 0x0300cc03, 0x0280ca03, 0x0280ca03},
{0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04},
{0x0000a628, 0x0300cc03, 0x0300cc03, 0x04014c04, 0x04014c04},
{0x0000a62c, 0x03810c03, 0x03810c03, 0x04015005, 0x04015005},
{0x0000a630, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
{0x0000a634, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
{0x0000a638, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
{0x0000a63c, 0x03810e04, 0x03810e04, 0x04015005, 0x04015005},
{0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800},
{0x0000b2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000},
{0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000},
{0x0000a614, 0x02004000, 0x02004000, 0x01404000, 0x01404000},
{0x0000a618, 0x02004801, 0x02004801, 0x01404501, 0x01404501},
{0x0000a61c, 0x02808a02, 0x02808a02, 0x02008501, 0x02008501},
{0x0000a620, 0x0380ce03, 0x0380ce03, 0x0280ca03, 0x0280ca03},
{0x0000a624, 0x04411104, 0x04411104, 0x03010c04, 0x03010c04},
{0x0000a628, 0x04411104, 0x04411104, 0x04014c04, 0x04014c04},
{0x0000a62c, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
{0x0000a630, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
{0x0000a634, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
{0x0000a638, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
{0x0000a63c, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
{0x0000b2dc, 0x00033800, 0x00033800, 0x00637800, 0x00637800},
{0x0000b2e0, 0x0003c000, 0x0003c000, 0x03838000, 0x03838000},
{0x0000b2e4, 0x03fc0000, 0x03fc0000, 0x03fc0000, 0x03fc0000},
{0x0000b2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x00637800, 0x00637800},
{0x0000c2e0, 0x0000f800, 0x0000f800, 0x03838000, 0x03838000},
{0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03fc0000, 0x03fc0000},
{0x0000c2dc, 0x00033800, 0x00033800, 0x00637800, 0x00637800},
{0x0000c2e0, 0x0003c000, 0x0003c000, 0x03838000, 0x03838000},
{0x0000c2e4, 0x03fc0000, 0x03fc0000, 0x03fc0000, 0x03fc0000},
{0x0000c2e8, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
{0x00016048, 0x62480001, 0x62480001, 0x62480001, 0x62480001},
@ -638,6 +638,7 @@ static const u32 ar9300_2p2_baseband_postamble[][5] = {
{0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
{0x0000a204, 0x000037c0, 0x000037c4, 0x000037c4, 0x000037c0},
{0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004},
{0x0000a22c, 0x01026a2f, 0x01026a2f, 0x01026a2f, 0x01026a2f},
{0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
{0x0000a234, 0x00000fff, 0x10000fff, 0x10000fff, 0x00000fff},
{0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018},
@ -680,7 +681,7 @@ static const u32 ar9300_2p2_baseband_core[][2] = {
{0x0000981c, 0x00020028},
{0x00009834, 0x6400a290},
{0x00009838, 0x0108ecff},
{0x0000983c, 0x14750600},
{0x0000983c, 0x0d000600},
{0x00009880, 0x201fff00},
{0x00009884, 0x00001042},
{0x000098a4, 0x00200400},
@ -722,7 +723,6 @@ static const u32 ar9300_2p2_baseband_core[][2] = {
{0x0000a220, 0x00000000},
{0x0000a224, 0x00000000},
{0x0000a228, 0x10002310},
{0x0000a22c, 0x01036a27},
{0x0000a23c, 0x00000000},
{0x0000a244, 0x0c000000},
{0x0000a2a0, 0x00000001},

View File

@ -608,120 +608,6 @@ static bool ar9003_hw_calc_iq_corr(struct ath_hw *ah,
return true;
}
static void ar9003_hw_tx_iq_cal(struct ath_hw *ah)
{
struct ath_common *common = ath9k_hw_common(ah);
static const u32 txiqcal_status[AR9300_MAX_CHAINS] = {
AR_PHY_TX_IQCAL_STATUS_B0,
AR_PHY_TX_IQCAL_STATUS_B1,
AR_PHY_TX_IQCAL_STATUS_B2,
};
static const u32 rx_corr[AR9300_MAX_CHAINS] = {
AR_PHY_RX_IQCAL_CORR_B0,
AR_PHY_RX_IQCAL_CORR_B1,
AR_PHY_RX_IQCAL_CORR_B2,
};
static const u_int32_t chan_info_tab[] = {
AR_PHY_CHAN_INFO_TAB_0,
AR_PHY_CHAN_INFO_TAB_1,
AR_PHY_CHAN_INFO_TAB_2,
};
u32 tx_corr_coeff[AR9300_MAX_CHAINS];
s32 iq_res[6];
s32 iqc_coeff[2];
s32 i, j;
u32 num_chains = 0;
tx_corr_coeff[0] = AR_PHY_TX_IQCAL_CORR_COEFF_B0(0);
tx_corr_coeff[1] = AR_PHY_TX_IQCAL_CORR_COEFF_B1(0);
tx_corr_coeff[2] = AR_PHY_TX_IQCAL_CORR_COEFF_B2(0);
for (i = 0; i < AR9300_MAX_CHAINS; i++) {
if (ah->txchainmask & (1 << i))
num_chains++;
}
REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1,
AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT,
DELPT);
REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START,
AR_PHY_TX_IQCAL_START_DO_CAL,
AR_PHY_TX_IQCAL_START_DO_CAL);
if (!ath9k_hw_wait(ah, AR_PHY_TX_IQCAL_START,
AR_PHY_TX_IQCAL_START_DO_CAL,
0, AH_WAIT_TIMEOUT)) {
ath_dbg(common, ATH_DBG_CALIBRATE,
"Tx IQ Cal not complete.\n");
goto TX_IQ_CAL_FAILED;
}
for (i = 0; i < num_chains; i++) {
ath_dbg(common, ATH_DBG_CALIBRATE,
"Doing Tx IQ Cal for chain %d.\n", i);
if (REG_READ(ah, txiqcal_status[i]) &
AR_PHY_TX_IQCAL_STATUS_FAILED) {
ath_dbg(common, ATH_DBG_CALIBRATE,
"Tx IQ Cal failed for chain %d.\n", i);
goto TX_IQ_CAL_FAILED;
}
for (j = 0; j < 3; j++) {
u_int8_t idx = 2 * j,
offset = 4 * j;
REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY,
AR_PHY_CHAN_INFO_TAB_S2_READ, 0);
/* 32 bits */
iq_res[idx] = REG_READ(ah, chan_info_tab[i] + offset);
REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY,
AR_PHY_CHAN_INFO_TAB_S2_READ, 1);
/* 16 bits */
iq_res[idx+1] = 0xffff & REG_READ(ah,
chan_info_tab[i] +
offset);
ath_dbg(common, ATH_DBG_CALIBRATE,
"IQ RES[%d]=0x%x IQ_RES[%d]=0x%x\n",
idx, iq_res[idx], idx+1, iq_res[idx+1]);
}
if (!ar9003_hw_calc_iq_corr(ah, i, iq_res, iqc_coeff)) {
ath_dbg(common, ATH_DBG_CALIBRATE,
"Failed in calculation of IQ correction.\n");
goto TX_IQ_CAL_FAILED;
}
ath_dbg(common, ATH_DBG_CALIBRATE,
"IQ_COEFF[0] = 0x%x IQ_COEFF[1] = 0x%x\n",
iqc_coeff[0], iqc_coeff[1]);
REG_RMW_FIELD(ah, tx_corr_coeff[i],
AR_PHY_TX_IQCAL_CORR_COEFF_01_COEFF_TABLE,
iqc_coeff[0]);
REG_RMW_FIELD(ah, rx_corr[i],
AR_PHY_RX_IQCAL_CORR_LOOPBACK_IQCORR_Q_Q_COFF,
iqc_coeff[1] >> 7);
REG_RMW_FIELD(ah, rx_corr[i],
AR_PHY_RX_IQCAL_CORR_LOOPBACK_IQCORR_Q_I_COFF,
iqc_coeff[1]);
}
REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_3,
AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN, 0x1);
REG_RMW_FIELD(ah, AR_PHY_RX_IQCAL_CORR_B0,
AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x1);
return;
TX_IQ_CAL_FAILED:
ath_dbg(common, ATH_DBG_CALIBRATE, "Tx IQ Cal failed\n");
}
static bool ar9003_hw_compute_closest_pass_and_avg(int *mp_coeff, int *mp_avg)
{
int diff[MPASS];
@ -730,9 +616,9 @@ static bool ar9003_hw_compute_closest_pass_and_avg(int *mp_coeff, int *mp_avg)
diff[1] = abs(mp_coeff[1] - mp_coeff[2]);
diff[2] = abs(mp_coeff[2] - mp_coeff[0]);
if (diff[0] > MAX_MEASUREMENT &&
diff[1] > MAX_MEASUREMENT &&
diff[2] > MAX_MEASUREMENT)
if (diff[0] > MAX_DIFFERENCE &&
diff[1] > MAX_DIFFERENCE &&
diff[2] > MAX_DIFFERENCE)
return false;
if (diff[0] <= diff[1] && diff[0] <= diff[2])
@ -830,6 +716,111 @@ disable_txiqcal:
ath_dbg(common, ATH_DBG_CALIBRATE, "TX IQ Cal disabled\n");
}
static void ar9003_hw_tx_iq_cal(struct ath_hw *ah)
{
struct ath_common *common = ath9k_hw_common(ah);
static const u32 txiqcal_status[AR9300_MAX_CHAINS] = {
AR_PHY_TX_IQCAL_STATUS_B0,
AR_PHY_TX_IQCAL_STATUS_B1,
AR_PHY_TX_IQCAL_STATUS_B2,
};
static const u32 chan_info_tab[] = {
AR_PHY_CHAN_INFO_TAB_0,
AR_PHY_CHAN_INFO_TAB_1,
AR_PHY_CHAN_INFO_TAB_2,
};
struct coeff coeff;
s32 iq_res[6];
s32 i, j, ip, im, nmeasurement;
u8 nchains = get_streams(common->tx_chainmask);
for (ip = 0; ip < MPASS; ip++) {
REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1,
AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT,
DELPT);
REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START,
AR_PHY_TX_IQCAL_START_DO_CAL,
AR_PHY_TX_IQCAL_START_DO_CAL);
if (!ath9k_hw_wait(ah, AR_PHY_TX_IQCAL_START,
AR_PHY_TX_IQCAL_START_DO_CAL,
0, AH_WAIT_TIMEOUT)) {
ath_dbg(common, ATH_DBG_CALIBRATE,
"Tx IQ Cal not complete.\n");
goto TX_IQ_CAL_FAILED;
}
nmeasurement = REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_STATUS_B0,
AR_PHY_CALIBRATED_GAINS_0);
if (nmeasurement > MAX_MEASUREMENT)
nmeasurement = MAX_MEASUREMENT;
for (i = 0; i < nchains; i++) {
ath_dbg(common, ATH_DBG_CALIBRATE,
"Doing Tx IQ Cal for chain %d.\n", i);
for (im = 0; im < nmeasurement; im++) {
if (REG_READ(ah, txiqcal_status[i]) &
AR_PHY_TX_IQCAL_STATUS_FAILED) {
ath_dbg(common, ATH_DBG_CALIBRATE,
"Tx IQ Cal failed for chain %d.\n", i);
goto TX_IQ_CAL_FAILED;
}
for (j = 0; j < 3; j++) {
u8 idx = 2 * j,
offset = 4 * (3 * im + j);
REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY,
AR_PHY_CHAN_INFO_TAB_S2_READ,
0);
/* 32 bits */
iq_res[idx] = REG_READ(ah,
chan_info_tab[i] +
offset);
REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY,
AR_PHY_CHAN_INFO_TAB_S2_READ,
1);
/* 16 bits */
iq_res[idx+1] = 0xffff & REG_READ(ah,
chan_info_tab[i] +
offset);
ath_dbg(common, ATH_DBG_CALIBRATE,
"IQ RES[%d]=0x%x IQ_RES[%d]=0x%x\n",
idx, iq_res[idx], idx+1, iq_res[idx+1]);
}
if (!ar9003_hw_calc_iq_corr(ah, i, iq_res,
coeff.iqc_coeff)) {
ath_dbg(common, ATH_DBG_CALIBRATE,
"Failed in calculation of IQ correction.\n");
goto TX_IQ_CAL_FAILED;
}
coeff.mag_coeff[i][im][ip] =
coeff.iqc_coeff[0] & 0x7f;
coeff.phs_coeff[i][im][ip] =
(coeff.iqc_coeff[0] >> 7) & 0x7f;
if (coeff.mag_coeff[i][im][ip] > 63)
coeff.mag_coeff[i][im][ip] -= 128;
if (coeff.phs_coeff[i][im][ip] > 63)
coeff.phs_coeff[i][im][ip] -= 128;
}
}
}
ar9003_hw_tx_iqcal_load_avg_2_passes(ah, nchains, &coeff);
return;
TX_IQ_CAL_FAILED:
ath_dbg(common, ATH_DBG_CALIBRATE, "Tx IQ Cal failed\n");
}
static void ar9003_hw_tx_iq_cal_run(struct ath_hw *ah)
{
u8 tx_gain_forced;

View File

@ -73,7 +73,7 @@ static const struct ar9300_eeprom ar9300_default = {
.regDmn = { LE16(0), LE16(0x1f) },
.txrxMask = 0x77, /* 4 bits tx and 4 bits rx */
.opCapFlags = {
.opFlags = AR9300_OPFLAGS_11G | AR9300_OPFLAGS_11A,
.opFlags = AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A,
.eepMisc = 0,
},
.rfSilent = 0,
@ -650,7 +650,7 @@ static const struct ar9300_eeprom ar9300_x113 = {
.regDmn = { LE16(0), LE16(0x1f) },
.txrxMask = 0x77, /* 4 bits tx and 4 bits rx */
.opCapFlags = {
.opFlags = AR9300_OPFLAGS_11G | AR9300_OPFLAGS_11A,
.opFlags = AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A,
.eepMisc = 0,
},
.rfSilent = 0,
@ -1228,7 +1228,7 @@ static const struct ar9300_eeprom ar9300_h112 = {
.regDmn = { LE16(0), LE16(0x1f) },
.txrxMask = 0x77, /* 4 bits tx and 4 bits rx */
.opCapFlags = {
.opFlags = AR9300_OPFLAGS_11G | AR9300_OPFLAGS_11A,
.opFlags = AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A,
.eepMisc = 0,
},
.rfSilent = 0,
@ -1806,7 +1806,7 @@ static const struct ar9300_eeprom ar9300_x112 = {
.regDmn = { LE16(0), LE16(0x1f) },
.txrxMask = 0x77, /* 4 bits tx and 4 bits rx */
.opCapFlags = {
.opFlags = AR9300_OPFLAGS_11G | AR9300_OPFLAGS_11A,
.opFlags = AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A,
.eepMisc = 0,
},
.rfSilent = 0,
@ -2383,7 +2383,7 @@ static const struct ar9300_eeprom ar9300_h116 = {
.regDmn = { LE16(0), LE16(0x1f) },
.txrxMask = 0x33, /* 4 bits tx and 4 bits rx */
.opCapFlags = {
.opFlags = AR9300_OPFLAGS_11G | AR9300_OPFLAGS_11A,
.opFlags = AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A,
.eepMisc = 0,
},
.rfSilent = 0,
@ -2975,7 +2975,7 @@ static const struct ar9300_eeprom *ar9003_eeprom_struct_find_by_id(int id)
static u16 ath9k_hw_fbin2freq(u8 fbin, bool is2GHz)
{
if (fbin == AR9300_BCHAN_UNUSED)
if (fbin == AR5416_BCHAN_UNUSED)
return fbin;
return (u16) ((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin));
@ -3428,18 +3428,6 @@ static int ath9k_hw_ar9300_get_eeprom_rev(struct ath_hw *ah)
return 0;
}
static u8 ath9k_hw_ar9300_get_num_ant_config(struct ath_hw *ah,
enum ath9k_hal_freq_band freq_band)
{
return 1;
}
static u32 ath9k_hw_ar9300_get_eeprom_antenna_cfg(struct ath_hw *ah,
struct ath9k_channel *chan)
{
return -EINVAL;
}
static s32 ar9003_hw_xpa_bias_level_get(struct ath_hw *ah, bool is2ghz)
{
struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
@ -4486,7 +4474,7 @@ static u16 ar9003_hw_get_indirect_edge_power(struct ar9300_eeprom *eep,
return CTL_EDGE_TPOWER(ctl_5g[idx].ctlEdges[edge - 1]);
}
return AR9300_MAX_RATE_POWER;
return MAX_RATE_POWER;
}
/*
@ -4495,7 +4483,7 @@ static u16 ar9003_hw_get_indirect_edge_power(struct ar9300_eeprom *eep,
static u16 ar9003_hw_get_max_edge_power(struct ar9300_eeprom *eep,
u16 freq, int idx, bool is2GHz)
{
u16 twiceMaxEdgePower = AR9300_MAX_RATE_POWER;
u16 twiceMaxEdgePower = MAX_RATE_POWER;
u8 *ctl_freqbin = is2GHz ?
&eep->ctl_freqbin_2G[idx][0] :
&eep->ctl_freqbin_5G[idx][0];
@ -4505,7 +4493,7 @@ static u16 ar9003_hw_get_max_edge_power(struct ar9300_eeprom *eep,
/* Get the edge power */
for (edge = 0;
(edge < num_edges) && (ctl_freqbin[edge] != AR9300_BCHAN_UNUSED);
(edge < num_edges) && (ctl_freqbin[edge] != AR5416_BCHAN_UNUSED);
edge++) {
/*
* If there's an exact channel match or an inband flag set
@ -4543,9 +4531,9 @@ static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah,
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
struct ath_common *common = ath9k_hw_common(ah);
struct ar9300_eeprom *pEepData = &ah->eeprom.ar9300_eep;
u16 twiceMaxEdgePower = AR9300_MAX_RATE_POWER;
u16 twiceMaxEdgePower = MAX_RATE_POWER;
static const u16 tpScaleReductionTable[5] = {
0, 3, 6, 9, AR9300_MAX_RATE_POWER
0, 3, 6, 9, MAX_RATE_POWER
};
int i;
int16_t twiceLargestAntenna;
@ -4756,6 +4744,16 @@ static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah,
} /* end ctl mode checking */
}
static inline u8 mcsidx_to_tgtpwridx(unsigned int mcs_idx, u8 base_pwridx)
{
u8 mod_idx = mcs_idx % 8;
if (mod_idx <= 3)
return mod_idx ? (base_pwridx + 1) : base_pwridx;
else
return base_pwridx + 4 * (mcs_idx / 8) + mod_idx - 2;
}
static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
struct ath9k_channel *chan, u16 cfgCtl,
u8 twiceAntennaReduction,
@ -4764,16 +4762,70 @@ static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
{
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
struct ath_common *common = ath9k_hw_common(ah);
struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
struct ar9300_modal_eep_header *modal_hdr;
u8 targetPowerValT2[ar9300RateSize];
unsigned int i = 0;
u8 target_power_val_t2_eep[ar9300RateSize];
unsigned int i = 0, paprd_scale_factor = 0;
u8 pwr_idx, min_pwridx = 0;
ar9003_hw_set_target_power_eeprom(ah, chan->channel, targetPowerValT2);
if (ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) {
if (IS_CHAN_2GHZ(chan))
modal_hdr = &eep->modalHeader2G;
else
modal_hdr = &eep->modalHeader5G;
ah->paprd_ratemask =
le32_to_cpu(modal_hdr->papdRateMaskHt20) &
AR9300_PAPRD_RATE_MASK;
ah->paprd_ratemask_ht40 =
le32_to_cpu(modal_hdr->papdRateMaskHt40) &
AR9300_PAPRD_RATE_MASK;
paprd_scale_factor = ar9003_get_paprd_scale_factor(ah, chan);
min_pwridx = IS_CHAN_HT40(chan) ? ALL_TARGET_HT40_0_8_16 :
ALL_TARGET_HT20_0_8_16;
if (!ah->paprd_table_write_done) {
memcpy(target_power_val_t2_eep, targetPowerValT2,
sizeof(targetPowerValT2));
for (i = 0; i < 24; i++) {
pwr_idx = mcsidx_to_tgtpwridx(i, min_pwridx);
if (ah->paprd_ratemask & (1 << i)) {
if (targetPowerValT2[pwr_idx] &&
targetPowerValT2[pwr_idx] ==
target_power_val_t2_eep[pwr_idx])
targetPowerValT2[pwr_idx] -=
paprd_scale_factor;
}
}
}
memcpy(target_power_val_t2_eep, targetPowerValT2,
sizeof(targetPowerValT2));
}
ar9003_hw_set_power_per_rate_table(ah, chan,
targetPowerValT2, cfgCtl,
twiceAntennaReduction,
twiceMaxRegulatoryPower,
powerLimit);
if (ah->eep_ops->get_eeprom(ah, EEP_PAPRD)) {
for (i = 0; i < ar9300RateSize; i++) {
if ((ah->paprd_ratemask & (1 << i)) &&
(abs(targetPowerValT2[i] -
target_power_val_t2_eep[i]) >
paprd_scale_factor)) {
ah->paprd_ratemask &= ~(1 << i);
ath_dbg(common, ATH_DBG_EEPROM,
"paprd disabled for mcs %d\n", i);
}
}
}
regulatory->max_power_level = 0;
for (i = 0; i < ar9300RateSize; i++) {
if (targetPowerValT2[i] > regulatory->max_power_level)
@ -4811,6 +4863,19 @@ static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
/* Write target power array to registers */
ar9003_hw_tx_power_regwrite(ah, targetPowerValT2);
ar9003_hw_calibration_apply(ah, chan->channel);
if (IS_CHAN_2GHZ(chan)) {
if (IS_CHAN_HT40(chan))
i = ALL_TARGET_HT40_0_8_16;
else
i = ALL_TARGET_HT20_0_8_16;
} else {
if (IS_CHAN_HT40(chan))
i = ALL_TARGET_HT40_7;
else
i = ALL_TARGET_HT20_7;
}
ah->paprd_target_power = targetPowerValT2[i];
}
static u16 ath9k_hw_ar9300_get_spur_channel(struct ath_hw *ah,
@ -4843,14 +4908,33 @@ u8 *ar9003_get_spur_chan_ptr(struct ath_hw *ah, bool is_2ghz)
return eep->modalHeader5G.spurChans;
}
unsigned int ar9003_get_paprd_scale_factor(struct ath_hw *ah,
struct ath9k_channel *chan)
{
struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
if (IS_CHAN_2GHZ(chan))
return MS(le32_to_cpu(eep->modalHeader2G.papdRateMaskHt20),
AR9300_PAPRD_SCALE_1);
else {
if (chan->channel >= 5700)
return MS(le32_to_cpu(eep->modalHeader5G.papdRateMaskHt20),
AR9300_PAPRD_SCALE_1);
else if (chan->channel >= 5400)
return MS(le32_to_cpu(eep->modalHeader5G.papdRateMaskHt40),
AR9300_PAPRD_SCALE_2);
else
return MS(le32_to_cpu(eep->modalHeader5G.papdRateMaskHt40),
AR9300_PAPRD_SCALE_1);
}
}
const struct eeprom_ops eep_ar9300_ops = {
.check_eeprom = ath9k_hw_ar9300_check_eeprom,
.get_eeprom = ath9k_hw_ar9300_get_eeprom,
.fill_eeprom = ath9k_hw_ar9300_fill_eeprom,
.get_eeprom_ver = ath9k_hw_ar9300_get_eeprom_ver,
.get_eeprom_rev = ath9k_hw_ar9300_get_eeprom_rev,
.get_num_ant_config = ath9k_hw_ar9300_get_num_ant_config,
.get_eeprom_antenna_cfg = ath9k_hw_ar9300_get_eeprom_antenna_cfg,
.set_board_values = ath9k_hw_ar9300_set_board_values,
.set_addac = ath9k_hw_ar9300_set_addac,
.set_txpower = ath9k_hw_ar9300_set_txpower,

View File

@ -20,47 +20,22 @@
/* #define AR9300_NUM_CTLS 21 */
#define AR9300_NUM_CTLS_5G 9
#define AR9300_NUM_CTLS_2G 12
#define AR9300_CTL_MODE_M 0xF
#define AR9300_NUM_BAND_EDGES_5G 8
#define AR9300_NUM_BAND_EDGES_2G 4
#define AR9300_NUM_PD_GAINS 4
#define AR9300_PD_GAINS_IN_MASK 4
#define AR9300_PD_GAIN_ICEPTS 5
#define AR9300_EEPROM_MODAL_SPURS 5
#define AR9300_MAX_RATE_POWER 63
#define AR9300_NUM_PDADC_VALUES 128
#define AR9300_NUM_RATES 16
#define AR9300_BCHAN_UNUSED 0xFF
#define AR9300_MAX_PWR_RANGE_IN_HALF_DB 64
#define AR9300_OPFLAGS_11A 0x01
#define AR9300_OPFLAGS_11G 0x02
#define AR9300_OPFLAGS_5G_HT40 0x04
#define AR9300_OPFLAGS_2G_HT40 0x08
#define AR9300_OPFLAGS_5G_HT20 0x10
#define AR9300_OPFLAGS_2G_HT20 0x20
#define AR9300_EEPMISC_BIG_ENDIAN 0x01
#define AR9300_EEPMISC_WOW 0x02
#define AR9300_CUSTOMER_DATA_SIZE 20
#define FREQ2FBIN(x, y) ((y) ? ((x) - 2300) : (((x) - 4800) / 5))
#define FBIN2FREQ(x, y) ((y) ? (2300 + x) : (4800 + 5 * x))
#define AR9300_MAX_CHAINS 3
#define AR9300_ANT_16S 25
#define AR9300_FUTURE_MODAL_SZ 6
#define AR9300_NUM_ANT_CHAIN_FIELDS 7
#define AR9300_NUM_ANT_COMMON_FIELDS 4
#define AR9300_SIZE_ANT_CHAIN_FIELD 3
#define AR9300_SIZE_ANT_COMMON_FIELD 4
#define AR9300_ANT_CHAIN_MASK 0x7
#define AR9300_ANT_COMMON_MASK 0xf
#define AR9300_CHAIN_0_IDX 0
#define AR9300_CHAIN_1_IDX 1
#define AR9300_CHAIN_2_IDX 2
#define AR928X_NUM_ANT_CHAIN_FIELDS 6
#define AR928X_SIZE_ANT_CHAIN_FIELD 2
#define AR928X_ANT_CHAIN_MASK 0x3
#define AR9300_PAPRD_RATE_MASK 0x01ffffff
#define AR9300_PAPRD_SCALE_1 0x0e000000
#define AR9300_PAPRD_SCALE_1_S 25
#define AR9300_PAPRD_SCALE_2 0x70000000
#define AR9300_PAPRD_SCALE_2_S 28
/* Delta from which to start power to pdadc table */
/* This offset is used in both open loop and closed loop power control
@ -71,12 +46,8 @@
*/
#define AR9300_PWR_TABLE_OFFSET 0
/* enable flags for voltage and temp compensation */
#define ENABLE_TEMP_COMPENSATION 0x01
#define ENABLE_VOLT_COMPENSATION 0x02
/* byte addressable */
#define AR9300_EEPROM_SIZE (16*1024)
#define FIXED_CCA_THRESHOLD 15
#define AR9300_BASE_ADDR_4K 0xfff
#define AR9300_BASE_ADDR 0x3ff
@ -226,7 +197,7 @@ struct ar9300_modal_eep_header {
int8_t tempSlope;
int8_t voltSlope;
/* spur channels in usual fbin coding format */
u8 spurChans[AR9300_EEPROM_MODAL_SPURS];
u8 spurChans[AR_EEPROM_MODAL_SPURS];
/* 3 Check if the register is per chain */
int8_t noiseFloorThreshCh[AR9300_MAX_CHAINS];
u8 ob[AR9300_MAX_CHAINS];
@ -344,4 +315,7 @@ s32 ar9003_hw_get_tx_gain_idx(struct ath_hw *ah);
s32 ar9003_hw_get_rx_gain_idx(struct ath_hw *ah);
u8 *ar9003_get_spur_chan_ptr(struct ath_hw *ah, bool is_2ghz);
unsigned int ar9003_get_paprd_scale_factor(struct ath_hw *ah,
struct ath9k_channel *chan);
#endif

View File

@ -21,18 +21,6 @@
/* General hardware code for the AR9003 hadware family */
static bool ar9003_hw_macversion_supported(u32 macversion)
{
switch (macversion) {
case AR_SREV_VERSION_9300:
case AR_SREV_VERSION_9485:
return true;
default:
break;
}
return false;
}
/*
* The AR9003 family uses a new INI format (pre, core, post
* arrays per subsystem). This provides support for the
@ -322,7 +310,6 @@ void ar9003_hw_attach_ops(struct ath_hw *ah)
priv_ops->init_mode_regs = ar9003_hw_init_mode_regs;
priv_ops->init_mode_gain_regs = ar9003_hw_init_mode_gain_regs;
priv_ops->macversion_supported = ar9003_hw_macversion_supported;
ops->config_pci_powersave = ar9003_hw_configpcipowersave;

View File

@ -322,7 +322,6 @@ static void ar9003_hw_set11n_txdesc(struct ath_hw *ah, void *ds,
if (txpower > ah->txpower_limit)
txpower = ah->txpower_limit;
txpower += ah->txpower_indexoffset;
if (txpower > 63)
txpower = 63;

View File

@ -19,6 +19,20 @@
void ar9003_paprd_enable(struct ath_hw *ah, bool val)
{
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
struct ath9k_channel *chan = ah->curchan;
if (val) {
ah->paprd_table_write_done = true;
ah->eep_ops->set_txpower(ah, chan,
ath9k_regd_get_ctl(regulatory, chan),
chan->chan->max_antenna_gain * 2,
chan->chan->max_power * 2,
min((u32) MAX_RATE_POWER,
(u32) regulatory->power_limit), false);
}
REG_RMW_FIELD(ah, AR_PHY_PAPRD_CTRL0_B0,
AR_PHY_PAPRD_CTRL0_PAPRD_ENABLE, !!val);
if (ah->caps.tx_chainmask & BIT(1))
@ -30,10 +44,63 @@ void ar9003_paprd_enable(struct ath_hw *ah, bool val)
}
EXPORT_SYMBOL(ar9003_paprd_enable);
static void ar9003_paprd_setup_single_table(struct ath_hw *ah)
static int ar9003_get_training_power_2g(struct ath_hw *ah)
{
struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
struct ar9300_modal_eep_header *hdr;
struct ar9300_modal_eep_header *hdr = &eep->modalHeader2G;
unsigned int power, scale, delta;
scale = MS(le32_to_cpu(hdr->papdRateMaskHt20), AR9300_PAPRD_SCALE_1);
power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE5,
AR_PHY_POWERTX_RATE5_POWERTXHT20_0);
delta = abs((int) ah->paprd_target_power - (int) power);
if (delta > scale)
return -1;
if (delta < 4)
power -= 4 - delta;
return power;
}
static int ar9003_get_training_power_5g(struct ath_hw *ah)
{
struct ath_common *common = ath9k_hw_common(ah);
struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
struct ar9300_modal_eep_header *hdr = &eep->modalHeader5G;
struct ath9k_channel *chan = ah->curchan;
unsigned int power, scale, delta;
if (chan->channel >= 5700)
scale = MS(le32_to_cpu(hdr->papdRateMaskHt20),
AR9300_PAPRD_SCALE_1);
else if (chan->channel >= 5400)
scale = MS(le32_to_cpu(hdr->papdRateMaskHt40),
AR9300_PAPRD_SCALE_2);
else
scale = MS(le32_to_cpu(hdr->papdRateMaskHt40),
AR9300_PAPRD_SCALE_1);
if (IS_CHAN_HT40(chan))
power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE8,
AR_PHY_POWERTX_RATE8_POWERTXHT40_5);
else
power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE6,
AR_PHY_POWERTX_RATE6_POWERTXHT20_5);
power += scale;
delta = abs((int) ah->paprd_target_power - (int) power);
if (delta > scale)
return -1;
power += 2 * get_streams(common->tx_chainmask);
return power;
}
static int ar9003_paprd_setup_single_table(struct ath_hw *ah)
{
struct ath_common *common = ath9k_hw_common(ah);
static const u32 ctrl0[3] = {
AR_PHY_PAPRD_CTRL0_B0,
AR_PHY_PAPRD_CTRL0_B1,
@ -44,21 +111,30 @@ static void ar9003_paprd_setup_single_table(struct ath_hw *ah)
AR_PHY_PAPRD_CTRL1_B1,
AR_PHY_PAPRD_CTRL1_B2
};
u32 am_mask, ht40_mask;
int training_power;
int i;
if (ah->curchan && IS_CHAN_5GHZ(ah->curchan))
hdr = &eep->modalHeader5G;
if (IS_CHAN_2GHZ(ah->curchan))
training_power = ar9003_get_training_power_2g(ah);
else
hdr = &eep->modalHeader2G;
training_power = ar9003_get_training_power_5g(ah);
am_mask = le32_to_cpu(hdr->papdRateMaskHt20);
ht40_mask = le32_to_cpu(hdr->papdRateMaskHt40);
REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2AM, AR_PHY_PAPRD_AM2AM_MASK, am_mask);
REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2PM, AR_PHY_PAPRD_AM2PM_MASK, am_mask);
REG_RMW_FIELD(ah, AR_PHY_PAPRD_HT40, AR_PHY_PAPRD_HT40_MASK, ht40_mask);
if (training_power < 0) {
ath_dbg(common, ATH_DBG_CALIBRATE,
"PAPRD target power delta out of range");
return -ERANGE;
}
ah->paprd_training_power = training_power;
ath_dbg(common, ATH_DBG_CALIBRATE,
"Training power: %d, Target power: %d\n",
ah->paprd_training_power, ah->paprd_target_power);
REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2AM, AR_PHY_PAPRD_AM2AM_MASK,
ah->paprd_ratemask);
REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2PM, AR_PHY_PAPRD_AM2PM_MASK,
ah->paprd_ratemask);
REG_RMW_FIELD(ah, AR_PHY_PAPRD_HT40, AR_PHY_PAPRD_HT40_MASK,
ah->paprd_ratemask_ht40);
for (i = 0; i < ah->caps.max_txchains; i++) {
REG_RMW_FIELD(ah, ctrl0[i],
@ -141,6 +217,7 @@ static void ar9003_paprd_setup_single_table(struct ath_hw *ah)
AR_PHY_PAPRD_PRE_POST_SCALING, 185706);
REG_RMW_FIELD(ah, AR_PHY_PAPRD_PRE_POST_SCALE_7_B0,
AR_PHY_PAPRD_PRE_POST_SCALING, 175487);
return 0;
}
static void ar9003_paprd_get_gain_table(struct ath_hw *ah)
@ -595,15 +672,10 @@ void ar9003_paprd_populate_single_table(struct ath_hw *ah,
{
u32 *paprd_table_val = caldata->pa_table[chain];
u32 small_signal_gain = caldata->small_signal_gain[chain];
u32 training_power;
u32 training_power = ah->paprd_training_power;
u32 reg = 0;
int i;
training_power =
REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE5,
AR_PHY_POWERTX_RATE5_POWERTXHT20_0);
training_power -= 4;
if (chain == 0)
reg = AR_PHY_PAPRD_MEM_TAB_B0;
else if (chain == 1)
@ -643,14 +715,8 @@ EXPORT_SYMBOL(ar9003_paprd_populate_single_table);
int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain)
{
unsigned int i, desired_gain, gain_index;
unsigned int train_power;
train_power = REG_READ_FIELD(ah, AR_PHY_POWERTX_RATE5,
AR_PHY_POWERTX_RATE5_POWERTXHT20_0);
train_power = train_power - 4;
unsigned int train_power = ah->paprd_training_power;
desired_gain = ar9003_get_desired_gain(ah, chain, train_power);
@ -716,7 +782,12 @@ EXPORT_SYMBOL(ar9003_paprd_create_curve);
int ar9003_paprd_init_table(struct ath_hw *ah)
{
ar9003_paprd_setup_single_table(ah);
int ret;
ret = ar9003_paprd_setup_single_table(ah);
if (ret < 0)
return ret;
ar9003_paprd_get_gain_table(ah);
return 0;
}

View File

@ -578,10 +578,7 @@ static void ar9003_hw_prog_ini(struct ath_hw *ah,
u32 reg = INI_RA(iniArr, i, 0);
u32 val = INI_RA(iniArr, i, column);
if (reg >= 0x16000 && reg < 0x17000)
ath9k_hw_analog_shift_regwrite(ah, reg, val);
else
REG_WRITE(ah, reg, val);
REG_WRITE(ah, reg, val);
DO_DELAY(regWrites);
}
@ -748,28 +745,6 @@ static void ar9003_hw_rfbus_done(struct ath_hw *ah)
REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0);
}
/*
* Set the interrupt and GPIO values so the ISR can disable RF
* on a switch signal. Assumes GPIO port and interrupt polarity
* are set prior to call.
*/
static void ar9003_hw_enable_rfkill(struct ath_hw *ah)
{
/* Connect rfsilent_bb_l to baseband */
REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL,
AR_GPIO_INPUT_EN_VAL_RFSILENT_BB);
/* Set input mux for rfsilent_bb_l to GPIO #0 */
REG_CLR_BIT(ah, AR_GPIO_INPUT_MUX2,
AR_GPIO_INPUT_MUX2_RFSILENT);
/*
* Configure the desired GPIO port for input and
* enable baseband rf silence.
*/
ath9k_hw_cfg_gpio_input(ah, ah->rfkill_gpio);
REG_SET_BIT(ah, AR_PHY_TEST, RFSILENT_BB);
}
static void ar9003_hw_set_diversity(struct ath_hw *ah, bool value)
{
u32 v = REG_READ(ah, AR_PHY_CCK_DETECT);
@ -1206,7 +1181,6 @@ void ar9003_hw_attach_phy_ops(struct ath_hw *ah)
priv_ops->set_delta_slope = ar9003_hw_set_delta_slope;
priv_ops->rfbus_req = ar9003_hw_rfbus_req;
priv_ops->rfbus_done = ar9003_hw_rfbus_done;
priv_ops->enable_rfkill = ar9003_hw_enable_rfkill;
priv_ops->set_diversity = ar9003_hw_set_diversity;
priv_ops->ani_control = ar9003_hw_ani_control;
priv_ops->do_getnf = ar9003_hw_do_getnf;

View File

@ -1090,6 +1090,14 @@
#define AR_PHY_POWERTX_RATE5_POWERTXHT20_0 0x3F
#define AR_PHY_POWERTX_RATE5_POWERTXHT20_0_S 0
#define AR_PHY_POWERTX_RATE6 (AR_SM_BASE + 0x1d4)
#define AR_PHY_POWERTX_RATE6_POWERTXHT20_5 0x3F00
#define AR_PHY_POWERTX_RATE6_POWERTXHT20_5_S 8
#define AR_PHY_POWERTX_RATE8 (AR_SM_BASE + 0x1dc)
#define AR_PHY_POWERTX_RATE8_POWERTXHT40_5 0x3F00
#define AR_PHY_POWERTX_RATE8_POWERTXHT40_5_S 8
void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx);
#endif /* AR9003_PHY_H */

View File

@ -57,6 +57,8 @@ struct ath_node;
#define A_MAX(a, b) ((a) > (b) ? (a) : (b))
#define ATH9K_PM_QOS_DEFAULT_VALUE 55
#define TSF_TO_TU(_h,_l) \
((((u32)(_h)) << 22) | (((u32)(_l)) >> 10))
@ -187,6 +189,7 @@ struct ath_txq {
struct list_head axq_q;
spinlock_t axq_lock;
u32 axq_depth;
u32 axq_ampdu_depth;
bool stopped;
bool axq_tx_inprogress;
struct list_head axq_acq;
@ -663,6 +666,7 @@ static inline void ath_read_cachesize(struct ath_common *common, int *csz)
extern struct ieee80211_ops ath9k_ops;
extern int modparam_nohwcrypt;
extern int led_blink;
extern int ath9k_pm_qos_value;
irqreturn_t ath_isr(int irq, void *dev);
int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,
@ -671,7 +675,6 @@ void ath9k_deinit_device(struct ath_softc *sc);
void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw);
void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw,
struct ath9k_channel *ichan);
void ath_update_chainmask(struct ath_softc *sc, int is_ht);
int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
struct ath9k_channel *hchan);

View File

@ -234,7 +234,7 @@ void ath9k_hw_get_target_powers(struct ath_hw *ah,
u16 ath9k_hw_get_max_edge_power(u16 freq, struct cal_ctl_edges *pRdEdgesPower,
bool is2GHz, int num_band_edges)
{
u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
u16 twiceMaxEdgePower = MAX_RATE_POWER;
int i;
for (i = 0; (i < num_band_edges) &&
@ -279,6 +279,219 @@ void ath9k_hw_update_regulatory_maxpower(struct ath_hw *ah)
}
}
void ath9k_hw_get_gain_boundaries_pdadcs(struct ath_hw *ah,
struct ath9k_channel *chan,
void *pRawDataSet,
u8 *bChans, u16 availPiers,
u16 tPdGainOverlap,
u16 *pPdGainBoundaries, u8 *pPDADCValues,
u16 numXpdGains)
{
int i, j, k;
int16_t ss;
u16 idxL = 0, idxR = 0, numPiers;
static u8 vpdTableL[AR5416_NUM_PD_GAINS]
[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
static u8 vpdTableR[AR5416_NUM_PD_GAINS]
[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
static u8 vpdTableI[AR5416_NUM_PD_GAINS]
[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR;
u8 minPwrT4[AR5416_NUM_PD_GAINS];
u8 maxPwrT4[AR5416_NUM_PD_GAINS];
int16_t vpdStep;
int16_t tmpVal;
u16 sizeCurrVpdTable, maxIndex, tgtIndex;
bool match;
int16_t minDelta = 0;
struct chan_centers centers;
int pdgain_boundary_default;
struct cal_data_per_freq *data_def = pRawDataSet;
struct cal_data_per_freq_4k *data_4k = pRawDataSet;
struct cal_data_per_freq_ar9287 *data_9287 = pRawDataSet;
bool eeprom_4k = AR_SREV_9285(ah) || AR_SREV_9271(ah);
int intercepts;
if (AR_SREV_9287(ah))
intercepts = AR9287_PD_GAIN_ICEPTS;
else
intercepts = AR5416_PD_GAIN_ICEPTS;
memset(&minPwrT4, 0, AR5416_NUM_PD_GAINS);
ath9k_hw_get_channel_centers(ah, chan, &centers);
for (numPiers = 0; numPiers < availPiers; numPiers++) {
if (bChans[numPiers] == AR5416_BCHAN_UNUSED)
break;
}
match = ath9k_hw_get_lower_upper_index((u8)FREQ2FBIN(centers.synth_center,
IS_CHAN_2GHZ(chan)),
bChans, numPiers, &idxL, &idxR);
if (match) {
if (AR_SREV_9287(ah)) {
/* FIXME: array overrun? */
for (i = 0; i < numXpdGains; i++) {
minPwrT4[i] = data_9287[idxL].pwrPdg[i][0];
maxPwrT4[i] = data_9287[idxL].pwrPdg[i][4];
ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
data_9287[idxL].pwrPdg[i],
data_9287[idxL].vpdPdg[i],
intercepts,
vpdTableI[i]);
}
} else if (eeprom_4k) {
for (i = 0; i < numXpdGains; i++) {
minPwrT4[i] = data_4k[idxL].pwrPdg[i][0];
maxPwrT4[i] = data_4k[idxL].pwrPdg[i][4];
ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
data_4k[idxL].pwrPdg[i],
data_4k[idxL].vpdPdg[i],
intercepts,
vpdTableI[i]);
}
} else {
for (i = 0; i < numXpdGains; i++) {
minPwrT4[i] = data_def[idxL].pwrPdg[i][0];
maxPwrT4[i] = data_def[idxL].pwrPdg[i][4];
ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
data_def[idxL].pwrPdg[i],
data_def[idxL].vpdPdg[i],
intercepts,
vpdTableI[i]);
}
}
} else {
for (i = 0; i < numXpdGains; i++) {
if (AR_SREV_9287(ah)) {
pVpdL = data_9287[idxL].vpdPdg[i];
pPwrL = data_9287[idxL].pwrPdg[i];
pVpdR = data_9287[idxR].vpdPdg[i];
pPwrR = data_9287[idxR].pwrPdg[i];
} else if (eeprom_4k) {
pVpdL = data_4k[idxL].vpdPdg[i];
pPwrL = data_4k[idxL].pwrPdg[i];
pVpdR = data_4k[idxR].vpdPdg[i];
pPwrR = data_4k[idxR].pwrPdg[i];
} else {
pVpdL = data_def[idxL].vpdPdg[i];
pPwrL = data_def[idxL].pwrPdg[i];
pVpdR = data_def[idxR].vpdPdg[i];
pPwrR = data_def[idxR].pwrPdg[i];
}
minPwrT4[i] = max(pPwrL[0], pPwrR[0]);
maxPwrT4[i] =
min(pPwrL[intercepts - 1],
pPwrR[intercepts - 1]);
ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
pPwrL, pVpdL,
intercepts,
vpdTableL[i]);
ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
pPwrR, pVpdR,
intercepts,
vpdTableR[i]);
for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) {
vpdTableI[i][j] =
(u8)(ath9k_hw_interpolate((u16)
FREQ2FBIN(centers.
synth_center,
IS_CHAN_2GHZ
(chan)),
bChans[idxL], bChans[idxR],
vpdTableL[i][j], vpdTableR[i][j]));
}
}
}
k = 0;
for (i = 0; i < numXpdGains; i++) {
if (i == (numXpdGains - 1))
pPdGainBoundaries[i] =
(u16)(maxPwrT4[i] / 2);
else
pPdGainBoundaries[i] =
(u16)((maxPwrT4[i] + minPwrT4[i + 1]) / 4);
pPdGainBoundaries[i] =
min((u16)MAX_RATE_POWER, pPdGainBoundaries[i]);
if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) {
minDelta = pPdGainBoundaries[0] - 23;
pPdGainBoundaries[0] = 23;
} else {
minDelta = 0;
}
if (i == 0) {
if (AR_SREV_9280_20_OR_LATER(ah))
ss = (int16_t)(0 - (minPwrT4[i] / 2));
else
ss = 0;
} else {
ss = (int16_t)((pPdGainBoundaries[i - 1] -
(minPwrT4[i] / 2)) -
tPdGainOverlap + 1 + minDelta);
}
vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]);
vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep);
pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal);
ss++;
}
sizeCurrVpdTable = (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1);
tgtIndex = (u8)(pPdGainBoundaries[i] + tPdGainOverlap -
(minPwrT4[i] / 2));
maxIndex = (tgtIndex < sizeCurrVpdTable) ?
tgtIndex : sizeCurrVpdTable;
while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
pPDADCValues[k++] = vpdTableI[i][ss++];
}
vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] -
vpdTableI[i][sizeCurrVpdTable - 2]);
vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
if (tgtIndex >= maxIndex) {
while ((ss <= tgtIndex) &&
(k < (AR5416_NUM_PDADC_VALUES - 1))) {
tmpVal = (int16_t)((vpdTableI[i][sizeCurrVpdTable - 1] +
(ss - maxIndex + 1) * vpdStep));
pPDADCValues[k++] = (u8)((tmpVal > 255) ?
255 : tmpVal);
ss++;
}
}
}
if (eeprom_4k)
pdgain_boundary_default = 58;
else
pdgain_boundary_default = pPdGainBoundaries[i - 1];
while (i < AR5416_PD_GAINS_IN_MASK) {
pPdGainBoundaries[i] = pdgain_boundary_default;
i++;
}
while (k < AR5416_NUM_PDADC_VALUES) {
pPDADCValues[k] = pPDADCValues[k - 1];
k++;
}
}
int ath9k_hw_eeprom_init(struct ath_hw *ah)
{
int status;

View File

@ -17,6 +17,8 @@
#ifndef EEPROM_H
#define EEPROM_H
#define AR_EEPROM_MODAL_SPURS 5
#include "../ath.h"
#include <net/cfg80211.h>
#include "ar9003_eeprom.h"
@ -149,8 +151,6 @@
#define AR5416_NUM_PD_GAINS 4
#define AR5416_PD_GAINS_IN_MASK 4
#define AR5416_PD_GAIN_ICEPTS 5
#define AR5416_EEPROM_MODAL_SPURS 5
#define AR5416_MAX_RATE_POWER 63
#define AR5416_NUM_PDADC_VALUES 128
#define AR5416_BCHAN_UNUSED 0xFF
#define AR5416_MAX_PWR_RANGE_IN_HALF_DB 64
@ -175,8 +175,6 @@
#define AR5416_EEP4K_NUM_CTLS 12
#define AR5416_EEP4K_NUM_BAND_EDGES 4
#define AR5416_EEP4K_NUM_PD_GAINS 2
#define AR5416_EEP4K_PD_GAINS_IN_MASK 4
#define AR5416_EEP4K_PD_GAIN_ICEPTS 5
#define AR5416_EEP4K_MAX_CHAINS 1
#define AR9280_TX_GAIN_TABLE_SIZE 22
@ -198,35 +196,12 @@
#define AR9287_NUM_2G_40_TARGET_POWERS 3
#define AR9287_NUM_CTLS 12
#define AR9287_NUM_BAND_EDGES 4
#define AR9287_NUM_PD_GAINS 4
#define AR9287_PD_GAINS_IN_MASK 4
#define AR9287_PD_GAIN_ICEPTS 1
#define AR9287_EEPROM_MODAL_SPURS 5
#define AR9287_MAX_RATE_POWER 63
#define AR9287_NUM_PDADC_VALUES 128
#define AR9287_NUM_RATES 16
#define AR9287_BCHAN_UNUSED 0xFF
#define AR9287_MAX_PWR_RANGE_IN_HALF_DB 64
#define AR9287_OPFLAGS_11A 0x01
#define AR9287_OPFLAGS_11G 0x02
#define AR9287_OPFLAGS_2G_HT40 0x08
#define AR9287_OPFLAGS_2G_HT20 0x20
#define AR9287_OPFLAGS_5G_HT40 0x04
#define AR9287_OPFLAGS_5G_HT20 0x10
#define AR9287_EEPMISC_BIG_ENDIAN 0x01
#define AR9287_EEPMISC_WOW 0x02
#define AR9287_MAX_CHAINS 2
#define AR9287_ANT_16S 32
#define AR9287_custdatasize 20
#define AR9287_NUM_ANT_CHAIN_FIELDS 6
#define AR9287_NUM_ANT_COMMON_FIELDS 4
#define AR9287_SIZE_ANT_CHAIN_FIELD 2
#define AR9287_SIZE_ANT_COMMON_FIELD 4
#define AR9287_ANT_CHAIN_MASK 0x3
#define AR9287_ANT_COMMON_MASK 0xf
#define AR9287_CHAIN_0_IDX 0
#define AR9287_CHAIN_1_IDX 1
#define AR9287_DATA_SZ 32
#define AR9287_PWR_TABLE_OFFSET_DB -5
@ -396,7 +371,7 @@ struct modal_eep_header {
u16 xpaBiasLvlFreq[3];
u8 futureModal[6];
struct spur_chan spurChans[AR5416_EEPROM_MODAL_SPURS];
struct spur_chan spurChans[AR_EEPROM_MODAL_SPURS];
} __packed;
struct calDataPerFreqOpLoop {
@ -464,7 +439,7 @@ struct modal_eep_4k_header {
u8 db2_4:4, reserved:4;
#endif
u8 futureModal[4];
struct spur_chan spurChans[AR5416_EEPROM_MODAL_SPURS];
struct spur_chan spurChans[AR_EEPROM_MODAL_SPURS];
} __packed;
struct base_eep_ar9287_header {
@ -522,7 +497,7 @@ struct modal_eep_ar9287_header {
u8 ob_qam;
u8 ob_pal_off;
u8 futureModal[30];
struct spur_chan spurChans[AR9287_EEPROM_MODAL_SPURS];
struct spur_chan spurChans[AR_EEPROM_MODAL_SPURS];
} __packed;
struct cal_data_per_freq {
@ -531,8 +506,8 @@ struct cal_data_per_freq {
} __packed;
struct cal_data_per_freq_4k {
u8 pwrPdg[AR5416_EEP4K_NUM_PD_GAINS][AR5416_EEP4K_PD_GAIN_ICEPTS];
u8 vpdPdg[AR5416_EEP4K_NUM_PD_GAINS][AR5416_EEP4K_PD_GAIN_ICEPTS];
u8 pwrPdg[AR5416_EEP4K_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS];
u8 vpdPdg[AR5416_EEP4K_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS];
} __packed;
struct cal_target_power_leg {
@ -558,8 +533,8 @@ struct cal_data_op_loop_ar9287 {
} __packed;
struct cal_data_per_freq_ar9287 {
u8 pwrPdg[AR9287_NUM_PD_GAINS][AR9287_PD_GAIN_ICEPTS];
u8 vpdPdg[AR9287_NUM_PD_GAINS][AR9287_PD_GAIN_ICEPTS];
u8 pwrPdg[AR5416_NUM_PD_GAINS][AR9287_PD_GAIN_ICEPTS];
u8 vpdPdg[AR5416_NUM_PD_GAINS][AR9287_PD_GAIN_ICEPTS];
} __packed;
union cal_data_per_freq_ar9287_u {
@ -674,10 +649,6 @@ struct eeprom_ops {
bool (*fill_eeprom)(struct ath_hw *hw);
int (*get_eeprom_ver)(struct ath_hw *hw);
int (*get_eeprom_rev)(struct ath_hw *hw);
u8 (*get_num_ant_config)(struct ath_hw *hw,
enum ath9k_hal_freq_band band);
u32 (*get_eeprom_antenna_cfg)(struct ath_hw *hw,
struct ath9k_channel *chan);
void (*set_board_values)(struct ath_hw *hw, struct ath9k_channel *chan);
void (*set_addac)(struct ath_hw *hw, struct ath9k_channel *chan);
void (*set_txpower)(struct ath_hw *hw, struct ath9k_channel *chan,
@ -716,6 +687,14 @@ u16 ath9k_hw_get_max_edge_power(u16 freq, struct cal_ctl_edges *pRdEdgesPower,
void ath9k_hw_update_regulatory_maxpower(struct ath_hw *ah);
int ath9k_hw_eeprom_init(struct ath_hw *ah);
void ath9k_hw_get_gain_boundaries_pdadcs(struct ath_hw *ah,
struct ath9k_channel *chan,
void *pRawDataSet,
u8 *bChans, u16 availPiers,
u16 tPdGainOverlap,
u16 *pPdGainBoundaries, u8 *pPDADCValues,
u16 numXpdGains);
#define ar5416_get_ntxchains(_txchainmask) \
(((_txchainmask >> 2) & 1) + \
((_txchainmask >> 1) & 1) + (_txchainmask & 1))

View File

@ -153,7 +153,7 @@ static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah)
eep->modalHeader.antCtrlChain[i] = integer;
}
for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) {
for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
word = swab16(eep->modalHeader.spurChans[i].spurChan);
eep->modalHeader.spurChans[i].spurChan = word;
}
@ -227,173 +227,6 @@ static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah,
}
}
static void ath9k_hw_get_4k_gain_boundaries_pdadcs(struct ath_hw *ah,
struct ath9k_channel *chan,
struct cal_data_per_freq_4k *pRawDataSet,
u8 *bChans, u16 availPiers,
u16 tPdGainOverlap,
u16 *pPdGainBoundaries, u8 *pPDADCValues,
u16 numXpdGains)
{
#define TMP_VAL_VPD_TABLE \
((vpdTableI[i][sizeCurrVpdTable - 1] + (ss - maxIndex + 1) * vpdStep));
int i, j, k;
int16_t ss;
u16 idxL = 0, idxR = 0, numPiers;
static u8 vpdTableL[AR5416_EEP4K_NUM_PD_GAINS]
[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
static u8 vpdTableR[AR5416_EEP4K_NUM_PD_GAINS]
[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
static u8 vpdTableI[AR5416_EEP4K_NUM_PD_GAINS]
[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR;
u8 minPwrT4[AR5416_EEP4K_NUM_PD_GAINS];
u8 maxPwrT4[AR5416_EEP4K_NUM_PD_GAINS];
int16_t vpdStep;
int16_t tmpVal;
u16 sizeCurrVpdTable, maxIndex, tgtIndex;
bool match;
int16_t minDelta = 0;
struct chan_centers centers;
#define PD_GAIN_BOUNDARY_DEFAULT 58;
memset(&minPwrT4, 0, AR9287_NUM_PD_GAINS);
ath9k_hw_get_channel_centers(ah, chan, &centers);
for (numPiers = 0; numPiers < availPiers; numPiers++) {
if (bChans[numPiers] == AR5416_BCHAN_UNUSED)
break;
}
match = ath9k_hw_get_lower_upper_index(
(u8)FREQ2FBIN(centers.synth_center,
IS_CHAN_2GHZ(chan)), bChans, numPiers,
&idxL, &idxR);
if (match) {
for (i = 0; i < numXpdGains; i++) {
minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0];
maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4];
ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
pRawDataSet[idxL].pwrPdg[i],
pRawDataSet[idxL].vpdPdg[i],
AR5416_EEP4K_PD_GAIN_ICEPTS,
vpdTableI[i]);
}
} else {
for (i = 0; i < numXpdGains; i++) {
pVpdL = pRawDataSet[idxL].vpdPdg[i];
pPwrL = pRawDataSet[idxL].pwrPdg[i];
pVpdR = pRawDataSet[idxR].vpdPdg[i];
pPwrR = pRawDataSet[idxR].pwrPdg[i];
minPwrT4[i] = max(pPwrL[0], pPwrR[0]);
maxPwrT4[i] =
min(pPwrL[AR5416_EEP4K_PD_GAIN_ICEPTS - 1],
pPwrR[AR5416_EEP4K_PD_GAIN_ICEPTS - 1]);
ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
pPwrL, pVpdL,
AR5416_EEP4K_PD_GAIN_ICEPTS,
vpdTableL[i]);
ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
pPwrR, pVpdR,
AR5416_EEP4K_PD_GAIN_ICEPTS,
vpdTableR[i]);
for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) {
vpdTableI[i][j] =
(u8)(ath9k_hw_interpolate((u16)
FREQ2FBIN(centers.
synth_center,
IS_CHAN_2GHZ
(chan)),
bChans[idxL], bChans[idxR],
vpdTableL[i][j], vpdTableR[i][j]));
}
}
}
k = 0;
for (i = 0; i < numXpdGains; i++) {
if (i == (numXpdGains - 1))
pPdGainBoundaries[i] =
(u16)(maxPwrT4[i] / 2);
else
pPdGainBoundaries[i] =
(u16)((maxPwrT4[i] + minPwrT4[i + 1]) / 4);
pPdGainBoundaries[i] =
min((u16)AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]);
if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) {
minDelta = pPdGainBoundaries[0] - 23;
pPdGainBoundaries[0] = 23;
} else {
minDelta = 0;
}
if (i == 0) {
if (AR_SREV_9280_20_OR_LATER(ah))
ss = (int16_t)(0 - (minPwrT4[i] / 2));
else
ss = 0;
} else {
ss = (int16_t)((pPdGainBoundaries[i - 1] -
(minPwrT4[i] / 2)) -
tPdGainOverlap + 1 + minDelta);
}
vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]);
vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep);
pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal);
ss++;
}
sizeCurrVpdTable = (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1);
tgtIndex = (u8)(pPdGainBoundaries[i] + tPdGainOverlap -
(minPwrT4[i] / 2));
maxIndex = (tgtIndex < sizeCurrVpdTable) ?
tgtIndex : sizeCurrVpdTable;
while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1)))
pPDADCValues[k++] = vpdTableI[i][ss++];
vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] -
vpdTableI[i][sizeCurrVpdTable - 2]);
vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
if (tgtIndex >= maxIndex) {
while ((ss <= tgtIndex) &&
(k < (AR5416_NUM_PDADC_VALUES - 1))) {
tmpVal = (int16_t) TMP_VAL_VPD_TABLE;
pPDADCValues[k++] = (u8)((tmpVal > 255) ?
255 : tmpVal);
ss++;
}
}
}
while (i < AR5416_EEP4K_PD_GAINS_IN_MASK) {
pPdGainBoundaries[i] = PD_GAIN_BOUNDARY_DEFAULT;
i++;
}
while (k < AR5416_NUM_PDADC_VALUES) {
pPDADCValues[k] = pPDADCValues[k - 1];
k++;
}
return;
#undef TMP_VAL_VPD_TABLE
}
static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah,
struct ath9k_channel *chan,
int16_t *pTxPowerIndexOffset)
@ -404,7 +237,7 @@ static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah,
u8 *pCalBChans = NULL;
u16 pdGainOverlap_t2;
static u8 pdadcValues[AR5416_NUM_PDADC_VALUES];
u16 gainBoundaries[AR5416_EEP4K_PD_GAINS_IN_MASK];
u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK];
u16 numPiers, i, j;
u16 numXpdGain, xpdMask;
u16 xpdGainValues[AR5416_EEP4K_NUM_PD_GAINS] = { 0, 0 };
@ -426,12 +259,12 @@ static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah,
numXpdGain = 0;
for (i = 1; i <= AR5416_EEP4K_PD_GAINS_IN_MASK; i++) {
if ((xpdMask >> (AR5416_EEP4K_PD_GAINS_IN_MASK - i)) & 1) {
for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) {
if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) {
if (numXpdGain >= AR5416_EEP4K_NUM_PD_GAINS)
break;
xpdGainValues[numXpdGain] =
(u16)(AR5416_EEP4K_PD_GAINS_IN_MASK - i);
(u16)(AR5416_PD_GAINS_IN_MASK - i);
numXpdGain++;
}
}
@ -455,7 +288,7 @@ static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah,
if (pEepData->baseEepHeader.txMask & (1 << i)) {
pRawDataset = pEepData->calPierData2G[i];
ath9k_hw_get_4k_gain_boundaries_pdadcs(ah, chan,
ath9k_hw_get_gain_boundaries_pdadcs(ah, chan,
pRawDataset, pCalBChans,
numPiers, pdGainOverlap_t2,
gainBoundaries,
@ -528,7 +361,7 @@ static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
int i;
int16_t twiceLargestAntenna;
u16 twiceMinEdgePower;
u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
u16 twiceMaxEdgePower = MAX_RATE_POWER;
u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
u16 numCtlModes;
const u16 *pCtlMode;
@ -537,7 +370,7 @@ static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
struct cal_ctl_data_4k *rep;
struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
static const u16 tpScaleReductionTable[5] =
{ 0, 3, 6, 9, AR5416_MAX_RATE_POWER };
{ 0, 3, 6, 9, MAX_RATE_POWER };
struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
0, { 0, 0, 0, 0}
};
@ -613,7 +446,7 @@ static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
if (ah->eep_ops->get_eeprom_ver(ah) == 14 &&
ah->eep_ops->get_eeprom_rev(ah) <= 2)
twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
twiceMaxEdgePower = MAX_RATE_POWER;
for (i = 0; (i < AR5416_EEP4K_NUM_CTLS) &&
pEepData->ctlIndex[i]; i++) {
@ -752,8 +585,8 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
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] > MAX_RATE_POWER)
ratesArray[i] = MAX_RATE_POWER;
if (ratesArray[i] > regulatory->max_power_level)
regulatory->max_power_level = ratesArray[i];
@ -937,8 +770,7 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah,
pModal = &eep->modalHeader;
txRxAttenLocal = 23;
REG_WRITE(ah, AR_PHY_SWITCH_COM,
ah->eep_ops->get_eeprom_antenna_cfg(ah, chan));
REG_WRITE(ah, AR_PHY_SWITCH_COM, pModal->antCtrlCommon);
/* Single chain for 4K EEPROM*/
ath9k_hw_4k_set_gain(ah, pModal, eep, txRxAttenLocal);
@ -1154,21 +986,6 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah,
}
}
static u32 ath9k_hw_4k_get_eeprom_antenna_cfg(struct ath_hw *ah,
struct ath9k_channel *chan)
{
struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
struct modal_eep_4k_header *pModal = &eep->modalHeader;
return pModal->antCtrlCommon;
}
static u8 ath9k_hw_4k_get_num_ant_config(struct ath_hw *ah,
enum ath9k_hal_freq_band freq_band)
{
return 1;
}
static u16 ath9k_hw_4k_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz)
{
#define EEP_MAP4K_SPURCHAN \
@ -1205,8 +1022,6 @@ const struct eeprom_ops eep_4k_ops = {
.fill_eeprom = ath9k_hw_4k_fill_eeprom,
.get_eeprom_ver = ath9k_hw_4k_get_eeprom_ver,
.get_eeprom_rev = ath9k_hw_4k_get_eeprom_rev,
.get_num_ant_config = ath9k_hw_4k_get_num_ant_config,
.get_eeprom_antenna_cfg = ath9k_hw_4k_get_eeprom_antenna_cfg,
.set_board_values = ath9k_hw_4k_set_board_values,
.set_addac = ath9k_hw_4k_set_addac,
.set_txpower = ath9k_hw_4k_set_txpower,

View File

@ -150,7 +150,7 @@ static int ath9k_hw_ar9287_check_eeprom(struct ath_hw *ah)
eep->modalHeader.antCtrlChain[i] = integer;
}
for (i = 0; i < AR9287_EEPROM_MODAL_SPURS; i++) {
for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
word = swab16(eep->modalHeader.spurChans[i].spurChan);
eep->modalHeader.spurChans[i].spurChan = word;
}
@ -220,163 +220,6 @@ static u32 ath9k_hw_ar9287_get_eeprom(struct ath_hw *ah,
}
}
static void ath9k_hw_get_ar9287_gain_boundaries_pdadcs(struct ath_hw *ah,
struct ath9k_channel *chan,
struct cal_data_per_freq_ar9287 *pRawDataSet,
u8 *bChans, u16 availPiers,
u16 tPdGainOverlap,
u16 *pPdGainBoundaries,
u8 *pPDADCValues,
u16 numXpdGains)
{
#define TMP_VAL_VPD_TABLE \
((vpdTableI[i][sizeCurrVpdTable - 1] + (ss - maxIndex + 1) * vpdStep));
int i, j, k;
int16_t ss;
u16 idxL = 0, idxR = 0, numPiers;
u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR;
u8 minPwrT4[AR9287_NUM_PD_GAINS];
u8 maxPwrT4[AR9287_NUM_PD_GAINS];
int16_t vpdStep;
int16_t tmpVal;
u16 sizeCurrVpdTable, maxIndex, tgtIndex;
bool match;
int16_t minDelta = 0;
struct chan_centers centers;
static u8 vpdTableL[AR5416_EEP4K_NUM_PD_GAINS]
[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
static u8 vpdTableR[AR5416_EEP4K_NUM_PD_GAINS]
[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
static u8 vpdTableI[AR5416_EEP4K_NUM_PD_GAINS]
[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
memset(&minPwrT4, 0, AR9287_NUM_PD_GAINS);
ath9k_hw_get_channel_centers(ah, chan, &centers);
for (numPiers = 0; numPiers < availPiers; numPiers++) {
if (bChans[numPiers] == AR9287_BCHAN_UNUSED)
break;
}
match = ath9k_hw_get_lower_upper_index(
(u8)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)),
bChans, numPiers, &idxL, &idxR);
if (match) {
for (i = 0; i < numXpdGains; i++) {
minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0];
maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4];
ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
pRawDataSet[idxL].pwrPdg[i],
pRawDataSet[idxL].vpdPdg[i],
AR9287_PD_GAIN_ICEPTS,
vpdTableI[i]);
}
} else {
for (i = 0; i < numXpdGains; i++) {
pVpdL = pRawDataSet[idxL].vpdPdg[i];
pPwrL = pRawDataSet[idxL].pwrPdg[i];
pVpdR = pRawDataSet[idxR].vpdPdg[i];
pPwrR = pRawDataSet[idxR].pwrPdg[i];
minPwrT4[i] = max(pPwrL[0], pPwrR[0]);
maxPwrT4[i] = min(pPwrL[AR9287_PD_GAIN_ICEPTS - 1],
pPwrR[AR9287_PD_GAIN_ICEPTS - 1]);
ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
pPwrL, pVpdL,
AR9287_PD_GAIN_ICEPTS,
vpdTableL[i]);
ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
pPwrR, pVpdR,
AR9287_PD_GAIN_ICEPTS,
vpdTableR[i]);
for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) {
vpdTableI[i][j] = (u8)(ath9k_hw_interpolate(
(u16)FREQ2FBIN(centers. synth_center,
IS_CHAN_2GHZ(chan)),
bChans[idxL], bChans[idxR],
vpdTableL[i][j], vpdTableR[i][j]));
}
}
}
k = 0;
for (i = 0; i < numXpdGains; i++) {
if (i == (numXpdGains - 1))
pPdGainBoundaries[i] =
(u16)(maxPwrT4[i] / 2);
else
pPdGainBoundaries[i] =
(u16)((maxPwrT4[i] + minPwrT4[i+1]) / 4);
pPdGainBoundaries[i] = min((u16)AR5416_MAX_RATE_POWER,
pPdGainBoundaries[i]);
minDelta = 0;
if (i == 0) {
if (AR_SREV_9280_20_OR_LATER(ah))
ss = (int16_t)(0 - (minPwrT4[i] / 2));
else
ss = 0;
} else {
ss = (int16_t)((pPdGainBoundaries[i-1] -
(minPwrT4[i] / 2)) -
tPdGainOverlap + 1 + minDelta);
}
vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]);
vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
while ((ss < 0) && (k < (AR9287_NUM_PDADC_VALUES - 1))) {
tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep);
pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal);
ss++;
}
sizeCurrVpdTable = (u8)((maxPwrT4[i] - minPwrT4[i]) / 2 + 1);
tgtIndex = (u8)(pPdGainBoundaries[i] +
tPdGainOverlap - (minPwrT4[i] / 2));
maxIndex = (tgtIndex < sizeCurrVpdTable) ?
tgtIndex : sizeCurrVpdTable;
while ((ss < maxIndex) && (k < (AR9287_NUM_PDADC_VALUES - 1)))
pPDADCValues[k++] = vpdTableI[i][ss++];
vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] -
vpdTableI[i][sizeCurrVpdTable - 2]);
vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
if (tgtIndex > maxIndex) {
while ((ss <= tgtIndex) &&
(k < (AR9287_NUM_PDADC_VALUES - 1))) {
tmpVal = (int16_t) TMP_VAL_VPD_TABLE;
pPDADCValues[k++] =
(u8)((tmpVal > 255) ? 255 : tmpVal);
ss++;
}
}
}
while (i < AR9287_PD_GAINS_IN_MASK) {
pPdGainBoundaries[i] = pPdGainBoundaries[i-1];
i++;
}
while (k < AR9287_NUM_PDADC_VALUES) {
pPDADCValues[k] = pPDADCValues[k-1];
k++;
}
#undef TMP_VAL_VPD_TABLE
}
static void ar9287_eeprom_get_tx_gain_index(struct ath_hw *ah,
struct ath9k_channel *chan,
struct cal_data_op_loop_ar9287 *pRawDatasetOpLoop,
@ -389,7 +232,7 @@ static void ar9287_eeprom_get_tx_gain_index(struct ath_hw *ah,
ath9k_hw_get_channel_centers(ah, chan, &centers);
for (numPiers = 0; numPiers < availPiers; numPiers++) {
if (pCalChans[numPiers] == AR9287_BCHAN_UNUSED)
if (pCalChans[numPiers] == AR5416_BCHAN_UNUSED)
break;
}
@ -455,11 +298,11 @@ static void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah,
struct cal_data_op_loop_ar9287 *pRawDatasetOpenLoop;
u8 *pCalBChans = NULL;
u16 pdGainOverlap_t2;
u8 pdadcValues[AR9287_NUM_PDADC_VALUES];
u16 gainBoundaries[AR9287_PD_GAINS_IN_MASK];
u8 pdadcValues[AR5416_NUM_PDADC_VALUES];
u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK];
u16 numPiers = 0, i, j;
u16 numXpdGain, xpdMask;
u16 xpdGainValues[AR9287_NUM_PD_GAINS] = {0, 0, 0, 0};
u16 xpdGainValues[AR5416_NUM_PD_GAINS] = {0, 0, 0, 0};
u32 reg32, regOffset, regChainOffset, regval;
int16_t modalIdx, diff = 0;
struct ar9287_eeprom *pEepData = &ah->eeprom.map9287;
@ -487,12 +330,12 @@ static void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah,
numXpdGain = 0;
/* Calculate the value of xpdgains from the xpdGain Mask */
for (i = 1; i <= AR9287_PD_GAINS_IN_MASK; i++) {
if ((xpdMask >> (AR9287_PD_GAINS_IN_MASK - i)) & 1) {
if (numXpdGain >= AR9287_NUM_PD_GAINS)
for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) {
if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) {
if (numXpdGain >= AR5416_NUM_PD_GAINS)
break;
xpdGainValues[numXpdGain] =
(u16)(AR9287_PD_GAINS_IN_MASK-i);
(u16)(AR5416_PD_GAINS_IN_MASK-i);
numXpdGain++;
}
}
@ -525,7 +368,7 @@ static void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah,
(struct cal_data_per_freq_ar9287 *)
pEepData->calPierData2G[i];
ath9k_hw_get_ar9287_gain_boundaries_pdadcs(ah, chan,
ath9k_hw_get_gain_boundaries_pdadcs(ah, chan,
pRawDataset,
pCalBChans, numPiers,
pdGainOverlap_t2,
@ -561,13 +404,13 @@ static void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah,
(int32_t)AR9287_PWR_TABLE_OFFSET_DB);
diff *= 2;
for (j = 0; j < ((u16)AR9287_NUM_PDADC_VALUES-diff); j++)
for (j = 0; j < ((u16)AR5416_NUM_PDADC_VALUES-diff); j++)
pdadcValues[j] = pdadcValues[j+diff];
for (j = (u16)(AR9287_NUM_PDADC_VALUES-diff);
j < AR9287_NUM_PDADC_VALUES; j++)
for (j = (u16)(AR5416_NUM_PDADC_VALUES-diff);
j < AR5416_NUM_PDADC_VALUES; j++)
pdadcValues[j] =
pdadcValues[AR9287_NUM_PDADC_VALUES-diff];
pdadcValues[AR5416_NUM_PDADC_VALUES-diff];
}
if (!ath9k_hw_ar9287_get_eeprom(ah, EEP_OL_PWRCTRL)) {
@ -610,9 +453,9 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah,
#define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
u16 twiceMaxEdgePower = MAX_RATE_POWER;
static const u16 tpScaleReductionTable[5] =
{ 0, 3, 6, 9, AR5416_MAX_RATE_POWER };
{ 0, 3, 6, 9, MAX_RATE_POWER };
int i;
int16_t twiceLargestAntenna;
struct cal_ctl_data_ar9287 *rep;
@ -877,8 +720,8 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah,
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] > MAX_RATE_POWER)
ratesArray[i] = MAX_RATE_POWER;
if (ratesArray[i] > regulatory->max_power_level)
regulatory->max_power_level = ratesArray[i];
@ -1023,8 +866,7 @@ static void ath9k_hw_ar9287_set_board_values(struct ath_hw *ah,
antWrites[j++] = (u16)(pModal->antCtrlChain[i] & 0x3);
}
REG_WRITE(ah, AR_PHY_SWITCH_COM,
ah->eep_ops->get_eeprom_antenna_cfg(ah, chan));
REG_WRITE(ah, AR_PHY_SWITCH_COM, pModal->antCtrlCommon);
for (i = 0; i < AR9287_MAX_CHAINS; i++) {
regChainOffset = i * 0x1000;
@ -1125,21 +967,6 @@ static void ath9k_hw_ar9287_set_board_values(struct ath_hw *ah,
pModal->xpaBiasLvl);
}
static u8 ath9k_hw_ar9287_get_num_ant_config(struct ath_hw *ah,
enum ath9k_hal_freq_band freq_band)
{
return 1;
}
static u32 ath9k_hw_ar9287_get_eeprom_antenna_cfg(struct ath_hw *ah,
struct ath9k_channel *chan)
{
struct ar9287_eeprom *eep = &ah->eeprom.map9287;
struct modal_eep_ar9287_header *pModal = &eep->modalHeader;
return pModal->antCtrlCommon;
}
static u16 ath9k_hw_ar9287_get_spur_channel(struct ath_hw *ah,
u16 i, bool is2GHz)
{
@ -1177,8 +1004,6 @@ const struct eeprom_ops eep_ar9287_ops = {
.fill_eeprom = ath9k_hw_ar9287_fill_eeprom,
.get_eeprom_ver = ath9k_hw_ar9287_get_eeprom_ver,
.get_eeprom_rev = ath9k_hw_ar9287_get_eeprom_rev,
.get_num_ant_config = ath9k_hw_ar9287_get_num_ant_config,
.get_eeprom_antenna_cfg = ath9k_hw_ar9287_get_eeprom_antenna_cfg,
.set_board_values = ath9k_hw_ar9287_set_board_values,
.set_addac = ath9k_hw_ar9287_set_addac,
.set_txpower = ath9k_hw_ar9287_set_txpower,

View File

@ -206,7 +206,7 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah)
pModal->antCtrlChain[i] = integer;
}
for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) {
for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
word = swab16(pModal->spurChans[i].spurChan);
pModal->spurChans[i].spurChan = word;
}
@ -374,8 +374,7 @@ static void ath9k_hw_def_set_board_values(struct ath_hw *ah,
pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
txRxAttenLocal = IS_CHAN_2GHZ(chan) ? 23 : 44;
REG_WRITE(ah, AR_PHY_SWITCH_COM,
ah->eep_ops->get_eeprom_antenna_cfg(ah, chan));
REG_WRITE(ah, AR_PHY_SWITCH_COM, pModal->antCtrlCommon & 0xffff);
for (i = 0; i < AR5416_MAX_CHAINS; i++) {
if (AR_SREV_9280(ah)) {
@ -588,168 +587,6 @@ static void ath9k_hw_def_set_addac(struct ath_hw *ah,
#undef XPA_LVL_FREQ
}
static void ath9k_hw_get_def_gain_boundaries_pdadcs(struct ath_hw *ah,
struct ath9k_channel *chan,
struct cal_data_per_freq *pRawDataSet,
u8 *bChans, u16 availPiers,
u16 tPdGainOverlap,
u16 *pPdGainBoundaries, u8 *pPDADCValues,
u16 numXpdGains)
{
int i, j, k;
int16_t ss;
u16 idxL = 0, idxR = 0, numPiers;
static u8 vpdTableL[AR5416_NUM_PD_GAINS]
[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
static u8 vpdTableR[AR5416_NUM_PD_GAINS]
[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
static u8 vpdTableI[AR5416_NUM_PD_GAINS]
[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR;
u8 minPwrT4[AR5416_NUM_PD_GAINS];
u8 maxPwrT4[AR5416_NUM_PD_GAINS];
int16_t vpdStep;
int16_t tmpVal;
u16 sizeCurrVpdTable, maxIndex, tgtIndex;
bool match;
int16_t minDelta = 0;
struct chan_centers centers;
memset(&minPwrT4, 0, AR9287_NUM_PD_GAINS);
ath9k_hw_get_channel_centers(ah, chan, &centers);
for (numPiers = 0; numPiers < availPiers; numPiers++) {
if (bChans[numPiers] == AR5416_BCHAN_UNUSED)
break;
}
match = ath9k_hw_get_lower_upper_index((u8)FREQ2FBIN(centers.synth_center,
IS_CHAN_2GHZ(chan)),
bChans, numPiers, &idxL, &idxR);
if (match) {
for (i = 0; i < numXpdGains; i++) {
minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0];
maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4];
ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
pRawDataSet[idxL].pwrPdg[i],
pRawDataSet[idxL].vpdPdg[i],
AR5416_PD_GAIN_ICEPTS,
vpdTableI[i]);
}
} else {
for (i = 0; i < numXpdGains; i++) {
pVpdL = pRawDataSet[idxL].vpdPdg[i];
pPwrL = pRawDataSet[idxL].pwrPdg[i];
pVpdR = pRawDataSet[idxR].vpdPdg[i];
pPwrR = pRawDataSet[idxR].pwrPdg[i];
minPwrT4[i] = max(pPwrL[0], pPwrR[0]);
maxPwrT4[i] =
min(pPwrL[AR5416_PD_GAIN_ICEPTS - 1],
pPwrR[AR5416_PD_GAIN_ICEPTS - 1]);
ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
pPwrL, pVpdL,
AR5416_PD_GAIN_ICEPTS,
vpdTableL[i]);
ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
pPwrR, pVpdR,
AR5416_PD_GAIN_ICEPTS,
vpdTableR[i]);
for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) {
vpdTableI[i][j] =
(u8)(ath9k_hw_interpolate((u16)
FREQ2FBIN(centers.
synth_center,
IS_CHAN_2GHZ
(chan)),
bChans[idxL], bChans[idxR],
vpdTableL[i][j], vpdTableR[i][j]));
}
}
}
k = 0;
for (i = 0; i < numXpdGains; i++) {
if (i == (numXpdGains - 1))
pPdGainBoundaries[i] =
(u16)(maxPwrT4[i] / 2);
else
pPdGainBoundaries[i] =
(u16)((maxPwrT4[i] + minPwrT4[i + 1]) / 4);
pPdGainBoundaries[i] =
min((u16)AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]);
if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) {
minDelta = pPdGainBoundaries[0] - 23;
pPdGainBoundaries[0] = 23;
} else {
minDelta = 0;
}
if (i == 0) {
if (AR_SREV_9280_20_OR_LATER(ah))
ss = (int16_t)(0 - (minPwrT4[i] / 2));
else
ss = 0;
} else {
ss = (int16_t)((pPdGainBoundaries[i - 1] -
(minPwrT4[i] / 2)) -
tPdGainOverlap + 1 + minDelta);
}
vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]);
vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep);
pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal);
ss++;
}
sizeCurrVpdTable = (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1);
tgtIndex = (u8)(pPdGainBoundaries[i] + tPdGainOverlap -
(minPwrT4[i] / 2));
maxIndex = (tgtIndex < sizeCurrVpdTable) ?
tgtIndex : sizeCurrVpdTable;
while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
pPDADCValues[k++] = vpdTableI[i][ss++];
}
vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] -
vpdTableI[i][sizeCurrVpdTable - 2]);
vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
if (tgtIndex >= maxIndex) {
while ((ss <= tgtIndex) &&
(k < (AR5416_NUM_PDADC_VALUES - 1))) {
tmpVal = (int16_t)((vpdTableI[i][sizeCurrVpdTable - 1] +
(ss - maxIndex + 1) * vpdStep));
pPDADCValues[k++] = (u8)((tmpVal > 255) ?
255 : tmpVal);
ss++;
}
}
}
while (i < AR5416_PD_GAINS_IN_MASK) {
pPdGainBoundaries[i] = pPdGainBoundaries[i - 1];
i++;
}
while (k < AR5416_NUM_PDADC_VALUES) {
pPDADCValues[k] = pPDADCValues[k - 1];
k++;
}
}
static int16_t ath9k_change_gain_boundary_setting(struct ath_hw *ah,
u16 *gb,
u16 numXpdGain,
@ -782,7 +619,7 @@ static int16_t ath9k_change_gain_boundary_setting(struct ath_hw *ah,
/* Because of a hardware limitation, ensure the gain boundary
* is not larger than (63 - overlap)
*/
gb_limit = (u16)(AR5416_MAX_RATE_POWER - pdGainOverlap_t2);
gb_limit = (u16)(MAX_RATE_POWER - pdGainOverlap_t2);
for (k = 0; k < numXpdGain; k++)
gb[k] = (u16)min(gb_limit, gb[k]);
@ -916,7 +753,7 @@ static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
ath9k_olc_get_pdadcs(ah, pcdacIdx,
txPower/2, pdadcValues);
} else {
ath9k_hw_get_def_gain_boundaries_pdadcs(ah,
ath9k_hw_get_gain_boundaries_pdadcs(ah,
chan, pRawDataset,
pCalBChans, numPiers,
pdGainOverlap_t2,
@ -1001,9 +838,9 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
u16 twiceMaxEdgePower = MAX_RATE_POWER;
static const u16 tpScaleReductionTable[5] =
{ 0, 3, 6, 9, AR5416_MAX_RATE_POWER };
{ 0, 3, 6, 9, MAX_RATE_POWER };
int i;
int16_t twiceLargestAntenna;
@ -1148,7 +985,7 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
if (ah->eep_ops->get_eeprom_ver(ah) == 14 &&
ah->eep_ops->get_eeprom_rev(ah) <= 2)
twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
twiceMaxEdgePower = MAX_RATE_POWER;
for (i = 0; (i < AR5416_NUM_CTLS) && pEepData->ctlIndex[i]; i++) {
if ((((cfgCtl & ~CTL_MODE_M) |
@ -1293,8 +1130,8 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
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] > MAX_RATE_POWER)
ratesArray[i] = MAX_RATE_POWER;
if (ratesArray[i] > regulatory->max_power_level)
regulatory->max_power_level = ratesArray[i];
}
@ -1426,34 +1263,6 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
| ATH9K_POW_SM(pModal->pwrDecreaseFor2Chain, 0));
}
static u8 ath9k_hw_def_get_num_ant_config(struct ath_hw *ah,
enum ath9k_hal_freq_band freq_band)
{
struct ar5416_eeprom_def *eep = &ah->eeprom.def;
struct modal_eep_header *pModal =
&(eep->modalHeader[freq_band]);
struct base_eep_header *pBase = &eep->baseEepHeader;
u8 num_ant_config;
num_ant_config = 1;
if (pBase->version >= 0x0E0D &&
(pModal->lna_ctl & LNA_CTL_USE_ANT1))
num_ant_config += 1;
return num_ant_config;
}
static u32 ath9k_hw_def_get_eeprom_antenna_cfg(struct ath_hw *ah,
struct ath9k_channel *chan)
{
struct ar5416_eeprom_def *eep = &ah->eeprom.def;
struct modal_eep_header *pModal =
&(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
return pModal->antCtrlCommon;
}
static u16 ath9k_hw_def_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz)
{
#define EEP_DEF_SPURCHAN \
@ -1490,8 +1299,6 @@ const struct eeprom_ops eep_def_ops = {
.fill_eeprom = ath9k_hw_def_fill_eeprom,
.get_eeprom_ver = ath9k_hw_def_get_eeprom_ver,
.get_eeprom_rev = ath9k_hw_def_get_eeprom_rev,
.get_num_ant_config = ath9k_hw_def_get_num_ant_config,
.get_eeprom_antenna_cfg = ath9k_hw_def_get_eeprom_antenna_cfg,
.set_board_values = ath9k_hw_def_set_board_values,
.set_addac = ath9k_hw_def_set_addac,
.set_txpower = ath9k_hw_def_set_txpower,

View File

@ -38,6 +38,7 @@ static struct usb_device_id ath9k_hif_usb_ids[] = {
{ USB_DEVICE(0x13D3, 0x3350) }, /* Azurewave */
{ USB_DEVICE(0x04CA, 0x4605) }, /* Liteon */
{ USB_DEVICE(0x040D, 0x3801) }, /* VIA */
{ USB_DEVICE(0x0cf3, 0xb003) }, /* Ubiquiti WifiStation Ext */
{ USB_DEVICE(0x0cf3, 0x7015),
.driver_info = AR9287_USB }, /* Atheros */

View File

@ -1170,9 +1170,6 @@ static int ath9k_htc_start(struct ieee80211_hw *hw)
/* setup initial channel */
init_channel = ath9k_cmn_get_curchannel(hw, ah);
/* Reset SERDES registers */
ath9k_hw_configpcipowersave(ah, 0, 0);
ath9k_hw_htc_resetinit(ah);
ret = ath9k_hw_reset(ah, init_channel, ah->caldata, false);
if (ret) {
@ -1258,7 +1255,6 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw)
ath9k_hw_phy_disable(ah);
ath9k_hw_disable(ah);
ath9k_hw_configpcipowersave(ah, 1, 1);
ath9k_htc_ps_restore(priv);
ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP);

View File

@ -251,7 +251,7 @@ void ath9k_tx_tasklet(unsigned long data)
ista = (struct ath9k_htc_sta *)sta->drv_priv;
if (ath9k_htc_check_tx_aggr(priv, ista, tid)) {
ieee80211_start_tx_ba_session(sta, tid);
ieee80211_start_tx_ba_session(sta, tid, 0);
spin_lock_bh(&priv->tx_lock);
ista->tid_state[tid] = AGGR_PROGRESS;
spin_unlock_bh(&priv->tx_lock);

View File

@ -223,11 +223,6 @@ static inline void ath9k_hw_rfbus_done(struct ath_hw *ah)
return ath9k_hw_private_ops(ah)->rfbus_done(ah);
}
static inline void ath9k_enable_rfkill(struct ath_hw *ah)
{
return ath9k_hw_private_ops(ah)->enable_rfkill(ah);
}
static inline void ath9k_hw_restore_chainmask(struct ath_hw *ah)
{
if (!ath9k_hw_private_ops(ah)->restore_chainmask)

View File

@ -54,13 +54,6 @@ static void ath9k_hw_init_mode_regs(struct ath_hw *ah)
ath9k_hw_private_ops(ah)->init_mode_regs(ah);
}
static bool ath9k_hw_macversion_supported(struct ath_hw *ah)
{
struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
return priv_ops->macversion_supported(ah->hw_version.macVersion);
}
static u32 ath9k_hw_compute_pll_control(struct ath_hw *ah,
struct ath9k_channel *chan)
{
@ -284,11 +277,9 @@ static void ath9k_hw_read_revisions(struct ath_hw *ah)
static void ath9k_hw_disablepcie(struct ath_hw *ah)
{
if (AR_SREV_9100(ah))
if (!AR_SREV_5416(ah))
return;
ENABLE_REGWRITE_BUFFER(ah);
REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);
REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
REG_WRITE(ah, AR_PCIE_SERDES, 0x28000029);
@ -300,8 +291,6 @@ static void ath9k_hw_disablepcie(struct ath_hw *ah)
REG_WRITE(ah, AR_PCIE_SERDES, 0x000e1007);
REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
REGWRITE_BUFFER_FLUSH(ah);
}
/* This should work for all families including legacy */
@ -418,9 +407,8 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah)
ah->sta_id1_defaults =
AR_STA_ID1_CRPT_MIC_ENABLE |
AR_STA_ID1_MCAST_KSRCH;
ah->beacon_interval = 100;
ah->enable_32kHz_clock = DONT_USE_32KHZ;
ah->slottime = (u32) -1;
ah->slottime = 20;
ah->globaltxtimeout = (u32) -1;
ah->power_mode = ATH9K_PM_UNDEFINED;
}
@ -538,7 +526,19 @@ static int __ath9k_hw_init(struct ath_hw *ah)
else
ah->config.max_txtrig_level = MAX_TX_FIFO_THRESHOLD;
if (!ath9k_hw_macversion_supported(ah)) {
switch (ah->hw_version.macVersion) {
case AR_SREV_VERSION_5416_PCI:
case AR_SREV_VERSION_5416_PCIE:
case AR_SREV_VERSION_9160:
case AR_SREV_VERSION_9100:
case AR_SREV_VERSION_9280:
case AR_SREV_VERSION_9285:
case AR_SREV_VERSION_9287:
case AR_SREV_VERSION_9271:
case AR_SREV_VERSION_9300:
case AR_SREV_VERSION_9485:
break;
default:
ath_err(common,
"Mac Chip Rev 0x%02x.%x is not supported by this driver\n",
ah->hw_version.macVersion, ah->hw_version.macRev);
@ -808,7 +808,7 @@ void ath9k_hw_init_global_settings(struct ath_hw *ah)
if (conf->channel && conf->channel->band == IEEE80211_BAND_2GHZ)
acktimeout += 64 - sifstime - ah->slottime;
ath9k_hw_setslottime(ah, slottime);
ath9k_hw_setslottime(ah, ah->slottime);
ath9k_hw_set_ack_timeout(ah, acktimeout);
ath9k_hw_set_cts_timeout(ah, acktimeout);
if (ah->globaltxtimeout != (u32) -1)
@ -1272,6 +1272,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
ath9k_hw_mark_phy_inactive(ah);
ah->paprd_table_write_done = false;
/* Only required on the first reset */
if (AR_SREV_9271(ah) && ah->htc_reset_init) {
REG_WRITE(ah,
@ -1383,7 +1385,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
ath9k_hw_init_qos(ah);
if (ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
ath9k_enable_rfkill(ah);
ath9k_hw_cfg_gpio_input(ah, ah->rfkill_gpio);
ath9k_hw_init_global_settings(ah);
@ -1627,17 +1629,9 @@ void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period)
{
int flags = 0;
ah->beacon_interval = beacon_period;
ENABLE_REGWRITE_BUFFER(ah);
switch (ah->opmode) {
case NL80211_IFTYPE_STATION:
REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(next_beacon));
REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, 0xffff);
REG_WRITE(ah, AR_NEXT_SWBA, 0x7ffff);
flags |= AR_TBTT_TIMER_EN;
break;
case NL80211_IFTYPE_ADHOC:
case NL80211_IFTYPE_MESH_POINT:
REG_SET_BIT(ah, AR_TXCFG,
@ -1661,14 +1655,6 @@ void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period)
AR_TBTT_TIMER_EN | AR_DBA_TIMER_EN | AR_SWBA_TIMER_EN;
break;
default:
if (ah->is_monitoring) {
REG_WRITE(ah, AR_NEXT_TBTT_TIMER,
TU_TO_USEC(next_beacon));
REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, 0xffff);
REG_WRITE(ah, AR_NEXT_SWBA, 0x7ffff);
flags |= AR_TBTT_TIMER_EN;
break;
}
ath_dbg(ath9k_hw_common(ah), ATH_DBG_BEACON,
"%s: unsupported opmode: %d\n",
__func__, ah->opmode);
@ -1920,11 +1906,6 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
AR_SREV_5416(ah))
pCap->reg_cap |= AR_EEPROM_EEREGCAP_EN_FCC_MIDBAND;
pCap->num_antcfg_5ghz =
ah->eep_ops->get_num_ant_config(ah, ATH9K_HAL_FREQ_BAND_5GHZ);
pCap->num_antcfg_2ghz =
ah->eep_ops->get_num_ant_config(ah, ATH9K_HAL_FREQ_BAND_2GHZ);
if (AR_SREV_9280_20_OR_LATER(ah) && common->btcoex_enabled) {
btcoex_hw->btactive_gpio = ATH_BTACTIVE_GPIO;
btcoex_hw->wlanactive_gpio = ATH_WLANACTIVE_GPIO;

View File

@ -204,8 +204,6 @@ struct ath9k_hw_capabilities {
u16 tx_triglevel_max;
u16 reg_cap;
u8 num_gpio_pins;
u8 num_antcfg_2ghz;
u8 num_antcfg_5ghz;
u8 rx_hp_qdepth;
u8 rx_lp_qdepth;
u8 rx_status_len;
@ -238,7 +236,6 @@ struct ath9k_ops_config {
#define SPUR_DISABLE 0
#define SPUR_ENABLE_IOCTL 1
#define SPUR_ENABLE_EEPROM 2
#define AR_EEPROM_MODAL_SPURS 5
#define AR_SPUR_5413_1 1640
#define AR_SPUR_5413_2 1200
#define AR_NO_SPUR 0x8000
@ -535,7 +532,6 @@ struct ath_hw_radar_conf {
*
* @init_mode_regs: Initializes mode registers
* @init_mode_gain_regs: Initialize TX/RX gain registers
* @macversion_supported: If this specific mac revision is supported
*
* @rf_set_freq: change frequency
* @spur_mitigate_freq: spur mitigation
@ -557,7 +553,6 @@ struct ath_hw_private_ops {
void (*init_mode_regs)(struct ath_hw *ah);
void (*init_mode_gain_regs)(struct ath_hw *ah);
bool (*macversion_supported)(u32 macversion);
void (*setup_calibration)(struct ath_hw *ah,
struct ath9k_cal_list *currCal);
@ -581,7 +576,6 @@ struct ath_hw_private_ops {
void (*set_delta_slope)(struct ath_hw *ah, struct ath9k_channel *chan);
bool (*rfbus_req)(struct ath_hw *ah);
void (*rfbus_done)(struct ath_hw *ah);
void (*enable_rfkill)(struct ath_hw *ah);
void (*restore_chainmask)(struct ath_hw *ah);
void (*set_diversity)(struct ath_hw *ah, bool value);
u32 (*compute_pll_control)(struct ath_hw *ah,
@ -767,9 +761,7 @@ struct ath_hw {
u32 *bank6Temp;
u8 txpower_limit;
int16_t txpower_indexoffset;
int coverage_class;
u32 beacon_interval;
u32 slottime;
u32 globaltxtimeout;
@ -840,6 +832,11 @@ struct ath_hw {
u32 bb_watchdog_last_status;
u32 bb_watchdog_timeout_ms; /* in ms, 0 to disable */
unsigned int paprd_target_power;
unsigned int paprd_training_power;
unsigned int paprd_ratemask;
unsigned int paprd_ratemask_ht40;
bool paprd_table_write_done;
u32 paprd_gain_table_entries[PAPRD_GAIN_TABLE_ENTRIES];
u8 paprd_gain_table_index[PAPRD_GAIN_TABLE_ENTRIES];
/*
@ -873,6 +870,11 @@ static inline struct ath_hw_ops *ath9k_hw_ops(struct ath_hw *ah)
return &ah->ops;
}
static inline u8 get_streams(int mask)
{
return !!(mask & BIT(0)) + !!(mask & BIT(1)) + !!(mask & BIT(2));
}
/* Initialization, Detach, Reset */
const char *ath9k_hw_probe(u16 vendorid, u16 devid);
void ath9k_hw_deinit(struct ath_hw *ah);

View File

@ -41,9 +41,14 @@ static int ath9k_btcoex_enable;
module_param_named(btcoex_enable, ath9k_btcoex_enable, int, 0444);
MODULE_PARM_DESC(btcoex_enable, "Enable wifi-BT coexistence");
int ath9k_pm_qos_value = ATH9K_PM_QOS_DEFAULT_VALUE;
module_param_named(pmqos, ath9k_pm_qos_value, int, S_IRUSR | S_IRGRP | S_IROTH);
MODULE_PARM_DESC(pmqos, "User specified PM-QOS value");
/* We use the hw_value as an index into our private channel structure */
#define CHAN2G(_freq, _idx) { \
.band = IEEE80211_BAND_2GHZ, \
.center_freq = (_freq), \
.hw_value = (_idx), \
.max_power = 20, \

View File

@ -320,6 +320,42 @@ static void ath_paprd_activate(struct ath_softc *sc)
ath9k_ps_restore(sc);
}
static bool ath_paprd_send_frame(struct ath_softc *sc, struct sk_buff *skb, int chain)
{
struct ieee80211_hw *hw = sc->hw;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
struct ath_tx_control txctl;
int time_left;
memset(&txctl, 0, sizeof(txctl));
txctl.txq = sc->tx.txq_map[WME_AC_BE];
memset(tx_info, 0, sizeof(*tx_info));
tx_info->band = hw->conf.channel->band;
tx_info->flags |= IEEE80211_TX_CTL_NO_ACK;
tx_info->control.rates[0].idx = 0;
tx_info->control.rates[0].count = 1;
tx_info->control.rates[0].flags = IEEE80211_TX_RC_MCS;
tx_info->control.rates[1].idx = -1;
init_completion(&sc->paprd_complete);
sc->paprd_pending = true;
txctl.paprd = BIT(chain);
if (ath_tx_start(hw, skb, &txctl) != 0)
return false;
time_left = wait_for_completion_timeout(&sc->paprd_complete,
msecs_to_jiffies(ATH_PAPRD_TIMEOUT));
sc->paprd_pending = false;
if (!time_left)
ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_CALIBRATE,
"Timeout waiting for paprd training on TX chain %d\n",
chain);
return !!time_left;
}
void ath_paprd_calibrate(struct work_struct *work)
{
struct ath_softc *sc = container_of(work, struct ath_softc, paprd_work);
@ -327,28 +363,23 @@ void ath_paprd_calibrate(struct work_struct *work)
struct ath_hw *ah = sc->sc_ah;
struct ieee80211_hdr *hdr;
struct sk_buff *skb = NULL;
struct ieee80211_tx_info *tx_info;
int band = hw->conf.channel->band;
struct ieee80211_supported_band *sband = &sc->sbands[band];
struct ath_tx_control txctl;
struct ath9k_hw_cal_data *caldata = ah->caldata;
struct ath_common *common = ath9k_hw_common(ah);
int ftype;
int chain_ok = 0;
int chain;
int len = 1800;
int time_left;
int i;
if (!caldata)
return;
if (ar9003_paprd_init_table(ah) < 0)
return;
skb = alloc_skb(len, GFP_KERNEL);
if (!skb)
return;
tx_info = IEEE80211_SKB_CB(skb);
skb_put(skb, len);
memset(skb->data, 0, len);
hdr = (struct ieee80211_hdr *)skb->data;
@ -359,40 +390,25 @@ void ath_paprd_calibrate(struct work_struct *work)
memcpy(hdr->addr2, hw->wiphy->perm_addr, ETH_ALEN);
memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN);
memset(&txctl, 0, sizeof(txctl));
txctl.txq = sc->tx.txq_map[WME_AC_BE];
ath9k_ps_wakeup(sc);
ar9003_paprd_init_table(ah);
for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
if (!(common->tx_chainmask & BIT(chain)))
continue;
chain_ok = 0;
memset(tx_info, 0, sizeof(*tx_info));
tx_info->band = band;
for (i = 0; i < 4; i++) {
tx_info->control.rates[i].idx = sband->n_bitrates - 1;
tx_info->control.rates[i].count = 6;
}
init_completion(&sc->paprd_complete);
sc->paprd_pending = true;
ar9003_paprd_setup_gain_table(ah, chain);
txctl.paprd = BIT(chain);
if (ath_tx_start(hw, skb, &txctl) != 0)
break;
time_left = wait_for_completion_timeout(&sc->paprd_complete,
msecs_to_jiffies(ATH_PAPRD_TIMEOUT));
sc->paprd_pending = false;
if (!time_left) {
ath_dbg(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
"Timeout waiting for paprd training on TX chain %d\n",
chain);
ath_dbg(common, ATH_DBG_CALIBRATE,
"Sending PAPRD frame for thermal measurement "
"on chain %d\n", chain);
if (!ath_paprd_send_frame(sc, skb, chain))
goto fail_paprd;
ar9003_paprd_setup_gain_table(ah, chain);
ath_dbg(common, ATH_DBG_CALIBRATE,
"Sending PAPRD training frame on chain %d\n", chain);
if (!ath_paprd_send_frame(sc, skb, chain))
goto fail_paprd;
}
if (!ar9003_paprd_is_done(ah))
break;
@ -517,37 +533,11 @@ set_timer:
if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_PAPRD) && ah->caldata) {
if (!ah->caldata->paprd_done)
ieee80211_queue_work(sc->hw, &sc->paprd_work);
else
else if (!ah->paprd_table_write_done)
ath_paprd_activate(sc);
}
}
/*
* Update tx/rx chainmask. For legacy association,
* hard code chainmask to 1x1, for 11n association, use
* the chainmask configuration, for bt coexistence, use
* the chainmask configuration even in legacy mode.
*/
void ath_update_chainmask(struct ath_softc *sc, int is_ht)
{
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
if ((sc->sc_flags & SC_OP_OFFCHANNEL) || is_ht ||
(ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE)) {
common->tx_chainmask = ah->caps.tx_chainmask;
common->rx_chainmask = ah->caps.rx_chainmask;
} else {
common->tx_chainmask = 1;
common->rx_chainmask = 1;
}
ath_dbg(common, ATH_DBG_CONFIG,
"tx chmask: %d, rx chmask: %d\n",
common->tx_chainmask,
common->rx_chainmask);
}
static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta)
{
struct ath_node *an;
@ -900,8 +890,7 @@ void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw)
ath_update_txpow(sc);
if (ath_startrecv(sc) != 0) {
ath_err(common, "Unable to restart recv logic\n");
spin_unlock_bh(&sc->sc_pcu_lock);
return;
goto out;
}
if (sc->sc_flags & SC_OP_BEACONS)
ath_beacon_config(sc, NULL); /* restart beacons */
@ -915,6 +904,7 @@ 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);
out:
spin_unlock_bh(&sc->sc_pcu_lock);
ath9k_ps_restore(sc);
@ -1180,7 +1170,11 @@ static int ath9k_start(struct ieee80211_hw *hw)
ath9k_btcoex_timer_resume(sc);
}
pm_qos_update_request(&sc->pm_qos_req, 55);
/* User has the option to provide pm-qos value as a module
* parameter rather than using the default value of
* 'ATH9K_PM_QOS_DEFAULT_VALUE'.
*/
pm_qos_update_request(&sc->pm_qos_req, ath9k_pm_qos_value);
if (ah->caps.pcie_lcr_extsync_en && common->bus_ops->extn_synch_en)
common->bus_ops->extn_synch_en(common);
@ -1333,8 +1327,8 @@ static void ath9k_stop(struct ieee80211_hw *hw)
ath9k_ps_restore(sc);
/* Finally, put the chip in FULL SLEEP mode */
ath9k_setpower(sc, ATH9K_PM_FULL_SLEEP);
sc->ps_idle = true;
ath_radio_disable(sc, hw);
sc->sc_flags |= SC_OP_INVALID;
@ -1428,13 +1422,78 @@ out:
return ret;
}
static void ath9k_reclaim_beacon(struct ath_softc *sc,
struct ieee80211_vif *vif)
{
struct ath_vif *avp = (void *)vif->drv_priv;
/* Disable SWBA interrupt */
sc->sc_ah->imask &= ~ATH9K_INT_SWBA;
ath9k_ps_wakeup(sc);
ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask);
ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
tasklet_kill(&sc->bcon_tasklet);
ath9k_ps_restore(sc);
ath_beacon_return(sc, avp);
sc->sc_flags &= ~SC_OP_BEACONS;
if (sc->nbcnvifs > 0) {
/* Re-enable beaconing */
sc->sc_ah->imask |= ATH9K_INT_SWBA;
ath9k_ps_wakeup(sc);
ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask);
ath9k_ps_restore(sc);
}
}
static int ath9k_change_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
enum nl80211_iftype new_type,
bool p2p)
{
struct ath_wiphy *aphy = hw->priv;
struct ath_softc *sc = aphy->sc;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
ath_dbg(common, ATH_DBG_CONFIG, "Change Interface\n");
mutex_lock(&sc->mutex);
switch (new_type) {
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_ADHOC:
if (sc->nbcnvifs >= ATH_BCBUF) {
ath_err(common, "No beacon slot available\n");
return -ENOBUFS;
}
break;
case NL80211_IFTYPE_STATION:
/* Stop ANI */
sc->sc_flags &= ~SC_OP_ANI_RUN;
del_timer_sync(&common->ani.timer);
if ((vif->type == NL80211_IFTYPE_AP) ||
(vif->type == NL80211_IFTYPE_ADHOC))
ath9k_reclaim_beacon(sc, vif);
break;
default:
ath_err(common, "Interface type %d not yet supported\n",
vif->type);
mutex_unlock(&sc->mutex);
return -ENOTSUPP;
}
vif->type = new_type;
vif->p2p = p2p;
mutex_unlock(&sc->mutex);
return 0;
}
static void ath9k_remove_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct ath_wiphy *aphy = hw->priv;
struct ath_softc *sc = aphy->sc;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_vif *avp = (void *)vif->drv_priv;
ath_dbg(common, ATH_DBG_CONFIG, "Detach Interface\n");
@ -1447,26 +1506,8 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
/* Reclaim beacon resources */
if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) ||
(sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) ||
(sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) {
/* Disable SWBA interrupt */
sc->sc_ah->imask &= ~ATH9K_INT_SWBA;
ath9k_ps_wakeup(sc);
ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask);
ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
ath9k_ps_restore(sc);
tasklet_kill(&sc->bcon_tasklet);
}
ath_beacon_return(sc, avp);
sc->sc_flags &= ~SC_OP_BEACONS;
if (sc->nbcnvifs) {
/* Re-enable SWBA interrupt */
sc->sc_ah->imask |= ATH9K_INT_SWBA;
ath9k_ps_wakeup(sc);
ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask);
ath9k_ps_restore(sc);
}
(sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT))
ath9k_reclaim_beacon(sc, vif);
sc->nvifs--;
@ -1612,8 +1653,6 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
/* XXX: remove me eventualy */
ath9k_update_ichannel(sc, hw, &sc->sc_ah->channels[pos]);
ath_update_chainmask(sc, conf_is_ht(conf));
/* update survey stats for the old channel before switching */
spin_lock_irqsave(&common->cc_lock, flags);
ath_update_survey_stats(sc);
@ -1845,10 +1884,6 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
/* Set aggregation protection mode parameters */
sc->config.ath_aggr_prot = 0;
/* Only legacy IBSS for now */
if (vif->type == NL80211_IFTYPE_ADHOC)
ath_update_chainmask(sc, 0);
ath_dbg(common, ATH_DBG_CONFIG, "BSSID: %pM aid: 0x%x\n",
common->curbssid, common->curaid);
@ -1940,7 +1975,9 @@ static u64 ath9k_get_tsf(struct ieee80211_hw *hw)
struct ath_softc *sc = aphy->sc;
mutex_lock(&sc->mutex);
ath9k_ps_wakeup(sc);
tsf = ath9k_hw_gettsf64(sc->sc_ah);
ath9k_ps_restore(sc);
mutex_unlock(&sc->mutex);
return tsf;
@ -1952,7 +1989,9 @@ static void ath9k_set_tsf(struct ieee80211_hw *hw, u64 tsf)
struct ath_softc *sc = aphy->sc;
mutex_lock(&sc->mutex);
ath9k_ps_wakeup(sc);
ath9k_hw_settsf64(sc->sc_ah, tsf);
ath9k_ps_restore(sc);
mutex_unlock(&sc->mutex);
}
@ -2111,6 +2150,7 @@ struct ieee80211_ops ath9k_ops = {
.start = ath9k_start,
.stop = ath9k_stop,
.add_interface = ath9k_add_interface,
.change_interface = ath9k_change_interface,
.remove_interface = ath9k_remove_interface,
.config = ath9k_config,
.configure_filter = ath9k_configure_filter,

View File

@ -309,6 +309,9 @@ static int ath_pci_resume(struct device *device)
AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1);
sc->ps_idle = true;
ath_radio_disable(sc, hw);
return 0;
}

View File

@ -1373,7 +1373,7 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband,
an = (struct ath_node *)sta->drv_priv;
if(ath_tx_aggr_check(sc, an, tid))
ieee80211_start_tx_ba_session(sta, tid);
ieee80211_start_tx_ba_session(sta, tid, 0);
}
}

View File

@ -288,7 +288,6 @@ void ath9k_wiphy_chan_work(struct work_struct *work)
/* sync hw configuration for hw code */
common->hw = aphy->hw;
ath_update_chainmask(sc, sc->chan_is_ht);
if (ath_set_channel(sc, aphy->hw,
&sc->sc_ah->channels[sc->chan_idx]) < 0) {
printk(KERN_DEBUG "ath9k: Failed to set channel for new "

View File

@ -838,7 +838,7 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
ath_tx_txqaddbuf(sc, txq, &bf_q);
TX_STAT_INC(txq->axq_qnum, a_aggr);
} while (txq->axq_depth < ATH_AGGR_MIN_QDEPTH &&
} while (txq->axq_ampdu_depth < ATH_AGGR_MIN_QDEPTH &&
status != ATH_AGGR_BAW_CLOSED);
}
@ -999,6 +999,7 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
INIT_LIST_HEAD(&txq->axq_acq);
spin_lock_init(&txq->axq_lock);
txq->axq_depth = 0;
txq->axq_ampdu_depth = 0;
txq->axq_tx_inprogress = false;
sc->tx.txqsetup |= 1<<qnum;
@ -1068,6 +1069,12 @@ int ath_cabq_update(struct ath_softc *sc)
return 0;
}
static bool bf_is_ampdu_not_probing(struct ath_buf *bf)
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(bf->bf_mpdu);
return bf_isampdu(bf) && !(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE);
}
/*
* Drain a given TX queue (could be Beacon or Data)
*
@ -1126,7 +1133,8 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
}
txq->axq_depth--;
if (bf_is_ampdu_not_probing(bf))
txq->axq_ampdu_depth--;
spin_unlock_bh(&txq->axq_lock);
if (bf_isampdu(bf))
@ -1316,6 +1324,8 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
ath9k_hw_txstart(ah, txq->axq_qnum);
}
txq->axq_depth++;
if (bf_is_ampdu_not_probing(bf))
txq->axq_ampdu_depth++;
}
static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
@ -1336,7 +1346,7 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
*/
if (!list_empty(&tid->buf_q) || tid->paused ||
!BAW_WITHIN(tid->seq_start, tid->baw_size, fi->seqno) ||
txctl->txq->axq_depth >= ATH_AGGR_MIN_QDEPTH) {
txctl->txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH) {
/*
* Add this frame to software queue for scheduling later
* for aggregation.
@ -1685,17 +1695,20 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf,
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct list_head bf_head;
struct ath_atx_tid *tid;
struct ath_atx_tid *tid = NULL;
u8 tidno;
spin_lock_bh(&txctl->txq->axq_lock);
if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && txctl->an) {
if (ieee80211_is_data_qos(hdr->frame_control) && txctl->an) {
tidno = ieee80211_get_qos_ctl(hdr)[0] &
IEEE80211_QOS_CTL_TID_MASK;
tid = ATH_AN_2_TID(txctl->an, tidno);
WARN_ON(tid->ac->txq != txctl->txq);
}
if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) && tid) {
/*
* Try aggregation if it's a unicast data frame
* and the destination is HT capable.
@ -1712,7 +1725,7 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf,
ar9003_hw_set_paprd_txdesc(sc->sc_ah, bf->bf_desc,
bf->bf_state.bfs_paprd);
ath_tx_send_normal(sc, txctl->txq, NULL, &bf_head);
ath_tx_send_normal(sc, txctl->txq, tid, &bf_head);
}
spin_unlock_bh(&txctl->txq->axq_lock);
@ -2037,6 +2050,9 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
txq->axq_tx_inprogress = false;
if (bf_held)
list_del(&bf_held->list);
if (bf_is_ampdu_not_probing(bf))
txq->axq_ampdu_depth--;
spin_unlock_bh(&txq->axq_lock);
if (bf_held)
@ -2165,6 +2181,8 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
INCR(txq->txq_tailidx, ATH_TXFIFO_DEPTH);
txq->axq_depth--;
txq->axq_tx_inprogress = false;
if (bf_is_ampdu_not_probing(bf))
txq->axq_ampdu_depth--;
spin_unlock_bh(&txq->axq_lock);
txok = !(txs.ts_status & ATH9K_TXERR_MASK);

View File

@ -58,6 +58,8 @@ bool ath_hw_keyreset(struct ath_common *common, u16 entry)
REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0);
REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), 0);
REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0);
if (common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED)
REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), 0);
}

View File

@ -342,6 +342,14 @@ int ath_reg_notifier_apply(struct wiphy *wiphy,
/* We always apply this */
ath_reg_apply_radar_flags(wiphy);
/*
* This would happen when we have sent a custom regulatory request
* a world regulatory domain and the scheduler hasn't yet processed
* any pending requests in the queue.
*/
if (!request)
return 0;
switch (request->initiator) {
case NL80211_REGDOM_SET_BY_DRIVER:
case NL80211_REGDOM_SET_BY_CORE:

View File

@ -416,10 +416,10 @@ enum {
/* 802.11 core specific TM State Low (SSB_TMSLOW) flags */
#define B43_TMSLOW_GMODE 0x20000000 /* G Mode Enable */
#define B43_TMSLOW_PHYCLKSPEED 0x00C00000 /* PHY clock speed mask (N-PHY only) */
#define B43_TMSLOW_PHYCLKSPEED_40MHZ 0x00000000 /* 40 MHz PHY */
#define B43_TMSLOW_PHYCLKSPEED_80MHZ 0x00400000 /* 80 MHz PHY */
#define B43_TMSLOW_PHYCLKSPEED_160MHZ 0x00800000 /* 160 MHz PHY */
#define B43_TMSLOW_PHY_BANDWIDTH 0x00C00000 /* PHY band width and clock speed mask (N-PHY only) */
#define B43_TMSLOW_PHY_BANDWIDTH_10MHZ 0x00000000 /* 10 MHz bandwidth, 40 MHz PHY */
#define B43_TMSLOW_PHY_BANDWIDTH_20MHZ 0x00400000 /* 20 MHz bandwidth, 80 MHz PHY */
#define B43_TMSLOW_PHY_BANDWIDTH_40MHZ 0x00800000 /* 40 MHz bandwidth, 160 MHz PHY */
#define B43_TMSLOW_PLLREFSEL 0x00200000 /* PLL Frequency Reference Select (rev >= 5) */
#define B43_TMSLOW_MACPHYCLKEN 0x00100000 /* MAC PHY Clock Control Enable (rev >= 5) */
#define B43_TMSLOW_PHYRESET 0x00080000 /* PHY Reset */

View File

@ -1150,12 +1150,8 @@ void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags)
flags |= B43_TMSLOW_PHYCLKEN;
flags |= B43_TMSLOW_PHYRESET;
if (dev->phy.type == B43_PHYTYPE_N) {
if (b43_channel_type_is_40mhz(dev->phy.channel_type))
flags |= B43_TMSLOW_PHYCLKSPEED_160MHZ;
else
flags |= B43_TMSLOW_PHYCLKSPEED_80MHZ;
}
if (dev->phy.type == B43_PHYTYPE_N)
flags |= B43_TMSLOW_PHY_BANDWIDTH_20MHZ; /* Make 20 MHz def */
ssb_device_enable(dev->dev, flags);
msleep(2); /* Wait for the PLL to turn on. */

View File

@ -1209,29 +1209,18 @@ static void b43_nphy_workarounds(struct b43_wldev *dev)
b43_radio_set(dev, B2055_C2_TX_RF_SPARE, 0x8);
}
/* TODO: convert to b43_ntab_write? */
b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2000);
b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x000A);
b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2010);
b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x000A);
b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2002);
b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0xCDAA);
b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2012);
b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0xCDAA);
b43_ntab_write(dev, B43_NTAB16(8, 0x00), 0x000A);
b43_ntab_write(dev, B43_NTAB16(8, 0x10), 0x000A);
b43_ntab_write(dev, B43_NTAB16(8, 0x02), 0xCDAA);
b43_ntab_write(dev, B43_NTAB16(8, 0x12), 0xCDAA);
if (dev->phy.rev < 2) {
b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2008);
b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0000);
b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2018);
b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0000);
b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2007);
b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x7AAB);
b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2017);
b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x7AAB);
b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2006);
b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0800);
b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x2016);
b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0800);
b43_ntab_write(dev, B43_NTAB16(8, 0x08), 0x0000);
b43_ntab_write(dev, B43_NTAB16(8, 0x18), 0x0000);
b43_ntab_write(dev, B43_NTAB16(8, 0x07), 0x7AAB);
b43_ntab_write(dev, B43_NTAB16(8, 0x17), 0x7AAB);
b43_ntab_write(dev, B43_NTAB16(8, 0x06), 0x0800);
b43_ntab_write(dev, B43_NTAB16(8, 0x16), 0x0800);
}
b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8);
@ -3278,9 +3267,9 @@ static void b43_nphy_mac_phy_clock_set(struct b43_wldev *dev, bool on)
{
u32 tmslow = ssb_read32(dev->dev, SSB_TMSLOW);
if (on)
tmslow |= SSB_TMSLOW_PHYCLK;
tmslow |= B43_TMSLOW_MACPHYCLKEN;
else
tmslow &= ~SSB_TMSLOW_PHYCLK;
tmslow &= ~B43_TMSLOW_MACPHYCLKEN;
ssb_write32(dev->dev, SSB_TMSLOW, tmslow);
}

View File

@ -1835,12 +1835,12 @@ void b43_nphy_rev0_1_2_tables_init(struct b43_wldev *dev)
/* Volatile tables */
ntab_upload(dev, B43_NTAB_BDI, b43_ntab_bdi);
ntab_upload(dev, B43_NTAB_PILOTLT, b43_ntab_pilotlt);
ntab_upload(dev, B43_NTAB_C0_GAINCTL, b43_ntab_gainctl0);
ntab_upload(dev, B43_NTAB_C1_GAINCTL, b43_ntab_gainctl1);
ntab_upload(dev, B43_NTAB_C0_ESTPLT, b43_ntab_estimatepowerlt0);
ntab_upload(dev, B43_NTAB_C1_ESTPLT, b43_ntab_estimatepowerlt1);
ntab_upload(dev, B43_NTAB_C0_ADJPLT, b43_ntab_adjustpower0);
ntab_upload(dev, B43_NTAB_C1_ADJPLT, b43_ntab_adjustpower1);
ntab_upload(dev, B43_NTAB_C0_GAINCTL, b43_ntab_gainctl0);
ntab_upload(dev, B43_NTAB_C1_GAINCTL, b43_ntab_gainctl1);
ntab_upload(dev, B43_NTAB_C0_IQLT, b43_ntab_iqlt0);
ntab_upload(dev, B43_NTAB_C1_IQLT, b43_ntab_iqlt1);
ntab_upload(dev, B43_NTAB_C0_LOFEEDTH, b43_ntab_loftlt0);

View File

@ -147,7 +147,11 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv)
priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR;
priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant);
if (priv->cfg->rx_with_siso_diversity)
priv->hw_params.rx_chains_num = 1;
else
priv->hw_params.rx_chains_num =
num_of_ant(priv->cfg->valid_rx_ant);
priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant;
priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant;
@ -272,60 +276,49 @@ static struct iwl_ht_params iwl1000_ht_params = {
.use_rts_for_aggregation = true, /* use rts/cts protection */
};
#define IWL_DEVICE_1000 \
.fw_name_pre = IWL1000_FW_PRE, \
.ucode_api_max = IWL1000_UCODE_API_MAX, \
.ucode_api_min = IWL1000_UCODE_API_MIN, \
.eeprom_ver = EEPROM_1000_EEPROM_VERSION, \
.eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, \
.ops = &iwl1000_ops, \
.mod_params = &iwlagn_mod_params, \
.base_params = &iwl1000_base_params, \
.led_mode = IWL_LED_BLINK
struct iwl_cfg iwl1000_bgn_cfg = {
.name = "Intel(R) Centrino(R) Wireless-N 1000 BGN",
.fw_name_pre = IWL1000_FW_PRE,
.ucode_api_max = IWL1000_UCODE_API_MAX,
.ucode_api_min = IWL1000_UCODE_API_MIN,
.eeprom_ver = EEPROM_1000_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION,
.ops = &iwl1000_ops,
.mod_params = &iwlagn_mod_params,
.base_params = &iwl1000_base_params,
IWL_DEVICE_1000,
.ht_params = &iwl1000_ht_params,
.led_mode = IWL_LED_BLINK,
};
struct iwl_cfg iwl1000_bg_cfg = {
.name = "Intel(R) Centrino(R) Wireless-N 1000 BG",
.fw_name_pre = IWL1000_FW_PRE,
.ucode_api_max = IWL1000_UCODE_API_MAX,
.ucode_api_min = IWL1000_UCODE_API_MIN,
.eeprom_ver = EEPROM_1000_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION,
.ops = &iwl1000_ops,
.mod_params = &iwlagn_mod_params,
.base_params = &iwl1000_base_params,
.led_mode = IWL_LED_BLINK,
IWL_DEVICE_1000,
};
#define IWL_DEVICE_100 \
.fw_name_pre = IWL100_FW_PRE, \
.ucode_api_max = IWL100_UCODE_API_MAX, \
.ucode_api_min = IWL100_UCODE_API_MIN, \
.eeprom_ver = EEPROM_1000_EEPROM_VERSION, \
.eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, \
.ops = &iwl1000_ops, \
.mod_params = &iwlagn_mod_params, \
.base_params = &iwl1000_base_params, \
.led_mode = IWL_LED_RF_STATE, \
.rx_with_siso_diversity = true
struct iwl_cfg iwl100_bgn_cfg = {
.name = "Intel(R) Centrino(R) Wireless-N 100 BGN",
.fw_name_pre = IWL100_FW_PRE,
.ucode_api_max = IWL100_UCODE_API_MAX,
.ucode_api_min = IWL100_UCODE_API_MIN,
.eeprom_ver = EEPROM_1000_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION,
.ops = &iwl1000_ops,
.mod_params = &iwlagn_mod_params,
.base_params = &iwl1000_base_params,
IWL_DEVICE_100,
.ht_params = &iwl1000_ht_params,
.led_mode = IWL_LED_RF_STATE,
.use_new_eeprom_reading = true,
};
struct iwl_cfg iwl100_bg_cfg = {
.name = "Intel(R) Centrino(R) Wireless-N 100 BG",
.fw_name_pre = IWL100_FW_PRE,
.ucode_api_max = IWL100_UCODE_API_MAX,
.ucode_api_min = IWL100_UCODE_API_MIN,
.eeprom_ver = EEPROM_1000_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION,
.ops = &iwl1000_ops,
.mod_params = &iwlagn_mod_params,
.base_params = &iwl1000_base_params,
.led_mode = IWL_LED_RF_STATE,
.use_new_eeprom_reading = true,
IWL_DEVICE_100,
};
MODULE_FIRMWARE(IWL1000_MODULE_FIRMWARE(IWL1000_UCODE_API_MAX));

View File

@ -520,65 +520,44 @@ static struct iwl_ht_params iwl5000_ht_params = {
.use_rts_for_aggregation = true, /* use rts/cts protection */
};
#define IWL_DEVICE_5000 \
.fw_name_pre = IWL5000_FW_PRE, \
.ucode_api_max = IWL5000_UCODE_API_MAX, \
.ucode_api_min = IWL5000_UCODE_API_MIN, \
.eeprom_ver = EEPROM_5000_EEPROM_VERSION, \
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, \
.ops = &iwl5000_ops, \
.mod_params = &iwlagn_mod_params, \
.base_params = &iwl5000_base_params, \
.led_mode = IWL_LED_BLINK
struct iwl_cfg iwl5300_agn_cfg = {
.name = "Intel(R) Ultimate N WiFi Link 5300 AGN",
.fw_name_pre = IWL5000_FW_PRE,
.ucode_api_max = IWL5000_UCODE_API_MAX,
.ucode_api_min = IWL5000_UCODE_API_MIN,
.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
.ops = &iwl5000_ops,
.mod_params = &iwlagn_mod_params,
.base_params = &iwl5000_base_params,
IWL_DEVICE_5000,
.ht_params = &iwl5000_ht_params,
.led_mode = IWL_LED_BLINK,
};
struct iwl_cfg iwl5100_bgn_cfg = {
.name = "Intel(R) WiFi Link 5100 BGN",
.fw_name_pre = IWL5000_FW_PRE,
.ucode_api_max = IWL5000_UCODE_API_MAX,
.ucode_api_min = IWL5000_UCODE_API_MIN,
IWL_DEVICE_5000,
.valid_tx_ant = ANT_B, /* .cfg overwrite */
.valid_rx_ant = ANT_AB, /* .cfg overwrite */
.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
.ops = &iwl5000_ops,
.mod_params = &iwlagn_mod_params,
.base_params = &iwl5000_base_params,
.ht_params = &iwl5000_ht_params,
.led_mode = IWL_LED_BLINK,
};
struct iwl_cfg iwl5100_abg_cfg = {
.name = "Intel(R) WiFi Link 5100 ABG",
.fw_name_pre = IWL5000_FW_PRE,
.ucode_api_max = IWL5000_UCODE_API_MAX,
.ucode_api_min = IWL5000_UCODE_API_MIN,
IWL_DEVICE_5000,
.valid_tx_ant = ANT_B, /* .cfg overwrite */
.valid_rx_ant = ANT_AB, /* .cfg overwrite */
.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
.ops = &iwl5000_ops,
.mod_params = &iwlagn_mod_params,
.base_params = &iwl5000_base_params,
.led_mode = IWL_LED_BLINK,
};
struct iwl_cfg iwl5100_agn_cfg = {
.name = "Intel(R) WiFi Link 5100 AGN",
.fw_name_pre = IWL5000_FW_PRE,
.ucode_api_max = IWL5000_UCODE_API_MAX,
.ucode_api_min = IWL5000_UCODE_API_MIN,
IWL_DEVICE_5000,
.valid_tx_ant = ANT_B, /* .cfg overwrite */
.valid_rx_ant = ANT_AB, /* .cfg overwrite */
.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
.ops = &iwl5000_ops,
.mod_params = &iwlagn_mod_params,
.base_params = &iwl5000_base_params,
.ht_params = &iwl5000_ht_params,
.led_mode = IWL_LED_BLINK,
};
struct iwl_cfg iwl5350_agn_cfg = {
@ -593,35 +572,32 @@ struct iwl_cfg iwl5350_agn_cfg = {
.base_params = &iwl5000_base_params,
.ht_params = &iwl5000_ht_params,
.led_mode = IWL_LED_BLINK,
.internal_wimax_coex = true,
};
#define IWL_DEVICE_5150 \
.fw_name_pre = IWL5150_FW_PRE, \
.ucode_api_max = IWL5150_UCODE_API_MAX, \
.ucode_api_min = IWL5150_UCODE_API_MIN, \
.eeprom_ver = EEPROM_5050_EEPROM_VERSION, \
.eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, \
.ops = &iwl5150_ops, \
.mod_params = &iwlagn_mod_params, \
.base_params = &iwl5000_base_params, \
.need_dc_calib = true, \
.led_mode = IWL_LED_BLINK, \
.internal_wimax_coex = true
struct iwl_cfg iwl5150_agn_cfg = {
.name = "Intel(R) WiMAX/WiFi Link 5150 AGN",
.fw_name_pre = IWL5150_FW_PRE,
.ucode_api_max = IWL5150_UCODE_API_MAX,
.ucode_api_min = IWL5150_UCODE_API_MIN,
.eeprom_ver = EEPROM_5050_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION,
.ops = &iwl5150_ops,
.mod_params = &iwlagn_mod_params,
.base_params = &iwl5000_base_params,
IWL_DEVICE_5150,
.ht_params = &iwl5000_ht_params,
.need_dc_calib = true,
.led_mode = IWL_LED_BLINK,
};
struct iwl_cfg iwl5150_abg_cfg = {
.name = "Intel(R) WiMAX/WiFi Link 5150 ABG",
.fw_name_pre = IWL5150_FW_PRE,
.ucode_api_max = IWL5150_UCODE_API_MAX,
.ucode_api_min = IWL5150_UCODE_API_MIN,
.eeprom_ver = EEPROM_5050_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION,
.ops = &iwl5150_ops,
.mod_params = &iwlagn_mod_params,
.base_params = &iwl5000_base_params,
.need_dc_calib = true,
.led_mode = IWL_LED_BLINK,
IWL_DEVICE_5150,
};
MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX));

View File

@ -182,7 +182,11 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv)
priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR;
priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant);
if (priv->cfg->rx_with_siso_diversity)
priv->hw_params.rx_chains_num = 1;
else
priv->hw_params.rx_chains_num =
num_of_ant(priv->cfg->valid_rx_ant);
priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant;
priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant;
@ -511,7 +515,7 @@ static struct iwl_base_params iwl6050_base_params = {
.chain_noise_calib_by_driver = true,
.shadow_reg_enable = true,
};
static struct iwl_base_params iwl6000_coex_base_params = {
static struct iwl_base_params iwl6000_g2_base_params = {
.eeprom_size = OTP_LOW_IMAGE_SIZE,
.num_of_queues = IWLAGN_NUM_QUEUES,
.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
@ -520,7 +524,7 @@ static struct iwl_base_params iwl6000_coex_base_params = {
.use_bsm = false,
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
.shadow_ram_support = true,
.led_compensation = 51,
.led_compensation = 57,
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
.supports_idle = true,
.adv_thermal_throttle = true,
@ -550,243 +554,156 @@ static struct iwl_bt_params iwl6000_bt_params = {
.bt_sco_disable = true,
};
#define IWL_DEVICE_6005 \
.fw_name_pre = IWL6000G2A_FW_PRE, \
.ucode_api_max = IWL6000G2_UCODE_API_MAX, \
.ucode_api_min = IWL6000G2_UCODE_API_MIN, \
.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, \
.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, \
.ops = &iwl6000_ops, \
.mod_params = &iwlagn_mod_params, \
.base_params = &iwl6000_g2_base_params, \
.need_dc_calib = true, \
.need_temp_offset_calib = true, \
.led_mode = IWL_LED_RF_STATE
struct iwl_cfg iwl6005_2agn_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N 6205 AGN",
.fw_name_pre = IWL6000G2A_FW_PRE,
.ucode_api_max = IWL6000G2_UCODE_API_MAX,
.ucode_api_min = IWL6000G2_UCODE_API_MIN,
.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
.ops = &iwl6000_ops,
.mod_params = &iwlagn_mod_params,
.base_params = &iwl6000_base_params,
IWL_DEVICE_6005,
.ht_params = &iwl6000_ht_params,
.need_dc_calib = true,
.need_temp_offset_calib = true,
.led_mode = IWL_LED_RF_STATE,
.use_new_eeprom_reading = true,
};
struct iwl_cfg iwl6005_2abg_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N 6205 ABG",
.fw_name_pre = IWL6000G2A_FW_PRE,
.ucode_api_max = IWL6000G2_UCODE_API_MAX,
.ucode_api_min = IWL6000G2_UCODE_API_MIN,
.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
.ops = &iwl6000_ops,
.mod_params = &iwlagn_mod_params,
.base_params = &iwl6000_base_params,
.need_dc_calib = true,
.need_temp_offset_calib = true,
.led_mode = IWL_LED_RF_STATE,
.use_new_eeprom_reading = true,
IWL_DEVICE_6005,
};
struct iwl_cfg iwl6005_2bg_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N 6205 BG",
.fw_name_pre = IWL6000G2A_FW_PRE,
.ucode_api_max = IWL6000G2_UCODE_API_MAX,
.ucode_api_min = IWL6000G2_UCODE_API_MIN,
.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
.ops = &iwl6000_ops,
.mod_params = &iwlagn_mod_params,
.base_params = &iwl6000_base_params,
.need_dc_calib = true,
.need_temp_offset_calib = true,
.led_mode = IWL_LED_RF_STATE,
.use_new_eeprom_reading = true,
IWL_DEVICE_6005,
};
#define IWL_DEVICE_6030 \
.fw_name_pre = IWL6000G2B_FW_PRE, \
.ucode_api_max = IWL6000G2_UCODE_API_MAX, \
.ucode_api_min = IWL6000G2_UCODE_API_MIN, \
.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION, \
.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION, \
.ops = &iwl6000g2b_ops, \
.mod_params = &iwlagn_mod_params, \
.base_params = &iwl6000_g2_base_params, \
.bt_params = &iwl6000_bt_params, \
.need_dc_calib = true, \
.need_temp_offset_calib = true, \
.led_mode = IWL_LED_RF_STATE, \
.adv_pm = true, \
/* \
*Due to bluetooth, we transmit 2.4 GHz probes \
* only on antenna A \
*/ \
.scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A
struct iwl_cfg iwl6030_2agn_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N 6230 AGN",
.fw_name_pre = IWL6000G2B_FW_PRE,
.ucode_api_max = IWL6000G2_UCODE_API_MAX,
.ucode_api_min = IWL6000G2_UCODE_API_MIN,
.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
.ops = &iwl6000g2b_ops,
.mod_params = &iwlagn_mod_params,
.base_params = &iwl6000_coex_base_params,
.bt_params = &iwl6000_bt_params,
IWL_DEVICE_6030,
.ht_params = &iwl6000_ht_params,
.need_dc_calib = true,
.need_temp_offset_calib = true,
.led_mode = IWL_LED_RF_STATE,
.adv_pm = true,
/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
.scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
.use_new_eeprom_reading = true,
};
struct iwl_cfg iwl6030_2abg_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N 6230 ABG",
.fw_name_pre = IWL6000G2B_FW_PRE,
.ucode_api_max = IWL6000G2_UCODE_API_MAX,
.ucode_api_min = IWL6000G2_UCODE_API_MIN,
.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
.ops = &iwl6000g2b_ops,
.mod_params = &iwlagn_mod_params,
.base_params = &iwl6000_coex_base_params,
.bt_params = &iwl6000_bt_params,
.need_dc_calib = true,
.need_temp_offset_calib = true,
.led_mode = IWL_LED_RF_STATE,
.adv_pm = true,
/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
.scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
.use_new_eeprom_reading = true,
IWL_DEVICE_6030,
};
struct iwl_cfg iwl6030_2bgn_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N 6230 BGN",
.fw_name_pre = IWL6000G2B_FW_PRE,
.ucode_api_max = IWL6000G2_UCODE_API_MAX,
.ucode_api_min = IWL6000G2_UCODE_API_MIN,
.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
.ops = &iwl6000g2b_ops,
.mod_params = &iwlagn_mod_params,
.base_params = &iwl6000_coex_base_params,
.bt_params = &iwl6000_bt_params,
IWL_DEVICE_6030,
.ht_params = &iwl6000_ht_params,
.need_dc_calib = true,
.need_temp_offset_calib = true,
.led_mode = IWL_LED_RF_STATE,
.adv_pm = true,
/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
.scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
.use_new_eeprom_reading = true,
};
struct iwl_cfg iwl6030_2bg_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N 6230 BG",
.fw_name_pre = IWL6000G2B_FW_PRE,
.ucode_api_max = IWL6000G2_UCODE_API_MAX,
.ucode_api_min = IWL6000G2_UCODE_API_MIN,
.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
.ops = &iwl6000g2b_ops,
.mod_params = &iwlagn_mod_params,
.base_params = &iwl6000_coex_base_params,
.bt_params = &iwl6000_bt_params,
.need_dc_calib = true,
.need_temp_offset_calib = true,
.led_mode = IWL_LED_RF_STATE,
.adv_pm = true,
/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
.scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
.use_new_eeprom_reading = true,
IWL_DEVICE_6030,
};
struct iwl_cfg iwl1030_bgn_cfg = {
.name = "Intel(R) Centrino(R) Wireless-N 1030 BGN",
.fw_name_pre = IWL6000G2B_FW_PRE,
.ucode_api_max = IWL6000G2_UCODE_API_MAX,
.ucode_api_min = IWL6000G2_UCODE_API_MIN,
.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
.ops = &iwl6000g2b_ops,
.mod_params = &iwlagn_mod_params,
.base_params = &iwl6000_coex_base_params,
.bt_params = &iwl6000_bt_params,
IWL_DEVICE_6030,
.ht_params = &iwl6000_ht_params,
.need_dc_calib = true,
.need_temp_offset_calib = true,
.led_mode = IWL_LED_RF_STATE,
.adv_pm = true,
/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
.scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
.use_new_eeprom_reading = true,
};
struct iwl_cfg iwl1030_bg_cfg = {
.name = "Intel(R) Centrino(R) Wireless-N 1030 BG",
.fw_name_pre = IWL6000G2B_FW_PRE,
.ucode_api_max = IWL6000G2_UCODE_API_MAX,
.ucode_api_min = IWL6000G2_UCODE_API_MIN,
.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
.ops = &iwl6000g2b_ops,
.mod_params = &iwlagn_mod_params,
.base_params = &iwl6000_coex_base_params,
.bt_params = &iwl6000_bt_params,
.need_dc_calib = true,
.need_temp_offset_calib = true,
.led_mode = IWL_LED_RF_STATE,
.adv_pm = true,
/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
.scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
.use_new_eeprom_reading = true,
IWL_DEVICE_6030,
};
struct iwl_cfg iwl130_bgn_cfg = {
.name = "Intel(R) Centrino(R) Wireless-N 130 BGN",
IWL_DEVICE_6030,
.ht_params = &iwl6000_ht_params,
.rx_with_siso_diversity = true,
};
struct iwl_cfg iwl130_bg_cfg = {
.name = "Intel(R) Centrino(R) Wireless-N 130 BG",
IWL_DEVICE_6030,
.rx_with_siso_diversity = true,
};
/*
* "i": Internal configuration, use internal Power Amplifier
*/
#define IWL_DEVICE_6000i \
.fw_name_pre = IWL6000_FW_PRE, \
.ucode_api_max = IWL6000_UCODE_API_MAX, \
.ucode_api_min = IWL6000_UCODE_API_MIN, \
.valid_tx_ant = ANT_BC, /* .cfg overwrite */ \
.valid_rx_ant = ANT_BC, /* .cfg overwrite */ \
.eeprom_ver = EEPROM_6000_EEPROM_VERSION, \
.eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION, \
.ops = &iwl6000_ops, \
.mod_params = &iwlagn_mod_params, \
.base_params = &iwl6000_base_params, \
.pa_type = IWL_PA_INTERNAL, \
.led_mode = IWL_LED_BLINK
struct iwl_cfg iwl6000i_2agn_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N 6200 AGN",
.fw_name_pre = IWL6000_FW_PRE,
.ucode_api_max = IWL6000_UCODE_API_MAX,
.ucode_api_min = IWL6000_UCODE_API_MIN,
.valid_tx_ant = ANT_BC, /* .cfg overwrite */
.valid_rx_ant = ANT_BC, /* .cfg overwrite */
.eeprom_ver = EEPROM_6000_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION,
.ops = &iwl6000_ops,
.mod_params = &iwlagn_mod_params,
.base_params = &iwl6000_base_params,
IWL_DEVICE_6000i,
.ht_params = &iwl6000_ht_params,
.pa_type = IWL_PA_INTERNAL,
.led_mode = IWL_LED_BLINK,
};
struct iwl_cfg iwl6000i_2abg_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N 6200 ABG",
.fw_name_pre = IWL6000_FW_PRE,
.ucode_api_max = IWL6000_UCODE_API_MAX,
.ucode_api_min = IWL6000_UCODE_API_MIN,
.valid_tx_ant = ANT_BC, /* .cfg overwrite */
.valid_rx_ant = ANT_BC, /* .cfg overwrite */
.eeprom_ver = EEPROM_6000_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION,
.ops = &iwl6000_ops,
.mod_params = &iwlagn_mod_params,
.base_params = &iwl6000_base_params,
.pa_type = IWL_PA_INTERNAL,
.led_mode = IWL_LED_BLINK,
IWL_DEVICE_6000i,
};
struct iwl_cfg iwl6000i_2bg_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N 6200 BG",
.fw_name_pre = IWL6000_FW_PRE,
.ucode_api_max = IWL6000_UCODE_API_MAX,
.ucode_api_min = IWL6000_UCODE_API_MIN,
.valid_tx_ant = ANT_BC, /* .cfg overwrite */
.valid_rx_ant = ANT_BC, /* .cfg overwrite */
.eeprom_ver = EEPROM_6000_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_6000_TX_POWER_VERSION,
.ops = &iwl6000_ops,
.mod_params = &iwlagn_mod_params,
.base_params = &iwl6000_base_params,
.pa_type = IWL_PA_INTERNAL,
.led_mode = IWL_LED_BLINK,
IWL_DEVICE_6000i,
};
#define IWL_DEVICE_6050 \
.fw_name_pre = IWL6050_FW_PRE, \
.ucode_api_max = IWL6050_UCODE_API_MAX, \
.ucode_api_min = IWL6050_UCODE_API_MIN, \
.ops = &iwl6050_ops, \
.eeprom_ver = EEPROM_6050_EEPROM_VERSION, \
.eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION, \
.mod_params = &iwlagn_mod_params, \
.base_params = &iwl6050_base_params, \
.need_dc_calib = true, \
.led_mode = IWL_LED_BLINK, \
.internal_wimax_coex = true
struct iwl_cfg iwl6050_2agn_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N + WiMAX 6250 AGN",
.fw_name_pre = IWL6050_FW_PRE,
.ucode_api_max = IWL6050_UCODE_API_MAX,
.ucode_api_min = IWL6050_UCODE_API_MIN,
.ops = &iwl6050_ops,
.eeprom_ver = EEPROM_6050_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION,
.mod_params = &iwlagn_mod_params,
.base_params = &iwl6050_base_params,
IWL_DEVICE_6050,
.ht_params = &iwl6000_ht_params,
.need_dc_calib = true,
.led_mode = IWL_LED_BLINK,
};
struct iwl_cfg iwl6050_2abg_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N + WiMAX 6250 ABG",
IWL_DEVICE_6050,
};
struct iwl_cfg iwl6150_bgn_cfg = {
@ -802,21 +719,7 @@ struct iwl_cfg iwl6150_bgn_cfg = {
.ht_params = &iwl6000_ht_params,
.need_dc_calib = true,
.led_mode = IWL_LED_RF_STATE,
.use_new_eeprom_reading = true,
};
struct iwl_cfg iwl6050_2abg_cfg = {
.name = "Intel(R) Centrino(R) Advanced-N + WiMAX 6250 ABG",
.fw_name_pre = IWL6050_FW_PRE,
.ucode_api_max = IWL6050_UCODE_API_MAX,
.ucode_api_min = IWL6050_UCODE_API_MIN,
.eeprom_ver = EEPROM_6050_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION,
.ops = &iwl6050_ops,
.mod_params = &iwlagn_mod_params,
.base_params = &iwl6050_base_params,
.need_dc_calib = true,
.led_mode = IWL_LED_BLINK,
.internal_wimax_coex = true,
};
struct iwl_cfg iwl6000_3agn_cfg = {
@ -834,45 +737,6 @@ struct iwl_cfg iwl6000_3agn_cfg = {
.led_mode = IWL_LED_BLINK,
};
struct iwl_cfg iwl130_bgn_cfg = {
.name = "Intel(R) Centrino(R) Wireless-N 130 BGN",
.fw_name_pre = IWL6000G2B_FW_PRE,
.ucode_api_max = IWL6000G2_UCODE_API_MAX,
.ucode_api_min = IWL6000G2_UCODE_API_MIN,
.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
.ops = &iwl6000g2b_ops,
.mod_params = &iwlagn_mod_params,
.base_params = &iwl6000_coex_base_params,
.bt_params = &iwl6000_bt_params,
.ht_params = &iwl6000_ht_params,
.need_dc_calib = true,
.led_mode = IWL_LED_RF_STATE,
.adv_pm = true,
/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
.scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
.use_new_eeprom_reading = true,
};
struct iwl_cfg iwl130_bg_cfg = {
.name = "Intel(R) Centrino(R) Wireless-N 130 BG",
.fw_name_pre = IWL6000G2B_FW_PRE,
.ucode_api_max = IWL6000G2_UCODE_API_MAX,
.ucode_api_min = IWL6000G2_UCODE_API_MIN,
.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,
.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,
.ops = &iwl6000g2b_ops,
.mod_params = &iwlagn_mod_params,
.base_params = &iwl6000_coex_base_params,
.bt_params = &iwl6000_bt_params,
.need_dc_calib = true,
.led_mode = IWL_LED_RF_STATE,
.adv_pm = true,
/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
.scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
.use_new_eeprom_reading = true,
};
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));

View File

@ -856,6 +856,9 @@ ssize_t iwl_ucode_bt_stats_read(struct file *file,
if (!iwl_is_alive(priv))
return -EAGAIN;
if (!priv->bt_enable_flag)
return -EINVAL;
/* make request to uCode to retrieve statistics information */
mutex_lock(&priv->mutex);
ret = iwl_send_statistics_request(priv, CMD_SYNC, false);

View File

@ -75,109 +75,6 @@
#include "iwl-agn.h"
#include "iwl-io.h"
/************************** EEPROM BANDS ****************************
*
* The iwl_eeprom_band definitions below provide the mapping from the
* EEPROM contents to the specific channel number supported for each
* band.
*
* For example, iwl_priv->eeprom.band_3_channels[4] from the band_3
* definition below maps to physical channel 42 in the 5.2GHz spectrum.
* The specific geography and calibration information for that channel
* is contained in the eeprom map itself.
*
* During init, we copy the eeprom information and channel map
* information into priv->channel_info_24/52 and priv->channel_map_24/52
*
* channel_map_24/52 provides the index in the channel_info array for a
* given channel. We have to have two separate maps as there is channel
* overlap with the 2.4GHz and 5.2GHz spectrum as seen in band_1 and
* band_2
*
* A value of 0xff stored in the channel_map indicates that the channel
* is not supported by the hardware at all.
*
* A value of 0xfe in the channel_map indicates that the channel is not
* valid for Tx with the current hardware. This means that
* while the system can tune and receive on a given channel, it may not
* be able to associate or transmit any frames on that
* channel. There is no corresponding channel information for that
* entry.
*
*********************************************************************/
/**
* struct iwl_txpwr_section: eeprom section information
* @offset: indirect address into eeprom image
* @count: number of "struct iwl_eeprom_enhanced_txpwr" in this section
* @band: band type for the section
* @is_common - true: common section, false: channel section
* @is_cck - true: cck section, false: not cck section
* @is_ht_40 - true: all channel in the section are HT40 channel,
* false: legacy or HT 20 MHz
* ignore if it is common section
* @iwl_eeprom_section_channel: channel array in the section,
* ignore if common section
*/
struct iwl_txpwr_section {
u32 offset;
u8 count;
enum ieee80211_band band;
bool is_common;
bool is_cck;
bool is_ht40;
u8 iwl_eeprom_section_channel[EEPROM_MAX_TXPOWER_SECTION_ELEMENTS];
};
/**
* section 1 - 3 are regulatory tx power apply to all channels based on
* modulation: CCK, OFDM
* Band: 2.4GHz, 5.2GHz
* section 4 - 10 are regulatory tx power apply to specified channels
* For example:
* 1L - Channel 1 Legacy
* 1HT - Channel 1 HT
* (1,+1) - Channel 1 HT40 "_above_"
*
* Section 1: all CCK channels
* Section 2: all 2.4 GHz OFDM (Legacy, HT and HT40) channels
* Section 3: all 5.2 GHz OFDM (Legacy, HT and HT40) channels
* Section 4: 2.4 GHz 20MHz channels: 1L, 1HT, 2L, 2HT, 10L, 10HT, 11L, 11HT
* Section 5: 2.4 GHz 40MHz channels: (1,+1) (2,+1) (6,+1) (7,+1) (9,+1)
* Section 6: 5.2 GHz 20MHz channels: 36L, 64L, 100L, 36HT, 64HT, 100HT
* Section 7: 5.2 GHz 40MHz channels: (36,+1) (60,+1) (100,+1)
* Section 8: 2.4 GHz channel: 13L, 13HT
* Section 9: 2.4 GHz channel: 140L, 140HT
* Section 10: 2.4 GHz 40MHz channels: (132,+1) (44,+1)
*
*/
static const struct iwl_txpwr_section enhinfo[] = {
{ EEPROM_LB_CCK_20_COMMON, 1, IEEE80211_BAND_2GHZ, true, true, false },
{ EEPROM_LB_OFDM_COMMON, 3, IEEE80211_BAND_2GHZ, true, false, false },
{ EEPROM_HB_OFDM_COMMON, 3, IEEE80211_BAND_5GHZ, true, false, false },
{ EEPROM_LB_OFDM_20_BAND, 8, IEEE80211_BAND_2GHZ,
false, false, false,
{1, 1, 2, 2, 10, 10, 11, 11 } },
{ EEPROM_LB_OFDM_HT40_BAND, 5, IEEE80211_BAND_2GHZ,
false, false, true,
{ 1, 2, 6, 7, 9 } },
{ EEPROM_HB_OFDM_20_BAND, 6, IEEE80211_BAND_5GHZ,
false, false, false,
{ 36, 64, 100, 36, 64, 100 } },
{ EEPROM_HB_OFDM_HT40_BAND, 3, IEEE80211_BAND_5GHZ,
false, false, true,
{ 36, 60, 100 } },
{ EEPROM_LB_OFDM_20_CHANNEL_13, 2, IEEE80211_BAND_2GHZ,
false, false, false,
{ 13, 13 } },
{ EEPROM_HB_OFDM_20_CHANNEL_140, 2, IEEE80211_BAND_5GHZ,
false, false, false,
{ 140, 140 } },
{ EEPROM_HB_OFDM_HT40_BAND_1, 2, IEEE80211_BAND_5GHZ,
false, false, true,
{ 132, 44 } },
};
/******************************************************************************
*
* EEPROM related functions
@ -306,15 +203,6 @@ static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv,
{
s8 max_txpower_avg = 0; /* (dBm) */
IWL_DEBUG_INFO(priv, "%d - "
"chain_a: %d dB chain_b: %d dB "
"chain_c: %d dB mimo2: %d dB mimo3: %d dB\n",
element,
enhanced_txpower[element].chain_a_max >> 1,
enhanced_txpower[element].chain_b_max >> 1,
enhanced_txpower[element].chain_c_max >> 1,
enhanced_txpower[element].mimo2_max >> 1,
enhanced_txpower[element].mimo3_max >> 1);
/* Take the highest tx power from any valid chains */
if ((priv->cfg->valid_tx_ant & ANT_A) &&
(enhanced_txpower[element].chain_a_max > max_txpower_avg))
@ -344,157 +232,6 @@ static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv,
return (max_txpower_avg & 0x01) + (max_txpower_avg >> 1);
}
/**
* iwl_update_common_txpower: update channel tx power
* update tx power per band based on EEPROM enhanced tx power info.
*/
static s8 iwl_update_common_txpower(struct iwl_priv *priv,
struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
int section, int element, s8 *max_txpower_in_half_dbm)
{
struct iwl_channel_info *ch_info;
int ch;
bool is_ht40 = false;
s8 max_txpower_avg; /* (dBm) */
/* it is common section, contain all type (Legacy, HT and HT40)
* based on the element in the section to determine
* is it HT 40 or not
*/
if (element == EEPROM_TXPOWER_COMMON_HT40_INDEX)
is_ht40 = true;
max_txpower_avg =
iwl_get_max_txpower_avg(priv, enhanced_txpower,
element, max_txpower_in_half_dbm);
ch_info = priv->channel_info;
for (ch = 0; ch < priv->channel_count; ch++) {
/* find matching band and update tx power if needed */
if ((ch_info->band == enhinfo[section].band) &&
(ch_info->max_power_avg < max_txpower_avg) &&
(!is_ht40)) {
/* Update regulatory-based run-time data */
ch_info->max_power_avg = ch_info->curr_txpow =
max_txpower_avg;
ch_info->scan_power = max_txpower_avg;
}
if ((ch_info->band == enhinfo[section].band) && is_ht40 &&
(ch_info->ht40_max_power_avg < max_txpower_avg)) {
/* Update regulatory-based run-time data */
ch_info->ht40_max_power_avg = max_txpower_avg;
}
ch_info++;
}
return max_txpower_avg;
}
/**
* iwl_update_channel_txpower: update channel tx power
* update channel tx power based on EEPROM enhanced tx power info.
*/
static s8 iwl_update_channel_txpower(struct iwl_priv *priv,
struct iwl_eeprom_enhanced_txpwr *enhanced_txpower,
int section, int element, s8 *max_txpower_in_half_dbm)
{
struct iwl_channel_info *ch_info;
int ch;
u8 channel;
s8 max_txpower_avg; /* (dBm) */
channel = enhinfo[section].iwl_eeprom_section_channel[element];
max_txpower_avg =
iwl_get_max_txpower_avg(priv, enhanced_txpower,
element, max_txpower_in_half_dbm);
ch_info = priv->channel_info;
for (ch = 0; ch < priv->channel_count; ch++) {
/* find matching channel and update tx power if needed */
if (ch_info->channel == channel) {
if ((ch_info->max_power_avg < max_txpower_avg) &&
(!enhinfo[section].is_ht40)) {
/* Update regulatory-based run-time data */
ch_info->max_power_avg = max_txpower_avg;
ch_info->curr_txpow = max_txpower_avg;
ch_info->scan_power = max_txpower_avg;
}
if ((enhinfo[section].is_ht40) &&
(ch_info->ht40_max_power_avg < max_txpower_avg)) {
/* Update regulatory-based run-time data */
ch_info->ht40_max_power_avg = max_txpower_avg;
}
break;
}
ch_info++;
}
return max_txpower_avg;
}
/**
* iwlcore_eeprom_enhanced_txpower: process enhanced tx power info
*/
static void iwlcore_eeprom_enhanced_txpower_old(struct iwl_priv *priv)
{
int eeprom_section_count = 0;
int section, element;
struct iwl_eeprom_enhanced_txpwr *enhanced_txpower;
u32 offset;
s8 max_txpower_avg; /* (dBm) */
s8 max_txpower_in_half_dbm; /* (half-dBm) */
/* Loop through all the sections
* adjust bands and channel's max tx power
* Set the tx_power_user_lmt to the highest power
* supported by any channels and chains
*/
for (section = 0; section < ARRAY_SIZE(enhinfo); section++) {
eeprom_section_count = enhinfo[section].count;
offset = enhinfo[section].offset;
enhanced_txpower = (struct iwl_eeprom_enhanced_txpwr *)
iwl_eeprom_query_addr(priv, offset);
/*
* check for valid entry -
* different version of EEPROM might contain different set
* of enhanced tx power table
* always check for valid entry before process
* the information
*/
if (!(enhanced_txpower->flags || enhanced_txpower->channel) ||
enhanced_txpower->delta_20_in_40)
continue;
for (element = 0; element < eeprom_section_count; element++) {
if (enhinfo[section].is_common)
max_txpower_avg =
iwl_update_common_txpower(priv,
enhanced_txpower, section,
element,
&max_txpower_in_half_dbm);
else
max_txpower_avg =
iwl_update_channel_txpower(priv,
enhanced_txpower, section,
element,
&max_txpower_in_half_dbm);
/* Update the tx_power_user_lmt to the highest power
* supported by any channel */
if (max_txpower_avg > priv->tx_power_user_lmt)
priv->tx_power_user_lmt = max_txpower_avg;
/*
* Update the tx_power_lmt_in_half_dbm to
* the highest power supported by any channel
*/
if (max_txpower_in_half_dbm >
priv->tx_power_lmt_in_half_dbm)
priv->tx_power_lmt_in_half_dbm =
max_txpower_in_half_dbm;
}
}
}
static void
iwlcore_eeprom_enh_txp_read_element(struct iwl_priv *priv,
struct iwl_eeprom_enhanced_txpwr *txp,
@ -533,7 +270,10 @@ iwlcore_eeprom_enh_txp_read_element(struct iwl_priv *priv,
#define EEPROM_TXP_ENTRY_LEN sizeof(struct iwl_eeprom_enhanced_txpwr)
#define EEPROM_TXP_SZ_OFFS (0x00 | INDIRECT_ADDRESS | INDIRECT_TXP_LIMIT_SIZE)
static void iwlcore_eeprom_enhanced_txpower_new(struct iwl_priv *priv)
#define TXP_CHECK_AND_PRINT(x) ((txp->flags & IWL_EEPROM_ENH_TXP_FL_##x) \
? # x " " : "")
void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv)
{
struct iwl_eeprom_enhanced_txpwr *txp_array, *txp;
int idx, entries;
@ -547,13 +287,39 @@ static void iwlcore_eeprom_enhanced_txpower_new(struct iwl_priv *priv)
entries = le16_to_cpup(txp_len) * 2 / EEPROM_TXP_ENTRY_LEN;
txp_array = (void *) iwlagn_eeprom_query_addr(priv, EEPROM_TXP_OFFS);
for (idx = 0; idx < entries; idx++) {
txp = &txp_array[idx];
/* skip invalid entries */
if (!(txp->flags & IWL_EEPROM_ENH_TXP_FL_VALID))
continue;
IWL_DEBUG_EEPROM(priv, "%s %d:\t %s%s%s%s%s%s%s%s (0x%02x)\n",
(txp->channel && (txp->flags &
IWL_EEPROM_ENH_TXP_FL_COMMON_TYPE)) ?
"Common " : (txp->channel) ?
"Channel" : "Common",
(txp->channel),
TXP_CHECK_AND_PRINT(VALID),
TXP_CHECK_AND_PRINT(BAND_52G),
TXP_CHECK_AND_PRINT(OFDM),
TXP_CHECK_AND_PRINT(40MHZ),
TXP_CHECK_AND_PRINT(HT_AP),
TXP_CHECK_AND_PRINT(RES1),
TXP_CHECK_AND_PRINT(RES2),
TXP_CHECK_AND_PRINT(COMMON_TYPE),
txp->flags);
IWL_DEBUG_EEPROM(priv, "\t\t chain_A: 0x%02x "
"chain_B: 0X%02x chain_C: 0X%02x\n",
txp->chain_a_max, txp->chain_b_max,
txp->chain_c_max);
IWL_DEBUG_EEPROM(priv, "\t\t MIMO2: 0x%02x "
"MIMO3: 0x%02x High 20_on_40: 0x%02x "
"Low 20_on_40: 0x%02x\n",
txp->mimo2_max, txp->mimo3_max,
((txp->delta_20_in_40 & 0xf0) >> 4),
(txp->delta_20_in_40 & 0x0f));
max_txp_avg = iwl_get_max_txpower_avg(priv, txp_array, idx,
&max_txp_avg_halfdbm);
@ -569,11 +335,3 @@ static void iwlcore_eeprom_enhanced_txpower_new(struct iwl_priv *priv)
iwlcore_eeprom_enh_txp_read_element(priv, txp, max_txp_avg);
}
}
void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv)
{
if (priv->cfg->use_new_eeprom_reading)
iwlcore_eeprom_enhanced_txpower_new(priv);
else
iwlcore_eeprom_enhanced_txpower_old(priv);
}

View File

@ -1845,6 +1845,7 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv)
bt_cmd.flags |= IWLAGN_BT_FLAG_CHANNEL_INHIBITION;
IWL_DEBUG_INFO(priv, "BT coex flag: 0X%x\n", bt_cmd.flags);
}
priv->bt_enable_flag = bt_cmd.flags;
if (priv->bt_full_concurrent)
memcpy(bt_cmd.bt3_lookup_table, iwlagn_concurrent_lookup,
sizeof(iwlagn_concurrent_lookup));

View File

@ -387,7 +387,7 @@ static int rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv,
if (load > IWL_AGG_LOAD_THRESHOLD) {
IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n",
sta->addr, tid);
ret = ieee80211_start_tx_ba_session(sta, tid);
ret = ieee80211_start_tx_ba_session(sta, tid, 5000);
if (ret == -EAGAIN) {
/*
* driver and mac80211 is out of sync
@ -2873,6 +2873,10 @@ void iwl_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_i
lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
lq_sta->is_agg = 0;
#ifdef CONFIG_MAC80211_DEBUGFS
lq_sta->dbg_fixed_rate = 0;
#endif
rs_initialize_lq(priv, conf, sta, lq_sta);
}

View File

@ -518,7 +518,14 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
mutex_lock(&priv->mutex);
if (WARN_ON(!ctx->vif)) {
if (unlikely(!iwl_is_ready(priv))) {
IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
mutex_unlock(&priv->mutex);
return;
}
if (unlikely(!ctx->vif)) {
IWL_DEBUG_MAC80211(priv, "leave - vif is NULL\n");
mutex_unlock(&priv->mutex);
return;
}

View File

@ -1237,7 +1237,6 @@ static int iwlagn_tx_status_reply_compressed_ba(struct iwl_priv *priv,
int i, sh, ack;
u16 seq_ctl = le16_to_cpu(ba_resp->seq_ctl);
u16 scd_flow = le16_to_cpu(ba_resp->scd_flow);
u64 bitmap, sent_bitmap;
int successes = 0;
struct ieee80211_tx_info *info;
@ -1278,6 +1277,8 @@ static int iwlagn_tx_status_reply_compressed_ba(struct iwl_priv *priv,
IWL_DEBUG_HT(priv, "agg frames sent:%d, acked:%d\n",
ba_resp->txed, ba_resp->txed_2_done);
} else {
u64 bitmap, sent_bitmap;
/* don't use 64-bit values for now */
bitmap = le64_to_cpu(ba_resp->bitmap) >> sh;
@ -1298,7 +1299,11 @@ static int iwlagn_tx_status_reply_compressed_ba(struct iwl_priv *priv,
sent_bitmap >>= 1;
++i;
}
IWL_DEBUG_TX_REPLY(priv, "Bitmap %llx\n",
(unsigned long long)bitmap);
}
info = IEEE80211_SKB_CB(priv->txq[scd_flow].txb[agg->start_idx].skb);
memset(&info->status, 0, sizeof(info->status));
info->flags |= IEEE80211_TX_STAT_ACK;
@ -1313,8 +1318,6 @@ static int iwlagn_tx_status_reply_compressed_ba(struct iwl_priv *priv,
}
iwlagn_hwrate_to_tx_control(priv, agg->rate_n_flags, info);
IWL_DEBUG_TX_REPLY(priv, "Bitmap %llx\n", (unsigned long long)bitmap);
return 0;
}

View File

@ -957,6 +957,22 @@ void iwl_irq_handle_error(struct iwl_priv *priv)
/* Cancel currently queued command. */
clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
/* W/A for WiFi/WiMAX coex and WiMAX own the RF */
if (priv->cfg->internal_wimax_coex &&
(!(iwl_read_prph(priv, APMG_CLK_CTRL_REG) &
APMS_CLK_VAL_MRB_FUNC_MODE) ||
(iwl_read_prph(priv, APMG_PS_CTRL_REG) &
APMG_PS_CTRL_VAL_RESET_REQ))) {
wake_up_interruptible(&priv->wait_command_queue);
/*
*Keep the restart process from trying to send host
* commands by clearing the INIT status bit
*/
clear_bit(STATUS_READY, &priv->status);
IWL_ERR(priv, "RF is used by WiMAX\n");
return;
}
IWL_ERR(priv, "Loaded firmware version: %s\n",
priv->hw->wiphy->fw_version);
@ -1207,6 +1223,7 @@ void iwl_send_bt_config(struct iwl_priv *priv)
else
bt_cmd.flags = BT_COEX_ENABLE;
priv->bt_enable_flag = bt_cmd.flags;
IWL_DEBUG_INFO(priv, "BT coex %s\n",
(bt_cmd.flags == BT_COEX_DISABLE) ? "disable" : "active");

View File

@ -364,6 +364,8 @@ struct iwl_ht_params {
* @scan_antennas: available antenna for scan operation
* @led_mode: 0=blinking, 1=On(RF On)/Off(RF Off)
* @adv_pm: advance power management
* @rx_with_siso_diversity: 1x1 device with rx antenna diversity
* @internal_wimax_coex: internal wifi/wimax combo device
*
* We enable the driver to be backward compatible wrt API version. The
* driver specifies which APIs it supports (with @ucode_api_max being the
@ -412,7 +414,8 @@ struct iwl_cfg {
u8 scan_tx_antennas[IEEE80211_NUM_BANDS];
enum iwl_led_mode led_mode;
const bool adv_pm;
const bool use_new_eeprom_reading; /* temporary, remove later */
const bool rx_with_siso_diversity;
const bool internal_wimax_coex;
};
/***************************

View File

@ -120,6 +120,7 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv)
/* 0x000000F0 - 0x00000010 */
#define IWL_DL_MACDUMP (1 << 4)
#define IWL_DL_HCMD_DUMP (1 << 5)
#define IWL_DL_EEPROM (1 << 6)
#define IWL_DL_RADIO (1 << 7)
/* 0x00000F00 - 0x00000100 */
#define IWL_DL_POWER (1 << 8)
@ -164,6 +165,7 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv)
#define IWL_DEBUG_WEP(p, f, a...) IWL_DEBUG(p, IWL_DL_WEP, f, ## a)
#define IWL_DEBUG_HC(p, f, a...) IWL_DEBUG(p, IWL_DL_HCMD, f, ## a)
#define IWL_DEBUG_HC_DUMP(p, f, a...) IWL_DEBUG(p, IWL_DL_HCMD_DUMP, f, ## a)
#define IWL_DEBUG_EEPROM(p, f, a...) IWL_DEBUG(p, IWL_DL_EEPROM, f, ## a)
#define IWL_DEBUG_CALIB(p, f, a...) IWL_DEBUG(p, IWL_DL_CALIB, f, ## a)
#define IWL_DEBUG_FW(p, f, a...) IWL_DEBUG(p, IWL_DL_FW, f, ## a)
#define IWL_DEBUG_RF_KILL(p, f, a...) IWL_DEBUG(p, IWL_DL_RF_KILL, f, ## a)

View File

@ -1567,6 +1567,13 @@ static ssize_t iwl_dbgfs_bt_traffic_read(struct file *file,
const size_t bufsz = sizeof(buf);
ssize_t ret;
if (!priv->bt_enable_flag) {
pos += scnprintf(buf + pos, bufsz - pos, "BT coex disabled\n");
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
return ret;
}
pos += scnprintf(buf + pos, bufsz - pos, "BT enable flag: 0x%x\n",
priv->bt_enable_flag);
pos += scnprintf(buf + pos, bufsz - pos, "BT in %s mode\n",
priv->bt_full_concurrent ? "full concurrency" : "3-wire");
pos += scnprintf(buf + pos, bufsz - pos, "BT status: %s, "

View File

@ -1468,6 +1468,7 @@ struct iwl_priv {
};
/* bt coex */
u8 bt_enable_flag;
u8 bt_status;
u8 bt_traffic_load, last_bt_traffic_load;
bool bt_ch_announce;

View File

@ -147,7 +147,7 @@ static int iwl_eeprom_verify_signature(struct iwl_priv *priv)
u32 gp = iwl_read32(priv, CSR_EEPROM_GP) & CSR_EEPROM_GP_VALID_MSK;
int ret = 0;
IWL_DEBUG_INFO(priv, "EEPROM signature=0x%08x\n", gp);
IWL_DEBUG_EEPROM(priv, "EEPROM signature=0x%08x\n", gp);
switch (gp) {
case CSR_EEPROM_GP_BAD_SIG_EEP_GOOD_SIG_OTP:
if (priv->nvm_device_type != NVM_DEVICE_TYPE_OTP) {
@ -354,7 +354,7 @@ static int iwl_find_otp_image(struct iwl_priv *priv,
*/
valid_addr = next_link_addr;
next_link_addr = le16_to_cpu(link_value) * sizeof(u16);
IWL_DEBUG_INFO(priv, "OTP blocks %d addr 0x%x\n",
IWL_DEBUG_EEPROM(priv, "OTP blocks %d addr 0x%x\n",
usedblocks, next_link_addr);
if (iwl_read_otp_word(priv, next_link_addr, &link_value))
return -EINVAL;
@ -374,7 +374,7 @@ static int iwl_find_otp_image(struct iwl_priv *priv,
} while (usedblocks <= priv->cfg->base_params->max_ll_items);
/* OTP has no valid blocks */
IWL_DEBUG_INFO(priv, "OTP has no valid blocks\n");
IWL_DEBUG_EEPROM(priv, "OTP has no valid blocks\n");
return -EINVAL;
}
@ -414,7 +414,7 @@ int iwl_eeprom_init(struct iwl_priv *priv)
return -ENOENT;
/* allocate eeprom */
sz = priv->cfg->base_params->eeprom_size;
IWL_DEBUG_INFO(priv, "NVM size = %d\n", sz);
IWL_DEBUG_EEPROM(priv, "NVM size = %d\n", sz);
priv->eeprom = kzalloc(sz, GFP_KERNEL);
if (!priv->eeprom) {
ret = -ENOMEM;
@ -492,7 +492,7 @@ int iwl_eeprom_init(struct iwl_priv *priv)
}
}
IWL_DEBUG_INFO(priv, "NVM Type: %s, version: 0x%x\n",
IWL_DEBUG_EEPROM(priv, "NVM Type: %s, version: 0x%x\n",
(priv->nvm_device_type == NVM_DEVICE_TYPE_OTP)
? "OTP" : "EEPROM",
iwl_eeprom_query16(priv, EEPROM_VERSION));
@ -594,7 +594,7 @@ static int iwl_mod_ht40_chan_info(struct iwl_priv *priv,
if (!is_channel_valid(ch_info))
return -1;
IWL_DEBUG_INFO(priv, "HT40 Ch. %d [%sGHz] %s%s%s%s%s(0x%02x %ddBm):"
IWL_DEBUG_EEPROM(priv, "HT40 Ch. %d [%sGHz] %s%s%s%s%s(0x%02x %ddBm):"
" Ad-Hoc %ssupported\n",
ch_info->channel,
is_channel_a_band(ch_info) ?
@ -634,11 +634,11 @@ int iwl_init_channel_map(struct iwl_priv *priv)
struct iwl_channel_info *ch_info;
if (priv->channel_count) {
IWL_DEBUG_INFO(priv, "Channel map already initialized.\n");
IWL_DEBUG_EEPROM(priv, "Channel map already initialized.\n");
return 0;
}
IWL_DEBUG_INFO(priv, "Initializing regulatory info from EEPROM\n");
IWL_DEBUG_EEPROM(priv, "Initializing regulatory info from EEPROM\n");
priv->channel_count =
ARRAY_SIZE(iwl_eeprom_band_1) +
@ -647,7 +647,8 @@ int iwl_init_channel_map(struct iwl_priv *priv)
ARRAY_SIZE(iwl_eeprom_band_4) +
ARRAY_SIZE(iwl_eeprom_band_5);
IWL_DEBUG_INFO(priv, "Parsing data for %d channels.\n", priv->channel_count);
IWL_DEBUG_EEPROM(priv, "Parsing data for %d channels.\n",
priv->channel_count);
priv->channel_info = kzalloc(sizeof(struct iwl_channel_info) *
priv->channel_count, GFP_KERNEL);
@ -686,7 +687,8 @@ int iwl_init_channel_map(struct iwl_priv *priv)
IEEE80211_CHAN_NO_HT40;
if (!(is_channel_valid(ch_info))) {
IWL_DEBUG_INFO(priv, "Ch. %d Flags %x [%sGHz] - "
IWL_DEBUG_EEPROM(priv,
"Ch. %d Flags %x [%sGHz] - "
"No traffic\n",
ch_info->channel,
ch_info->flags,
@ -702,7 +704,8 @@ int iwl_init_channel_map(struct iwl_priv *priv)
ch_info->scan_power = eeprom_ch_info[ch].max_power_avg;
ch_info->min_power = 0;
IWL_DEBUG_INFO(priv, "Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x %ddBm):"
IWL_DEBUG_EEPROM(priv, "Ch. %d [%sGHz] "
"%s%s%s%s%s%s(0x%02x %ddBm):"
" Ad-Hoc %ssupported\n",
ch_info->channel,
is_channel_a_band(ch_info) ?

View File

@ -231,59 +231,6 @@ struct iwl_eeprom_enhanced_txpwr {
#define EEPROM_6000_REG_BAND_24_HT40_CHANNELS ((0x80)\
| INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 14 bytes */
/* 6000 and up regulatory tx power - indirect access */
/* max. elements per section */
#define EEPROM_MAX_TXPOWER_SECTION_ELEMENTS (8)
#define EEPROM_TXPOWER_COMMON_HT40_INDEX (2)
/**
* Partition the enhanced tx power portion of eeprom image into
* 10 sections based on band, modulation, frequency and channel
*
* Section 1: all CCK channels
* Section 2: all 2.4 GHz OFDM (Legacy, HT and HT40 ) channels
* Section 3: all 5.2 GHz OFDM (Legacy, HT and HT40) channels
* Section 4: 2.4 GHz 20MHz channels: 1, 2, 10, 11. Both Legacy and HT
* Section 5: 2.4 GHz 40MHz channels: 1, 2, 6, 7, 9, (_above_)
* Section 6: 5.2 GHz 20MHz channels: 36, 64, 100, both Legacy and HT
* Section 7: 5.2 GHz 40MHz channels: 36, 60, 100 (_above_)
* Section 8: 2.4 GHz channel 13, Both Legacy and HT
* Section 9: 2.4 GHz channel 140, Both Legacy and HT
* Section 10: 2.4 GHz 40MHz channels: 132, 44 (_above_)
*/
/* 2.4 GHz band: CCK */
#define EEPROM_LB_CCK_20_COMMON ((0xA8)\
| INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 8 bytes */
/* 2.4 GHz band: 20MHz-Legacy, 20MHz-HT, 40MHz-HT */
#define EEPROM_LB_OFDM_COMMON ((0xB0)\
| INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 24 bytes */
/* 5.2 GHz band: 20MHz-Legacy, 20MHz-HT, 40MHz-HT */
#define EEPROM_HB_OFDM_COMMON ((0xC8)\
| INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 24 bytes */
/* 2.4GHz band channels:
* 1Legacy, 1HT, 2Legacy, 2HT, 10Legacy, 10HT, 11Legacy, 11HT */
#define EEPROM_LB_OFDM_20_BAND ((0xE0)\
| INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 64 bytes */
/* 2.4 GHz band HT40 channels: (1,+1) (2,+1) (6,+1) (7,+1) (9,+1) */
#define EEPROM_LB_OFDM_HT40_BAND ((0x120)\
| INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 40 bytes */
/* 5.2GHz band channels: 36Legacy, 36HT, 64Legacy, 64HT, 100Legacy, 100HT */
#define EEPROM_HB_OFDM_20_BAND ((0x148)\
| INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 48 bytes */
/* 5.2 GHz band HT40 channels: (36,+1) (60,+1) (100,+1) */
#define EEPROM_HB_OFDM_HT40_BAND ((0x178)\
| INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 24 bytes */
/* 2.4 GHz band, channnel 13: Legacy, HT */
#define EEPROM_LB_OFDM_20_CHANNEL_13 ((0x190)\
| INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 16 bytes */
/* 5.2 GHz band, channnel 140: Legacy, HT */
#define EEPROM_HB_OFDM_20_CHANNEL_140 ((0x1A0)\
| INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 16 bytes */
/* 5.2 GHz band, HT40 channnels (132,+1) (44,+1) */
#define EEPROM_HB_OFDM_HT40_BAND_1 ((0x1B0)\
| INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 16 bytes */
/* 5050 Specific */
#define EEPROM_5050_TX_POWER_VERSION (4)
#define EEPROM_5050_EEPROM_VERSION (0x21E)

View File

@ -83,10 +83,10 @@
#define APMG_DIGITAL_SVR_REG (APMG_BASE + 0x0058)
#define APMG_ANALOG_SVR_REG (APMG_BASE + 0x006C)
#define APMS_CLK_VAL_MRB_FUNC_MODE (0x00000001)
#define APMG_CLK_VAL_DMA_CLK_RQT (0x00000200)
#define APMG_CLK_VAL_BSM_CLK_RQT (0x00000800)
#define APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS (0x00400000)
#define APMG_PS_CTRL_VAL_RESET_REQ (0x04000000)
#define APMG_PS_CTRL_MSK_PWR_SRC (0x03000000)

View File

@ -225,7 +225,8 @@ static int iwm_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
static int iwm_cfg80211_set_default_key(struct wiphy *wiphy,
struct net_device *ndev,
u8 key_index)
u8 key_index, bool unicast,
bool multicast)
{
struct iwm_priv *iwm = ndev_to_iwm(ndev);

View File

@ -1422,7 +1422,8 @@ static int lbs_cfg_disconnect(struct wiphy *wiphy, struct net_device *dev,
static int lbs_cfg_set_default_key(struct wiphy *wiphy,
struct net_device *netdev,
u8 key_index)
u8 key_index, bool unicast,
bool multicast)
{
struct lbs_private *priv = wiphy_priv(wiphy);

View File

@ -554,7 +554,7 @@ static int rndis_del_key(struct wiphy *wiphy, struct net_device *netdev,
u8 key_index, bool pairwise, const u8 *mac_addr);
static int rndis_set_default_key(struct wiphy *wiphy, struct net_device *netdev,
u8 key_index);
u8 key_index, bool unicast, bool multicast);
static int rndis_get_station(struct wiphy *wiphy, struct net_device *dev,
u8 *mac, struct station_info *sinfo);
@ -2381,7 +2381,7 @@ static int rndis_del_key(struct wiphy *wiphy, struct net_device *netdev,
}
static int rndis_set_default_key(struct wiphy *wiphy, struct net_device *netdev,
u8 key_index)
u8 key_index, bool unicast, bool multicast)
{
struct rndis_wlan_private *priv = wiphy_priv(wiphy);
struct usbnet *usbdev = priv->usbdev;

View File

@ -632,6 +632,88 @@ static void rt2400pci_link_tuner(struct rt2x00_dev *rt2x00dev,
rt2400pci_set_vgc(rt2x00dev, qual, --qual->vgc_level);
}
/*
* Queue handlers.
*/
static void rt2400pci_start_queue(struct data_queue *queue)
{
struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
u32 reg;
switch (queue->qid) {
case QID_RX:
rt2x00pci_register_read(rt2x00dev, RXCSR0, &reg);
rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX, 0);
rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
break;
case QID_BEACON:
rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
rt2x00_set_field32(&reg, CSR14_TBCN, 1);
rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 1);
rt2x00pci_register_write(rt2x00dev, CSR14, reg);
break;
default:
break;
}
}
static void rt2400pci_kick_queue(struct data_queue *queue)
{
struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
u32 reg;
switch (queue->qid) {
case QID_AC_VO:
rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
rt2x00_set_field32(&reg, TXCSR0_KICK_PRIO, 1);
rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
break;
case QID_AC_VI:
rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
rt2x00_set_field32(&reg, TXCSR0_KICK_TX, 1);
rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
break;
case QID_ATIM:
rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
rt2x00_set_field32(&reg, TXCSR0_KICK_ATIM, 1);
rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
break;
default:
break;
}
}
static void rt2400pci_stop_queue(struct data_queue *queue)
{
struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
u32 reg;
switch (queue->qid) {
case QID_AC_VO:
case QID_AC_VI:
case QID_ATIM:
rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
rt2x00_set_field32(&reg, TXCSR0_ABORT, 1);
rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
break;
case QID_RX:
rt2x00pci_register_read(rt2x00dev, RXCSR0, &reg);
rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX, 1);
rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
break;
case QID_BEACON:
rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 0);
rt2x00_set_field32(&reg, CSR14_TBCN, 0);
rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
rt2x00pci_register_write(rt2x00dev, CSR14, reg);
break;
default:
break;
}
}
/*
* Initialization functions.
*/
@ -878,17 +960,6 @@ static int rt2400pci_init_bbp(struct rt2x00_dev *rt2x00dev)
/*
* Device state switch handlers.
*/
static void rt2400pci_toggle_rx(struct rt2x00_dev *rt2x00dev,
enum dev_state state)
{
u32 reg;
rt2x00pci_register_read(rt2x00dev, RXCSR0, &reg);
rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX,
(state == STATE_RADIO_RX_OFF));
rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
}
static void rt2400pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
enum dev_state state)
{
@ -987,10 +1058,6 @@ static int rt2400pci_set_device_state(struct rt2x00_dev *rt2x00dev,
case STATE_RADIO_OFF:
rt2400pci_disable_radio(rt2x00dev);
break;
case STATE_RADIO_RX_ON:
case STATE_RADIO_RX_OFF:
rt2400pci_toggle_rx(rt2x00dev, state);
break;
case STATE_RADIO_IRQ_ON:
case STATE_RADIO_IRQ_ON_ISR:
case STATE_RADIO_IRQ_OFF:
@ -1122,32 +1189,6 @@ static void rt2400pci_write_beacon(struct queue_entry *entry,
rt2x00pci_register_write(rt2x00dev, CSR14, reg);
}
static void rt2400pci_kick_tx_queue(struct data_queue *queue)
{
struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
u32 reg;
rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
rt2x00_set_field32(&reg, TXCSR0_KICK_PRIO, (queue->qid == QID_AC_BE));
rt2x00_set_field32(&reg, TXCSR0_KICK_TX, (queue->qid == QID_AC_BK));
rt2x00_set_field32(&reg, TXCSR0_KICK_ATIM, (queue->qid == QID_ATIM));
rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
}
static void rt2400pci_kill_tx_queue(struct data_queue *queue)
{
struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
u32 reg;
if (queue->qid == QID_BEACON) {
rt2x00pci_register_write(rt2x00dev, CSR14, 0);
} else {
rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
rt2x00_set_field32(&reg, TXCSR0_ABORT, 1);
rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
}
}
/*
* RX control handlers
*/
@ -1281,13 +1322,13 @@ static irqreturn_t rt2400pci_interrupt_thread(int irq, void *dev_instance)
* 4 - Priority ring transmit done interrupt.
*/
if (rt2x00_get_field32(reg, CSR7_TXDONE_PRIORING))
rt2400pci_txdone(rt2x00dev, QID_AC_BE);
rt2400pci_txdone(rt2x00dev, QID_AC_VO);
/*
* 5 - Tx ring transmit done interrupt.
*/
if (rt2x00_get_field32(reg, CSR7_TXDONE_TXRING))
rt2400pci_txdone(rt2x00dev, QID_AC_BK);
rt2400pci_txdone(rt2x00dev, QID_AC_VI);
/* Enable interrupts again. */
rt2x00dev->ops->lib->set_device_state(rt2x00dev,
@ -1625,10 +1666,11 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
.link_stats = rt2400pci_link_stats,
.reset_tuner = rt2400pci_reset_tuner,
.link_tuner = rt2400pci_link_tuner,
.start_queue = rt2400pci_start_queue,
.kick_queue = rt2400pci_kick_queue,
.stop_queue = rt2400pci_stop_queue,
.write_tx_desc = rt2400pci_write_tx_desc,
.write_beacon = rt2400pci_write_beacon,
.kick_tx_queue = rt2400pci_kick_tx_queue,
.kill_tx_queue = rt2400pci_kill_tx_queue,
.fill_rxdone = rt2400pci_fill_rxdone,
.config_filter = rt2400pci_config_filter,
.config_intf = rt2400pci_config_intf,

View File

@ -722,6 +722,88 @@ dynamic_cca_tune:
rt2500pci_set_vgc(rt2x00dev, qual, --qual->vgc_level_reg);
}
/*
* Queue handlers.
*/
static void rt2500pci_start_queue(struct data_queue *queue)
{
struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
u32 reg;
switch (queue->qid) {
case QID_RX:
rt2x00pci_register_read(rt2x00dev, RXCSR0, &reg);
rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX, 0);
rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
break;
case QID_BEACON:
rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
rt2x00_set_field32(&reg, CSR14_TBCN, 1);
rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 1);
rt2x00pci_register_write(rt2x00dev, CSR14, reg);
break;
default:
break;
}
}
static void rt2500pci_kick_queue(struct data_queue *queue)
{
struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
u32 reg;
switch (queue->qid) {
case QID_AC_VO:
rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
rt2x00_set_field32(&reg, TXCSR0_KICK_PRIO, 1);
rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
break;
case QID_AC_VI:
rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
rt2x00_set_field32(&reg, TXCSR0_KICK_TX, 1);
rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
break;
case QID_ATIM:
rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
rt2x00_set_field32(&reg, TXCSR0_KICK_ATIM, 1);
rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
break;
default:
break;
}
}
static void rt2500pci_stop_queue(struct data_queue *queue)
{
struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
u32 reg;
switch (queue->qid) {
case QID_AC_VO:
case QID_AC_VI:
case QID_ATIM:
rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
rt2x00_set_field32(&reg, TXCSR0_ABORT, 1);
rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
break;
case QID_RX:
rt2x00pci_register_read(rt2x00dev, RXCSR0, &reg);
rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX, 1);
rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
break;
case QID_BEACON:
rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 0);
rt2x00_set_field32(&reg, CSR14_TBCN, 0);
rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
rt2x00pci_register_write(rt2x00dev, CSR14, reg);
break;
default:
break;
}
}
/*
* Initialization functions.
*/
@ -1033,17 +1115,6 @@ static int rt2500pci_init_bbp(struct rt2x00_dev *rt2x00dev)
/*
* Device state switch handlers.
*/
static void rt2500pci_toggle_rx(struct rt2x00_dev *rt2x00dev,
enum dev_state state)
{
u32 reg;
rt2x00pci_register_read(rt2x00dev, RXCSR0, &reg);
rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX,
(state == STATE_RADIO_RX_OFF));
rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
}
static void rt2500pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
enum dev_state state)
{
@ -1142,10 +1213,6 @@ static int rt2500pci_set_device_state(struct rt2x00_dev *rt2x00dev,
case STATE_RADIO_OFF:
rt2500pci_disable_radio(rt2x00dev);
break;
case STATE_RADIO_RX_ON:
case STATE_RADIO_RX_OFF:
rt2500pci_toggle_rx(rt2x00dev, state);
break;
case STATE_RADIO_IRQ_ON:
case STATE_RADIO_IRQ_ON_ISR:
case STATE_RADIO_IRQ_OFF:
@ -1276,32 +1343,6 @@ static void rt2500pci_write_beacon(struct queue_entry *entry,
rt2x00pci_register_write(rt2x00dev, CSR14, reg);
}
static void rt2500pci_kick_tx_queue(struct data_queue *queue)
{
struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
u32 reg;
rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
rt2x00_set_field32(&reg, TXCSR0_KICK_PRIO, (queue->qid == QID_AC_BE));
rt2x00_set_field32(&reg, TXCSR0_KICK_TX, (queue->qid == QID_AC_BK));
rt2x00_set_field32(&reg, TXCSR0_KICK_ATIM, (queue->qid == QID_ATIM));
rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
}
static void rt2500pci_kill_tx_queue(struct data_queue *queue)
{
struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
u32 reg;
if (queue->qid == QID_BEACON) {
rt2x00pci_register_write(rt2x00dev, CSR14, 0);
} else {
rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
rt2x00_set_field32(&reg, TXCSR0_ABORT, 1);
rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
}
}
/*
* RX control handlers
*/
@ -1414,13 +1455,13 @@ static irqreturn_t rt2500pci_interrupt_thread(int irq, void *dev_instance)
* 4 - Priority ring transmit done interrupt.
*/
if (rt2x00_get_field32(reg, CSR7_TXDONE_PRIORING))
rt2500pci_txdone(rt2x00dev, QID_AC_BE);
rt2500pci_txdone(rt2x00dev, QID_AC_VO);
/*
* 5 - Tx ring transmit done interrupt.
*/
if (rt2x00_get_field32(reg, CSR7_TXDONE_TXRING))
rt2500pci_txdone(rt2x00dev, QID_AC_BK);
rt2500pci_txdone(rt2x00dev, QID_AC_VI);
/* Enable interrupts again. */
rt2x00dev->ops->lib->set_device_state(rt2x00dev,
@ -1922,10 +1963,11 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
.link_stats = rt2500pci_link_stats,
.reset_tuner = rt2500pci_reset_tuner,
.link_tuner = rt2500pci_link_tuner,
.start_queue = rt2500pci_start_queue,
.kick_queue = rt2500pci_kick_queue,
.stop_queue = rt2500pci_stop_queue,
.write_tx_desc = rt2500pci_write_tx_desc,
.write_beacon = rt2500pci_write_beacon,
.kick_tx_queue = rt2500pci_kick_tx_queue,
.kill_tx_queue = rt2500pci_kill_tx_queue,
.fill_rxdone = rt2500pci_fill_rxdone,
.config_filter = rt2500pci_config_filter,
.config_intf = rt2500pci_config_intf,

View File

@ -738,6 +738,55 @@ static void rt2500usb_reset_tuner(struct rt2x00_dev *rt2x00dev,
qual->vgc_level = value;
}
/*
* Queue handlers.
*/
static void rt2500usb_start_queue(struct data_queue *queue)
{
struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
u16 reg;
switch (queue->qid) {
case QID_RX:
rt2500usb_register_read(rt2x00dev, TXRX_CSR2, &reg);
rt2x00_set_field16(&reg, TXRX_CSR2_DISABLE_RX, 0);
rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg);
break;
case QID_BEACON:
rt2500usb_register_read(rt2x00dev, TXRX_CSR19, &reg);
rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 1);
rt2x00_set_field16(&reg, TXRX_CSR19_TBCN, 1);
rt2x00_set_field16(&reg, TXRX_CSR19_BEACON_GEN, 1);
rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
break;
default:
break;
}
}
static void rt2500usb_stop_queue(struct data_queue *queue)
{
struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
u16 reg;
switch (queue->qid) {
case QID_RX:
rt2500usb_register_read(rt2x00dev, TXRX_CSR2, &reg);
rt2x00_set_field16(&reg, TXRX_CSR2_DISABLE_RX, 1);
rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg);
break;
case QID_BEACON:
rt2500usb_register_read(rt2x00dev, TXRX_CSR19, &reg);
rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 0);
rt2x00_set_field16(&reg, TXRX_CSR19_TBCN, 0);
rt2x00_set_field16(&reg, TXRX_CSR19_BEACON_GEN, 0);
rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
break;
default:
break;
}
}
/*
* Initialization functions.
*/
@ -931,17 +980,6 @@ static int rt2500usb_init_bbp(struct rt2x00_dev *rt2x00dev)
/*
* Device state switch handlers.
*/
static void rt2500usb_toggle_rx(struct rt2x00_dev *rt2x00dev,
enum dev_state state)
{
u16 reg;
rt2500usb_register_read(rt2x00dev, TXRX_CSR2, &reg);
rt2x00_set_field16(&reg, TXRX_CSR2_DISABLE_RX,
(state == STATE_RADIO_RX_OFF));
rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg);
}
static int rt2500usb_enable_radio(struct rt2x00_dev *rt2x00dev)
{
/*
@ -1017,10 +1055,6 @@ static int rt2500usb_set_device_state(struct rt2x00_dev *rt2x00dev,
case STATE_RADIO_OFF:
rt2500usb_disable_radio(rt2x00dev);
break;
case STATE_RADIO_RX_ON:
case STATE_RADIO_RX_OFF:
rt2500usb_toggle_rx(rt2x00dev, state);
break;
case STATE_RADIO_IRQ_ON:
case STATE_RADIO_IRQ_ON_ISR:
case STATE_RADIO_IRQ_OFF:
@ -1203,14 +1237,6 @@ static int rt2500usb_get_tx_data_len(struct queue_entry *entry)
return length;
}
static void rt2500usb_kill_tx_queue(struct data_queue *queue)
{
if (queue->qid == QID_BEACON)
rt2500usb_register_write(queue->rt2x00dev, TXRX_CSR19, 0);
rt2x00usb_kill_tx_queue(queue);
}
/*
* RX control handlers
*/
@ -1811,11 +1837,13 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
.link_stats = rt2500usb_link_stats,
.reset_tuner = rt2500usb_reset_tuner,
.watchdog = rt2x00usb_watchdog,
.start_queue = rt2500usb_start_queue,
.kick_queue = rt2x00usb_kick_queue,
.stop_queue = rt2500usb_stop_queue,
.flush_queue = rt2x00usb_flush_queue,
.write_tx_desc = rt2500usb_write_tx_desc,
.write_beacon = rt2500usb_write_beacon,
.get_tx_data_len = rt2500usb_get_tx_data_len,
.kick_tx_queue = rt2x00usb_kick_tx_queue,
.kill_tx_queue = rt2500usb_kill_tx_queue,
.fill_rxdone = rt2500usb_fill_rxdone,
.config_shared_key = rt2500usb_config_key,
.config_pairwise_key = rt2500usb_config_key,

View File

@ -46,8 +46,11 @@
* RF2020 2.4G B/G
* RF3021 2.4G 1T2R
* RF3022 2.4G 2T2R
* RF3052 2.4G 2T2R
* RF3320 2.4G 1T1R
* RF3052 2.4G/5G 2T2R
* RF2853 2.4G/5G 3T3R
* RF3320 2.4G 1T1R(RT3350/RT3370/RT3390)
* RF3322 2.4G 2T2R(RT3352/RT3371/RT3372/RT3391/RT3392)
* RF3853 2.4G/5G 3T3R(RT3883/RT3563/RT3573/RT3593/RT3662)
*/
#define RF2820 0x0001
#define RF2850 0x0002
@ -58,7 +61,10 @@
#define RF3021 0x0007
#define RF3022 0x0008
#define RF3052 0x0009
#define RF2853 0x000a
#define RF3320 0x000b
#define RF3322 0x000c
#define RF3853 0x000d
/*
* Chipset revisions.
@ -207,10 +213,10 @@
/*
* WMM_AIFSN_CFG: Aifsn for each EDCA AC
* AIFSN0: AC_BE
* AIFSN1: AC_BK
* AIFSN2: AC_VI
* AIFSN3: AC_VO
* AIFSN0: AC_VO
* AIFSN1: AC_VI
* AIFSN2: AC_BE
* AIFSN3: AC_BK
*/
#define WMM_AIFSN_CFG 0x0214
#define WMM_AIFSN_CFG_AIFSN0 FIELD32(0x0000000f)
@ -220,10 +226,10 @@
/*
* WMM_CWMIN_CSR: CWmin for each EDCA AC
* CWMIN0: AC_BE
* CWMIN1: AC_BK
* CWMIN2: AC_VI
* CWMIN3: AC_VO
* CWMIN0: AC_VO
* CWMIN1: AC_VI
* CWMIN2: AC_BE
* CWMIN3: AC_BK
*/
#define WMM_CWMIN_CFG 0x0218
#define WMM_CWMIN_CFG_CWMIN0 FIELD32(0x0000000f)
@ -233,10 +239,10 @@
/*
* WMM_CWMAX_CSR: CWmax for each EDCA AC
* CWMAX0: AC_BE
* CWMAX1: AC_BK
* CWMAX2: AC_VI
* CWMAX3: AC_VO
* CWMAX0: AC_VO
* CWMAX1: AC_VI
* CWMAX2: AC_BE
* CWMAX3: AC_BK
*/
#define WMM_CWMAX_CFG 0x021c
#define WMM_CWMAX_CFG_CWMAX0 FIELD32(0x0000000f)
@ -245,18 +251,18 @@
#define WMM_CWMAX_CFG_CWMAX3 FIELD32(0x0000f000)
/*
* AC_TXOP0: AC_BK/AC_BE TXOP register
* AC0TXOP: AC_BK in unit of 32us
* AC1TXOP: AC_BE in unit of 32us
* AC_TXOP0: AC_VO/AC_VI TXOP register
* AC0TXOP: AC_VO in unit of 32us
* AC1TXOP: AC_VI in unit of 32us
*/
#define WMM_TXOP0_CFG 0x0220
#define WMM_TXOP0_CFG_AC0TXOP FIELD32(0x0000ffff)
#define WMM_TXOP0_CFG_AC1TXOP FIELD32(0xffff0000)
/*
* AC_TXOP1: AC_VO/AC_VI TXOP register
* AC2TXOP: AC_VI in unit of 32us
* AC3TXOP: AC_VO in unit of 32us
* AC_TXOP1: AC_BE/AC_BK TXOP register
* AC2TXOP: AC_BE in unit of 32us
* AC3TXOP: AC_BK in unit of 32us
*/
#define WMM_TXOP1_CFG 0x0224
#define WMM_TXOP1_CFG_AC2TXOP FIELD32(0x0000ffff)
@ -282,7 +288,7 @@
#define MCU_CMD_CFG 0x022c
/*
* AC_BK register offsets
* AC_VO register offsets
*/
#define TX_BASE_PTR0 0x0230
#define TX_MAX_CNT0 0x0234
@ -290,7 +296,7 @@
#define TX_DTX_IDX0 0x023c
/*
* AC_BE register offsets
* AC_VI register offsets
*/
#define TX_BASE_PTR1 0x0240
#define TX_MAX_CNT1 0x0244
@ -298,7 +304,7 @@
#define TX_DTX_IDX1 0x024c
/*
* AC_VI register offsets
* AC_BE register offsets
*/
#define TX_BASE_PTR2 0x0250
#define TX_MAX_CNT2 0x0254
@ -306,7 +312,7 @@
#define TX_DTX_IDX2 0x025c
/*
* AC_VO register offsets
* AC_BK register offsets
*/
#define TX_BASE_PTR3 0x0260
#define TX_MAX_CNT3 0x0264
@ -699,8 +705,18 @@
/*
* CH_TIME_CFG: count as channel busy
* EIFS_BUSY: Count EIFS as channel busy
* NAV_BUSY: Count NAS as channel busy
* RX_BUSY: Count RX as channel busy
* TX_BUSY: Count TX as channel busy
* TMR_EN: Enable channel statistics timer
*/
#define CH_TIME_CFG 0x110c
#define CH_TIME_CFG_EIFS_BUSY FIELD32(0x00000010)
#define CH_TIME_CFG_NAV_BUSY FIELD32(0x00000008)
#define CH_TIME_CFG_RX_BUSY FIELD32(0x00000004)
#define CH_TIME_CFG_TX_BUSY FIELD32(0x00000002)
#define CH_TIME_CFG_TMR_EN FIELD32(0x00000001)
/*
* PBF_LIFE_TIMER: TX/RX MPDU timestamp timer (free run) Unit: 1us
@ -1841,32 +1857,51 @@ struct mac_iveiv_entry {
#define EEPROM_MAC_ADDR_BYTE5 FIELD16(0xff00)
/*
* EEPROM ANTENNA config
* EEPROM NIC Configuration 0
* RXPATH: 1: 1R, 2: 2R, 3: 3R
* TXPATH: 1: 1T, 2: 2T
* TXPATH: 1: 1T, 2: 2T, 3: 3T
* RF_TYPE: RFIC type
*/
#define EEPROM_ANTENNA 0x001a
#define EEPROM_ANTENNA_RXPATH FIELD16(0x000f)
#define EEPROM_ANTENNA_TXPATH FIELD16(0x00f0)
#define EEPROM_ANTENNA_RF_TYPE FIELD16(0x0f00)
#define EEPROM_NIC_CONF0 0x001a
#define EEPROM_NIC_CONF0_RXPATH FIELD16(0x000f)
#define EEPROM_NIC_CONF0_TXPATH FIELD16(0x00f0)
#define EEPROM_NIC_CONF0_RF_TYPE FIELD16(0x0f00)
/*
* EEPROM NIC config
* CARDBUS_ACCEL: 0 - enable, 1 - disable
* EEPROM NIC Configuration 1
* HW_RADIO: 0: disable, 1: enable
* EXTERNAL_TX_ALC: 0: disable, 1: enable
* EXTERNAL_LNA_2G: 0: disable, 1: enable
* EXTERNAL_LNA_5G: 0: disable, 1: enable
* CARDBUS_ACCEL: 0: enable, 1: disable
* BW40M_SB_2G: 0: disable, 1: enable
* BW40M_SB_5G: 0: disable, 1: enable
* WPS_PBC: 0: disable, 1: enable
* BW40M_2G: 0: enable, 1: disable
* BW40M_5G: 0: enable, 1: disable
* BROADBAND_EXT_LNA: 0: disable, 1: enable
* ANT_DIVERSITY: 00: Disable, 01: Diversity,
* 10: Main antenna, 11: Aux antenna
* INTERNAL_TX_ALC: 0: disable, 1: enable
* BT_COEXIST: 0: disable, 1: enable
* DAC_TEST: 0: disable, 1: enable
*/
#define EEPROM_NIC 0x001b
#define EEPROM_NIC_HW_RADIO FIELD16(0x0001)
#define EEPROM_NIC_DYNAMIC_TX_AGC FIELD16(0x0002)
#define EEPROM_NIC_EXTERNAL_LNA_BG FIELD16(0x0004)
#define EEPROM_NIC_EXTERNAL_LNA_A FIELD16(0x0008)
#define EEPROM_NIC_CARDBUS_ACCEL FIELD16(0x0010)
#define EEPROM_NIC_BW40M_SB_BG FIELD16(0x0020)
#define EEPROM_NIC_BW40M_SB_A FIELD16(0x0040)
#define EEPROM_NIC_WPS_PBC FIELD16(0x0080)
#define EEPROM_NIC_BW40M_BG FIELD16(0x0100)
#define EEPROM_NIC_BW40M_A FIELD16(0x0200)
#define EEPROM_NIC_ANT_DIVERSITY FIELD16(0x0800)
#define EEPROM_NIC_DAC_TEST FIELD16(0x8000)
#define EEPROM_NIC_CONF1 0x001b
#define EEPROM_NIC_CONF1_HW_RADIO FIELD16(0x0001)
#define EEPROM_NIC_CONF1_EXTERNAL_TX_ALC FIELD16(0x0002)
#define EEPROM_NIC_CONF1_EXTERNAL_LNA_2G FIELD16(0x0004)
#define EEPROM_NIC_CONF1_EXTERNAL_LNA_5G FIELD16(0x0008)
#define EEPROM_NIC_CONF1_CARDBUS_ACCEL FIELD16(0x0010)
#define EEPROM_NIC_CONF1_BW40M_SB_2G FIELD16(0x0020)
#define EEPROM_NIC_CONF1_BW40M_SB_5G FIELD16(0x0040)
#define EEPROM_NIC_CONF1_WPS_PBC FIELD16(0x0080)
#define EEPROM_NIC_CONF1_BW40M_2G FIELD16(0x0100)
#define EEPROM_NIC_CONF1_BW40M_5G FIELD16(0x0200)
#define EEPROM_NIC_CONF1_BROADBAND_EXT_LNA FIELD16(0x400)
#define EEPROM_NIC_CONF1_ANT_DIVERSITY FIELD16(0x1800)
#define EEPROM_NIC_CONF1_INTERNAL_TX_ALC FIELD16(0x2000)
#define EEPROM_NIC_CONF1_BT_COEXIST FIELD16(0x4000)
#define EEPROM_NIC_CONF1_DAC_TEST FIELD16(0x8000)
/*
* EEPROM frequency
@ -1888,9 +1923,9 @@ struct mac_iveiv_entry {
* POLARITY_GPIO_4: Polarity GPIO4 setting.
* LED_MODE: Led mode.
*/
#define EEPROM_LED1 0x001e
#define EEPROM_LED2 0x001f
#define EEPROM_LED3 0x0020
#define EEPROM_LED_AG_CONF 0x001e
#define EEPROM_LED_ACT_CONF 0x001f
#define EEPROM_LED_POLARITY 0x0020
#define EEPROM_LED_POLARITY_RDY_BG FIELD16(0x0001)
#define EEPROM_LED_POLARITY_RDY_A FIELD16(0x0002)
#define EEPROM_LED_POLARITY_ACT FIELD16(0x0004)
@ -1901,6 +1936,17 @@ struct mac_iveiv_entry {
#define EEPROM_LED_POLARITY_GPIO_4 FIELD16(0x0080)
#define EEPROM_LED_LED_MODE FIELD16(0x1f00)
/*
* EEPROM NIC Configuration 2
* RX_STREAM: 0: Reserved, 1: 1 Stream, 2: 2 Stream
* TX_STREAM: 0: Reserved, 1: 1 Stream, 2: 2 Stream
* CRYSTAL: 00: Reserved, 01: One crystal, 10: Two crystal, 11: Reserved
*/
#define EEPROM_NIC_CONF2 0x0021
#define EEPROM_NIC_CONF2_RX_STREAM FIELD16(0x000f)
#define EEPROM_NIC_CONF2_TX_STREAM FIELD16(0x00f0)
#define EEPROM_NIC_CONF2_CRYSTAL FIELD16(0x0600)
/*
* EEPROM LNA
*/
@ -1951,7 +1997,7 @@ struct mac_iveiv_entry {
/*
* EEPROM TXpower delta: 20MHZ AND 40 MHZ use different power.
* This is delta in 40MHZ.
* This is delta in 40MHZ.
* VALUE: Tx Power dalta value (MAX=4)
* TYPE: 1: Plus the delta value, 0: minus the delta value
* TXPOWER: Enable:
@ -2007,9 +2053,9 @@ struct mac_iveiv_entry {
#define MCU_CURRENT 0x36
#define MCU_LED 0x50
#define MCU_LED_STRENGTH 0x51
#define MCU_LED_1 0x52
#define MCU_LED_2 0x53
#define MCU_LED_3 0x54
#define MCU_LED_AG_CONF 0x52
#define MCU_LED_ACT_CONF 0x53
#define MCU_LED_LED_POLARITY 0x54
#define MCU_RADAR 0x60
#define MCU_BOOT_SIGNAL 0x72
#define MCU_BBP_SIGNAL 0x80

View File

@ -772,6 +772,7 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
unsigned int beacon_base;
unsigned int padding_len;
u32 reg;
/*
@ -806,11 +807,13 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb);
/*
* Write entire beacon with TXWI to register.
* Write entire beacon with TXWI and padding to register.
*/
padding_len = roundup(entry->skb->len, 4) - entry->skb->len;
skb_pad(entry->skb, padding_len);
beacon_base = HW_BEACON_OFFSET(entry->entry_idx);
rt2800_register_multiwrite(rt2x00dev, beacon_base,
entry->skb->data, entry->skb->len);
rt2800_register_multiwrite(rt2x00dev, beacon_base, entry->skb->data,
entry->skb->len + padding_len);
/*
* Enable beaconing again.
@ -1625,6 +1628,13 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
}
msleep(1);
/*
* Clear channel statistic counters
*/
rt2800_register_read(rt2x00dev, CH_IDLE_STA, &reg);
rt2800_register_read(rt2x00dev, CH_BUSY_STA, &reg);
rt2800_register_read(rt2x00dev, CH_BUSY_STA_SEC, &reg);
}
static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev,
@ -1930,8 +1940,8 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) ||
rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) {
rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom);
if (rt2x00_get_field16(eeprom, EEPROM_NIC_DAC_TEST))
rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_DAC_TEST))
rt2800_register_write(rt2x00dev, TX_SW_CFG2,
0x0000002c);
else
@ -2259,6 +2269,17 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(&reg, INT_TIMER_CFG_PRE_TBTT_TIMER, 6 << 4);
rt2800_register_write(rt2x00dev, INT_TIMER_CFG, reg);
/*
* Set up channel statistics timer
*/
rt2800_register_read(rt2x00dev, CH_TIME_CFG, &reg);
rt2x00_set_field32(&reg, CH_TIME_CFG_EIFS_BUSY, 1);
rt2x00_set_field32(&reg, CH_TIME_CFG_NAV_BUSY, 1);
rt2x00_set_field32(&reg, CH_TIME_CFG_RX_BUSY, 1);
rt2x00_set_field32(&reg, CH_TIME_CFG_TX_BUSY, 1);
rt2x00_set_field32(&reg, CH_TIME_CFG_TMR_EN, 1);
rt2800_register_write(rt2x00dev, CH_TIME_CFG, reg);
return 0;
}
@ -2376,10 +2397,10 @@ static int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
rt2x00_rt(rt2x00dev, RT3390)) {
rt2800_bbp_read(rt2x00dev, 138, &value);
rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom);
if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) == 1)
rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom);
if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) == 1)
value |= 0x20;
if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH) == 1)
if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) == 1)
value &= ~0x02;
rt2800_bbp_write(rt2x00dev, 138, value);
@ -2591,8 +2612,8 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(&reg, LDO_CFG0_BGSEL, 1);
if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E)) {
rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom);
if (rt2x00_get_field16(eeprom, EEPROM_NIC_DAC_TEST))
rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_DAC_TEST))
rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 3);
else
rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 0);
@ -2665,10 +2686,10 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
if (rt2x00_rt(rt2x00dev, RT3090)) {
rt2800_bbp_read(rt2x00dev, 138, &bbp);
rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom);
if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH) == 1)
rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom);
if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) == 1)
rt2x00_set_field8(&bbp, BBP138_RX_ADC1, 0);
if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) == 1)
if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) == 1)
rt2x00_set_field8(&bbp, BBP138_TX_DAC1, 1);
rt2800_bbp_write(rt2x00dev, 138, bbp);
@ -2767,16 +2788,16 @@ int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev)
/*
* Initialize LED control
*/
rt2x00_eeprom_read(rt2x00dev, EEPROM_LED1, &word);
rt2800_mcu_request(rt2x00dev, MCU_LED_1, 0xff,
rt2x00_eeprom_read(rt2x00dev, EEPROM_LED_AG_CONF, &word);
rt2800_mcu_request(rt2x00dev, MCU_LED_AG_CONF, 0xff,
word & 0xff, (word >> 8) & 0xff);
rt2x00_eeprom_read(rt2x00dev, EEPROM_LED2, &word);
rt2800_mcu_request(rt2x00dev, MCU_LED_2, 0xff,
rt2x00_eeprom_read(rt2x00dev, EEPROM_LED_ACT_CONF, &word);
rt2800_mcu_request(rt2x00dev, MCU_LED_ACT_CONF, 0xff,
word & 0xff, (word >> 8) & 0xff);
rt2x00_eeprom_read(rt2x00dev, EEPROM_LED3, &word);
rt2800_mcu_request(rt2x00dev, MCU_LED_3, 0xff,
rt2x00_eeprom_read(rt2x00dev, EEPROM_LED_POLARITY, &word);
rt2800_mcu_request(rt2x00dev, MCU_LED_LED_POLARITY, 0xff,
word & 0xff, (word >> 8) & 0xff);
return 0;
@ -2870,38 +2891,41 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
EEPROM(rt2x00dev, "MAC: %pM\n", mac);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &word);
if (word == 0xffff) {
rt2x00_set_field16(&word, EEPROM_ANTENNA_RXPATH, 2);
rt2x00_set_field16(&word, EEPROM_ANTENNA_TXPATH, 1);
rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2820);
rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word);
rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RXPATH, 2);
rt2x00_set_field16(&word, EEPROM_NIC_CONF0_TXPATH, 1);
rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RF_TYPE, RF2820);
rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC_CONF0, word);
EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word);
} else if (rt2x00_rt(rt2x00dev, RT2860) ||
rt2x00_rt(rt2x00dev, RT2872)) {
/*
* There is a max of 2 RX streams for RT28x0 series
*/
if (rt2x00_get_field16(word, EEPROM_ANTENNA_RXPATH) > 2)
rt2x00_set_field16(&word, EEPROM_ANTENNA_RXPATH, 2);
rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word);
if (rt2x00_get_field16(word, EEPROM_NIC_CONF0_RXPATH) > 2)
rt2x00_set_field16(&word, EEPROM_NIC_CONF0_RXPATH, 2);
rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC_CONF0, word);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &word);
rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &word);
if (word == 0xffff) {
rt2x00_set_field16(&word, EEPROM_NIC_HW_RADIO, 0);
rt2x00_set_field16(&word, EEPROM_NIC_DYNAMIC_TX_AGC, 0);
rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA_BG, 0);
rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA_A, 0);
rt2x00_set_field16(&word, EEPROM_NIC_CARDBUS_ACCEL, 0);
rt2x00_set_field16(&word, EEPROM_NIC_BW40M_SB_BG, 0);
rt2x00_set_field16(&word, EEPROM_NIC_BW40M_SB_A, 0);
rt2x00_set_field16(&word, EEPROM_NIC_WPS_PBC, 0);
rt2x00_set_field16(&word, EEPROM_NIC_BW40M_BG, 0);
rt2x00_set_field16(&word, EEPROM_NIC_BW40M_A, 0);
rt2x00_set_field16(&word, EEPROM_NIC_ANT_DIVERSITY, 0);
rt2x00_set_field16(&word, EEPROM_NIC_DAC_TEST, 0);
rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word);
rt2x00_set_field16(&word, EEPROM_NIC_CONF1_HW_RADIO, 0);
rt2x00_set_field16(&word, EEPROM_NIC_CONF1_EXTERNAL_TX_ALC, 0);
rt2x00_set_field16(&word, EEPROM_NIC_CONF1_EXTERNAL_LNA_2G, 0);
rt2x00_set_field16(&word, EEPROM_NIC_CONF1_EXTERNAL_LNA_5G, 0);
rt2x00_set_field16(&word, EEPROM_NIC_CONF1_CARDBUS_ACCEL, 0);
rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BW40M_SB_2G, 0);
rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BW40M_SB_5G, 0);
rt2x00_set_field16(&word, EEPROM_NIC_CONF1_WPS_PBC, 0);
rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BW40M_2G, 0);
rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BW40M_5G, 0);
rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BROADBAND_EXT_LNA, 0);
rt2x00_set_field16(&word, EEPROM_NIC_CONF1_ANT_DIVERSITY, 0);
rt2x00_set_field16(&word, EEPROM_NIC_CONF1_INTERNAL_TX_ALC, 0);
rt2x00_set_field16(&word, EEPROM_NIC_CONF1_BT_COEXIST, 0);
rt2x00_set_field16(&word, EEPROM_NIC_CONF1_DAC_TEST, 0);
rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC_CONF1, word);
EEPROM(rt2x00dev, "NIC: 0x%04x\n", word);
}
@ -2916,9 +2940,9 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
LED_MODE_TXRX_ACTIVITY);
rt2x00_set_field16(&word, EEPROM_FREQ_LED_POLARITY, 0);
rt2x00_eeprom_write(rt2x00dev, EEPROM_FREQ, word);
rt2x00_eeprom_write(rt2x00dev, EEPROM_LED1, 0x5555);
rt2x00_eeprom_write(rt2x00dev, EEPROM_LED2, 0x2221);
rt2x00_eeprom_write(rt2x00dev, EEPROM_LED3, 0xa9f8);
rt2x00_eeprom_write(rt2x00dev, EEPROM_LED_AG_CONF, 0x5555);
rt2x00_eeprom_write(rt2x00dev, EEPROM_LED_ACT_CONF, 0x2221);
rt2x00_eeprom_write(rt2x00dev, EEPROM_LED_POLARITY, 0xa9f8);
EEPROM(rt2x00dev, "Led Mode: 0x%04x\n", word);
}
@ -2982,12 +3006,12 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
/*
* Read EEPROM word for configuration.
*/
rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom);
rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom);
/*
* Identify RF chipset.
*/
value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
value = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RF_TYPE);
rt2800_register_read(rt2x00dev, MAC_CSR0, &reg);
rt2x00_set_chip(rt2x00dev, rt2x00_get_field32(reg, MAC_CSR0_CHIPSET),
@ -3023,9 +3047,9 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
* Identify default antenna configuration.
*/
rt2x00dev->default_ant.tx =
rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH);
rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH);
rt2x00dev->default_ant.rx =
rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH);
rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH);
/*
* Read frequency offset and RF programming sequence.
@ -3036,17 +3060,17 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
/*
* Read external LNA informations.
*/
rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom);
rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_A))
if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_EXTERNAL_LNA_5G))
__set_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags);
if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_BG))
if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_EXTERNAL_LNA_2G))
__set_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags);
/*
* Detect if this device has an hardware controlled radio.
*/
if (rt2x00_get_field16(eeprom, EEPROM_NIC_HW_RADIO))
if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_HW_RADIO))
__set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags);
/*
@ -3258,7 +3282,7 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
rt2x00dev->hw->max_report_rates = 7;
rt2x00dev->hw->max_rate_tries = 1;
rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom);
rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom);
/*
* Initialize hw_mode information.
@ -3302,11 +3326,11 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
IEEE80211_HT_CAP_SGI_20 |
IEEE80211_HT_CAP_SGI_40;
if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) >= 2)
if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) >= 2)
spec->ht.cap |= IEEE80211_HT_CAP_TX_STBC;
spec->ht.cap |=
rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH) <<
rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) <<
IEEE80211_HT_CAP_RX_STBC_SHIFT;
spec->ht.ampdu_factor = 3;
@ -3314,10 +3338,10 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
spec->ht.mcs.tx_params =
IEEE80211_HT_MCS_TX_DEFINED |
IEEE80211_HT_MCS_TX_RX_DIFF |
((rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) - 1) <<
((rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH) - 1) <<
IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT);
switch (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH)) {
switch (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH)) {
case 3:
spec->ht.mcs.rx_mask[2] = 0xff;
case 2:
@ -3536,6 +3560,37 @@ int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
}
EXPORT_SYMBOL_GPL(rt2800_ampdu_action);
int rt2800_get_survey(struct ieee80211_hw *hw, int idx,
struct survey_info *survey)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
struct ieee80211_conf *conf = &hw->conf;
u32 idle, busy, busy_ext;
if (idx != 0)
return -ENOENT;
survey->channel = conf->channel;
rt2800_register_read(rt2x00dev, CH_IDLE_STA, &idle);
rt2800_register_read(rt2x00dev, CH_BUSY_STA, &busy);
rt2800_register_read(rt2x00dev, CH_BUSY_STA_SEC, &busy_ext);
if (idle || busy) {
survey->filled = SURVEY_INFO_CHANNEL_TIME |
SURVEY_INFO_CHANNEL_TIME_BUSY |
SURVEY_INFO_CHANNEL_TIME_EXT_BUSY;
survey->channel_time = (idle + busy) / 1000;
survey->channel_time_busy = busy / 1000;
survey->channel_time_ext_busy = busy_ext / 1000;
}
return 0;
}
EXPORT_SYMBOL_GPL(rt2800_get_survey);
MODULE_AUTHOR(DRV_PROJECT ", Bartlomiej Zolnierkiewicz");
MODULE_VERSION(DRV_VERSION);
MODULE_DESCRIPTION("Ralink RT2800 library");

View File

@ -199,5 +199,7 @@ u64 rt2800_get_tsf(struct ieee80211_hw *hw);
int rt2800_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 rt2800_get_survey(struct ieee80211_hw *hw, int idx,
struct survey_info *survey);
#endif /* RT2800LIB_H */

View File

@ -185,6 +185,77 @@ static inline void rt2800pci_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev)
}
#endif /* CONFIG_PCI */
/*
* Queue handlers.
*/
static void rt2800pci_start_queue(struct data_queue *queue)
{
struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
u32 reg;
switch (queue->qid) {
case QID_RX:
rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 1);
rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
break;
case QID_BEACON:
rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 1);
rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 1);
rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 1);
rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
break;
default:
break;
};
}
static void rt2800pci_kick_queue(struct data_queue *queue)
{
struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
struct queue_entry *entry;
switch (queue->qid) {
case QID_AC_VO:
case QID_AC_VI:
case QID_AC_BE:
case QID_AC_BK:
entry = rt2x00queue_get_entry(queue, Q_INDEX);
rt2800_register_write(rt2x00dev, TX_CTX_IDX(queue->qid), entry->entry_idx);
break;
case QID_MGMT:
entry = rt2x00queue_get_entry(queue, Q_INDEX);
rt2800_register_write(rt2x00dev, TX_CTX_IDX(5), entry->entry_idx);
break;
default:
break;
}
}
static void rt2800pci_stop_queue(struct data_queue *queue)
{
struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
u32 reg;
switch (queue->qid) {
case QID_RX:
rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 0);
rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
break;
case QID_BEACON:
rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 0);
rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 0);
rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 0);
rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
break;
default:
break;
}
}
/*
* Firmware functions
*/
@ -323,17 +394,6 @@ static int rt2800pci_init_queues(struct rt2x00_dev *rt2x00dev)
/*
* Device state switch handlers.
*/
static void rt2800pci_toggle_rx(struct rt2x00_dev *rt2x00dev,
enum dev_state state)
{
u32 reg;
rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX,
(state == STATE_RADIO_RX_ON));
rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
}
static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
enum dev_state state)
{
@ -477,10 +537,6 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev,
rt2800pci_disable_radio(rt2x00dev);
rt2800pci_set_state(rt2x00dev, STATE_SLEEP);
break;
case STATE_RADIO_RX_ON:
case STATE_RADIO_RX_OFF:
rt2800pci_toggle_rx(rt2x00dev, state);
break;
case STATE_RADIO_IRQ_ON:
case STATE_RADIO_IRQ_ON_ISR:
case STATE_RADIO_IRQ_OFF:
@ -565,41 +621,6 @@ static void rt2800pci_write_tx_desc(struct queue_entry *entry,
skbdesc->desc_len = TXD_DESC_SIZE;
}
/*
* TX data initialization
*/
static void rt2800pci_kick_tx_queue(struct data_queue *queue)
{
struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX);
unsigned int qidx;
if (queue->qid == QID_MGMT)
qidx = 5;
else
qidx = queue->qid;
rt2800_register_write(rt2x00dev, TX_CTX_IDX(qidx), entry->entry_idx);
}
static void rt2800pci_kill_tx_queue(struct data_queue *queue)
{
struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
u32 reg;
if (queue->qid == QID_BEACON) {
rt2800_register_write(rt2x00dev, BCN_TIME_CFG, 0);
return;
}
rt2800_register_read(rt2x00dev, WPDMA_RST_IDX, &reg);
rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX0, (queue->qid == QID_AC_BE));
rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX1, (queue->qid == QID_AC_BK));
rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX2, (queue->qid == QID_AC_VI));
rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX3, (queue->qid == QID_AC_VO));
rt2800_register_write(rt2x00dev, WPDMA_RST_IDX, reg);
}
/*
* RX control handlers
*/
@ -682,7 +703,7 @@ static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev)
* this tx status.
*/
WARNING(rt2x00dev, "Got TX status report with "
"unexpected pid %u, dropping", qid);
"unexpected pid %u, dropping\n", qid);
break;
}
@ -693,7 +714,7 @@ static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev)
* processing here and drop the tx status
*/
WARNING(rt2x00dev, "Got TX status for an unavailable "
"queue %u, dropping", qid);
"queue %u, dropping\n", qid);
break;
}
@ -703,7 +724,7 @@ static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev)
* and drop the tx status.
*/
WARNING(rt2x00dev, "Got TX status for an empty "
"queue %u, dropping", qid);
"queue %u, dropping\n", qid);
break;
}
@ -944,6 +965,7 @@ static const struct ieee80211_ops rt2800pci_mac80211_ops = {
.rfkill_poll = rt2x00mac_rfkill_poll,
.ampdu_action = rt2800_ampdu_action,
.flush = rt2x00mac_flush,
.get_survey = rt2800_get_survey,
};
static const struct rt2800_ops rt2800pci_rt2800_ops = {
@ -976,11 +998,12 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
.link_stats = rt2800_link_stats,
.reset_tuner = rt2800_reset_tuner,
.link_tuner = rt2800_link_tuner,
.start_queue = rt2800pci_start_queue,
.kick_queue = rt2800pci_kick_queue,
.stop_queue = rt2800pci_stop_queue,
.write_tx_desc = rt2800pci_write_tx_desc,
.write_tx_data = rt2800_write_tx_data,
.write_beacon = rt2800_write_beacon,
.kick_tx_queue = rt2800pci_kick_tx_queue,
.kill_tx_queue = rt2800pci_kill_tx_queue,
.fill_rxdone = rt2800pci_fill_rxdone,
.config_shared_key = rt2800_config_shared_key,
.config_pairwise_key = rt2800_config_pairwise_key,

View File

@ -49,6 +49,55 @@ static int modparam_nohwcrypt;
module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
/*
* Queue handlers.
*/
static void rt2800usb_start_queue(struct data_queue *queue)
{
struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
u32 reg;
switch (queue->qid) {
case QID_RX:
rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 1);
rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
break;
case QID_BEACON:
rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 1);
rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 1);
rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 1);
rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
break;
default:
break;
}
}
static void rt2800usb_stop_queue(struct data_queue *queue)
{
struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
u32 reg;
switch (queue->qid) {
case QID_RX:
rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 0);
rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
break;
case QID_BEACON:
rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 0);
rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 0);
rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 0);
rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
break;
default:
break;
}
}
/*
* Firmware functions
*/
@ -107,17 +156,6 @@ static int rt2800usb_write_firmware(struct rt2x00_dev *rt2x00dev,
/*
* Device state switch handlers.
*/
static void rt2800usb_toggle_rx(struct rt2x00_dev *rt2x00dev,
enum dev_state state)
{
u32 reg;
rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX,
(state == STATE_RADIO_RX_ON));
rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
}
static int rt2800usb_init_registers(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
@ -214,10 +252,6 @@ static int rt2800usb_set_device_state(struct rt2x00_dev *rt2x00dev,
rt2800usb_disable_radio(rt2x00dev);
rt2800usb_set_state(rt2x00dev, STATE_SLEEP);
break;
case STATE_RADIO_RX_ON:
case STATE_RADIO_RX_OFF:
rt2800usb_toggle_rx(rt2x00dev, state);
break;
case STATE_RADIO_IRQ_ON:
case STATE_RADIO_IRQ_ON_ISR:
case STATE_RADIO_IRQ_OFF:
@ -253,7 +287,7 @@ static void rt2800usb_watchdog(struct rt2x00_dev *rt2x00dev)
rt2800_register_read(rt2x00dev, TXRXQ_PCNT, &reg);
if (rt2x00_get_field32(reg, TXRXQ_PCNT_TX0Q)) {
WARNING(rt2x00dev, "TX HW queue 0 timed out,"
" invoke forced kick");
" invoke forced kick\n");
rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40012);
@ -269,7 +303,7 @@ static void rt2800usb_watchdog(struct rt2x00_dev *rt2x00dev)
rt2800_register_read(rt2x00dev, TXRXQ_PCNT, &reg);
if (rt2x00_get_field32(reg, TXRXQ_PCNT_TX1Q)) {
WARNING(rt2x00dev, "TX HW queue 1 timed out,"
" invoke forced kick");
" invoke forced kick\n");
rt2800_register_write(rt2x00dev, PBF_CFG, 0xf4000a);
@ -389,14 +423,6 @@ static void rt2800usb_work_txdone(struct work_struct *work)
}
}
static void rt2800usb_kill_tx_queue(struct data_queue *queue)
{
if (queue->qid == QID_BEACON)
rt2x00usb_register_write(queue->rt2x00dev, BCN_TIME_CFG, 0);
rt2x00usb_kill_tx_queue(queue);
}
/*
* RX control handlers
*/
@ -562,6 +588,7 @@ static const struct ieee80211_ops rt2800usb_mac80211_ops = {
.rfkill_poll = rt2x00mac_rfkill_poll,
.ampdu_action = rt2800_ampdu_action,
.flush = rt2x00mac_flush,
.get_survey = rt2800_get_survey,
};
static const struct rt2800_ops rt2800usb_rt2800_ops = {
@ -591,12 +618,14 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
.reset_tuner = rt2800_reset_tuner,
.link_tuner = rt2800_link_tuner,
.watchdog = rt2800usb_watchdog,
.start_queue = rt2800usb_start_queue,
.kick_queue = rt2x00usb_kick_queue,
.stop_queue = rt2800usb_stop_queue,
.flush_queue = rt2x00usb_flush_queue,
.write_tx_desc = rt2800usb_write_tx_desc,
.write_tx_data = rt2800usb_write_tx_data,
.write_beacon = rt2800_write_beacon,
.get_tx_data_len = rt2800usb_get_tx_data_len,
.kick_tx_queue = rt2x00usb_kick_tx_queue,
.kill_tx_queue = rt2800usb_kill_tx_queue,
.fill_rxdone = rt2800usb_fill_rxdone,
.config_shared_key = rt2800_config_shared_key,
.config_pairwise_key = rt2800_config_pairwise_key,

View File

@ -66,7 +66,7 @@
#ifdef CONFIG_RT2X00_DEBUG
#define DEBUG_PRINTK(__dev, __kernlvl, __lvl, __msg, __args...) \
DEBUG_PRINTK_MSG(__dev, __kernlvl, __lvl, __msg, ##__args);
DEBUG_PRINTK_MSG(__dev, __kernlvl, __lvl, __msg, ##__args)
#else
#define DEBUG_PRINTK(__dev, __kernlvl, __lvl, __msg, __args...) \
do { } while (0)
@ -567,7 +567,15 @@ struct rt2x00lib_ops {
struct link_qual *qual);
void (*link_tuner) (struct rt2x00_dev *rt2x00dev,
struct link_qual *qual, const u32 count);
/*
* Data queue handlers.
*/
void (*watchdog) (struct rt2x00_dev *rt2x00dev);
void (*start_queue) (struct data_queue *queue);
void (*kick_queue) (struct data_queue *queue);
void (*stop_queue) (struct data_queue *queue);
void (*flush_queue) (struct data_queue *queue);
/*
* TX control handlers
@ -579,8 +587,6 @@ struct rt2x00lib_ops {
void (*write_beacon) (struct queue_entry *entry,
struct txentry_desc *txdesc);
int (*get_tx_data_len) (struct queue_entry *entry);
void (*kick_tx_queue) (struct data_queue *queue);
void (*kill_tx_queue) (struct data_queue *queue);
/*
* RX control handlers
@ -1068,6 +1074,78 @@ struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev,
struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue,
enum queue_index index);
/**
* rt2x00queue_pause_queue - Pause a data queue
* @queue: Pointer to &struct data_queue.
*
* This function will pause the data queue locally, preventing
* new frames to be added to the queue (while the hardware is
* still allowed to run).
*/
void rt2x00queue_pause_queue(struct data_queue *queue);
/**
* rt2x00queue_unpause_queue - unpause a data queue
* @queue: Pointer to &struct data_queue.
*
* This function will unpause the data queue locally, allowing
* new frames to be added to the queue again.
*/
void rt2x00queue_unpause_queue(struct data_queue *queue);
/**
* rt2x00queue_start_queue - Start a data queue
* @queue: Pointer to &struct data_queue.
*
* This function will start handling all pending frames in the queue.
*/
void rt2x00queue_start_queue(struct data_queue *queue);
/**
* rt2x00queue_stop_queue - Halt a data queue
* @queue: Pointer to &struct data_queue.
*
* This function will stop all pending frames in the queue.
*/
void rt2x00queue_stop_queue(struct data_queue *queue);
/**
* rt2x00queue_flush_queue - Flush a data queue
* @queue: Pointer to &struct data_queue.
* @drop: True to drop all pending frames.
*
* This function will flush the queue. After this call
* the queue is guarenteed to be empty.
*/
void rt2x00queue_flush_queue(struct data_queue *queue, bool drop);
/**
* rt2x00queue_start_queues - Start all data queues
* @rt2x00dev: Pointer to &struct rt2x00_dev.
*
* This function will loop through all available queues to start them
*/
void rt2x00queue_start_queues(struct rt2x00_dev *rt2x00dev);
/**
* rt2x00queue_stop_queues - Halt all data queues
* @rt2x00dev: Pointer to &struct rt2x00_dev.
*
* This function will loop through all available queues to stop
* any pending frames.
*/
void rt2x00queue_stop_queues(struct rt2x00_dev *rt2x00dev);
/**
* rt2x00queue_flush_queues - Flush all data queues
* @rt2x00dev: Pointer to &struct rt2x00_dev.
* @drop: True to drop all pending frames.
*
* This function will loop through all available queues to flush
* any pending frames.
*/
void rt2x00queue_flush_queues(struct rt2x00_dev *rt2x00dev, bool drop);
/*
* Debugfs handlers.
*/
@ -1093,6 +1171,7 @@ static inline void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
*/
void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev);
void rt2x00lib_pretbtt(struct rt2x00_dev *rt2x00dev);
void rt2x00lib_dmastart(struct queue_entry *entry);
void rt2x00lib_dmadone(struct queue_entry *entry);
void rt2x00lib_txdone(struct queue_entry *entry,
struct txdone_entry_desc *txdesc);

View File

@ -146,8 +146,7 @@ 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))
rt2x00dev->ops->lib->set_device_state(rt2x00dev,
STATE_RADIO_RX_OFF);
rt2x00queue_stop_queue(rt2x00dev->rx);
/*
* Write new antenna setup to device and reset the link tuner.
@ -161,8 +160,7 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
memcpy(active, &config, sizeof(config));
if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
rt2x00dev->ops->lib->set_device_state(rt2x00dev,
STATE_RADIO_RX_ON);
rt2x00queue_start_queue(rt2x00dev->rx);
}
void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,

View File

@ -339,12 +339,13 @@ static ssize_t rt2x00debug_read_queue_stats(struct file *file,
return -ENOMEM;
temp = data +
sprintf(data, "qid\tcount\tlimit\tlength\tindex\tdma done\tdone\n");
sprintf(data, "qid\tflags\t\tcount\tlimit\tlength\tindex\tdma done\tdone\n");
queue_for_each(intf->rt2x00dev, queue) {
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,
temp += sprintf(temp, "%d\t0x%.8x\t%d\t%d\t%d\t%d\t%d\t\t%d\n",
queue->qid, (unsigned int)queue->flags,
queue->count, queue->limit, queue->length,
queue->index[Q_INDEX],
queue->index[Q_INDEX_DMA_DONE],

View File

@ -66,9 +66,9 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev)
set_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags);
/*
* Enable RX.
* Enable queues.
*/
rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_RX_ON);
rt2x00queue_start_queues(rt2x00dev);
rt2x00link_start_tuner(rt2x00dev);
/*
@ -76,11 +76,6 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev)
*/
rt2x00link_start_watchdog(rt2x00dev);
/*
* Start the TX queues.
*/
ieee80211_wake_queues(rt2x00dev->hw);
return 0;
}
@ -89,22 +84,17 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev)
if (!test_and_clear_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
return;
/*
* Stop the TX queues in mac80211.
*/
ieee80211_stop_queues(rt2x00dev->hw);
rt2x00queue_stop_queues(rt2x00dev);
/*
* Stop watchdog monitoring.
*/
rt2x00link_stop_watchdog(rt2x00dev);
/*
* Disable RX.
* Stop all queues
*/
rt2x00link_stop_tuner(rt2x00dev);
rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_RX_OFF);
rt2x00queue_stop_queues(rt2x00dev);
rt2x00queue_flush_queues(rt2x00dev, true);
/*
* Disable radio.
@ -236,8 +226,16 @@ void rt2x00lib_pretbtt(struct rt2x00_dev *rt2x00dev)
}
EXPORT_SYMBOL_GPL(rt2x00lib_pretbtt);
void rt2x00lib_dmastart(struct queue_entry *entry)
{
set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
rt2x00queue_index_inc(entry->queue, Q_INDEX);
}
EXPORT_SYMBOL_GPL(rt2x00lib_dmastart);
void rt2x00lib_dmadone(struct queue_entry *entry)
{
set_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags);
clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
rt2x00queue_index_inc(entry->queue, Q_INDEX_DMA_DONE);
}
@ -249,7 +247,6 @@ void rt2x00lib_txdone(struct queue_entry *entry,
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
enum data_queue_qid qid = skb_get_queue_mapping(entry->skb);
unsigned int header_length, i;
u8 rate_idx, rate_flags, retry_rates;
u8 skbdesc_flags = skbdesc->flags;
@ -403,7 +400,7 @@ void rt2x00lib_txdone(struct queue_entry *entry,
* is reenabled when the txdone handler has finished.
*/
if (!rt2x00queue_threshold(entry->queue))
ieee80211_wake_queue(rt2x00dev->hw, qid);
rt2x00queue_unpause_queue(entry->queue);
}
EXPORT_SYMBOL_GPL(rt2x00lib_txdone);
@ -566,10 +563,8 @@ submit_entry:
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)) {
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);

View File

@ -177,15 +177,6 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
*/
void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index);
/**
* rt2x00queue_stop_queues - Halt all data queues
* @rt2x00dev: Pointer to &struct rt2x00_dev.
*
* This function will loop through all available queues to stop
* any pending outgoing frames.
*/
void rt2x00queue_stop_queues(struct rt2x00_dev *rt2x00dev);
/**
* rt2x00queue_init_queues - Initialize all data queues
* @rt2x00dev: Pointer to &struct rt2x00_dev.

View File

@ -104,7 +104,7 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
struct rt2x00_dev *rt2x00dev = hw->priv;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
enum data_queue_qid qid = skb_get_queue_mapping(skb);
struct data_queue *queue;
struct data_queue *queue = NULL;
/*
* Mac80211 might be calling this function while we are trying
@ -153,7 +153,7 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
goto exit_fail;
if (rt2x00queue_threshold(queue))
ieee80211_stop_queue(rt2x00dev->hw, qid);
rt2x00queue_pause_queue(queue);
return NETDEV_TX_OK;
@ -352,7 +352,7 @@ int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed)
* if for any reason the link tuner must be reset, this will be
* handled by rt2x00lib_config().
*/
rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_RX_OFF);
rt2x00queue_stop_queue(rt2x00dev->rx);
/*
* When we've just turned on the radio, we want to reprogram
@ -370,7 +370,7 @@ int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed)
rt2x00lib_config_antenna(rt2x00dev, rt2x00dev->default_ant);
/* Turn RX back on */
rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_RX_ON);
rt2x00queue_start_queue(rt2x00dev->rx);
return 0;
}
@ -718,36 +718,8 @@ void rt2x00mac_flush(struct ieee80211_hw *hw, bool drop)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
struct data_queue *queue;
unsigned int i = 0;
ieee80211_stop_queues(hw);
/*
* Run over all queues to kick them, this will force
* any pending frames to be transmitted.
*/
tx_queue_for_each(rt2x00dev, queue) {
rt2x00dev->ops->lib->kick_tx_queue(queue);
}
/**
* All queues have been kicked, now wait for each queue
* to become empty. With a bit of luck, we only have to wait
* for the first queue to become empty, because while waiting
* for the that queue, the other queues will have transmitted
* all their frames as well (since they were already kicked).
*/
tx_queue_for_each(rt2x00dev, queue) {
for (i = 0; i < 10; i++) {
if (rt2x00queue_empty(queue))
break;
msleep(100);
}
if (!rt2x00queue_empty(queue))
WARNING(rt2x00dev, "Failed to flush queue %d", queue->qid);
}
ieee80211_wake_queues(hw);
tx_queue_for_each(rt2x00dev, queue)
rt2x00queue_flush_queue(queue, drop);
}
EXPORT_SYMBOL_GPL(rt2x00mac_flush);

View File

@ -81,6 +81,13 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
skbdesc->desc = entry_priv->desc;
skbdesc->desc_len = entry->queue->desc_size;
/*
* DMA is already done, notify rt2x00lib that
* it finished successfully.
*/
rt2x00lib_dmastart(entry);
rt2x00lib_dmadone(entry);
/*
* Send the frame to rt2x00lib for further processing.
*/

View File

@ -64,7 +64,7 @@ static inline void rt2x00pci_register_multiwrite(struct rt2x00_dev *rt2x00dev,
const void *value,
const u32 length)
{
memcpy_toio(rt2x00dev->csr.base + offset, value, length);
__iowrite32_copy(rt2x00dev->csr.base + offset, value, length >> 2);
}
/**

View File

@ -199,15 +199,18 @@ void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int header_length)
void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int header_length)
{
unsigned int l2pad = L2PAD_SIZE(header_length);
/*
* L2 padding is only present if the skb contains more than just the
* IEEE 802.11 header.
*/
unsigned int l2pad = (skb->len > header_length) ?
L2PAD_SIZE(header_length) : 0;
if (!l2pad)
return;
memmove(skb->data + header_length, skb->data + header_length + l2pad,
skb->len - header_length - l2pad);
skb_trim(skb, skb->len - l2pad);
memmove(skb->data + l2pad, skb->data, header_length);
skb_pull(skb, l2pad);
}
static void rt2x00queue_create_tx_descriptor_seq(struct queue_entry *entry,
@ -468,7 +471,7 @@ static void rt2x00queue_kick_tx_queue(struct data_queue *queue,
*/
if (rt2x00queue_threshold(queue) ||
!test_bit(ENTRY_TXD_BURST, &txdesc->flags))
queue->rt2x00dev->ops->lib->kick_tx_queue(queue);
queue->rt2x00dev->ops->lib->kick_queue(queue);
}
int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
@ -582,7 +585,7 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
rt2x00queue_free_skb(intf->beacon);
if (!enable_beacon) {
rt2x00dev->ops->lib->kill_tx_queue(intf->beacon->queue);
rt2x00queue_stop_queue(intf->beacon->queue);
mutex_unlock(&intf->beacon_skb_mutex);
return 0;
}
@ -735,6 +738,210 @@ void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index)
spin_unlock_irqrestore(&queue->index_lock, irqflags);
}
void rt2x00queue_pause_queue(struct data_queue *queue)
{
if (!test_bit(DEVICE_STATE_PRESENT, &queue->rt2x00dev->flags) ||
!test_bit(QUEUE_STARTED, &queue->flags) ||
test_and_set_bit(QUEUE_PAUSED, &queue->flags))
return;
switch (queue->qid) {
case QID_AC_VO:
case QID_AC_VI:
case QID_AC_BE:
case QID_AC_BK:
/*
* For TX queues, we have to disable the queue
* inside mac80211.
*/
ieee80211_stop_queue(queue->rt2x00dev->hw, queue->qid);
break;
default:
break;
}
}
EXPORT_SYMBOL_GPL(rt2x00queue_pause_queue);
void rt2x00queue_unpause_queue(struct data_queue *queue)
{
if (!test_bit(DEVICE_STATE_PRESENT, &queue->rt2x00dev->flags) ||
!test_bit(QUEUE_STARTED, &queue->flags) ||
!test_and_clear_bit(QUEUE_PAUSED, &queue->flags))
return;
switch (queue->qid) {
case QID_AC_VO:
case QID_AC_VI:
case QID_AC_BE:
case QID_AC_BK:
/*
* For TX queues, we have to enable the queue
* inside mac80211.
*/
ieee80211_wake_queue(queue->rt2x00dev->hw, queue->qid);
break;
case QID_RX:
/*
* For RX we need to kick the queue now in order to
* receive frames.
*/
queue->rt2x00dev->ops->lib->kick_queue(queue);
default:
break;
}
}
EXPORT_SYMBOL_GPL(rt2x00queue_unpause_queue);
void rt2x00queue_start_queue(struct data_queue *queue)
{
mutex_lock(&queue->status_lock);
if (!test_bit(DEVICE_STATE_PRESENT, &queue->rt2x00dev->flags) ||
test_and_set_bit(QUEUE_STARTED, &queue->flags)) {
mutex_unlock(&queue->status_lock);
return;
}
set_bit(QUEUE_PAUSED, &queue->flags);
queue->rt2x00dev->ops->lib->start_queue(queue);
rt2x00queue_unpause_queue(queue);
mutex_unlock(&queue->status_lock);
}
EXPORT_SYMBOL_GPL(rt2x00queue_start_queue);
void rt2x00queue_stop_queue(struct data_queue *queue)
{
mutex_lock(&queue->status_lock);
if (!test_and_clear_bit(QUEUE_STARTED, &queue->flags)) {
mutex_unlock(&queue->status_lock);
return;
}
rt2x00queue_pause_queue(queue);
queue->rt2x00dev->ops->lib->stop_queue(queue);
mutex_unlock(&queue->status_lock);
}
EXPORT_SYMBOL_GPL(rt2x00queue_stop_queue);
void rt2x00queue_flush_queue(struct data_queue *queue, bool drop)
{
unsigned int i;
bool started;
bool tx_queue =
(queue->qid == QID_AC_VO) ||
(queue->qid == QID_AC_VI) ||
(queue->qid == QID_AC_BE) ||
(queue->qid == QID_AC_BK);
mutex_lock(&queue->status_lock);
/*
* If the queue has been started, we must stop it temporarily
* to prevent any new frames to be queued on the device. If
* we are not dropping the pending frames, the queue must
* only be stopped in the software and not the hardware,
* otherwise the queue will never become empty on its own.
*/
started = test_bit(QUEUE_STARTED, &queue->flags);
if (started) {
/*
* Pause the queue
*/
rt2x00queue_pause_queue(queue);
/*
* If we are not supposed to drop any pending
* frames, this means we must force a start (=kick)
* to the queue to make sure the hardware will
* start transmitting.
*/
if (!drop && tx_queue)
queue->rt2x00dev->ops->lib->kick_queue(queue);
}
/*
* Check if driver supports flushing, we can only guarentee
* full support for flushing if the driver is able
* to cancel all pending frames (drop = true).
*/
if (drop && queue->rt2x00dev->ops->lib->flush_queue)
queue->rt2x00dev->ops->lib->flush_queue(queue);
/*
* When we don't want to drop any frames, or when
* the driver doesn't fully flush the queue correcly,
* we must wait for the queue to become empty.
*/
for (i = 0; !rt2x00queue_empty(queue) && i < 100; i++)
msleep(10);
/*
* The queue flush has failed...
*/
if (unlikely(!rt2x00queue_empty(queue)))
WARNING(queue->rt2x00dev, "Queue %d failed to flush", queue->qid);
/*
* Restore the queue to the previous status
*/
if (started)
rt2x00queue_unpause_queue(queue);
mutex_unlock(&queue->status_lock);
}
EXPORT_SYMBOL_GPL(rt2x00queue_flush_queue);
void rt2x00queue_start_queues(struct rt2x00_dev *rt2x00dev)
{
struct data_queue *queue;
/*
* rt2x00queue_start_queue will call ieee80211_wake_queue
* for each queue after is has been properly initialized.
*/
tx_queue_for_each(rt2x00dev, queue)
rt2x00queue_start_queue(queue);
rt2x00queue_start_queue(rt2x00dev->rx);
}
EXPORT_SYMBOL_GPL(rt2x00queue_start_queues);
void rt2x00queue_stop_queues(struct rt2x00_dev *rt2x00dev)
{
struct data_queue *queue;
/*
* rt2x00queue_stop_queue will call ieee80211_stop_queue
* as well, but we are completely shutting doing everything
* now, so it is much safer to stop all TX queues at once,
* and use rt2x00queue_stop_queue for cleaning up.
*/
ieee80211_stop_queues(rt2x00dev->hw);
tx_queue_for_each(rt2x00dev, queue)
rt2x00queue_stop_queue(queue);
rt2x00queue_stop_queue(rt2x00dev->rx);
}
EXPORT_SYMBOL_GPL(rt2x00queue_stop_queues);
void rt2x00queue_flush_queues(struct rt2x00_dev *rt2x00dev, bool drop)
{
struct data_queue *queue;
tx_queue_for_each(rt2x00dev, queue)
rt2x00queue_flush_queue(queue, drop);
rt2x00queue_flush_queue(rt2x00dev->rx, drop);
}
EXPORT_SYMBOL_GPL(rt2x00queue_flush_queues);
static void rt2x00queue_reset(struct data_queue *queue)
{
unsigned long irqflags;
@ -753,14 +960,6 @@ static void rt2x00queue_reset(struct data_queue *queue)
spin_unlock_irqrestore(&queue->index_lock, irqflags);
}
void rt2x00queue_stop_queues(struct rt2x00_dev *rt2x00dev)
{
struct data_queue *queue;
txall_queue_for_each(rt2x00dev, queue)
rt2x00dev->ops->lib->kill_tx_queue(queue);
}
void rt2x00queue_init_queues(struct rt2x00_dev *rt2x00dev)
{
struct data_queue *queue;
@ -769,11 +968,8 @@ void rt2x00queue_init_queues(struct rt2x00_dev *rt2x00dev)
queue_for_each(rt2x00dev, queue) {
rt2x00queue_reset(queue);
for (i = 0; i < queue->limit; i++) {
for (i = 0; i < queue->limit; i++)
rt2x00dev->ops->lib->clear_entry(&queue->entries[i]);
if (queue->qid == QID_RX)
rt2x00queue_index_inc(queue, Q_INDEX);
}
}
}
@ -902,6 +1098,7 @@ void rt2x00queue_uninitialize(struct rt2x00_dev *rt2x00dev)
static void rt2x00queue_init(struct rt2x00_dev *rt2x00dev,
struct data_queue *queue, enum data_queue_qid qid)
{
mutex_init(&queue->status_lock);
spin_lock_init(&queue->index_lock);
queue->rt2x00dev = rt2x00dev;
@ -944,7 +1141,7 @@ int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev)
/*
* Initialize queue parameters.
* RX: qid = QID_RX
* TX: qid = QID_AC_BE + index
* TX: qid = QID_AC_VO + index
* TX: cw_min: 2^5 = 32.
* TX: cw_max: 2^10 = 1024.
* BCN: qid = QID_BEACON
@ -952,7 +1149,7 @@ int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev)
*/
rt2x00queue_init(rt2x00dev, rt2x00dev->rx, QID_RX);
qid = QID_AC_BE;
qid = QID_AC_VO;
tx_queue_for_each(rt2x00dev, queue)
rt2x00queue_init(rt2x00dev, queue, qid++);

View File

@ -45,10 +45,10 @@
/**
* enum data_queue_qid: Queue identification
*
* @QID_AC_VO: AC VO queue
* @QID_AC_VI: AC VI queue
* @QID_AC_BE: AC BE queue
* @QID_AC_BK: AC BK queue
* @QID_AC_VI: AC VI queue
* @QID_AC_VO: AC VO queue
* @QID_HCCA: HCCA queue
* @QID_MGMT: MGMT queue (prio queue)
* @QID_RX: RX queue
@ -57,10 +57,10 @@
* @QID_ATIM: Atim queue (value unspeficied, don't send it to device)
*/
enum data_queue_qid {
QID_AC_BE = 0,
QID_AC_BK = 1,
QID_AC_VI = 2,
QID_AC_VO = 3,
QID_AC_VO = 0,
QID_AC_VI = 1,
QID_AC_BE = 2,
QID_AC_BK = 3,
QID_HCCA = 4,
QID_MGMT = 13,
QID_RX = 14,
@ -340,12 +340,16 @@ struct txentry_desc {
* @ENTRY_DATA_IO_FAILED: Hardware indicated that an IO error occured
* while transfering the data to the hardware. No TX status report will
* be expected from the hardware.
* @ENTRY_DATA_STATUS_PENDING: The entry has been send to the device and
* returned. It is now waiting for the status reporting before the
* entry can be reused again.
*/
enum queue_entry_flags {
ENTRY_BCN_ASSIGNED,
ENTRY_OWNER_DEVICE_DATA,
ENTRY_DATA_PENDING,
ENTRY_DATA_IO_FAILED
ENTRY_DATA_IO_FAILED,
ENTRY_DATA_STATUS_PENDING,
};
/**
@ -391,6 +395,23 @@ enum queue_index {
Q_INDEX_MAX,
};
/**
* enum data_queue_flags: Status flags for data queues
*
* @QUEUE_STARTED: The queue has been started. Fox RX queues this means the
* device might be DMA'ing skbuffers. TX queues will accept skbuffers to
* be transmitted and beacon queues will start beaconing the configured
* beacons.
* @QUEUE_PAUSED: The queue has been started but is currently paused.
* When this bit is set, the queue has been stopped in mac80211,
* preventing new frames to be enqueued. However, a few frames
* might still appear shortly after the pausing...
*/
enum data_queue_flags {
QUEUE_STARTED,
QUEUE_PAUSED,
};
/**
* struct data_queue: Data queue
*
@ -398,6 +419,9 @@ enum queue_index {
* @entries: Base address of the &struct queue_entry which are
* part of this queue.
* @qid: The queue identification, see &enum data_queue_qid.
* @flags: Entry flags, see &enum queue_entry_flags.
* @status_lock: The mutex for protecting the start/stop/flush
* handling on this queue.
* @index_lock: Spinlock to protect index handling. Whenever @index, @index_done or
* @index_crypt needs to be changed this lock should be grabbed to prevent
* index corruption due to concurrency.
@ -421,8 +445,11 @@ struct data_queue {
struct queue_entry *entries;
enum data_queue_qid qid;
unsigned long flags;
struct mutex status_lock;
spinlock_t index_lock;
unsigned int count;
unsigned short limit;
unsigned short threshold;

View File

@ -83,8 +83,6 @@ enum dev_state {
*/
STATE_RADIO_ON,
STATE_RADIO_OFF,
STATE_RADIO_RX_ON,
STATE_RADIO_RX_OFF,
STATE_RADIO_IRQ_ON,
STATE_RADIO_IRQ_OFF,
STATE_RADIO_IRQ_ON_ISR,

View File

@ -195,7 +195,8 @@ static void rt2x00usb_work_txdone(struct work_struct *work)
while (!rt2x00queue_empty(queue)) {
entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
!test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
break;
rt2x00usb_work_txdone_entry(entry);
@ -235,8 +236,10 @@ static void rt2x00usb_kick_tx_entry(struct queue_entry *entry)
struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
struct queue_entry_priv_usb *entry_priv = entry->priv_data;
u32 length;
int status;
if (!test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags))
if (!test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags) ||
test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
return;
/*
@ -251,106 +254,15 @@ static void rt2x00usb_kick_tx_entry(struct queue_entry *entry)
entry->skb->data, length,
rt2x00usb_interrupt_txdone, entry);
if (usb_submit_urb(entry_priv->urb, GFP_ATOMIC)) {
status = usb_submit_urb(entry_priv->urb, GFP_ATOMIC);
if (status) {
if (status == -ENODEV)
clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
rt2x00lib_dmadone(entry);
}
}
void rt2x00usb_kick_tx_queue(struct data_queue *queue)
{
rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX,
rt2x00usb_kick_tx_entry);
}
EXPORT_SYMBOL_GPL(rt2x00usb_kick_tx_queue);
static void rt2x00usb_kill_tx_entry(struct queue_entry *entry)
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct queue_entry_priv_usb *entry_priv = entry->priv_data;
struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data;
if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
return;
usb_kill_urb(entry_priv->urb);
/*
* Kill guardian urb (if required by driver).
*/
if ((entry->queue->qid == QID_BEACON) &&
(test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags)))
usb_kill_urb(bcn_priv->guardian_urb);
}
void rt2x00usb_kill_tx_queue(struct data_queue *queue)
{
rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX,
rt2x00usb_kill_tx_entry);
}
EXPORT_SYMBOL_GPL(rt2x00usb_kill_tx_queue);
static void rt2x00usb_watchdog_tx_dma(struct data_queue *queue)
{
struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
unsigned short threshold = queue->threshold;
WARNING(queue->rt2x00dev, "TX queue %d DMA timed out,"
" invoke forced forced reset", queue->qid);
/*
* Temporarily disable the TX queue, this will force mac80211
* to use the other queues until this queue has been restored.
*
* Set the queue threshold to the queue limit. This prevents the
* queue from being enabled during the txdone handler.
*/
queue->threshold = queue->limit;
ieee80211_stop_queue(rt2x00dev->hw, queue->qid);
/*
* Kill all entries in the queue, afterwards we need to
* wait a bit for all URBs to be cancelled.
*/
rt2x00usb_kill_tx_queue(queue);
/*
* In case that a driver has overriden the txdone_work
* function, we invoke the TX done through there.
*/
rt2x00dev->txdone_work.func(&rt2x00dev->txdone_work);
/*
* The queue has been reset, and mac80211 is allowed to use the
* queue again.
*/
queue->threshold = threshold;
ieee80211_wake_queue(rt2x00dev->hw, queue->qid);
}
static void rt2x00usb_watchdog_tx_status(struct data_queue *queue)
{
WARNING(queue->rt2x00dev, "TX queue %d status timed out,"
" invoke forced tx handler", queue->qid);
ieee80211_queue_work(queue->rt2x00dev->hw, &queue->rt2x00dev->txdone_work);
}
void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev)
{
struct data_queue *queue;
tx_queue_for_each(rt2x00dev, queue) {
if (!rt2x00queue_empty(queue)) {
if (rt2x00queue_dma_timeout(queue))
rt2x00usb_watchdog_tx_dma(queue);
if (rt2x00queue_status_timeout(queue))
rt2x00usb_watchdog_tx_status(queue);
}
}
}
EXPORT_SYMBOL_GPL(rt2x00usb_watchdog);
/*
* RX data handlers.
*/
@ -365,7 +277,8 @@ static void rt2x00usb_work_rxdone(struct work_struct *work)
while (!rt2x00queue_empty(rt2x00dev->rx)) {
entry = rt2x00queue_get_entry(rt2x00dev->rx, Q_INDEX_DONE);
if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
!test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
break;
/*
@ -410,6 +323,154 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->rxdone_work);
}
static void rt2x00usb_kick_rx_entry(struct queue_entry *entry)
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
struct queue_entry_priv_usb *entry_priv = entry->priv_data;
int status;
if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) ||
test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags))
return;
rt2x00lib_dmastart(entry);
usb_fill_bulk_urb(entry_priv->urb, usb_dev,
usb_rcvbulkpipe(usb_dev, entry->queue->usb_endpoint),
entry->skb->data, entry->skb->len,
rt2x00usb_interrupt_rxdone, entry);
status = usb_submit_urb(entry_priv->urb, GFP_ATOMIC);
if (status) {
if (status == -ENODEV)
clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
rt2x00lib_dmadone(entry);
}
}
void rt2x00usb_kick_queue(struct data_queue *queue)
{
switch (queue->qid) {
case QID_AC_VO:
case QID_AC_VI:
case QID_AC_BE:
case QID_AC_BK:
if (!rt2x00queue_empty(queue))
rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX,
rt2x00usb_kick_tx_entry);
break;
case QID_RX:
if (!rt2x00queue_full(queue))
rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX,
rt2x00usb_kick_rx_entry);
break;
default:
break;
}
}
EXPORT_SYMBOL_GPL(rt2x00usb_kick_queue);
static void rt2x00usb_flush_entry(struct queue_entry *entry)
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct queue_entry_priv_usb *entry_priv = entry->priv_data;
struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data;
if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
return;
usb_kill_urb(entry_priv->urb);
/*
* Kill guardian urb (if required by driver).
*/
if ((entry->queue->qid == QID_BEACON) &&
(test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags)))
usb_kill_urb(bcn_priv->guardian_urb);
}
void rt2x00usb_flush_queue(struct data_queue *queue)
{
struct work_struct *completion;
unsigned int i;
rt2x00queue_for_each_entry(queue, Q_INDEX_DONE, Q_INDEX,
rt2x00usb_flush_entry);
/*
* Obtain the queue completion handler
*/
switch (queue->qid) {
case QID_AC_VO:
case QID_AC_VI:
case QID_AC_BE:
case QID_AC_BK:
completion = &queue->rt2x00dev->txdone_work;
break;
case QID_RX:
completion = &queue->rt2x00dev->rxdone_work;
break;
default:
return;
}
for (i = 0; i < 20; i++) {
/*
* Check if the driver is already done, otherwise we
* have to sleep a little while to give the driver/hw
* the oppurtunity to complete interrupt process itself.
*/
if (rt2x00queue_empty(queue))
break;
/*
* Schedule the completion handler manually, when this
* worker function runs, it should cleanup the queue.
*/
ieee80211_queue_work(queue->rt2x00dev->hw, completion);
/*
* Wait for a little while to give the driver
* the oppurtunity to recover itself.
*/
msleep(10);
}
}
EXPORT_SYMBOL_GPL(rt2x00usb_flush_queue);
static void rt2x00usb_watchdog_tx_dma(struct data_queue *queue)
{
WARNING(queue->rt2x00dev, "TX queue %d DMA timed out,"
" invoke forced forced reset\n", queue->qid);
rt2x00queue_flush_queue(queue, true);
}
static void rt2x00usb_watchdog_tx_status(struct data_queue *queue)
{
WARNING(queue->rt2x00dev, "TX queue %d status timed out,"
" invoke forced tx handler\n", queue->qid);
ieee80211_queue_work(queue->rt2x00dev->hw, &queue->rt2x00dev->txdone_work);
}
void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev)
{
struct data_queue *queue;
tx_queue_for_each(rt2x00dev, queue) {
if (!rt2x00queue_empty(queue)) {
if (rt2x00queue_dma_timeout(queue))
rt2x00usb_watchdog_tx_dma(queue);
if (rt2x00queue_status_timeout(queue))
rt2x00usb_watchdog_tx_status(queue);
}
}
}
EXPORT_SYMBOL_GPL(rt2x00usb_watchdog);
/*
* Radio handlers
*/
@ -417,12 +478,6 @@ void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev)
{
rt2x00usb_vendor_request_sw(rt2x00dev, USB_RX_CONTROL, 0, 0,
REGISTER_TIMEOUT);
/*
* The USB version of kill_tx_queue also works
* on the RX queue.
*/
rt2x00dev->ops->lib->kill_tx_queue(rt2x00dev->rx);
}
EXPORT_SYMBOL_GPL(rt2x00usb_disable_radio);
@ -431,25 +486,10 @@ EXPORT_SYMBOL_GPL(rt2x00usb_disable_radio);
*/
void rt2x00usb_clear_entry(struct queue_entry *entry)
{
struct usb_device *usb_dev =
to_usb_device_intf(entry->queue->rt2x00dev->dev);
struct queue_entry_priv_usb *entry_priv = entry->priv_data;
int pipe;
entry->flags = 0;
if (entry->queue->qid == QID_RX) {
pipe = usb_rcvbulkpipe(usb_dev, entry->queue->usb_endpoint);
usb_fill_bulk_urb(entry_priv->urb, usb_dev, pipe,
entry->skb->data, entry->skb->len,
rt2x00usb_interrupt_rxdone, entry);
set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
if (usb_submit_urb(entry_priv->urb, GFP_ATOMIC)) {
set_bit(ENTRY_DATA_IO_FAILED, &entry->flags);
rt2x00lib_dmadone(entry);
}
}
if (entry->queue->qid == QID_RX)
rt2x00usb_kick_rx_entry(entry);
}
EXPORT_SYMBOL_GPL(rt2x00usb_clear_entry);

View File

@ -378,22 +378,22 @@ struct queue_entry_priv_usb_bcn {
};
/**
* rt2x00usb_kick_tx_queue - Kick data queue
* rt2x00usb_kick_queue - Kick data queue
* @queue: Data queue to kick
*
* This will walk through all entries of the queue and push all pending
* frames to the hardware as a single burst.
*/
void rt2x00usb_kick_tx_queue(struct data_queue *queue);
void rt2x00usb_kick_queue(struct data_queue *queue);
/**
* rt2x00usb_kill_tx_queue - Kill data queue
* @queue: Data queue to kill
* rt2x00usb_flush_queue - Flush data queue
* @queue: Data queue to stop
*
* This will walk through all entries of the queue and kill all
* previously kicked frames before they can be send.
* URB's which were send to the device.
*/
void rt2x00usb_kill_tx_queue(struct data_queue *queue);
void rt2x00usb_flush_queue(struct data_queue *queue);
/**
* rt2x00usb_watchdog - Watchdog for USB communication

View File

@ -1139,6 +1139,106 @@ dynamic_cca_tune:
rt61pci_set_vgc(rt2x00dev, qual, --qual->vgc_level);
}
/*
* Queue handlers.
*/
static void rt61pci_start_queue(struct data_queue *queue)
{
struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
u32 reg;
switch (queue->qid) {
case QID_RX:
rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, &reg);
rt2x00_set_field32(&reg, TXRX_CSR0_DISABLE_RX, 0);
rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
break;
case QID_BEACON:
rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 1);
rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
break;
default:
break;
}
}
static void rt61pci_kick_queue(struct data_queue *queue)
{
struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
u32 reg;
switch (queue->qid) {
case QID_AC_VO:
rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC0, 1);
rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg);
break;
case QID_AC_VI:
rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC1, 1);
rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg);
break;
case QID_AC_BE:
rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC2, 1);
rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg);
break;
case QID_AC_BK:
rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC3, 1);
rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg);
break;
default:
break;
}
}
static void rt61pci_stop_queue(struct data_queue *queue)
{
struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
u32 reg;
switch (queue->qid) {
case QID_AC_VO:
rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC0, 1);
rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg);
break;
case QID_AC_VI:
rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC1, 1);
rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg);
break;
case QID_AC_BE:
rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC2, 1);
rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg);
break;
case QID_AC_BK:
rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC3, 1);
rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg);
break;
case QID_RX:
rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, &reg);
rt2x00_set_field32(&reg, TXRX_CSR0_DISABLE_RX, 1);
rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
break;
case QID_BEACON:
rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 0);
rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 0);
rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
break;
default:
break;
}
}
/*
* Firmware functions
*/
@ -1616,17 +1716,6 @@ static int rt61pci_init_bbp(struct rt2x00_dev *rt2x00dev)
/*
* Device state switch handlers.
*/
static void rt61pci_toggle_rx(struct rt2x00_dev *rt2x00dev,
enum dev_state state)
{
u32 reg;
rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, &reg);
rt2x00_set_field32(&reg, TXRX_CSR0_DISABLE_RX,
(state == STATE_RADIO_RX_OFF));
rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
}
static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
enum dev_state state)
{
@ -1743,10 +1832,6 @@ static int rt61pci_set_device_state(struct rt2x00_dev *rt2x00dev,
case STATE_RADIO_OFF:
rt61pci_disable_radio(rt2x00dev);
break;
case STATE_RADIO_RX_ON:
case STATE_RADIO_RX_OFF:
rt61pci_toggle_rx(rt2x00dev, state);
break;
case STATE_RADIO_IRQ_ON:
case STATE_RADIO_IRQ_ON_ISR:
case STATE_RADIO_IRQ_OFF:
@ -1876,6 +1961,7 @@ static void rt61pci_write_beacon(struct queue_entry *entry,
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct queue_entry_priv_pci *entry_priv = entry->priv_data;
unsigned int beacon_base;
unsigned int padding_len;
u32 reg;
/*
@ -1897,13 +1983,16 @@ static void rt61pci_write_beacon(struct queue_entry *entry,
rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb);
/*
* Write entire beacon with descriptor to register.
* Write entire beacon with descriptor and padding to register.
*/
padding_len = roundup(entry->skb->len, 4) - entry->skb->len;
skb_pad(entry->skb, padding_len);
beacon_base = HW_BEACON_OFFSET(entry->entry_idx);
rt2x00pci_register_multiwrite(rt2x00dev, beacon_base,
entry_priv->desc, TXINFO_SIZE);
rt2x00pci_register_multiwrite(rt2x00dev, beacon_base + TXINFO_SIZE,
entry->skb->data, entry->skb->len);
entry->skb->data,
entry->skb->len + padding_len);
/*
* Enable beaconing again.
@ -1925,37 +2014,6 @@ static void rt61pci_write_beacon(struct queue_entry *entry,
entry->skb = NULL;
}
static void rt61pci_kick_tx_queue(struct data_queue *queue)
{
struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
u32 reg;
rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC0, (queue->qid == QID_AC_BE));
rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC1, (queue->qid == QID_AC_BK));
rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC2, (queue->qid == QID_AC_VI));
rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC3, (queue->qid == QID_AC_VO));
rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg);
}
static void rt61pci_kill_tx_queue(struct data_queue *queue)
{
struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
u32 reg;
if (queue->qid == QID_BEACON) {
rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, 0);
return;
}
rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC0, (queue->qid == QID_AC_BE));
rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC1, (queue->qid == QID_AC_BK));
rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC2, (queue->qid == QID_AC_VI));
rt2x00_set_field32(&reg, TX_CNTL_CSR_ABORT_TX_AC3, (queue->qid == QID_AC_VO));
rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg);
}
/*
* RX control handlers
*/
@ -2840,10 +2898,11 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
.link_stats = rt61pci_link_stats,
.reset_tuner = rt61pci_reset_tuner,
.link_tuner = rt61pci_link_tuner,
.start_queue = rt61pci_start_queue,
.kick_queue = rt61pci_kick_queue,
.stop_queue = rt61pci_stop_queue,
.write_tx_desc = rt61pci_write_tx_desc,
.write_beacon = rt61pci_write_beacon,
.kick_tx_queue = rt61pci_kick_tx_queue,
.kill_tx_queue = rt61pci_kill_tx_queue,
.fill_rxdone = rt61pci_fill_rxdone,
.config_shared_key = rt61pci_config_shared_key,
.config_pairwise_key = rt61pci_config_pairwise_key,

View File

@ -784,25 +784,25 @@ struct hw_pairwise_ta_entry {
*/
/*
* AC0_BASE_CSR: AC_BK base address.
* AC0_BASE_CSR: AC_VO base address.
*/
#define AC0_BASE_CSR 0x3400
#define AC0_BASE_CSR_RING_REGISTER FIELD32(0xffffffff)
/*
* AC1_BASE_CSR: AC_BE base address.
* AC1_BASE_CSR: AC_VI base address.
*/
#define AC1_BASE_CSR 0x3404
#define AC1_BASE_CSR_RING_REGISTER FIELD32(0xffffffff)
/*
* AC2_BASE_CSR: AC_VI base address.
* AC2_BASE_CSR: AC_BE base address.
*/
#define AC2_BASE_CSR 0x3408
#define AC2_BASE_CSR_RING_REGISTER FIELD32(0xffffffff)
/*
* AC3_BASE_CSR: AC_VO base address.
* AC3_BASE_CSR: AC_BK base address.
*/
#define AC3_BASE_CSR 0x340c
#define AC3_BASE_CSR_RING_REGISTER FIELD32(0xffffffff)
@ -814,7 +814,7 @@ struct hw_pairwise_ta_entry {
#define MGMT_BASE_CSR_RING_REGISTER FIELD32(0xffffffff)
/*
* TX_RING_CSR0: TX Ring size for AC_BK, AC_BE, AC_VI, AC_VO.
* TX_RING_CSR0: TX Ring size for AC_VO, AC_VI, AC_BE, AC_BK.
*/
#define TX_RING_CSR0 0x3418
#define TX_RING_CSR0_AC0_RING_SIZE FIELD32(0x000000ff)
@ -833,10 +833,10 @@ struct hw_pairwise_ta_entry {
/*
* AIFSN_CSR: AIFSN for each EDCA AC.
* AIFSN0: For AC_BK.
* AIFSN1: For AC_BE.
* AIFSN2: For AC_VI.
* AIFSN3: For AC_VO.
* AIFSN0: For AC_VO.
* AIFSN1: For AC_VI.
* AIFSN2: For AC_BE.
* AIFSN3: For AC_BK.
*/
#define AIFSN_CSR 0x3420
#define AIFSN_CSR_AIFSN0 FIELD32(0x0000000f)
@ -846,10 +846,10 @@ struct hw_pairwise_ta_entry {
/*
* CWMIN_CSR: CWmin for each EDCA AC.
* CWMIN0: For AC_BK.
* CWMIN1: For AC_BE.
* CWMIN2: For AC_VI.
* CWMIN3: For AC_VO.
* CWMIN0: For AC_VO.
* CWMIN1: For AC_VI.
* CWMIN2: For AC_BE.
* CWMIN3: For AC_BK.
*/
#define CWMIN_CSR 0x3424
#define CWMIN_CSR_CWMIN0 FIELD32(0x0000000f)
@ -859,10 +859,10 @@ struct hw_pairwise_ta_entry {
/*
* CWMAX_CSR: CWmax for each EDCA AC.
* CWMAX0: For AC_BK.
* CWMAX1: For AC_BE.
* CWMAX2: For AC_VI.
* CWMAX3: For AC_VO.
* CWMAX0: For AC_VO.
* CWMAX1: For AC_VI.
* CWMAX2: For AC_BE.
* CWMAX3: For AC_BK.
*/
#define CWMAX_CSR 0x3428
#define CWMAX_CSR_CWMAX0 FIELD32(0x0000000f)
@ -883,14 +883,14 @@ struct hw_pairwise_ta_entry {
/*
* TX_CNTL_CSR: KICK/Abort TX.
* KICK_TX_AC0: For AC_BK.
* KICK_TX_AC1: For AC_BE.
* KICK_TX_AC2: For AC_VI.
* KICK_TX_AC3: For AC_VO.
* ABORT_TX_AC0: For AC_BK.
* ABORT_TX_AC1: For AC_BE.
* ABORT_TX_AC2: For AC_VI.
* ABORT_TX_AC3: For AC_VO.
* KICK_TX_AC0: For AC_VO.
* KICK_TX_AC1: For AC_VI.
* KICK_TX_AC2: For AC_BE.
* KICK_TX_AC3: For AC_BK.
* ABORT_TX_AC0: For AC_VO.
* ABORT_TX_AC1: For AC_VI.
* ABORT_TX_AC2: For AC_BE.
* ABORT_TX_AC3: For AC_BK.
*/
#define TX_CNTL_CSR 0x3430
#define TX_CNTL_CSR_KICK_TX_AC0 FIELD32(0x00000001)
@ -1010,18 +1010,18 @@ struct hw_pairwise_ta_entry {
#define E2PROM_CSR_LOAD_STATUS FIELD32(0x00000040)
/*
* AC_TXOP_CSR0: AC_BK/AC_BE TXOP register.
* AC0_TX_OP: For AC_BK, in unit of 32us.
* AC1_TX_OP: For AC_BE, in unit of 32us.
* AC_TXOP_CSR0: AC_VO/AC_VI TXOP register.
* AC0_TX_OP: For AC_VO, in unit of 32us.
* AC1_TX_OP: For AC_VI, in unit of 32us.
*/
#define AC_TXOP_CSR0 0x3474
#define AC_TXOP_CSR0_AC0_TX_OP FIELD32(0x0000ffff)
#define AC_TXOP_CSR0_AC1_TX_OP FIELD32(0xffff0000)
/*
* AC_TXOP_CSR1: AC_VO/AC_VI TXOP register.
* AC2_TX_OP: For AC_VI, in unit of 32us.
* AC3_TX_OP: For AC_VO, in unit of 32us.
* AC_TXOP_CSR1: AC_BE/AC_BK TXOP register.
* AC2_TX_OP: For AC_BE, in unit of 32us.
* AC3_TX_OP: For AC_BK, in unit of 32us.
*/
#define AC_TXOP_CSR1 0x3478
#define AC_TXOP_CSR1_AC2_TX_OP FIELD32(0x0000ffff)

View File

@ -1030,6 +1030,55 @@ dynamic_cca_tune:
max_t(u8, qual->vgc_level - 4, low_bound));
}
/*
* Queue handlers.
*/
static void rt73usb_start_queue(struct data_queue *queue)
{
struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
u32 reg;
switch (queue->qid) {
case QID_RX:
rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
rt2x00_set_field32(&reg, TXRX_CSR0_DISABLE_RX, 0);
rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg);
break;
case QID_BEACON:
rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 1);
rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
break;
default:
break;
}
}
static void rt73usb_stop_queue(struct data_queue *queue)
{
struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
u32 reg;
switch (queue->qid) {
case QID_RX:
rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
rt2x00_set_field32(&reg, TXRX_CSR0_DISABLE_RX, 1);
rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg);
break;
case QID_BEACON:
rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 0);
rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 0);
rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
break;
default:
break;
}
}
/*
* Firmware functions
*/
@ -1324,17 +1373,6 @@ static int rt73usb_init_bbp(struct rt2x00_dev *rt2x00dev)
/*
* Device state switch handlers.
*/
static void rt73usb_toggle_rx(struct rt2x00_dev *rt2x00dev,
enum dev_state state)
{
u32 reg;
rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
rt2x00_set_field32(&reg, TXRX_CSR0_DISABLE_RX,
(state == STATE_RADIO_RX_OFF));
rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg);
}
static int rt73usb_enable_radio(struct rt2x00_dev *rt2x00dev)
{
/*
@ -1401,10 +1439,6 @@ static int rt73usb_set_device_state(struct rt2x00_dev *rt2x00dev,
case STATE_RADIO_OFF:
rt73usb_disable_radio(rt2x00dev);
break;
case STATE_RADIO_RX_ON:
case STATE_RADIO_RX_OFF:
rt73usb_toggle_rx(rt2x00dev, state);
break;
case STATE_RADIO_IRQ_ON:
case STATE_RADIO_IRQ_ON_ISR:
case STATE_RADIO_IRQ_OFF:
@ -1512,6 +1546,7 @@ static void rt73usb_write_beacon(struct queue_entry *entry,
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
unsigned int beacon_base;
unsigned int padding_len;
u32 reg;
/*
@ -1539,11 +1574,13 @@ static void rt73usb_write_beacon(struct queue_entry *entry,
rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_BEACON, entry->skb);
/*
* Write entire beacon with descriptor to register.
* Write entire beacon with descriptor and padding to register.
*/
padding_len = roundup(entry->skb->len, 4) - entry->skb->len;
skb_pad(entry->skb, padding_len);
beacon_base = HW_BEACON_OFFSET(entry->entry_idx);
rt2x00usb_register_multiwrite(rt2x00dev, beacon_base,
entry->skb->data, entry->skb->len);
rt2x00usb_register_multiwrite(rt2x00dev, beacon_base, entry->skb->data,
entry->skb->len + padding_len);
/*
* Enable beaconing again.
@ -1579,14 +1616,6 @@ static int rt73usb_get_tx_data_len(struct queue_entry *entry)
return length;
}
static void rt73usb_kill_tx_queue(struct data_queue *queue)
{
if (queue->qid == QID_BEACON)
rt2x00usb_register_write(queue->rt2x00dev, TXRX_CSR9, 0);
rt2x00usb_kill_tx_queue(queue);
}
/*
* RX control handlers
*/
@ -2278,11 +2307,13 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {
.reset_tuner = rt73usb_reset_tuner,
.link_tuner = rt73usb_link_tuner,
.watchdog = rt2x00usb_watchdog,
.start_queue = rt73usb_start_queue,
.kick_queue = rt2x00usb_kick_queue,
.stop_queue = rt73usb_stop_queue,
.flush_queue = rt2x00usb_flush_queue,
.write_tx_desc = rt73usb_write_tx_desc,
.write_beacon = rt73usb_write_beacon,
.get_tx_data_len = rt73usb_get_tx_data_len,
.kick_tx_queue = rt2x00usb_kick_tx_queue,
.kill_tx_queue = rt73usb_kill_tx_queue,
.fill_rxdone = rt73usb_fill_rxdone,
.config_shared_key = rt73usb_config_shared_key,
.config_pairwise_key = rt73usb_config_pairwise_key,

View File

@ -689,10 +689,10 @@ struct hw_pairwise_ta_entry {
/*
* AIFSN_CSR: AIFSN for each EDCA AC.
* AIFSN0: For AC_BK.
* AIFSN1: For AC_BE.
* AIFSN2: For AC_VI.
* AIFSN3: For AC_VO.
* AIFSN0: For AC_VO.
* AIFSN1: For AC_VI.
* AIFSN2: For AC_BE.
* AIFSN3: For AC_BK.
*/
#define AIFSN_CSR 0x0400
#define AIFSN_CSR_AIFSN0 FIELD32(0x0000000f)
@ -702,10 +702,10 @@ struct hw_pairwise_ta_entry {
/*
* CWMIN_CSR: CWmin for each EDCA AC.
* CWMIN0: For AC_BK.
* CWMIN1: For AC_BE.
* CWMIN2: For AC_VI.
* CWMIN3: For AC_VO.
* CWMIN0: For AC_VO.
* CWMIN1: For AC_VI.
* CWMIN2: For AC_BE.
* CWMIN3: For AC_BK.
*/
#define CWMIN_CSR 0x0404
#define CWMIN_CSR_CWMIN0 FIELD32(0x0000000f)
@ -715,10 +715,10 @@ struct hw_pairwise_ta_entry {
/*
* CWMAX_CSR: CWmax for each EDCA AC.
* CWMAX0: For AC_BK.
* CWMAX1: For AC_BE.
* CWMAX2: For AC_VI.
* CWMAX3: For AC_VO.
* CWMAX0: For AC_VO.
* CWMAX1: For AC_VI.
* CWMAX2: For AC_BE.
* CWMAX3: For AC_BK.
*/
#define CWMAX_CSR 0x0408
#define CWMAX_CSR_CWMAX0 FIELD32(0x0000000f)
@ -727,18 +727,18 @@ struct hw_pairwise_ta_entry {
#define CWMAX_CSR_CWMAX3 FIELD32(0x0000f000)
/*
* AC_TXOP_CSR0: AC_BK/AC_BE TXOP register.
* AC0_TX_OP: For AC_BK, in unit of 32us.
* AC1_TX_OP: For AC_BE, in unit of 32us.
* AC_TXOP_CSR0: AC_VO/AC_VI TXOP register.
* AC0_TX_OP: For AC_VO, in unit of 32us.
* AC1_TX_OP: For AC_VI, in unit of 32us.
*/
#define AC_TXOP_CSR0 0x040c
#define AC_TXOP_CSR0_AC0_TX_OP FIELD32(0x0000ffff)
#define AC_TXOP_CSR0_AC1_TX_OP FIELD32(0xffff0000)
/*
* AC_TXOP_CSR1: AC_VO/AC_VI TXOP register.
* AC2_TX_OP: For AC_VI, in unit of 32us.
* AC3_TX_OP: For AC_VO, in unit of 32us.
* AC_TXOP_CSR1: AC_BE/AC_BK TXOP register.
* AC2_TX_OP: For AC_BE, in unit of 32us.
* AC3_TX_OP: For AC_BK, in unit of 32us.
*/
#define AC_TXOP_CSR1 0x0410
#define AC_TXOP_CSR1_AC2_TX_OP FIELD32(0x0000ffff)

View File

@ -0,0 +1,15 @@
config RTL8192CE
tristate "Realtek RTL8192CE/RTL8188SE Wireless Network Adapter"
depends on MAC80211 && EXPERIMENTAL
select FW_LOADER
select RTLWIFI
---help---
This is the driver for Realtek RTL8192CE/RTL8188CE 802.11n PCIe
wireless network adapters.
If you choose to build it as a module, it will be called rtl8192ce
config RTLWIFI
tristate
depends on RTL8192CE
default m

View File

@ -0,0 +1,13 @@
obj-$(CONFIG_RTLWIFI) += rtlwifi.o
rtlwifi-objs := \
base.o \
cam.o \
core.o \
debug.o \
efuse.o \
pci.o \
ps.o \
rc.o \
regd.o
obj-$(CONFIG_RTL8192CE) += rtl8192ce/

View File

@ -0,0 +1,958 @@
/******************************************************************************
*
* Copyright(c) 2009-2010 Realtek Corporation.
*
* 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:
* wlanfae <wlanfae@realtek.com>
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
* Hsinchu 300, Taiwan.
*
* Larry Finger <Larry.Finger@lwfinger.net>
*
*****************************************************************************/
#include <linux/ip.h>
#include "wifi.h"
#include "rc.h"
#include "base.h"
#include "efuse.h"
#include "cam.h"
#include "ps.h"
#include "regd.h"
/*
*NOTICE!!!: This file will be very big, we hsould
*keep it clear under follwing roles:
*
*This file include follwing part, so, if you add new
*functions into this file, please check which part it
*should includes. or check if you should add new part
*for this file:
*
*1) mac80211 init functions
*2) tx information functions
*3) functions called by core.c
*4) wq & timer callback functions
*5) frame process functions
*6) sysfs functions
*7) ...
*/
/*********************************************************
*
* mac80211 init functions
*
*********************************************************/
static struct ieee80211_channel rtl_channeltable[] = {
{.center_freq = 2412, .hw_value = 1,},
{.center_freq = 2417, .hw_value = 2,},
{.center_freq = 2422, .hw_value = 3,},
{.center_freq = 2427, .hw_value = 4,},
{.center_freq = 2432, .hw_value = 5,},
{.center_freq = 2437, .hw_value = 6,},
{.center_freq = 2442, .hw_value = 7,},
{.center_freq = 2447, .hw_value = 8,},
{.center_freq = 2452, .hw_value = 9,},
{.center_freq = 2457, .hw_value = 10,},
{.center_freq = 2462, .hw_value = 11,},
{.center_freq = 2467, .hw_value = 12,},
{.center_freq = 2472, .hw_value = 13,},
{.center_freq = 2484, .hw_value = 14,},
};
static struct ieee80211_rate rtl_ratetable[] = {
{.bitrate = 10, .hw_value = 0x00,},
{.bitrate = 20, .hw_value = 0x01,},
{.bitrate = 55, .hw_value = 0x02,},
{.bitrate = 110, .hw_value = 0x03,},
{.bitrate = 60, .hw_value = 0x04,},
{.bitrate = 90, .hw_value = 0x05,},
{.bitrate = 120, .hw_value = 0x06,},
{.bitrate = 180, .hw_value = 0x07,},
{.bitrate = 240, .hw_value = 0x08,},
{.bitrate = 360, .hw_value = 0x09,},
{.bitrate = 480, .hw_value = 0x0a,},
{.bitrate = 540, .hw_value = 0x0b,},
};
static const struct ieee80211_supported_band rtl_band_2ghz = {
.band = IEEE80211_BAND_2GHZ,
.channels = rtl_channeltable,
.n_channels = ARRAY_SIZE(rtl_channeltable),
.bitrates = rtl_ratetable,
.n_bitrates = ARRAY_SIZE(rtl_ratetable),
.ht_cap = {0},
};
static void _rtl_init_hw_ht_capab(struct ieee80211_hw *hw,
struct ieee80211_sta_ht_cap *ht_cap)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
ht_cap->ht_supported = true;
ht_cap->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
IEEE80211_HT_CAP_SGI_40 |
IEEE80211_HT_CAP_SGI_20 |
IEEE80211_HT_CAP_DSSSCCK40 | IEEE80211_HT_CAP_MAX_AMSDU;
/*
*Maximum length of AMPDU that the STA can receive.
*Length = 2 ^ (13 + max_ampdu_length_exp) - 1 (octets)
*/
ht_cap->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
/*Minimum MPDU start spacing , */
ht_cap->ampdu_density = IEEE80211_HT_MPDU_DENSITY_16;
ht_cap->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
/*
*hw->wiphy->bands[IEEE80211_BAND_2GHZ]
*base on ant_num
*rx_mask: RX mask
*if rx_ant =1 rx_mask[0]=0xff;==>MCS0-MCS7
*if rx_ant =2 rx_mask[1]=0xff;==>MCS8-MCS15
*if rx_ant >=3 rx_mask[2]=0xff;
*if BW_40 rx_mask[4]=0x01;
*highest supported RX rate
*/
if (get_rf_type(rtlphy) == RF_1T2R || get_rf_type(rtlphy) == RF_2T2R) {
RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, ("1T2R or 2T2R\n"));
ht_cap->mcs.rx_mask[0] = 0xFF;
ht_cap->mcs.rx_mask[1] = 0xFF;
ht_cap->mcs.rx_mask[4] = 0x01;
ht_cap->mcs.rx_highest = MAX_BIT_RATE_40MHZ_MCS15;
} else if (get_rf_type(rtlphy) == RF_1T1R) {
RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, ("1T1R\n"));
ht_cap->mcs.rx_mask[0] = 0xFF;
ht_cap->mcs.rx_mask[1] = 0x00;
ht_cap->mcs.rx_mask[4] = 0x01;
ht_cap->mcs.rx_highest = MAX_BIT_RATE_40MHZ_MCS7;
}
}
static void _rtl_init_mac80211(struct ieee80211_hw *hw)
{
struct rtl_mac *rtlmac = rtl_mac(rtl_priv(hw));
struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
struct ieee80211_supported_band *sband;
/* <1> use mac->bands as mem for hw->wiphy->bands */
sband = &(rtlmac->bands[IEEE80211_BAND_2GHZ]);
/*
* <2> set hw->wiphy->bands[IEEE80211_BAND_2GHZ]
* to default value(1T1R)
*/
memcpy(&(rtlmac->bands[IEEE80211_BAND_2GHZ]), &rtl_band_2ghz,
sizeof(struct ieee80211_supported_band));
/* <3> init ht cap base on ant_num */
_rtl_init_hw_ht_capab(hw, &sband->ht_cap);
/* <4> set mac->sband to wiphy->sband */
hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband;
/* <5> set hw caps */
hw->flags = IEEE80211_HW_SIGNAL_DBM |
IEEE80211_HW_RX_INCLUDES_FCS |
IEEE80211_HW_BEACON_FILTER | IEEE80211_HW_AMPDU_AGGREGATION | /*PS*/
/*IEEE80211_HW_SUPPORTS_PS | */
/*IEEE80211_HW_PS_NULLFUNC_STACK | */
/*IEEE80211_HW_SUPPORTS_DYNAMIC_PS | */
IEEE80211_HW_REPORTS_TX_ACK_STATUS | 0;
hw->wiphy->interface_modes =
BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC);
hw->wiphy->rts_threshold = 2347;
hw->queues = AC_MAX;
hw->extra_tx_headroom = RTL_TX_HEADER_SIZE;
/* TODO: Correct this value for our hw */
/* TODO: define these hard code value */
hw->channel_change_time = 100;
hw->max_listen_interval = 5;
hw->max_rate_tries = 4;
/* hw->max_rates = 1; */
/* <6> mac address */
if (is_valid_ether_addr(rtlefuse->dev_addr)) {
SET_IEEE80211_PERM_ADDR(hw, rtlefuse->dev_addr);
} else {
u8 rtlmac[] = { 0x00, 0xe0, 0x4c, 0x81, 0x92, 0x00 };
get_random_bytes((rtlmac + (ETH_ALEN - 1)), 1);
SET_IEEE80211_PERM_ADDR(hw, rtlmac);
}
}
static void _rtl_init_deferred_work(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
/* <1> timer */
init_timer(&rtlpriv->works.watchdog_timer);
setup_timer(&rtlpriv->works.watchdog_timer,
rtl_watch_dog_timer_callback, (unsigned long)hw);
/* <2> work queue */
rtlpriv->works.hw = hw;
rtlpriv->works.rtl_wq = alloc_workqueue(rtlpriv->cfg->name, 0, 0);
INIT_DELAYED_WORK(&rtlpriv->works.watchdog_wq,
(void *)rtl_watchdog_wq_callback);
INIT_DELAYED_WORK(&rtlpriv->works.ips_nic_off_wq,
(void *)rtl_ips_nic_off_wq_callback);
}
void rtl_deinit_deferred_work(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
del_timer_sync(&rtlpriv->works.watchdog_timer);
cancel_delayed_work(&rtlpriv->works.watchdog_wq);
cancel_delayed_work(&rtlpriv->works.ips_nic_off_wq);
}
void rtl_init_rfkill(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
bool radio_state;
bool blocked;
u8 valid = 0;
/*set init state to rf on */
rtlpriv->rfkill.rfkill_state = 1;
radio_state = rtlpriv->cfg->ops->radio_onoff_checking(hw, &valid);
if (valid) {
RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
(KERN_INFO "wireless switch is %s\n",
rtlpriv->rfkill.rfkill_state ? "on" : "off"));
rtlpriv->rfkill.rfkill_state = radio_state;
blocked = (rtlpriv->rfkill.rfkill_state == 1) ? 0 : 1;
wiphy_rfkill_set_hw_state(hw->wiphy, blocked);
}
wiphy_rfkill_start_polling(hw->wiphy);
}
void rtl_deinit_rfkill(struct ieee80211_hw *hw)
{
wiphy_rfkill_stop_polling(hw->wiphy);
}
int rtl_init_core(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_mac *rtlmac = rtl_mac(rtl_priv(hw));
/* <1> init mac80211 */
_rtl_init_mac80211(hw);
rtlmac->hw = hw;
/* <2> rate control register */
if (rtl_rate_control_register()) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
("rtl: Unable to register rtl_rc,"
"use default RC !!\n"));
} else {
hw->rate_control_algorithm = "rtl_rc";
}
/*
* <3> init CRDA must come after init
* mac80211 hw in _rtl_init_mac80211.
*/
if (rtl_regd_init(hw, rtl_reg_notifier)) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("REGD init failed\n"));
return 1;
} else {
/* CRDA regd hint must after init CRDA */
if (regulatory_hint(hw->wiphy, rtlpriv->regd.alpha2)) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
("regulatory_hint fail\n"));
}
}
/* <4> locks */
mutex_init(&rtlpriv->locks.conf_mutex);
spin_lock_init(&rtlpriv->locks.ips_lock);
spin_lock_init(&rtlpriv->locks.irq_th_lock);
spin_lock_init(&rtlpriv->locks.h2c_lock);
spin_lock_init(&rtlpriv->locks.rf_ps_lock);
spin_lock_init(&rtlpriv->locks.rf_lock);
spin_lock_init(&rtlpriv->locks.lps_lock);
rtlmac->link_state = MAC80211_NOLINK;
/* <5> init deferred work */
_rtl_init_deferred_work(hw);
return 0;
}
void rtl_deinit_core(struct ieee80211_hw *hw)
{
/*RC*/
rtl_rate_control_unregister();
}
void rtl_init_rx_config(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RCR, (u8 *) (&mac->rx_conf));
rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_MGT_FILTER,
(u8 *) (&mac->rx_mgt_filter));
rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_CTRL_FILTER,
(u8 *) (&mac->rx_ctrl_filter));
rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_DATA_FILTER,
(u8 *) (&mac->rx_data_filter));
}
/*********************************************************
*
* tx information functions
*
*********************************************************/
static void _rtl_qurey_shortpreamble_mode(struct ieee80211_hw *hw,
struct rtl_tcb_desc *tcb_desc,
struct ieee80211_tx_info *info)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u8 rate_flag = info->control.rates[0].flags;
tcb_desc->use_shortpreamble = false;
/* 1M can only use Long Preamble. 11B spec */
if (tcb_desc->hw_rate == rtlpriv->cfg->maps[RTL_RC_CCK_RATE1M])
return;
else if (rate_flag & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
tcb_desc->use_shortpreamble = true;
return;
}
static void _rtl_query_shortgi(struct ieee80211_hw *hw,
struct rtl_tcb_desc *tcb_desc,
struct ieee80211_tx_info *info)
{
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
u8 rate_flag = info->control.rates[0].flags;
tcb_desc->use_shortgi = false;
if (!mac->ht_enable)
return;
if (!mac->sgi_40 && !mac->sgi_20)
return;
if ((mac->bw_40 == true) && mac->sgi_40)
tcb_desc->use_shortgi = true;
else if ((mac->bw_40 == false) && mac->sgi_20)
tcb_desc->use_shortgi = true;
if (!(rate_flag & IEEE80211_TX_RC_SHORT_GI))
tcb_desc->use_shortgi = false;
}
static void _rtl_query_protection_mode(struct ieee80211_hw *hw,
struct rtl_tcb_desc *tcb_desc,
struct ieee80211_tx_info *info)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u8 rate_flag = info->control.rates[0].flags;
/* Common Settings */
tcb_desc->b_rts_stbc = false;
tcb_desc->b_cts_enable = false;
tcb_desc->rts_sc = 0;
tcb_desc->b_rts_bw = false;
tcb_desc->b_rts_use_shortpreamble = false;
tcb_desc->b_rts_use_shortgi = false;
if (rate_flag & IEEE80211_TX_RC_USE_CTS_PROTECT) {
/* Use CTS-to-SELF in protection mode. */
tcb_desc->b_rts_enable = true;
tcb_desc->b_cts_enable = true;
tcb_desc->rts_rate = rtlpriv->cfg->maps[RTL_RC_OFDM_RATE24M];
} else if (rate_flag & IEEE80211_TX_RC_USE_RTS_CTS) {
/* Use RTS-CTS in protection mode. */
tcb_desc->b_rts_enable = true;
tcb_desc->rts_rate = rtlpriv->cfg->maps[RTL_RC_OFDM_RATE24M];
}
}
static void _rtl_txrate_selectmode(struct ieee80211_hw *hw,
struct rtl_tcb_desc *tcb_desc)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
if (!tcb_desc->disable_ratefallback || !tcb_desc->use_driver_rate) {
if (mac->opmode == NL80211_IFTYPE_STATION)
tcb_desc->ratr_index = 0;
else if (mac->opmode == NL80211_IFTYPE_ADHOC) {
if (tcb_desc->b_multicast || tcb_desc->b_broadcast) {
tcb_desc->hw_rate =
rtlpriv->cfg->maps[RTL_RC_CCK_RATE2M];
tcb_desc->use_driver_rate = 1;
} else {
/* TODO */
}
}
}
if (rtlpriv->dm.b_useramask) {
/* TODO we will differentiate adhoc and station futrue */
tcb_desc->mac_id = 0;
if ((mac->mode == WIRELESS_MODE_N_24G) ||
(mac->mode == WIRELESS_MODE_N_5G)) {
tcb_desc->ratr_index = RATR_INX_WIRELESS_NGB;
} else if (mac->mode & WIRELESS_MODE_G) {
tcb_desc->ratr_index = RATR_INX_WIRELESS_GB;
} else if (mac->mode & WIRELESS_MODE_B) {
tcb_desc->ratr_index = RATR_INX_WIRELESS_B;
}
}
}
static void _rtl_query_bandwidth_mode(struct ieee80211_hw *hw,
struct rtl_tcb_desc *tcb_desc)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
tcb_desc->b_packet_bw = false;
if (!mac->bw_40 || !mac->ht_enable)
return;
if (tcb_desc->b_multicast || tcb_desc->b_broadcast)
return;
/*use legency rate, shall use 20MHz */
if (tcb_desc->hw_rate <= rtlpriv->cfg->maps[RTL_RC_OFDM_RATE54M])
return;
tcb_desc->b_packet_bw = true;
}
static u8 _rtl_get_highest_n_rate(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_phy *rtlphy = &(rtlpriv->phy);
u8 hw_rate;
if (get_rf_type(rtlphy) == RF_2T2R)
hw_rate = rtlpriv->cfg->maps[RTL_RC_HT_RATEMCS15];
else
hw_rate = rtlpriv->cfg->maps[RTL_RC_HT_RATEMCS7];
return hw_rate;
}
void rtl_get_tcb_desc(struct ieee80211_hw *hw,
struct ieee80211_tx_info *info,
struct sk_buff *skb, struct rtl_tcb_desc *tcb_desc)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_mac *rtlmac = rtl_mac(rtl_priv(hw));
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
struct ieee80211_rate *txrate;
u16 fc = le16_to_cpu(hdr->frame_control);
memset(tcb_desc, 0, sizeof(struct rtl_tcb_desc));
if (ieee80211_is_data(fc)) {
txrate = ieee80211_get_tx_rate(hw, info);
tcb_desc->hw_rate = txrate->hw_value;
/*
*we set data rate RTL_RC_CCK_RATE1M
*in rtl_rc.c if skb is special data or
*mgt which need low data rate.
*/
/*
*So tcb_desc->hw_rate is just used for
*special data and mgt frames
*/
if (tcb_desc->hw_rate < rtlpriv->cfg->maps[RTL_RC_CCK_RATE11M]) {
tcb_desc->use_driver_rate = true;
tcb_desc->ratr_index = 7;
tcb_desc->hw_rate =
rtlpriv->cfg->maps[RTL_RC_CCK_RATE1M];
tcb_desc->disable_ratefallback = 1;
} else {
/*
*because hw will nerver use hw_rate
*when tcb_desc->use_driver_rate = false
*so we never set highest N rate here,
*and N rate will all be controled by FW
*when tcb_desc->use_driver_rate = false
*/
if (rtlmac->ht_enable) {
tcb_desc->hw_rate = _rtl_get_highest_n_rate(hw);
} else {
if (rtlmac->mode == WIRELESS_MODE_B) {
tcb_desc->hw_rate =
rtlpriv->cfg->maps[RTL_RC_CCK_RATE11M];
} else {
tcb_desc->hw_rate =
rtlpriv->cfg->maps[RTL_RC_OFDM_RATE54M];
}
}
}
if (is_multicast_ether_addr(ieee80211_get_DA(hdr)))
tcb_desc->b_multicast = 1;
else if (is_broadcast_ether_addr(ieee80211_get_DA(hdr)))
tcb_desc->b_broadcast = 1;
_rtl_txrate_selectmode(hw, tcb_desc);
_rtl_query_bandwidth_mode(hw, tcb_desc);
_rtl_qurey_shortpreamble_mode(hw, tcb_desc, info);
_rtl_query_shortgi(hw, tcb_desc, info);
_rtl_query_protection_mode(hw, tcb_desc, info);
} else {
tcb_desc->use_driver_rate = true;
tcb_desc->ratr_index = 7;
tcb_desc->disable_ratefallback = 1;
tcb_desc->mac_id = 0;
tcb_desc->hw_rate = rtlpriv->cfg->maps[RTL_RC_CCK_RATE1M];
}
}
EXPORT_SYMBOL(rtl_get_tcb_desc);
bool rtl_tx_mgmt_proc(struct ieee80211_hw *hw, struct sk_buff *skb)
{
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
u16 fc = le16_to_cpu(hdr->frame_control);
if (ieee80211_is_auth(fc)) {
RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, ("MAC80211_LINKING\n"));
rtl_ips_nic_on(hw);
mac->link_state = MAC80211_LINKING;
}
return true;
}
bool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx)
{
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
struct rtl_priv *rtlpriv = rtl_priv(hw);
u16 fc = le16_to_cpu(hdr->frame_control);
u8 *act = (u8 *) (((u8 *) skb->data + MAC80211_3ADDR_LEN));
u8 category;
if (!ieee80211_is_action(fc))
return true;
category = *act;
act++;
switch (category) {
case ACT_CAT_BA:
switch (*act) {
case ACT_ADDBAREQ:
if (mac->act_scanning)
return false;
RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG,
("%s ACT_ADDBAREQ From :" MAC_FMT "\n",
is_tx ? "Tx" : "Rx", MAC_ARG(hdr->addr2)));
break;
case ACT_ADDBARSP:
RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG,
("%s ACT_ADDBARSP From :" MAC_FMT "\n",
is_tx ? "Tx" : "Rx", MAC_ARG(hdr->addr2)));
break;
case ACT_DELBA:
RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG,
("ACT_ADDBADEL From :" MAC_FMT "\n",
MAC_ARG(hdr->addr2)));
break;
}
break;
default:
break;
}
return true;
}
/*should call before software enc*/
u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
u16 fc = le16_to_cpu(hdr->frame_control);
u16 ether_type;
u8 mac_hdr_len = ieee80211_get_hdrlen_from_skb(skb);
const struct iphdr *ip;
if (!ieee80211_is_data(fc))
goto end;
if (ieee80211_is_nullfunc(fc))
return true;
ip = (struct iphdr *)((u8 *) skb->data + mac_hdr_len +
SNAP_SIZE + PROTOC_TYPE_SIZE);
ether_type = *(u16 *) ((u8 *) skb->data + mac_hdr_len + SNAP_SIZE);
ether_type = ntohs(ether_type);
if (ETH_P_IP == ether_type) {
if (IPPROTO_UDP == ip->protocol) {
struct udphdr *udp = (struct udphdr *)((u8 *) ip +
(ip->ihl << 2));
if (((((u8 *) udp)[1] == 68) &&
(((u8 *) udp)[3] == 67)) ||
((((u8 *) udp)[1] == 67) &&
(((u8 *) udp)[3] == 68))) {
/*
* 68 : UDP BOOTP client
* 67 : UDP BOOTP server
*/
RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV),
DBG_DMESG, ("dhcp %s !!\n",
(is_tx) ? "Tx" : "Rx"));
if (is_tx) {
rtl_lps_leave(hw);
ppsc->last_delaylps_stamp_jiffies =
jiffies;
}
return true;
}
}
} else if (ETH_P_ARP == ether_type) {
if (is_tx) {
rtl_lps_leave(hw);
ppsc->last_delaylps_stamp_jiffies = jiffies;
}
return true;
} else if (ETH_P_PAE == ether_type) {
RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG,
("802.1X %s EAPOL pkt!!\n", (is_tx) ? "Tx" : "Rx"));
if (is_tx) {
rtl_lps_leave(hw);
ppsc->last_delaylps_stamp_jiffies = jiffies;
}
return true;
} else if (0x86DD == ether_type) {
return true;
}
end:
return false;
}
/*********************************************************
*
* functions called by core.c
*
*********************************************************/
int rtl_tx_agg_start(struct ieee80211_hw *hw, const u8 *ra, u16 tid, u16 *ssn)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_tid_data *tid_data;
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG,
("on ra = %pM tid = %d\n", ra, tid));
if (unlikely(tid >= MAX_TID_COUNT))
return -EINVAL;
if (mac->tids[tid].agg.agg_state != RTL_AGG_OFF) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
("Start AGG when state is not RTL_AGG_OFF !\n"));
return -ENXIO;
}
tid_data = &mac->tids[tid];
*ssn = SEQ_TO_SN(tid_data->seq_number);
RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG,
("HW queue is empty tid:%d\n", tid));
tid_data->agg.agg_state = RTL_AGG_ON;
ieee80211_start_tx_ba_cb_irqsafe(mac->vif, ra, tid);
return 0;
}
int rtl_tx_agg_stop(struct ieee80211_hw *hw, const u8 * ra, u16 tid)
{
int ssn = -1;
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
struct rtl_tid_data *tid_data;
if (!ra) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("ra = NULL\n"));
return -EINVAL;
}
if (unlikely(tid >= MAX_TID_COUNT))
return -EINVAL;
if (mac->tids[tid].agg.agg_state != RTL_AGG_ON)
RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
("Stopping AGG while state not ON or starting\n"));
tid_data = &mac->tids[tid];
ssn = (tid_data->seq_number & IEEE80211_SCTL_SEQ) >> 4;
mac->tids[tid].agg.agg_state = RTL_AGG_OFF;
ieee80211_stop_tx_ba_cb_irqsafe(mac->vif, ra, tid);
return 0;
}
/*********************************************************
*
* wq & timer callback functions
*
*********************************************************/
void rtl_watchdog_wq_callback(void *data)
{
struct rtl_works *rtlworks = container_of_dwork_rtl(data,
struct rtl_works,
watchdog_wq);
struct ieee80211_hw *hw = rtlworks->hw;
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
bool b_busytraffic = false;
bool b_higher_busytraffic = false;
bool b_higher_busyrxtraffic = false;
bool b_higher_busytxtraffic = false;
u8 idx = 0;
u32 rx_cnt_inp4eriod = 0;
u32 tx_cnt_inp4eriod = 0;
u32 aver_rx_cnt_inperiod = 0;
u32 aver_tx_cnt_inperiod = 0;
bool benter_ps = false;
if (is_hal_stop(rtlhal))
return;
/* <1> Determine if action frame is allowed */
if (mac->link_state > MAC80211_NOLINK) {
if (mac->cnt_after_linked < 20)
mac->cnt_after_linked++;
} else {
mac->cnt_after_linked = 0;
}
/* <2> DM */
rtlpriv->cfg->ops->dm_watchdog(hw);
/*
*<3> to check if traffic busy, if
* busytraffic we don't change channel
*/
if (mac->link_state >= MAC80211_LINKED) {
/* (1) get aver_rx_cnt_inperiod & aver_tx_cnt_inperiod */
for (idx = 0; idx <= 2; idx++) {
rtlpriv->link_info.num_rx_in4period[idx] =
rtlpriv->link_info.num_rx_in4period[idx + 1];
rtlpriv->link_info.num_tx_in4period[idx] =
rtlpriv->link_info.num_tx_in4period[idx + 1];
}
rtlpriv->link_info.num_rx_in4period[3] =
rtlpriv->link_info.num_rx_inperiod;
rtlpriv->link_info.num_tx_in4period[3] =
rtlpriv->link_info.num_tx_inperiod;
for (idx = 0; idx <= 3; idx++) {
rx_cnt_inp4eriod +=
rtlpriv->link_info.num_rx_in4period[idx];
tx_cnt_inp4eriod +=
rtlpriv->link_info.num_tx_in4period[idx];
}
aver_rx_cnt_inperiod = rx_cnt_inp4eriod / 4;
aver_tx_cnt_inperiod = tx_cnt_inp4eriod / 4;
/* (2) check traffic busy */
if (aver_rx_cnt_inperiod > 100 || aver_tx_cnt_inperiod > 100)
b_busytraffic = true;
/* Higher Tx/Rx data. */
if (aver_rx_cnt_inperiod > 4000 ||
aver_tx_cnt_inperiod > 4000) {
b_higher_busytraffic = true;
/* Extremely high Rx data. */
if (aver_rx_cnt_inperiod > 5000)
b_higher_busyrxtraffic = true;
else
b_higher_busytxtraffic = false;
}
if (((rtlpriv->link_info.num_rx_inperiod +
rtlpriv->link_info.num_tx_inperiod) > 8) ||
(rtlpriv->link_info.num_rx_inperiod > 2))
benter_ps = false;
else
benter_ps = true;
/* LeisurePS only work in infra mode. */
if (benter_ps)
rtl_lps_enter(hw);
else
rtl_lps_leave(hw);
}
rtlpriv->link_info.num_rx_inperiod = 0;
rtlpriv->link_info.num_tx_inperiod = 0;
rtlpriv->link_info.b_busytraffic = b_busytraffic;
rtlpriv->link_info.b_higher_busytraffic = b_higher_busytraffic;
rtlpriv->link_info.b_higher_busyrxtraffic = b_higher_busyrxtraffic;
}
void rtl_watch_dog_timer_callback(unsigned long data)
{
struct ieee80211_hw *hw = (struct ieee80211_hw *)data;
struct rtl_priv *rtlpriv = rtl_priv(hw);
queue_delayed_work(rtlpriv->works.rtl_wq,
&rtlpriv->works.watchdog_wq, 0);
mod_timer(&rtlpriv->works.watchdog_timer,
jiffies + MSECS(RTL_WATCH_DOG_TIME));
}
/*********************************************************
*
* sysfs functions
*
*********************************************************/
static ssize_t rtl_show_debug_level(struct device *d,
struct device_attribute *attr, char *buf)
{
struct ieee80211_hw *hw = dev_get_drvdata(d);
struct rtl_priv *rtlpriv = rtl_priv(hw);
return sprintf(buf, "0x%08X\n", rtlpriv->dbg.global_debuglevel);
}
static ssize_t rtl_store_debug_level(struct device *d,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct ieee80211_hw *hw = dev_get_drvdata(d);
struct rtl_priv *rtlpriv = rtl_priv(hw);
unsigned long val;
int ret;
ret = strict_strtoul(buf, 0, &val);
if (ret) {
printk(KERN_DEBUG "%s is not in hex or decimal form.\n", buf);
} else {
rtlpriv->dbg.global_debuglevel = val;
printk(KERN_DEBUG "debuglevel:%x\n",
rtlpriv->dbg.global_debuglevel);
}
return strnlen(buf, count);
}
static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO,
rtl_show_debug_level, rtl_store_debug_level);
static struct attribute *rtl_sysfs_entries[] = {
&dev_attr_debug_level.attr,
NULL
};
/*
* "name" is folder name witch will be
* put in device directory like :
* sys/devices/pci0000:00/0000:00:1c.4/
* 0000:06:00.0/rtl_sysfs
*/
struct attribute_group rtl_attribute_group = {
.name = "rtlsysfs",
.attrs = rtl_sysfs_entries,
};
MODULE_AUTHOR("lizhaoming <chaoming_li@realsil.com.cn>");
MODULE_AUTHOR("Realtek WlanFAE <wlanfae@realtek.com>");
MODULE_AUTHOR("Larry Finger <Larry.FInger@lwfinger.net>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Realtek 802.11n PCI wireless core");
static int __init rtl_core_module_init(void)
{
return 0;
}
static void __exit rtl_core_module_exit(void)
{
}
module_init(rtl_core_module_init);
module_exit(rtl_core_module_exit);

View File

@ -0,0 +1,120 @@
/******************************************************************************
*
* Copyright(c) 2009-2010 Realtek Corporation.
*
* 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:
* wlanfae <wlanfae@realtek.com>
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
* Hsinchu 300, Taiwan.
*
* Larry Finger <Larry.Finger@lwfinger.net>
*****************************************************************************/
#ifndef __RTL_BASE_H__
#define __RTL_BASE_H__
#define RTL_DUMMY_OFFSET 0
#define RTL_DUMMY_UNIT 8
#define RTL_TX_DUMMY_SIZE (RTL_DUMMY_OFFSET * RTL_DUMMY_UNIT)
#define RTL_TX_DESC_SIZE 32
#define RTL_TX_HEADER_SIZE (RTL_TX_DESC_SIZE + RTL_TX_DUMMY_SIZE)
#define HT_AMSDU_SIZE_4K 3839
#define HT_AMSDU_SIZE_8K 7935
#define MAX_BIT_RATE_40MHZ_MCS15 300 /* Mbps */
#define MAX_BIT_RATE_40MHZ_MCS7 150 /* Mbps */
#define RTL_RATE_COUNT_LEGACY 12
#define RTL_CHANNEL_COUNT 14
#define FRAME_OFFSET_FRAME_CONTROL 0
#define FRAME_OFFSET_DURATION 2
#define FRAME_OFFSET_ADDRESS1 4
#define FRAME_OFFSET_ADDRESS2 10
#define FRAME_OFFSET_ADDRESS3 16
#define FRAME_OFFSET_SEQUENCE 22
#define FRAME_OFFSET_ADDRESS4 24
#define SET_80211_HDR_FRAME_CONTROL(_hdr, _val) \
WRITEEF2BYTE(_hdr, _val)
#define SET_80211_HDR_TYPE_AND_SUBTYPE(_hdr, _val) \
WRITEEF1BYTE(_hdr, _val)
#define SET_80211_HDR_PWR_MGNT(_hdr, _val) \
SET_BITS_TO_LE_2BYTE(_hdr, 12, 1, _val)
#define SET_80211_HDR_TO_DS(_hdr, _val) \
SET_BITS_TO_LE_2BYTE(_hdr, 8, 1, _val)
#define SET_80211_PS_POLL_AID(_hdr, _val) \
WRITEEF2BYTE(((u8 *)(_hdr)) + 2, _val)
#define SET_80211_PS_POLL_BSSID(_hdr, _val) \
CP_MACADDR(((u8 *)(_hdr)) + 4, (u8 *)(_val))
#define SET_80211_PS_POLL_TA(_hdr, _val) \
CP_MACADDR(((u8 *)(_hdr)) + 10, (u8 *)(_val))
#define SET_80211_HDR_DURATION(_hdr, _val) \
WRITEEF2BYTE((u8 *)(_hdr)+FRAME_OFFSET_DURATION, _val)
#define SET_80211_HDR_ADDRESS1(_hdr, _val) \
CP_MACADDR((u8 *)(_hdr)+FRAME_OFFSET_ADDRESS1, (u8*)(_val))
#define SET_80211_HDR_ADDRESS2(_hdr, _val) \
CP_MACADDR((u8 *)(_hdr) + FRAME_OFFSET_ADDRESS2, (u8 *)(_val))
#define SET_80211_HDR_ADDRESS3(_hdr, _val) \
CP_MACADDR((u8 *)(_hdr)+FRAME_OFFSET_ADDRESS3, (u8 *)(_val))
#define SET_80211_HDR_FRAGMENT_SEQUENCE(_hdr, _val) \
WRITEEF2BYTE((u8 *)(_hdr)+FRAME_OFFSET_SEQUENCE, _val)
#define SET_BEACON_PROBE_RSP_TIME_STAMP_LOW(__phdr, __val) \
WRITEEF4BYTE(((u8 *)(__phdr)) + 24, __val)
#define SET_BEACON_PROBE_RSP_TIME_STAMP_HIGH(__phdr, __val) \
WRITEEF4BYTE(((u8 *)(__phdr)) + 28, __val)
#define SET_BEACON_PROBE_RSP_BEACON_INTERVAL(__phdr, __val) \
WRITEEF2BYTE(((u8 *)(__phdr)) + 32, __val)
#define GET_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr) \
READEF2BYTE(((u8 *)(__phdr)) + 34)
#define SET_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr, __val) \
WRITEEF2BYTE(((u8 *)(__phdr)) + 34, __val)
#define MASK_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr, __val) \
SET_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr, \
(GET_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr) & (~(__val))))
int rtl_init_core(struct ieee80211_hw *hw);
void rtl_deinit_core(struct ieee80211_hw *hw);
void rtl_init_rx_config(struct ieee80211_hw *hw);
void rtl_init_rfkill(struct ieee80211_hw *hw);
void rtl_deinit_rfkill(struct ieee80211_hw *hw);
void rtl_watch_dog_timer_callback(unsigned long data);
void rtl_deinit_deferred_work(struct ieee80211_hw *hw);
bool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx);
bool rtl_tx_mgmt_proc(struct ieee80211_hw *hw, struct sk_buff *skb);
u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx);
void rtl_watch_dog_timer_callback(unsigned long data);
int rtl_tx_agg_start(struct ieee80211_hw *hw, const u8 *ra,
u16 tid, u16 *ssn);
int rtl_tx_agg_stop(struct ieee80211_hw *hw, const u8 *ra, u16 tid);
void rtl_watchdog_wq_callback(void *data);
void rtl_get_tcb_desc(struct ieee80211_hw *hw,
struct ieee80211_tx_info *info,
struct sk_buff *skb, struct rtl_tcb_desc *tcb_desc);
extern struct attribute_group rtl_attribute_group;
#endif

View File

@ -0,0 +1,291 @@
/******************************************************************************
*
* Copyright(c) 2009-2010 Realtek Corporation.
*
* 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:
* wlanfae <wlanfae@realtek.com>
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
* Hsinchu 300, Taiwan.
*
*****************************************************************************/
#include "wifi.h"
#include "cam.h"
void rtl_cam_reset_sec_info(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
rtlpriv->sec.use_defaultkey = false;
rtlpriv->sec.pairwise_enc_algorithm = NO_ENCRYPTION;
rtlpriv->sec.group_enc_algorithm = NO_ENCRYPTION;
memset(rtlpriv->sec.key_buf, 0, KEY_BUF_SIZE * MAX_KEY_LEN);
memset(rtlpriv->sec.key_len, 0, KEY_BUF_SIZE);
rtlpriv->sec.pairwise_key = NULL;
}
static void rtl_cam_program_entry(struct ieee80211_hw *hw, u32 entry_no,
u8 *mac_addr, u8 *key_cont_128, u16 us_config)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u32 target_command;
u32 target_content = 0;
u8 entry_i;
RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
("key_cont_128:\n %x:%x:%x:%x:%x:%x\n",
key_cont_128[0], key_cont_128[1],
key_cont_128[2], key_cont_128[3],
key_cont_128[4], key_cont_128[5]));
for (entry_i = 0; entry_i < CAM_CONTENT_COUNT; entry_i++) {
target_command = entry_i + CAM_CONTENT_COUNT * entry_no;
target_command = target_command | BIT(31) | BIT(16);
if (entry_i == 0) {
target_content = (u32) (*(mac_addr + 0)) << 16 |
(u32) (*(mac_addr + 1)) << 24 | (u32) us_config;
rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI],
target_content);
rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM],
target_command);
RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
("rtl_cam_program_entry(): "
"WRITE %x: %x\n",
rtlpriv->cfg->maps[WCAMI], target_content));
RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
("The Key ID is %d\n", entry_no));
RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
("rtl_cam_program_entry(): "
"WRITE %x: %x\n",
rtlpriv->cfg->maps[RWCAM], target_command));
} else if (entry_i == 1) {
target_content = (u32) (*(mac_addr + 5)) << 24 |
(u32) (*(mac_addr + 4)) << 16 |
(u32) (*(mac_addr + 3)) << 8 |
(u32) (*(mac_addr + 2));
rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI],
target_content);
rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM],
target_command);
RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
("rtl_cam_program_entry(): WRITE A4: %x\n",
target_content));
RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
("rtl_cam_program_entry(): WRITE A0: %x\n",
target_command));
} else {
target_content =
(u32) (*(key_cont_128 + (entry_i * 4 - 8) + 3)) <<
24 | (u32) (*(key_cont_128 + (entry_i * 4 - 8) + 2))
<< 16 |
(u32) (*(key_cont_128 + (entry_i * 4 - 8) + 1)) << 8
| (u32) (*(key_cont_128 + (entry_i * 4 - 8) + 0));
rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI],
target_content);
rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM],
target_command);
udelay(100);
RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
("rtl_cam_program_entry(): WRITE A4: %x\n",
target_content));
RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
("rtl_cam_program_entry(): WRITE A0: %x\n",
target_command));
}
}
RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
("after set key, usconfig:%x\n", us_config));
}
u8 rtl_cam_add_one_entry(struct ieee80211_hw *hw, u8 *mac_addr,
u32 ul_key_id, u32 ul_entry_idx, u32 ul_enc_alg,
u32 ul_default_key, u8 *key_content)
{
u32 us_config;
struct rtl_priv *rtlpriv = rtl_priv(hw);
RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
("EntryNo:%x, ulKeyId=%x, ulEncAlg=%x, "
"ulUseDK=%x MacAddr" MAC_FMT "\n",
ul_entry_idx, ul_key_id, ul_enc_alg,
ul_default_key, MAC_ARG(mac_addr)));
if (ul_key_id == TOTAL_CAM_ENTRY) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
("<=== ulKeyId exceed!\n"));
return 0;
}
if (ul_default_key == 1) {
us_config = CFG_VALID | ((u16) (ul_enc_alg) << 2);
} else {
us_config = CFG_VALID | ((ul_enc_alg) << 2) | ul_key_id;
}
rtl_cam_program_entry(hw, ul_entry_idx, mac_addr,
(u8 *) key_content, us_config);
RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, ("<===\n"));
return 1;
}
EXPORT_SYMBOL(rtl_cam_add_one_entry);
int rtl_cam_delete_one_entry(struct ieee80211_hw *hw,
u8 *mac_addr, u32 ul_key_id)
{
u32 ul_command;
struct rtl_priv *rtlpriv = rtl_priv(hw);
RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, ("key_idx:%d\n", ul_key_id));
ul_command = ul_key_id * CAM_CONTENT_COUNT;
ul_command = ul_command | BIT(31) | BIT(16);
rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI], 0);
rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], ul_command);
RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
("rtl_cam_delete_one_entry(): WRITE A4: %x\n", 0));
RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
("rtl_cam_delete_one_entry(): WRITE A0: %x\n", ul_command));
return 0;
}
EXPORT_SYMBOL(rtl_cam_delete_one_entry);
void rtl_cam_reset_all_entry(struct ieee80211_hw *hw)
{
u32 ul_command;
struct rtl_priv *rtlpriv = rtl_priv(hw);
ul_command = BIT(31) | BIT(30);
rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], ul_command);
}
EXPORT_SYMBOL(rtl_cam_reset_all_entry);
void rtl_cam_mark_invalid(struct ieee80211_hw *hw, u8 uc_index)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u32 ul_command;
u32 ul_content;
u32 ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_AES];
switch (rtlpriv->sec.pairwise_enc_algorithm) {
case WEP40_ENCRYPTION:
ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_WEP40];
break;
case WEP104_ENCRYPTION:
ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_WEP104];
break;
case TKIP_ENCRYPTION:
ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_TKIP];
break;
case AESCCMP_ENCRYPTION:
ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_AES];
break;
default:
ul_enc_algo = rtlpriv->cfg->maps[SEC_CAM_AES];
}
ul_content = (uc_index & 3) | ((u16) (ul_enc_algo) << 2);
ul_content |= BIT(15);
ul_command = CAM_CONTENT_COUNT * uc_index;
ul_command = ul_command | BIT(31) | BIT(16);
rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI], ul_content);
rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], ul_command);
RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
("rtl_cam_mark_invalid(): WRITE A4: %x\n", ul_content));
RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
("rtl_cam_mark_invalid(): WRITE A0: %x\n", ul_command));
}
EXPORT_SYMBOL(rtl_cam_mark_invalid);
void rtl_cam_empty_entry(struct ieee80211_hw *hw, u8 uc_index)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u32 ul_command;
u32 ul_content;
u32 ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_AES];
u8 entry_i;
switch (rtlpriv->sec.pairwise_enc_algorithm) {
case WEP40_ENCRYPTION:
ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_WEP40];
break;
case WEP104_ENCRYPTION:
ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_WEP104];
break;
case TKIP_ENCRYPTION:
ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_TKIP];
break;
case AESCCMP_ENCRYPTION:
ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_AES];
break;
default:
ul_encalgo = rtlpriv->cfg->maps[SEC_CAM_AES];
}
for (entry_i = 0; entry_i < CAM_CONTENT_COUNT; entry_i++) {
if (entry_i == 0) {
ul_content =
(uc_index & 0x03) | ((u16) (ul_encalgo) << 2);
ul_content |= BIT(15);
} else {
ul_content = 0;
}
ul_command = CAM_CONTENT_COUNT * uc_index + entry_i;
ul_command = ul_command | BIT(31) | BIT(16);
rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[WCAMI], ul_content);
rtl_write_dword(rtlpriv, rtlpriv->cfg->maps[RWCAM], ul_command);
RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
("rtl_cam_empty_entry(): WRITE A4: %x\n",
ul_content));
RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
("rtl_cam_empty_entry(): WRITE A0: %x\n",
ul_command));
}
}
EXPORT_SYMBOL(rtl_cam_empty_entry);

View File

@ -0,0 +1,53 @@
/******************************************************************************
*
* Copyright(c) 2009-2010 Realtek Corporation.
*
* 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:
* wlanfae <wlanfae@realtek.com>
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
* Hsinchu 300, Taiwan.
*
*****************************************************************************/
#ifndef __RTL_CAM_H_
#define __RTL_CAM_H_
#define TOTAL_CAM_ENTRY 32
#define CAM_CONTENT_COUNT 8
#define CFG_DEFAULT_KEY BIT(5)
#define CFG_VALID BIT(15)
#define PAIRWISE_KEYIDX 0
#define CAM_PAIRWISE_KEY_POSITION 4
#define CAM_CONFIG_USEDK 1
#define CAM_CONFIG_NO_USEDK 0
extern void rtl_cam_reset_all_entry(struct ieee80211_hw *hw);
extern u8 rtl_cam_add_one_entry(struct ieee80211_hw *hw, u8 *mac_addr,
u32 ul_key_id, u32 ul_entry_idx, u32 ul_enc_alg,
u32 ul_default_key, u8 *key_content);
int rtl_cam_delete_one_entry(struct ieee80211_hw *hw, u8 *mac_addr,
u32 ul_key_id);
void rtl_cam_mark_invalid(struct ieee80211_hw *hw, u8 uc_index);
void rtl_cam_empty_entry(struct ieee80211_hw *hw, u8 uc_index);
void rtl_cam_reset_sec_info(struct ieee80211_hw *hw);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,42 @@
/******************************************************************************
*
* Copyright(c) 2009-2010 Realtek Corporation.
*
* Tmis 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.
*
* Tmis 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
* tmis program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
* Tme full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
* Contact Information:
* wlanfae <wlanfae@realtek.com>
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
* Hsinchu 300, Taiwan.
*
* Larry Finger <Larry.Finger@lwfinger.net>
*****************************************************************************/
#ifndef __RTL_CORE_H__
#define __RTL_CORE_H__
#define RTL_SUPPORTED_FILTERS \
(FIF_PROMISC_IN_BSS | \
FIF_ALLMULTI | FIF_CONTROL | \
FIF_OTHER_BSS | \
FIF_FCSFAIL | \
FIF_BCN_PRBRESP_PROMISC)
#define RTL_SUPPORTED_CTRL_FILTER 0xFF
extern const struct ieee80211_ops rtl_ops;
#endif

View File

@ -0,0 +1,50 @@
/******************************************************************************
*
* Copyright(c) 2009-2010 Realtek Corporation.
*
* Tmis 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.
*
* Tmis 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
* tmis program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
* Tme full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
* Contact Information:
* wlanfae <wlanfae@realtek.com>
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
* Hsinchu 300, Taiwan.
*
* Larry Finger <Larry.Finger@lwfinger.net>
*****************************************************************************/
#include "wifi.h"
void rtl_dbgp_flag_init(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
u8 i;
rtlpriv->dbg.global_debuglevel = DBG_EMERG;
rtlpriv->dbg.global_debugcomponents =
COMP_ERR | COMP_FW | COMP_INIT | COMP_RECV | COMP_SEND |
COMP_MLME | COMP_SCAN | COMP_INTR | COMP_LED | COMP_SEC |
COMP_BEACON | COMP_RATE | COMP_RXDESC | COMP_DIG | COMP_TXAGC |
COMP_POWER | COMP_POWER_TRACKING | COMP_BB_POWERSAVING | COMP_SWAS |
COMP_RF | COMP_TURBO | COMP_RATR | COMP_CMD |
COMP_EFUSE | COMP_QOS | COMP_MAC80211 | COMP_REGD | COMP_CHAN;
for (i = 0; i < DBGP_TYPE_MAX; i++)
rtlpriv->dbg.dbgp_type[i] = 0;
/*Init Debug flag enable condition */
}

View File

@ -0,0 +1,212 @@
/******************************************************************************
*
* Copyright(c) 2009-2010 Realtek Corporation.
*
* Tmis 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.
*
* Tmis 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
* tmis program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
* Tme full GNU General Public License is included in this distribution in the
* file called LICENSE.
*
* Contact Information:
* wlanfae <wlanfae@realtek.com>
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
* Hsinchu 300, Taiwan.
*
* Larry Finger <Larry.Finger@lwfinger.net>
*****************************************************************************/
#ifndef __RTL_DEBUG_H__
#define __RTL_DEBUG_H__
/*--------------------------------------------------------------
Debug level
--------------------------------------------------------------*/
/*
*Fatal bug.
*For example, Tx/Rx/IO locked up,
*memory access violation,
*resource allocation failed,
*unexpected HW behavior, HW BUG
*and so on.
*/
#define DBG_EMERG 0
/*
*Abnormal, rare, or unexpeted cases.
*For example, Packet/IO Ctl canceled,
*device suprisely unremoved and so on.
*/
#define DBG_WARNING 2
/*
*Normal case driver developer should
*open, we can see link status like
*assoc/AddBA/DHCP/adapter start and
*so on basic and useful infromations.
*/
#define DBG_DMESG 3
/*
*Normal case with useful information
*about current SW or HW state.
*For example, Tx/Rx descriptor to fill,
*Tx/Rx descriptor completed status,
*SW protocol state change, dynamic
*mechanism state change and so on.
*/
#define DBG_LOUD 4
/*
*Normal case with detail execution
*flow or information.
*/
#define DBG_TRACE 5
/*--------------------------------------------------------------
Define the rt_trace components
--------------------------------------------------------------*/
#define COMP_ERR BIT(0)
#define COMP_FW BIT(1)
#define COMP_INIT BIT(2) /*For init/deinit */
#define COMP_RECV BIT(3) /*For Rx. */
#define COMP_SEND BIT(4) /*For Tx. */
#define COMP_MLME BIT(5) /*For MLME. */
#define COMP_SCAN BIT(6) /*For Scan. */
#define COMP_INTR BIT(7) /*For interrupt Related. */
#define COMP_LED BIT(8) /*For LED. */
#define COMP_SEC BIT(9) /*For sec. */
#define COMP_BEACON BIT(10) /*For beacon. */
#define COMP_RATE BIT(11) /*For rate. */
#define COMP_RXDESC BIT(12) /*For rx desc. */
#define COMP_DIG BIT(13) /*For DIG */
#define COMP_TXAGC BIT(14) /*For Tx power */
#define COMP_HIPWR BIT(15) /*For High Power Mechanism */
#define COMP_POWER BIT(16) /*For lps/ips/aspm. */
#define COMP_POWER_TRACKING BIT(17) /*For TX POWER TRACKING */
#define COMP_BB_POWERSAVING BIT(18)
#define COMP_SWAS BIT(19) /*For SW Antenna Switch */
#define COMP_RF BIT(20) /*For RF. */
#define COMP_TURBO BIT(21) /*For EDCA TURBO. */
#define COMP_RATR BIT(22)
#define COMP_CMD BIT(23)
#define COMP_EFUSE BIT(24)
#define COMP_QOS BIT(25)
#define COMP_MAC80211 BIT(26)
#define COMP_REGD BIT(27)
#define COMP_CHAN BIT(28)
/*--------------------------------------------------------------
Define the rt_print components
--------------------------------------------------------------*/
/* Define EEPROM and EFUSE check module bit*/
#define EEPROM_W BIT(0)
#define EFUSE_PG BIT(1)
#define EFUSE_READ_ALL BIT(2)
/* Define init check for module bit*/
#define INIT_EEPROM BIT(0)
#define INIT_TxPower BIT(1)
#define INIT_IQK BIT(2)
#define INIT_RF BIT(3)
/* Define PHY-BB/RF/MAC check module bit */
#define PHY_BBR BIT(0)
#define PHY_BBW BIT(1)
#define PHY_RFR BIT(2)
#define PHY_RFW BIT(3)
#define PHY_MACR BIT(4)
#define PHY_MACW BIT(5)
#define PHY_ALLR BIT(6)
#define PHY_ALLW BIT(7)
#define PHY_TXPWR BIT(8)
#define PHY_PWRDIFF BIT(9)
enum dbgp_flag_e {
FQOS = 0,
FTX = 1,
FRX = 2,
FSEC = 3,
FMGNT = 4,
FMLME = 5,
FRESOURCE = 6,
FBEACON = 7,
FISR = 8,
FPHY = 9,
FMP = 10,
FEEPROM = 11,
FPWR = 12,
FDM = 13,
FDBGCtrl = 14,
FC2H = 15,
FBT = 16,
FINIT = 17,
FIOCTL = 18,
DBGP_TYPE_MAX
};
#define RT_ASSERT(_exp, fmt) \
do { \
if (!(_exp)) { \
printk(KERN_DEBUG "%s:%s(): ", KBUILD_MODNAME, \
__func__); \
printk fmt; \
} \
} while (0);
#define RT_TRACE(rtlpriv, comp, level, fmt)\
do { \
if (unlikely(((comp) & rtlpriv->dbg.global_debugcomponents) && \
((level) <= rtlpriv->dbg.global_debuglevel))) {\
printk(KERN_DEBUG "%s:%s():<%lx-%x> ", KBUILD_MODNAME, \
__func__, in_interrupt(), in_atomic()); \
printk fmt; \
} \
} while (0);
#define RTPRINT(rtlpriv, dbgtype, dbgflag, printstr) \
do { \
if (unlikely(rtlpriv->dbg.dbgp_type[dbgtype] & dbgflag)) { \
printk(KERN_DEBUG "%s: ", KBUILD_MODNAME); \
printk printstr; \
} \
} while (0);
#define RT_PRINT_DATA(rtlpriv, _comp, _level, _titlestring, _hexdata, \
_hexdatalen) \
do {\
if (unlikely(((_comp) & rtlpriv->dbg.global_debugcomponents) &&\
(_level <= rtlpriv->dbg.global_debuglevel))) { \
int __i; \
u8* ptr = (u8 *)_hexdata; \
printk(KERN_DEBUG "%s: ", KBUILD_MODNAME); \
printk("In process \"%s\" (pid %i):", current->comm,\
current->pid); \
printk(_titlestring); \
for (__i = 0; __i < (int)_hexdatalen; __i++) { \
printk("%02X%s", ptr[__i], (((__i + 1) % 4)\
== 0) ? " " : " ");\
if (((__i + 1) % 16) == 0) \
printk("\n"); \
} \
printk(KERN_DEBUG "\n"); \
} \
} while (0);
#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x"
#define MAC_ARG(x) \
((u8 *)(x))[0], ((u8 *)(x))[1], ((u8 *)(x))[2],\
((u8 *)(x))[3], ((u8 *)(x))[4], ((u8 *)(x))[5]
void rtl_dbgp_flag_init(struct ieee80211_hw *hw);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,124 @@
/******************************************************************************
*
* Copyright(c) 2009-2010 Realtek Corporation.
*
* 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:
* wlanfae <wlanfae@realtek.com>
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
* Hsinchu 300, Taiwan.
*
* Larry Finger <Larry.Finger@lwfinger.net>
*
*****************************************************************************/
#ifndef __RTL_EFUSE_H_
#define __RTL_EFUSE_H_
#define EFUSE_REAL_CONTENT_LEN 512
#define EFUSE_MAP_LEN 128
#define EFUSE_MAX_SECTION 16
#define EFUSE_MAX_WORD_UNIT 4
#define EFUSE_INIT_MAP 0
#define EFUSE_MODIFY_MAP 1
#define PG_STATE_HEADER 0x01
#define PG_STATE_WORD_0 0x02
#define PG_STATE_WORD_1 0x04
#define PG_STATE_WORD_2 0x08
#define PG_STATE_WORD_3 0x10
#define PG_STATE_DATA 0x20
#define PG_SWBYTE_H 0x01
#define PG_SWBYTE_L 0x02
#define _POWERON_DELAY_
#define _PRE_EXECUTE_READ_CMD_
#define EFUSE_REPEAT_THRESHOLD_ 3
struct efuse_map {
u8 offset;
u8 word_start;
u8 byte_start;
u8 byte_cnts;
};
struct pgpkt_struct {
u8 offset;
u8 word_en;
u8 data[8];
};
enum efuse_data_item {
EFUSE_CHIP_ID = 0,
EFUSE_LDO_SETTING,
EFUSE_CLK_SETTING,
EFUSE_SDIO_SETTING,
EFUSE_CCCR,
EFUSE_SDIO_MODE,
EFUSE_OCR,
EFUSE_F0CIS,
EFUSE_F1CIS,
EFUSE_MAC_ADDR,
EFUSE_EEPROM_VER,
EFUSE_CHAN_PLAN,
EFUSE_TXPW_TAB
};
enum {
VOLTAGE_V25 = 0x03,
LDOE25_SHIFT = 28,
};
struct efuse_priv {
u8 id[2];
u8 ldo_setting[2];
u8 clk_setting[2];
u8 cccr;
u8 sdio_mode;
u8 ocr[3];
u8 cis0[17];
u8 cis1[48];
u8 mac_addr[6];
u8 eeprom_verno;
u8 channel_plan;
u8 tx_power_b[14];
u8 tx_power_g[14];
};
extern void efuse_initialize(struct ieee80211_hw *hw);
extern u8 efuse_read_1byte(struct ieee80211_hw *hw, u16 address);
extern void efuse_write_1byte(struct ieee80211_hw *hw, u16 address, u8 value);
extern void read_efuse(struct ieee80211_hw *hw, u16 _offset,
u16 _size_byte, u8 *pbuf);
extern void efuse_shadow_read(struct ieee80211_hw *hw, u8 type,
u16 offset, u32 *value);
extern void efuse_shadow_write(struct ieee80211_hw *hw, u8 type,
u16 offset, u32 value);
extern bool efuse_shadow_update(struct ieee80211_hw *hw);
extern bool efuse_shadow_update_chk(struct ieee80211_hw *hw);
extern void rtl_efuse_shadow_map_update(struct ieee80211_hw *hw);
extern void efuse_force_write_vendor_Id(struct ieee80211_hw *hw);
extern void efuse_re_pg_section(struct ieee80211_hw *hw, u8 section_idx);
extern bool efuse_program_map(struct ieee80211_hw *hw,
char *p_filename, u8 tabletype);
extern void efuse_reset_loader(struct ieee80211_hw *hw);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,302 @@
/******************************************************************************
*
* Copyright(c) 2009-2010 Realtek Corporation.
*
* 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:
* wlanfae <wlanfae@realtek.com>
* Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
* Hsinchu 300, Taiwan.
*
* Larry Finger <Larry.Finger@lwfinger.net>
*
*****************************************************************************/
#ifndef __RTL_PCI_H__
#define __RTL_PCI_H__
#include <linux/pci.h>
/*
1: MSDU packet queue,
2: Rx Command Queue
*/
#define RTL_PCI_RX_MPDU_QUEUE 0
#define RTL_PCI_RX_CMD_QUEUE 1
#define RTL_PCI_MAX_RX_QUEUE 2
#define RTL_PCI_MAX_RX_COUNT 64
#define RTL_PCI_MAX_TX_QUEUE_COUNT 9
#define RT_TXDESC_NUM 128
#define RT_TXDESC_NUM_BE_QUEUE 256
#define BK_QUEUE 0
#define BE_QUEUE 1
#define VI_QUEUE 2
#define VO_QUEUE 3
#define BEACON_QUEUE 4
#define TXCMD_QUEUE 5
#define MGNT_QUEUE 6
#define HIGH_QUEUE 7
#define HCCA_QUEUE 8
#define RTL_PCI_DEVICE(vend, dev, cfg) \
.vendor = (vend), \
.device = (dev), \
.subvendor = PCI_ANY_ID, \
.subdevice = PCI_ANY_ID,\
.driver_data = (kernel_ulong_t)&(cfg)
#define INTEL_VENDOR_ID 0x8086
#define SIS_VENDOR_ID 0x1039
#define ATI_VENDOR_ID 0x1002
#define ATI_DEVICE_ID 0x7914
#define AMD_VENDOR_ID 0x1022
#define PCI_MAX_BRIDGE_NUMBER 255
#define PCI_MAX_DEVICES 32
#define PCI_MAX_FUNCTION 8
#define PCI_CONF_ADDRESS 0x0CF8 /*PCI Configuration Space Address */
#define PCI_CONF_DATA 0x0CFC /*PCI Configuration Space Data */
#define PCI_CLASS_BRIDGE_DEV 0x06
#define PCI_SUBCLASS_BR_PCI_TO_PCI 0x04
#define PCI_CAPABILITY_ID_PCI_EXPRESS 0x10
#define PCI_CAP_ID_EXP 0x10
#define U1DONTCARE 0xFF
#define U2DONTCARE 0xFFFF
#define U4DONTCARE 0xFFFFFFFF
#define RTL_PCI_8192_DID 0x8192 /*8192 PCI-E */
#define RTL_PCI_8192SE_DID 0x8192 /*8192 SE */
#define RTL_PCI_8174_DID 0x8174 /*8192 SE */
#define RTL_PCI_8173_DID 0x8173 /*8191 SE Crab */
#define RTL_PCI_8172_DID 0x8172 /*8191 SE RE */
#define RTL_PCI_8171_DID 0x8171 /*8191 SE Unicron */
#define RTL_PCI_0045_DID 0x0045 /*8190 PCI for Ceraga */
#define RTL_PCI_0046_DID 0x0046 /*8190 Cardbus for Ceraga */
#define RTL_PCI_0044_DID 0x0044 /*8192e PCIE for Ceraga */
#define RTL_PCI_0047_DID 0x0047 /*8192e Express Card for Ceraga */
#define RTL_PCI_700F_DID 0x700F
#define RTL_PCI_701F_DID 0x701F
#define RTL_PCI_DLINK_DID 0x3304
#define RTL_PCI_8192CET_DID 0x8191 /*8192ce */
#define RTL_PCI_8192CE_DID 0x8178 /*8192ce */
#define RTL_PCI_8191CE_DID 0x8177 /*8192ce */
#define RTL_PCI_8188CE_DID 0x8176 /*8192ce */
#define RTL_PCI_8192CU_DID 0x8191 /*8192ce */
#define RTL_PCI_8192DE_DID 0x092D /*8192ce */
#define RTL_PCI_8192DU_DID 0x092D /*8192ce */
/*8192 support 16 pages of IO registers*/
#define RTL_MEM_MAPPED_IO_RANGE_8190PCI 0x1000
#define RTL_MEM_MAPPED_IO_RANGE_8192PCIE 0x4000
#define RTL_MEM_MAPPED_IO_RANGE_8192SE 0x4000
#define RTL_MEM_MAPPED_IO_RANGE_8192CE 0x4000
#define RTL_MEM_MAPPED_IO_RANGE_8192DE 0x4000
#define RTL_PCI_REVISION_ID_8190PCI 0x00
#define RTL_PCI_REVISION_ID_8192PCIE 0x01
#define RTL_PCI_REVISION_ID_8192SE 0x10
#define RTL_PCI_REVISION_ID_8192CE 0x1
#define RTL_PCI_REVISION_ID_8192DE 0x0
#define RTL_DEFAULT_HARDWARE_TYPE HARDWARE_TYPE_RTL8192CE
enum pci_bridge_vendor {
PCI_BRIDGE_VENDOR_INTEL = 0x0, /*0b'0000,0001 */
PCI_BRIDGE_VENDOR_ATI, /*0b'0000,0010*/
PCI_BRIDGE_VENDOR_AMD, /*0b'0000,0100*/
PCI_BRIDGE_VENDOR_SIS, /*0b'0000,1000*/
PCI_BRIDGE_VENDOR_UNKNOWN, /*0b'0100,0000*/
PCI_BRIDGE_VENDOR_MAX,
};
struct rtl_rx_desc {
u32 dword[8];
} __packed;
struct rtl_tx_desc {
u32 dword[16];
} __packed;
struct rtl_tx_cmd_desc {
u32 dword[16];
} __packed;
struct rtl8192_tx_ring {
struct rtl_tx_desc *desc;
dma_addr_t dma;
unsigned int idx;
unsigned int entries;
struct sk_buff_head queue;
};
struct rtl8192_rx_ring {
struct rtl_rx_desc *desc;
dma_addr_t dma;
unsigned int idx;
struct sk_buff *rx_buf[RTL_PCI_MAX_RX_COUNT];
};
struct rtl_pci {
struct pci_dev *pdev;
bool driver_is_goingto_unload;
bool up_first_time;
bool being_init_adapter;
bool irq_enabled;
/*Tx */
struct rtl8192_tx_ring tx_ring[RTL_PCI_MAX_TX_QUEUE_COUNT];
int txringcount[RTL_PCI_MAX_TX_QUEUE_COUNT];
u32 transmit_config;
/*Rx */
struct rtl8192_rx_ring rx_ring[RTL_PCI_MAX_RX_QUEUE];
int rxringcount;
u16 rxbuffersize;
u32 receive_config;
/*irq */
u8 irq_alloc;
u32 irq_mask[2];
/*Bcn control register setting */
u32 reg_bcn_ctrl_val;
/*ASPM*/ u8 const_pci_aspm;
u8 const_amdpci_aspm;
u8 const_hwsw_rfoff_d3;
u8 const_support_pciaspm;
/*pci-e bridge */
u8 const_hostpci_aspm_setting;
/*pci-e device */
u8 const_devicepci_aspm_setting;
/*If it supports ASPM, Offset[560h] = 0x40,
otherwise Offset[560h] = 0x00. */
bool b_support_aspm;
bool b_support_backdoor;
/*QOS & EDCA */
enum acm_method acm_method;
};
struct mp_adapter {
u8 linkctrl_reg;
u8 busnumber;
u8 devnumber;
u8 funcnumber;
u8 pcibridge_busnum;
u8 pcibridge_devnum;
u8 pcibridge_funcnum;
u8 pcibridge_vendor;
u16 pcibridge_vendorid;
u16 pcibridge_deviceid;
u32 pcicfg_addrport;
u8 num4bytes;
u8 pcibridge_pciehdr_offset;
u8 pcibridge_linkctrlreg;
bool amd_l1_patch;
};
struct rtl_pci_priv {
struct rtl_pci dev;
struct mp_adapter ndis_adapter;
struct rtl_led_ctl ledctl;
};
#define rtl_pcipriv(hw) (((struct rtl_pci_priv *)(rtl_priv(hw))->priv))
#define rtl_pcidev(pcipriv) (&((pcipriv)->dev))
int rtl_pci_reset_trx_ring(struct ieee80211_hw *hw);
extern struct rtl_intf_ops rtl_pci_ops;
int __devinit rtl_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *id);
void rtl_pci_disconnect(struct pci_dev *pdev);
int rtl_pci_suspend(struct pci_dev *pdev, pm_message_t state);
int rtl_pci_resume(struct pci_dev *pdev);
static inline u8 pci_read8_sync(struct rtl_priv *rtlpriv, u32 addr)
{
return 0xff & readb((u8 *) rtlpriv->io.pci_mem_start + addr);
}
static inline u16 pci_read16_sync(struct rtl_priv *rtlpriv, u32 addr)
{
return readw((u8 *) rtlpriv->io.pci_mem_start + addr);
}
static inline u32 pci_read32_sync(struct rtl_priv *rtlpriv, u32 addr)
{
return readl((u8 *) rtlpriv->io.pci_mem_start + addr);
}
static inline void pci_write8_async(struct rtl_priv *rtlpriv, u32 addr, u8 val)
{
writeb(val, (u8 *) rtlpriv->io.pci_mem_start + addr);
}
static inline void pci_write16_async(struct rtl_priv *rtlpriv,
u32 addr, u16 val)
{
writew(val, (u8 *) rtlpriv->io.pci_mem_start + addr);
}
static inline void pci_write32_async(struct rtl_priv *rtlpriv,
u32 addr, u32 val)
{
writel(val, (u8 *) rtlpriv->io.pci_mem_start + addr);
}
static inline void rtl_pci_raw_write_port_ulong(u32 port, u32 val)
{
outl(val, port);
}
static inline void rtl_pci_raw_write_port_uchar(u32 port, u8 val)
{
outb(val, port);
}
static inline void rtl_pci_raw_read_port_uchar(u32 port, u8 *pval)
{
*pval = inb(port);
}
static inline void rtl_pci_raw_read_port_ushort(u32 port, u16 *pval)
{
*pval = inw(port);
}
static inline void rtl_pci_raw_read_port_ulong(u32 port, u32 *pval)
{
*pval = inl(port);
}
#endif

Some files were not shown because too many files have changed in this diff Show More