mirror of
https://github.com/torvalds/linux.git
synced 2024-11-22 12:11:40 +00:00
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Conflicts: drivers/net/wireless/iwlwifi/iwl-core.h drivers/net/wireless/rt2x00/rt2800pci.c
This commit is contained in:
commit
19bc291c99
@ -5978,7 +5978,7 @@ S: Maintained
|
||||
F: drivers/input/misc/wistron_btns.c
|
||||
|
||||
WL1251 WIRELESS DRIVER
|
||||
M: Kalle Valo <kalle.valo@nokia.com>
|
||||
M: Kalle Valo <kalle.valo@iki.fi>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
W: http://wireless.kernel.org
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
|
||||
|
@ -112,6 +112,7 @@ config AIRO_CS
|
||||
depends on PCMCIA && (BROKEN || !M32R)
|
||||
select WIRELESS_EXT
|
||||
select WEXT_SPY
|
||||
select WEXT_PRIV
|
||||
select CRYPTO
|
||||
select CRYPTO_AES
|
||||
---help---
|
||||
|
@ -51,6 +51,7 @@
|
||||
#include <linux/freezer.h>
|
||||
|
||||
#include <linux/ieee80211.h>
|
||||
#include <net/iw_handler.h>
|
||||
|
||||
#include "airo.h"
|
||||
|
||||
|
@ -2329,54 +2329,55 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static void ar9170_sta_notify(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
enum sta_notify_cmd cmd,
|
||||
struct ieee80211_sta *sta)
|
||||
static int ar9170_sta_add(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
struct ar9170 *ar = hw->priv;
|
||||
struct ar9170_sta_info *sta_info = (void *) sta->drv_priv;
|
||||
unsigned int i;
|
||||
|
||||
switch (cmd) {
|
||||
case STA_NOTIFY_ADD:
|
||||
memset(sta_info, 0, sizeof(*sta_info));
|
||||
memset(sta_info, 0, sizeof(*sta_info));
|
||||
|
||||
if (!sta->ht_cap.ht_supported)
|
||||
break;
|
||||
if (!sta->ht_cap.ht_supported)
|
||||
return 0;
|
||||
|
||||
if (sta->ht_cap.ampdu_density > ar->global_ampdu_density)
|
||||
ar->global_ampdu_density = sta->ht_cap.ampdu_density;
|
||||
if (sta->ht_cap.ampdu_density > ar->global_ampdu_density)
|
||||
ar->global_ampdu_density = sta->ht_cap.ampdu_density;
|
||||
|
||||
if (sta->ht_cap.ampdu_factor < ar->global_ampdu_factor)
|
||||
ar->global_ampdu_factor = sta->ht_cap.ampdu_factor;
|
||||
if (sta->ht_cap.ampdu_factor < ar->global_ampdu_factor)
|
||||
ar->global_ampdu_factor = sta->ht_cap.ampdu_factor;
|
||||
|
||||
for (i = 0; i < AR9170_NUM_TID; i++) {
|
||||
sta_info->agg[i].state = AR9170_TID_STATE_SHUTDOWN;
|
||||
sta_info->agg[i].active = false;
|
||||
sta_info->agg[i].ssn = 0;
|
||||
sta_info->agg[i].tid = i;
|
||||
INIT_LIST_HEAD(&sta_info->agg[i].list);
|
||||
skb_queue_head_init(&sta_info->agg[i].queue);
|
||||
}
|
||||
|
||||
sta_info->ampdu_max_len = 1 << (3 + sta->ht_cap.ampdu_factor);
|
||||
break;
|
||||
|
||||
case STA_NOTIFY_REMOVE:
|
||||
if (!sta->ht_cap.ht_supported)
|
||||
break;
|
||||
|
||||
for (i = 0; i < AR9170_NUM_TID; i++) {
|
||||
sta_info->agg[i].state = AR9170_TID_STATE_INVALID;
|
||||
skb_queue_purge(&sta_info->agg[i].queue);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
for (i = 0; i < AR9170_NUM_TID; i++) {
|
||||
sta_info->agg[i].state = AR9170_TID_STATE_SHUTDOWN;
|
||||
sta_info->agg[i].active = false;
|
||||
sta_info->agg[i].ssn = 0;
|
||||
sta_info->agg[i].tid = i;
|
||||
INIT_LIST_HEAD(&sta_info->agg[i].list);
|
||||
skb_queue_head_init(&sta_info->agg[i].queue);
|
||||
}
|
||||
|
||||
sta_info->ampdu_max_len = 1 << (3 + sta->ht_cap.ampdu_factor);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ar9170_sta_remove(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
struct ar9170_sta_info *sta_info = (void *) sta->drv_priv;
|
||||
unsigned int i;
|
||||
|
||||
if (!sta->ht_cap.ht_supported)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < AR9170_NUM_TID; i++) {
|
||||
sta_info->agg[i].state = AR9170_TID_STATE_INVALID;
|
||||
skb_queue_purge(&sta_info->agg[i].queue);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ar9170_get_stats(struct ieee80211_hw *hw,
|
||||
@ -2495,7 +2496,8 @@ static const struct ieee80211_ops ar9170_ops = {
|
||||
.bss_info_changed = ar9170_op_bss_info_changed,
|
||||
.get_tsf = ar9170_op_get_tsf,
|
||||
.set_key = ar9170_set_key,
|
||||
.sta_notify = ar9170_sta_notify,
|
||||
.sta_add = ar9170_sta_add,
|
||||
.sta_remove = ar9170_sta_remove,
|
||||
.get_stats = ar9170_get_stats,
|
||||
.ampdu_action = ar9170_ampdu_action,
|
||||
};
|
||||
|
@ -62,7 +62,7 @@ int ath_beaconq_config(struct ath_softc *sc)
|
||||
* Beacons are always sent out at the lowest rate, and are not retried.
|
||||
*/
|
||||
static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp,
|
||||
struct ath_buf *bf)
|
||||
struct ath_buf *bf, int rateidx)
|
||||
{
|
||||
struct sk_buff *skb = bf->bf_mpdu;
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
@ -96,9 +96,9 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp,
|
||||
ds->ds_data = bf->bf_buf_addr;
|
||||
|
||||
sband = &sc->sbands[common->hw->conf.channel->band];
|
||||
rate = sband->bitrates[0].hw_value;
|
||||
rate = sband->bitrates[rateidx].hw_value;
|
||||
if (sc->sc_flags & SC_OP_PREAMBLE_SHORT)
|
||||
rate |= sband->bitrates[0].hw_value_short;
|
||||
rate |= sband->bitrates[rateidx].hw_value_short;
|
||||
|
||||
ath9k_hw_set11n_txdesc(ah, ds, skb->len + FCS_LEN,
|
||||
ATH9K_PKT_TYPE_BEACON,
|
||||
@ -206,7 +206,7 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw,
|
||||
}
|
||||
}
|
||||
|
||||
ath_beacon_setup(sc, avp, bf);
|
||||
ath_beacon_setup(sc, avp, bf, info->control.rates[0].idx);
|
||||
|
||||
while (skb) {
|
||||
ath_tx_cabq(hw, skb);
|
||||
@ -237,7 +237,7 @@ static void ath_beacon_start_adhoc(struct ath_softc *sc,
|
||||
bf = avp->av_bcbuf;
|
||||
skb = bf->bf_mpdu;
|
||||
|
||||
ath_beacon_setup(sc, avp, bf);
|
||||
ath_beacon_setup(sc, avp, bf, 0);
|
||||
|
||||
/* NB: caller is known to have already stopped tx dma */
|
||||
ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bf->bf_daddr);
|
||||
@ -526,16 +526,13 @@ static void ath_beacon_config_ap(struct ath_softc *sc,
|
||||
{
|
||||
u32 nexttbtt, intval;
|
||||
|
||||
/* Configure the timers only when the TSF has to be reset */
|
||||
|
||||
if (!(sc->sc_flags & SC_OP_TSF_RESET))
|
||||
return;
|
||||
|
||||
/* NB: the beacon interval is kept internally in TU's */
|
||||
intval = conf->beacon_interval & ATH9K_BEACON_PERIOD;
|
||||
intval /= ATH_BCBUF; /* for staggered beacons */
|
||||
nexttbtt = intval;
|
||||
intval |= ATH9K_BEACON_RESET_TSF;
|
||||
|
||||
if (sc->sc_flags & SC_OP_TSF_RESET)
|
||||
intval |= ATH9K_BEACON_RESET_TSF;
|
||||
|
||||
/*
|
||||
* In AP mode we enable the beacon timers and SWBA interrupts to
|
||||
|
@ -1684,24 +1684,28 @@ static void ath9k_configure_filter(struct ieee80211_hw *hw,
|
||||
"Set HW RX filter: 0x%x\n", rfilt);
|
||||
}
|
||||
|
||||
static void ath9k_sta_notify(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
enum sta_notify_cmd cmd,
|
||||
struct ieee80211_sta *sta)
|
||||
static int ath9k_sta_add(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
struct ath_wiphy *aphy = hw->priv;
|
||||
struct ath_softc *sc = aphy->sc;
|
||||
|
||||
switch (cmd) {
|
||||
case STA_NOTIFY_ADD:
|
||||
ath_node_attach(sc, sta);
|
||||
break;
|
||||
case STA_NOTIFY_REMOVE:
|
||||
ath_node_detach(sc, sta);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
ath_node_attach(sc, sta);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath9k_sta_remove(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
struct ath_wiphy *aphy = hw->priv;
|
||||
struct ath_softc *sc = aphy->sc;
|
||||
|
||||
ath_node_detach(sc, sta);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue,
|
||||
@ -2045,7 +2049,8 @@ struct ieee80211_ops ath9k_ops = {
|
||||
.remove_interface = ath9k_remove_interface,
|
||||
.config = ath9k_config,
|
||||
.configure_filter = ath9k_configure_filter,
|
||||
.sta_notify = ath9k_sta_notify,
|
||||
.sta_add = ath9k_sta_add,
|
||||
.sta_remove = ath9k_sta_remove,
|
||||
.conf_tx = ath9k_conf_tx,
|
||||
.bss_info_changed = ath9k_bss_info_changed,
|
||||
.set_key = ath9k_set_key,
|
||||
|
@ -668,7 +668,7 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
|
||||
struct ieee80211_tx_rate *rates = tx_info->control.rates;
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
__le16 fc = hdr->frame_control;
|
||||
u8 try_per_rate, i = 0, rix, nrix;
|
||||
u8 try_per_rate, i = 0, rix;
|
||||
int is_probe = 0;
|
||||
|
||||
if (rate_control_send_low(sta, priv_sta, txrc))
|
||||
@ -688,26 +688,25 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
|
||||
|
||||
rate_table = sc->cur_rate_table;
|
||||
rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table, &is_probe);
|
||||
nrix = rix;
|
||||
|
||||
if (is_probe) {
|
||||
/* set one try for probe rates. For the
|
||||
* probes don't enable rts */
|
||||
ath_rc_rate_set_series(rate_table, &rates[i++], txrc,
|
||||
1, nrix, 0);
|
||||
1, rix, 0);
|
||||
|
||||
/* Get the next tried/allowed rate. No RTS for the next series
|
||||
* after the probe rate
|
||||
*/
|
||||
ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &nrix);
|
||||
ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &rix);
|
||||
ath_rc_rate_set_series(rate_table, &rates[i++], txrc,
|
||||
try_per_rate, nrix, 0);
|
||||
try_per_rate, rix, 0);
|
||||
|
||||
tx_info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
|
||||
} else {
|
||||
/* Set the choosen rate. No RTS for first series entry. */
|
||||
ath_rc_rate_set_series(rate_table, &rates[i++], txrc,
|
||||
try_per_rate, nrix, 0);
|
||||
try_per_rate, rix, 0);
|
||||
}
|
||||
|
||||
/* Fill in the other rates for multirate retry */
|
||||
@ -716,10 +715,10 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
|
||||
if (i + 1 == 4)
|
||||
try_per_rate = 8;
|
||||
|
||||
ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &nrix);
|
||||
ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &rix);
|
||||
/* All other rates in the series have RTS enabled */
|
||||
ath_rc_rate_set_series(rate_table, &rates[i], txrc,
|
||||
try_per_rate, nrix, 1);
|
||||
try_per_rate, rix, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -45,7 +45,7 @@ enum b43legacy_led_behaviour {
|
||||
void b43legacy_leds_init(struct b43legacy_wldev *dev);
|
||||
void b43legacy_leds_exit(struct b43legacy_wldev *dev);
|
||||
|
||||
#else /* CONFIG_B43EGACY_LEDS */
|
||||
#else /* CONFIG_B43LEGACY_LEDS */
|
||||
/* LED support disabled */
|
||||
|
||||
struct b43legacy_led {
|
||||
|
@ -793,13 +793,6 @@ static struct pcmcia_device_id hostap_cs_ids[] = {
|
||||
0x4b801a17),
|
||||
PCMCIA_MFC_DEVICE_PROD_ID12(0, "SanDisk", "ConnectPlus",
|
||||
0x7a954bd9, 0x74be00c6),
|
||||
PCMCIA_DEVICE_PROD_ID123(
|
||||
"Intersil", "PRISM 2_5 PCMCIA ADAPTER", "ISL37300P",
|
||||
0x4b801a17, 0x6345a0bf, 0xc9049a39),
|
||||
/* D-Link DWL-650 Rev. P1; manfid 0x000b, 0x7110 */
|
||||
PCMCIA_DEVICE_PROD_ID123(
|
||||
"D-Link", "DWL-650 Wireless PC Card RevP", "ISL37101P-10",
|
||||
0x1a424a1c, 0x6ea57632, 0xdd97a26b),
|
||||
PCMCIA_DEVICE_PROD_ID123(
|
||||
"Addtron", "AWP-100 Wireless PCMCIA", "Version 01.02",
|
||||
0xe6ec52ce, 0x08649af2, 0x4b74baa0),
|
||||
@ -833,15 +826,13 @@ static struct pcmcia_device_id hostap_cs_ids[] = {
|
||||
"Allied Telesyn", "AT-WCL452 Wireless PCMCIA Radio",
|
||||
"Ver. 1.00",
|
||||
0x5cd01705, 0x4271660f, 0x9d08ee12),
|
||||
PCMCIA_DEVICE_PROD_ID123(
|
||||
"corega", "WL PCCL-11", "ISL37300P",
|
||||
0xa21501a, 0x59868926, 0xc9049a39),
|
||||
PCMCIA_DEVICE_PROD_ID123(
|
||||
"The Linksys Group, Inc.", "Wireless Network CF Card", "ISL37300P",
|
||||
0xa5f472c2, 0x9c05598d, 0xc9049a39),
|
||||
PCMCIA_DEVICE_PROD_ID123(
|
||||
"Wireless LAN" , "11Mbps PC Card", "Version 01.02",
|
||||
0x4b8870ff, 0x70e946d1, 0x4b74baa0),
|
||||
PCMCIA_DEVICE_PROD_ID3("HFA3863", 0x355cb092),
|
||||
PCMCIA_DEVICE_PROD_ID3("ISL37100P", 0x630d52b2),
|
||||
PCMCIA_DEVICE_PROD_ID3("ISL37101P-10", 0xdd97a26b),
|
||||
PCMCIA_DEVICE_PROD_ID3("ISL37300P", 0xc9049a39),
|
||||
PCMCIA_DEVICE_NULL
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pcmcia, hostap_cs_ids);
|
||||
|
@ -246,7 +246,7 @@ struct iwl_cfg iwl1000_bgn_cfg = {
|
||||
.use_rts_for_ht = true, /* use rts/cts protection */
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
.support_ct_kill_exit = true,
|
||||
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
|
||||
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF,
|
||||
.chain_noise_scale = 1000,
|
||||
};
|
||||
|
||||
@ -274,7 +274,7 @@ struct iwl_cfg iwl1000_bg_cfg = {
|
||||
.led_compensation = 51,
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
.support_ct_kill_exit = true,
|
||||
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
|
||||
.plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF,
|
||||
.chain_noise_scale = 1000,
|
||||
};
|
||||
|
||||
|
@ -45,8 +45,8 @@
|
||||
#include "iwl-sta.h"
|
||||
#include "iwl-3945.h"
|
||||
#include "iwl-eeprom.h"
|
||||
#include "iwl-helpers.h"
|
||||
#include "iwl-core.h"
|
||||
#include "iwl-helpers.h"
|
||||
#include "iwl-led.h"
|
||||
#include "iwl-3945-led.h"
|
||||
|
||||
@ -2470,11 +2470,9 @@ int iwl3945_hw_set_hw_params(struct iwl_priv *priv)
|
||||
memset((void *)&priv->hw_params, 0,
|
||||
sizeof(struct iwl_hw_params));
|
||||
|
||||
priv->shared_virt =
|
||||
pci_alloc_consistent(priv->pci_dev,
|
||||
sizeof(struct iwl3945_shared),
|
||||
&priv->shared_phys);
|
||||
|
||||
priv->shared_virt = dma_alloc_coherent(&priv->pci_dev->dev,
|
||||
sizeof(struct iwl3945_shared),
|
||||
&priv->shared_phys, GFP_KERNEL);
|
||||
if (!priv->shared_virt) {
|
||||
IWL_ERR(priv, "failed to allocate pci memory\n");
|
||||
mutex_unlock(&priv->mutex);
|
||||
|
@ -171,24 +171,6 @@ struct iwl3945_frame {
|
||||
|
||||
#define SCAN_INTERVAL 100
|
||||
|
||||
#define STATUS_HCMD_ACTIVE 0 /* host command in progress */
|
||||
#define STATUS_HCMD_SYNC_ACTIVE 1 /* sync host command in progress */
|
||||
#define STATUS_INT_ENABLED 2
|
||||
#define STATUS_RF_KILL_HW 3
|
||||
#define STATUS_INIT 5
|
||||
#define STATUS_ALIVE 6
|
||||
#define STATUS_READY 7
|
||||
#define STATUS_TEMPERATURE 8
|
||||
#define STATUS_GEO_CONFIGURED 9
|
||||
#define STATUS_EXIT_PENDING 10
|
||||
#define STATUS_STATISTICS 12
|
||||
#define STATUS_SCANNING 13
|
||||
#define STATUS_SCAN_ABORTING 14
|
||||
#define STATUS_SCAN_HW 15
|
||||
#define STATUS_POWER_PMI 16
|
||||
#define STATUS_FW_ERROR 17
|
||||
#define STATUS_CONF_PENDING 18
|
||||
|
||||
#define MAX_TID_COUNT 9
|
||||
|
||||
#define IWL_INVALID_RATE 0xFF
|
||||
|
@ -581,6 +581,13 @@ static int iwl4965_alive_notify(struct iwl_priv *priv)
|
||||
|
||||
iwl4965_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0);
|
||||
|
||||
/* make sure all queue are not stopped */
|
||||
memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped));
|
||||
for (i = 0; i < 4; i++)
|
||||
atomic_set(&priv->queue_stop_count[i], 0);
|
||||
|
||||
/* reset to 0 to enable all the queue first */
|
||||
priv->txq_ctx_active_msk = 0;
|
||||
/* Map each Tx/cmd queue to its corresponding fifo */
|
||||
for (i = 0; i < ARRAY_SIZE(default_queue_to_tx_fifo); i++) {
|
||||
int ac = default_queue_to_tx_fifo[i];
|
||||
|
@ -648,6 +648,13 @@ int iwl5000_alive_notify(struct iwl_priv *priv)
|
||||
|
||||
iwl5000_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0);
|
||||
|
||||
/* make sure all queue are not stopped */
|
||||
memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped));
|
||||
for (i = 0; i < 4; i++)
|
||||
atomic_set(&priv->queue_stop_count[i], 0);
|
||||
|
||||
/* reset to 0 to enable all the queue first */
|
||||
priv->txq_ctx_active_msk = 0;
|
||||
/* map qos queues to fifos one-to-one */
|
||||
for (i = 0; i < ARRAY_SIZE(iwl5000_default_queue_to_tx_fifo); i++) {
|
||||
int ac = iwl5000_default_queue_to_tx_fifo[i];
|
||||
|
@ -70,6 +70,14 @@ static void iwl6000_set_ct_threshold(struct iwl_priv *priv)
|
||||
priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD;
|
||||
}
|
||||
|
||||
/* Indicate calibration version to uCode. */
|
||||
static void iwl6050_set_calib_version(struct iwl_priv *priv)
|
||||
{
|
||||
if (priv->cfg->ops->lib->eeprom_ops.calib_version(priv) >= 6)
|
||||
iwl_set_bit(priv, CSR_GP_DRIVER_REG,
|
||||
CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6);
|
||||
}
|
||||
|
||||
/* NIC configuration for 6000 series */
|
||||
static void iwl6000_nic_config(struct iwl_priv *priv)
|
||||
{
|
||||
@ -96,6 +104,8 @@ static void iwl6000_nic_config(struct iwl_priv *priv)
|
||||
CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA);
|
||||
}
|
||||
/* else do nothing, uCode configured */
|
||||
if (priv->cfg->ops->lib->temp_ops.set_calib_version)
|
||||
priv->cfg->ops->lib->temp_ops.set_calib_version(priv);
|
||||
}
|
||||
|
||||
static struct iwl_sensitivity_ranges iwl6000_sensitivity = {
|
||||
@ -277,6 +287,71 @@ static const struct iwl_ops iwl6000_ops = {
|
||||
.led = &iwlagn_led_ops,
|
||||
};
|
||||
|
||||
static struct iwl_lib_ops iwl6050_lib = {
|
||||
.set_hw_params = iwl6000_hw_set_hw_params,
|
||||
.txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl,
|
||||
.txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl,
|
||||
.txq_set_sched = iwl5000_txq_set_sched,
|
||||
.txq_agg_enable = iwl5000_txq_agg_enable,
|
||||
.txq_agg_disable = iwl5000_txq_agg_disable,
|
||||
.txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd,
|
||||
.txq_free_tfd = iwl_hw_txq_free_tfd,
|
||||
.txq_init = iwl_hw_tx_queue_init,
|
||||
.rx_handler_setup = iwl5000_rx_handler_setup,
|
||||
.setup_deferred_work = iwl5000_setup_deferred_work,
|
||||
.is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr,
|
||||
.load_ucode = iwl5000_load_ucode,
|
||||
.dump_nic_event_log = iwl_dump_nic_event_log,
|
||||
.dump_nic_error_log = iwl_dump_nic_error_log,
|
||||
.dump_csr = iwl_dump_csr,
|
||||
.dump_fh = iwl_dump_fh,
|
||||
.init_alive_start = iwl5000_init_alive_start,
|
||||
.alive_notify = iwl5000_alive_notify,
|
||||
.send_tx_power = iwl5000_send_tx_power,
|
||||
.update_chain_flags = iwl_update_chain_flags,
|
||||
.set_channel_switch = iwl6000_hw_channel_switch,
|
||||
.apm_ops = {
|
||||
.init = iwl_apm_init,
|
||||
.stop = iwl_apm_stop,
|
||||
.config = iwl6000_nic_config,
|
||||
.set_pwr_src = iwl_set_pwr_src,
|
||||
},
|
||||
.eeprom_ops = {
|
||||
.regulatory_bands = {
|
||||
EEPROM_5000_REG_BAND_1_CHANNELS,
|
||||
EEPROM_5000_REG_BAND_2_CHANNELS,
|
||||
EEPROM_5000_REG_BAND_3_CHANNELS,
|
||||
EEPROM_5000_REG_BAND_4_CHANNELS,
|
||||
EEPROM_5000_REG_BAND_5_CHANNELS,
|
||||
EEPROM_5000_REG_BAND_24_HT40_CHANNELS,
|
||||
EEPROM_5000_REG_BAND_52_HT40_CHANNELS
|
||||
},
|
||||
.verify_signature = iwlcore_eeprom_verify_signature,
|
||||
.acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
|
||||
.release_semaphore = iwlcore_eeprom_release_semaphore,
|
||||
.calib_version = iwl5000_eeprom_calib_version,
|
||||
.query_addr = iwl5000_eeprom_query_addr,
|
||||
.update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower,
|
||||
},
|
||||
.post_associate = iwl_post_associate,
|
||||
.isr = iwl_isr_ict,
|
||||
.config_ap = iwl_config_ap,
|
||||
.temp_ops = {
|
||||
.temperature = iwl5000_temperature,
|
||||
.set_ct_kill = iwl6000_set_ct_threshold,
|
||||
.set_calib_version = iwl6050_set_calib_version,
|
||||
},
|
||||
.add_bcast_station = iwl_add_bcast_station,
|
||||
};
|
||||
|
||||
static const struct iwl_ops iwl6050_ops = {
|
||||
.ucode = &iwl5000_ucode,
|
||||
.lib = &iwl6050_lib,
|
||||
.hcmd = &iwl5000_hcmd,
|
||||
.utils = &iwl5000_hcmd_utils,
|
||||
.led = &iwlagn_led_ops,
|
||||
};
|
||||
|
||||
/*
|
||||
* "i": Internal configuration, use internal Power Amplifier
|
||||
*/
|
||||
@ -380,7 +455,7 @@ struct iwl_cfg iwl6050_2agn_cfg = {
|
||||
.ucode_api_max = IWL6050_UCODE_API_MAX,
|
||||
.ucode_api_min = IWL6050_UCODE_API_MIN,
|
||||
.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
|
||||
.ops = &iwl6000_ops,
|
||||
.ops = &iwl6050_ops,
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
.eeprom_ver = EEPROM_6050_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
|
||||
@ -412,7 +487,7 @@ struct iwl_cfg iwl6050_2abg_cfg = {
|
||||
.ucode_api_max = IWL6050_UCODE_API_MAX,
|
||||
.ucode_api_min = IWL6050_UCODE_API_MIN,
|
||||
.sku = IWL_SKU_A|IWL_SKU_G,
|
||||
.ops = &iwl6000_ops,
|
||||
.ops = &iwl6050_ops,
|
||||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
.eeprom_ver = EEPROM_6050_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
|
||||
|
@ -298,10 +298,23 @@ static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv,
|
||||
struct iwl_lq_sta *lq_data, u8 tid,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) {
|
||||
IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n",
|
||||
sta->addr, tid);
|
||||
ieee80211_start_tx_ba_session(sta, tid);
|
||||
ret = ieee80211_start_tx_ba_session(sta, tid);
|
||||
if (ret == -EAGAIN) {
|
||||
/*
|
||||
* driver and mac80211 is out of sync
|
||||
* this might be cause by reloading firmware
|
||||
* stop the tx ba session here
|
||||
*/
|
||||
IWL_DEBUG_HT(priv, "Fail start Tx agg on tid: %d\n",
|
||||
tid);
|
||||
ret = ieee80211_stop_tx_ba_session(sta, tid,
|
||||
WLAN_BACK_INITIATOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2941,10 +2941,21 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
|
||||
return ret;
|
||||
case IEEE80211_AMPDU_TX_START:
|
||||
IWL_DEBUG_HT(priv, "start Tx\n");
|
||||
return iwl_tx_agg_start(priv, sta->addr, tid, ssn);
|
||||
ret = iwl_tx_agg_start(priv, sta->addr, tid, ssn);
|
||||
if (ret == 0) {
|
||||
priv->agg_tids_count++;
|
||||
IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n",
|
||||
priv->agg_tids_count);
|
||||
}
|
||||
return ret;
|
||||
case IEEE80211_AMPDU_TX_STOP:
|
||||
IWL_DEBUG_HT(priv, "stop Tx\n");
|
||||
ret = iwl_tx_agg_stop(priv, sta->addr, tid);
|
||||
if ((ret == 0) && (priv->agg_tids_count > 0)) {
|
||||
priv->agg_tids_count--;
|
||||
IWL_DEBUG_HT(priv, "priv->agg_tids_count = %u\n",
|
||||
priv->agg_tids_count);
|
||||
}
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||
return 0;
|
||||
else
|
||||
@ -3353,6 +3364,7 @@ static int iwl_init_drv(struct iwl_priv *priv)
|
||||
INIT_LIST_HEAD(&priv->free_frames);
|
||||
|
||||
mutex_init(&priv->mutex);
|
||||
mutex_init(&priv->sync_cmd_mutex);
|
||||
|
||||
/* Clear the driver's (not device's) station table */
|
||||
iwl_clear_stations_table(priv);
|
||||
@ -3364,6 +3376,13 @@ static int iwl_init_drv(struct iwl_priv *priv)
|
||||
priv->iw_mode = NL80211_IFTYPE_STATION;
|
||||
priv->current_ht_config.smps = IEEE80211_SMPS_STATIC;
|
||||
priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF;
|
||||
priv->agg_tids_count = 0;
|
||||
|
||||
/* initialize force reset */
|
||||
priv->force_reset[IWL_RF_RESET].reset_duration =
|
||||
IWL_DELAY_NEXT_FORCE_RF_RESET;
|
||||
priv->force_reset[IWL_FW_RESET].reset_duration =
|
||||
IWL_DELAY_NEXT_FORCE_FW_RELOAD;
|
||||
|
||||
/* Choose which receivers/antennas to use */
|
||||
if (priv->cfg->ops->hcmd->set_rxon_chain)
|
||||
@ -3540,6 +3559,14 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
*/
|
||||
spin_lock_init(&priv->reg_lock);
|
||||
spin_lock_init(&priv->lock);
|
||||
|
||||
/*
|
||||
* stop and reset the on-board processor just in case it is in a
|
||||
* strange state ... like being left stranded by a primary kernel
|
||||
* and this is now the kdump kernel trying to start up
|
||||
*/
|
||||
iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
|
||||
|
||||
iwl_hw_detect(priv);
|
||||
IWL_INFO(priv, "Detected Intel Wireless WiFi Link %s REV=0x%X\n",
|
||||
priv->cfg->name, priv->hw_rev);
|
||||
|
@ -3470,11 +3470,7 @@ enum {
|
||||
IWL_PHY_CALIBRATE_DIFF_GAIN_CMD = 7,
|
||||
IWL_PHY_CALIBRATE_DC_CMD = 8,
|
||||
IWL_PHY_CALIBRATE_LO_CMD = 9,
|
||||
IWL_PHY_CALIBRATE_RX_BB_CMD = 10,
|
||||
IWL_PHY_CALIBRATE_TX_IQ_CMD = 11,
|
||||
IWL_PHY_CALIBRATE_RX_IQ_CMD = 12,
|
||||
IWL_PHY_CALIBRATION_NOISE_CMD = 13,
|
||||
IWL_PHY_CALIBRATE_AGC_TABLE_CMD = 14,
|
||||
IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD = 15,
|
||||
IWL_PHY_CALIBRATE_BASE_BAND_CMD = 16,
|
||||
IWL_PHY_CALIBRATE_TX_IQ_PERD_CMD = 17,
|
||||
|
@ -1670,9 +1670,9 @@ EXPORT_SYMBOL(iwl_set_tx_power);
|
||||
void iwl_free_isr_ict(struct iwl_priv *priv)
|
||||
{
|
||||
if (priv->ict_tbl_vir) {
|
||||
pci_free_consistent(priv->pci_dev, (sizeof(u32) * ICT_COUNT) +
|
||||
PAGE_SIZE, priv->ict_tbl_vir,
|
||||
priv->ict_tbl_dma);
|
||||
dma_free_coherent(&priv->pci_dev->dev,
|
||||
(sizeof(u32) * ICT_COUNT) + PAGE_SIZE,
|
||||
priv->ict_tbl_vir, priv->ict_tbl_dma);
|
||||
priv->ict_tbl_vir = NULL;
|
||||
}
|
||||
}
|
||||
@ -1688,9 +1688,9 @@ int iwl_alloc_isr_ict(struct iwl_priv *priv)
|
||||
if (priv->cfg->use_isr_legacy)
|
||||
return 0;
|
||||
/* allocate shrared data table */
|
||||
priv->ict_tbl_vir = pci_alloc_consistent(priv->pci_dev, (sizeof(u32) *
|
||||
ICT_COUNT) + PAGE_SIZE,
|
||||
&priv->ict_tbl_dma);
|
||||
priv->ict_tbl_vir = dma_alloc_coherent(&priv->pci_dev->dev,
|
||||
(sizeof(u32) * ICT_COUNT) + PAGE_SIZE,
|
||||
&priv->ict_tbl_dma, GFP_KERNEL);
|
||||
if (!priv->ict_tbl_vir)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -3334,7 +3334,7 @@ int iwl_dump_fh(struct iwl_priv *priv, char **buf, bool display)
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_dump_fh);
|
||||
|
||||
void iwl_force_rf_reset(struct iwl_priv *priv)
|
||||
static void iwl_force_rf_reset(struct iwl_priv *priv)
|
||||
{
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||
return;
|
||||
@ -3356,7 +3356,50 @@ void iwl_force_rf_reset(struct iwl_priv *priv)
|
||||
iwl_internal_short_hw_scan(priv);
|
||||
return;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_force_rf_reset);
|
||||
|
||||
|
||||
int iwl_force_reset(struct iwl_priv *priv, int mode)
|
||||
{
|
||||
struct iwl_force_reset *force_reset;
|
||||
|
||||
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
|
||||
return -EINVAL;
|
||||
|
||||
if (mode >= IWL_MAX_FORCE_RESET) {
|
||||
IWL_DEBUG_INFO(priv, "invalid reset request.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
force_reset = &priv->force_reset[mode];
|
||||
force_reset->reset_request_count++;
|
||||
if (force_reset->last_force_reset_jiffies &&
|
||||
time_after(force_reset->last_force_reset_jiffies +
|
||||
force_reset->reset_duration, jiffies)) {
|
||||
IWL_DEBUG_INFO(priv, "force reset rejected\n");
|
||||
force_reset->reset_reject_count++;
|
||||
return -EAGAIN;
|
||||
}
|
||||
force_reset->reset_success_count++;
|
||||
force_reset->last_force_reset_jiffies = jiffies;
|
||||
IWL_DEBUG_INFO(priv, "perform force reset (%d)\n", mode);
|
||||
switch (mode) {
|
||||
case IWL_RF_RESET:
|
||||
iwl_force_rf_reset(priv);
|
||||
break;
|
||||
case IWL_FW_RESET:
|
||||
IWL_ERR(priv, "On demand firmware reload\n");
|
||||
/* Set the FW error flag -- cleared on iwl_down */
|
||||
set_bit(STATUS_FW_ERROR, &priv->status);
|
||||
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);
|
||||
queue_work(priv->workqueue, &priv->restart);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
|
@ -117,6 +117,7 @@ struct iwl_apm_ops {
|
||||
struct iwl_temp_ops {
|
||||
void (*temperature)(struct iwl_priv *priv);
|
||||
void (*set_ct_kill)(struct iwl_priv *priv);
|
||||
void (*set_calib_version)(struct iwl_priv *priv);
|
||||
};
|
||||
|
||||
struct iwl_ucode_ops {
|
||||
@ -414,13 +415,13 @@ void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
|
||||
void iwl_cmd_queue_free(struct iwl_priv *priv);
|
||||
int iwl_rx_queue_alloc(struct iwl_priv *priv);
|
||||
void iwl_rx_handle(struct iwl_priv *priv);
|
||||
int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv,
|
||||
void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv,
|
||||
struct iwl_rx_queue *q);
|
||||
void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
|
||||
void iwl_rx_replenish(struct iwl_priv *priv);
|
||||
void iwl_rx_replenish_now(struct iwl_priv *priv);
|
||||
int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
|
||||
int iwl_rx_queue_restock(struct iwl_priv *priv);
|
||||
void iwl_rx_queue_restock(struct iwl_priv *priv);
|
||||
int iwl_rx_queue_space(const struct iwl_rx_queue *q);
|
||||
void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority);
|
||||
void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
|
||||
@ -450,9 +451,9 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb);
|
||||
void iwl_hw_txq_ctx_free(struct iwl_priv *priv);
|
||||
int iwl_hw_tx_queue_init(struct iwl_priv *priv,
|
||||
struct iwl_tx_queue *txq);
|
||||
int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq);
|
||||
void iwl_free_tfds_in_queue(struct iwl_priv *priv,
|
||||
int sta_id, int tid, int freed);
|
||||
void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq);
|
||||
int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
|
||||
int slots_num, u32 txq_id);
|
||||
void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id);
|
||||
@ -503,7 +504,7 @@ int iwl_scan_cancel(struct iwl_priv *priv);
|
||||
int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms);
|
||||
int iwl_mac_hw_scan(struct ieee80211_hw *hw, struct cfg80211_scan_request *req);
|
||||
int iwl_internal_short_hw_scan(struct iwl_priv *priv);
|
||||
void iwl_force_rf_reset(struct iwl_priv *priv);
|
||||
int iwl_force_reset(struct iwl_priv *priv, int mode);
|
||||
u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame,
|
||||
const u8 *ie, int ie_len, int left);
|
||||
void iwl_setup_rx_scan_handlers(struct iwl_priv *priv);
|
||||
@ -605,7 +606,7 @@ void iwlcore_free_geos(struct iwl_priv *priv);
|
||||
/*************** DRIVER STATUS FUNCTIONS *****/
|
||||
|
||||
#define STATUS_HCMD_ACTIVE 0 /* host command in progress */
|
||||
#define STATUS_HCMD_SYNC_ACTIVE 1 /* sync host command in progress */
|
||||
/* 1 is unused (used to be STATUS_HCMD_SYNC_ACTIVE) */
|
||||
#define STATUS_INT_ENABLED 2
|
||||
#define STATUS_RF_KILL_HW 3
|
||||
#define STATUS_CT_KILL 4
|
||||
|
@ -369,7 +369,7 @@
|
||||
#define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_3x3_HYB (0x00000000)
|
||||
#define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_HYB (0x00000001)
|
||||
#define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA (0x00000002)
|
||||
|
||||
#define CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6 (0x00000004)
|
||||
|
||||
/* GIO Chicken Bits (PCI Express bus link power management) */
|
||||
#define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX (0x00800000)
|
||||
|
@ -530,8 +530,6 @@ static ssize_t iwl_dbgfs_status_read(struct file *file,
|
||||
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_ACTIVE:\t %d\n",
|
||||
test_bit(STATUS_HCMD_ACTIVE, &priv->status));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_SYNC_ACTIVE: %d\n",
|
||||
test_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INT_ENABLED:\t %d\n",
|
||||
test_bit(STATUS_INT_ENABLED, &priv->status));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n",
|
||||
@ -2223,6 +2221,62 @@ static ssize_t iwl_dbgfs_plcp_delta_write(struct file *file,
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_force_reset_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos) {
|
||||
|
||||
struct iwl_priv *priv = file->private_data;
|
||||
int i, pos = 0;
|
||||
char buf[300];
|
||||
const size_t bufsz = sizeof(buf);
|
||||
struct iwl_force_reset *force_reset;
|
||||
|
||||
for (i = 0; i < IWL_MAX_FORCE_RESET; i++) {
|
||||
force_reset = &priv->force_reset[i];
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"Force reset method %d\n", i);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"\tnumber of reset request: %d\n",
|
||||
force_reset->reset_request_count);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"\tnumber of reset request success: %d\n",
|
||||
force_reset->reset_success_count);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"\tnumber of reset request reject: %d\n",
|
||||
force_reset->reset_reject_count);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"\treset duration: %lu\n",
|
||||
force_reset->reset_duration);
|
||||
}
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_force_reset_write(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos) {
|
||||
|
||||
struct iwl_priv *priv = file->private_data;
|
||||
char buf[8];
|
||||
int buf_size;
|
||||
int reset, ret;
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
buf_size = min(count, sizeof(buf) - 1);
|
||||
if (copy_from_user(buf, user_buf, buf_size))
|
||||
return -EFAULT;
|
||||
if (sscanf(buf, "%d", &reset) != 1)
|
||||
return -EINVAL;
|
||||
switch (reset) {
|
||||
case IWL_RF_RESET:
|
||||
case IWL_FW_RESET:
|
||||
ret = iwl_force_reset(priv, reset);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
return ret ? ret : count;
|
||||
}
|
||||
|
||||
DEBUGFS_READ_FILE_OPS(rx_statistics);
|
||||
DEBUGFS_READ_FILE_OPS(tx_statistics);
|
||||
DEBUGFS_READ_WRITE_FILE_OPS(traffic_log);
|
||||
@ -2243,6 +2297,7 @@ DEBUGFS_READ_FILE_OPS(fh_reg);
|
||||
DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon);
|
||||
DEBUGFS_WRITE_FILE_OPS(internal_scan);
|
||||
DEBUGFS_READ_WRITE_FILE_OPS(plcp_delta);
|
||||
DEBUGFS_READ_WRITE_FILE_OPS(force_reset);
|
||||
|
||||
/*
|
||||
* Create the debugfs files and directories
|
||||
@ -2296,6 +2351,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
|
||||
DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR);
|
||||
DEBUGFS_ADD_FILE(internal_scan, dir_debug, S_IWUSR);
|
||||
DEBUGFS_ADD_FILE(plcp_delta, dir_debug, S_IWUSR | S_IRUSR);
|
||||
DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR | S_IRUSR);
|
||||
if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) {
|
||||
DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR);
|
||||
DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR);
|
||||
|
@ -1033,8 +1033,26 @@ struct iwl_event_log {
|
||||
#define IWL_MAX_PLCP_ERR_THRESHOLD_MIN (0)
|
||||
#define IWL_MAX_PLCP_ERR_THRESHOLD_DEF (50)
|
||||
#define IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF (100)
|
||||
#define IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF (200)
|
||||
#define IWL_MAX_PLCP_ERR_THRESHOLD_MAX (255)
|
||||
|
||||
#define IWL_DELAY_NEXT_FORCE_RF_RESET (HZ*3)
|
||||
#define IWL_DELAY_NEXT_FORCE_FW_RELOAD (HZ*5)
|
||||
|
||||
enum iwl_reset {
|
||||
IWL_RF_RESET = 0,
|
||||
IWL_FW_RESET,
|
||||
IWL_MAX_FORCE_RESET,
|
||||
};
|
||||
|
||||
struct iwl_force_reset {
|
||||
int reset_request_count;
|
||||
int reset_success_count;
|
||||
int reset_reject_count;
|
||||
unsigned long reset_duration;
|
||||
unsigned long last_force_reset_jiffies;
|
||||
};
|
||||
|
||||
struct iwl_priv {
|
||||
|
||||
/* ieee device used by generic ieee processing code */
|
||||
@ -1066,6 +1084,12 @@ struct iwl_priv {
|
||||
/* storing the jiffies when the plcp error rate is received */
|
||||
unsigned long plcp_jiffies;
|
||||
|
||||
/* reporting the number of tids has AGG on. 0 means no AGGREGATION */
|
||||
u8 agg_tids_count;
|
||||
|
||||
/* force reset */
|
||||
struct iwl_force_reset force_reset[IWL_MAX_FORCE_RESET];
|
||||
|
||||
/* we allocate array of iwl4965_channel_info for NIC's valid channels.
|
||||
* Access via channel # using indirect index array */
|
||||
struct iwl_channel_info *channel_info; /* channel info array */
|
||||
@ -1087,7 +1111,6 @@ struct iwl_priv {
|
||||
unsigned long scan_start;
|
||||
unsigned long scan_pass_start;
|
||||
unsigned long scan_start_tsf;
|
||||
unsigned long last_internal_scan_jiffies;
|
||||
void *scan;
|
||||
int scan_bands;
|
||||
struct cfg80211_scan_request *scan_request;
|
||||
@ -1100,6 +1123,7 @@ struct iwl_priv {
|
||||
spinlock_t hcmd_lock; /* protect hcmd */
|
||||
spinlock_t reg_lock; /* protect hw register access */
|
||||
struct mutex mutex;
|
||||
struct mutex sync_cmd_mutex; /* enable serialization of sync commands */
|
||||
|
||||
/* basic pci-network driver stuff */
|
||||
struct pci_dev *pci_dev;
|
||||
|
@ -164,15 +164,13 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
|
||||
/* A synchronous command can not have a callback set. */
|
||||
BUG_ON(cmd->callback);
|
||||
|
||||
if (test_and_set_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status)) {
|
||||
IWL_ERR(priv,
|
||||
"Error sending %s: Already sending a host command\n",
|
||||
IWL_DEBUG_INFO(priv, "Attempting to send sync command %s\n",
|
||||
get_cmd_string(cmd->id));
|
||||
ret = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
mutex_lock(&priv->sync_cmd_mutex);
|
||||
|
||||
set_bit(STATUS_HCMD_ACTIVE, &priv->status);
|
||||
IWL_DEBUG_INFO(priv, "Setting HCMD_ACTIVE for command %s \n",
|
||||
get_cmd_string(cmd->id));
|
||||
|
||||
cmd_idx = iwl_enqueue_hcmd(priv, cmd);
|
||||
if (cmd_idx < 0) {
|
||||
@ -193,6 +191,8 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
|
||||
jiffies_to_msecs(HOST_COMPLETE_TIMEOUT));
|
||||
|
||||
clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
|
||||
IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command %s \n",
|
||||
get_cmd_string(cmd->id));
|
||||
ret = -ETIMEDOUT;
|
||||
goto cancel;
|
||||
}
|
||||
@ -237,7 +237,7 @@ fail:
|
||||
cmd->reply_page = 0;
|
||||
}
|
||||
out:
|
||||
clear_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status);
|
||||
mutex_unlock(&priv->sync_cmd_mutex);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_send_cmd_sync);
|
||||
|
@ -80,8 +80,8 @@ static inline void iwl_free_fw_desc(struct pci_dev *pci_dev,
|
||||
struct fw_desc *desc)
|
||||
{
|
||||
if (desc->v_addr)
|
||||
pci_free_consistent(pci_dev, desc->len,
|
||||
desc->v_addr, desc->p_addr);
|
||||
dma_free_coherent(&pci_dev->dev, desc->len,
|
||||
desc->v_addr, desc->p_addr);
|
||||
desc->v_addr = NULL;
|
||||
desc->len = 0;
|
||||
}
|
||||
@ -89,7 +89,8 @@ static inline void iwl_free_fw_desc(struct pci_dev *pci_dev,
|
||||
static inline int iwl_alloc_fw_desc(struct pci_dev *pci_dev,
|
||||
struct fw_desc *desc)
|
||||
{
|
||||
desc->v_addr = pci_alloc_consistent(pci_dev, desc->len, &desc->p_addr);
|
||||
desc->v_addr = dma_alloc_coherent(&pci_dev->dev, desc->len,
|
||||
&desc->p_addr, GFP_KERNEL);
|
||||
return (desc->v_addr != NULL) ? 0 : -ENOMEM;
|
||||
}
|
||||
|
||||
|
@ -123,12 +123,11 @@ EXPORT_SYMBOL(iwl_rx_queue_space);
|
||||
/**
|
||||
* iwl_rx_queue_update_write_ptr - Update the write pointer for the RX queue
|
||||
*/
|
||||
int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q)
|
||||
void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 rx_wrt_ptr_reg = priv->hw_params.rx_wrt_ptr_reg;
|
||||
u32 reg;
|
||||
int ret = 0;
|
||||
|
||||
spin_lock_irqsave(&q->lock, flags);
|
||||
|
||||
@ -161,7 +160,6 @@ int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q)
|
||||
|
||||
exit_unlock:
|
||||
spin_unlock_irqrestore(&q->lock, flags);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_rx_queue_update_write_ptr);
|
||||
/**
|
||||
@ -184,14 +182,13 @@ static inline __le32 iwl_dma_addr2rbd_ptr(struct iwl_priv *priv,
|
||||
* also updates the memory address in the firmware to reference the new
|
||||
* target buffer.
|
||||
*/
|
||||
int iwl_rx_queue_restock(struct iwl_priv *priv)
|
||||
void iwl_rx_queue_restock(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_rx_queue *rxq = &priv->rxq;
|
||||
struct list_head *element;
|
||||
struct iwl_rx_mem_buffer *rxb;
|
||||
unsigned long flags;
|
||||
int write;
|
||||
int ret = 0;
|
||||
|
||||
spin_lock_irqsave(&rxq->lock, flags);
|
||||
write = rxq->write & ~0x7;
|
||||
@ -220,10 +217,8 @@ int iwl_rx_queue_restock(struct iwl_priv *priv)
|
||||
spin_lock_irqsave(&rxq->lock, flags);
|
||||
rxq->need_update = 1;
|
||||
spin_unlock_irqrestore(&rxq->lock, flags);
|
||||
ret = iwl_rx_queue_update_write_ptr(priv, rxq);
|
||||
iwl_rx_queue_update_write_ptr(priv, rxq);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_rx_queue_restock);
|
||||
|
||||
@ -350,10 +345,10 @@ void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
|
||||
}
|
||||
}
|
||||
|
||||
pci_free_consistent(priv->pci_dev, 4 * RX_QUEUE_SIZE, rxq->bd,
|
||||
rxq->dma_addr);
|
||||
pci_free_consistent(priv->pci_dev, sizeof(struct iwl_rb_status),
|
||||
rxq->rb_stts, rxq->rb_stts_dma);
|
||||
dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd,
|
||||
rxq->dma_addr);
|
||||
dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status),
|
||||
rxq->rb_stts, rxq->rb_stts_dma);
|
||||
rxq->bd = NULL;
|
||||
rxq->rb_stts = NULL;
|
||||
}
|
||||
@ -362,7 +357,7 @@ EXPORT_SYMBOL(iwl_rx_queue_free);
|
||||
int iwl_rx_queue_alloc(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_rx_queue *rxq = &priv->rxq;
|
||||
struct pci_dev *dev = priv->pci_dev;
|
||||
struct device *dev = &priv->pci_dev->dev;
|
||||
int i;
|
||||
|
||||
spin_lock_init(&rxq->lock);
|
||||
@ -370,12 +365,13 @@ int iwl_rx_queue_alloc(struct iwl_priv *priv)
|
||||
INIT_LIST_HEAD(&rxq->rx_used);
|
||||
|
||||
/* Alloc the circular buffer of Read Buffer Descriptors (RBDs) */
|
||||
rxq->bd = pci_alloc_consistent(dev, 4 * RX_QUEUE_SIZE, &rxq->dma_addr);
|
||||
rxq->bd = dma_alloc_coherent(dev, 4 * RX_QUEUE_SIZE, &rxq->dma_addr,
|
||||
GFP_KERNEL);
|
||||
if (!rxq->bd)
|
||||
goto err_bd;
|
||||
|
||||
rxq->rb_stts = pci_alloc_consistent(dev, sizeof(struct iwl_rb_status),
|
||||
&rxq->rb_stts_dma);
|
||||
rxq->rb_stts = dma_alloc_coherent(dev, sizeof(struct iwl_rb_status),
|
||||
&rxq->rb_stts_dma, GFP_KERNEL);
|
||||
if (!rxq->rb_stts)
|
||||
goto err_rb;
|
||||
|
||||
@ -392,8 +388,8 @@ int iwl_rx_queue_alloc(struct iwl_priv *priv)
|
||||
return 0;
|
||||
|
||||
err_rb:
|
||||
pci_free_consistent(priv->pci_dev, 4 * RX_QUEUE_SIZE, rxq->bd,
|
||||
rxq->dma_addr);
|
||||
dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd,
|
||||
rxq->dma_addr);
|
||||
err_bd:
|
||||
return -ENOMEM;
|
||||
}
|
||||
@ -620,6 +616,11 @@ static void iwl_accumulative_statistics(struct iwl_priv *priv,
|
||||
|
||||
#define REG_RECALIB_PERIOD (60)
|
||||
|
||||
/* the threshold ratio of actual_ack_cnt to expected_ack_cnt in percent */
|
||||
#define ACK_CNT_RATIO (50)
|
||||
#define BA_TIMEOUT_CNT (5)
|
||||
#define BA_TIMEOUT_MAX (16)
|
||||
|
||||
#define PLCP_MSG "plcp_err exceeded %u, %u, %u, %u, %u, %d, %u mSecs\n"
|
||||
void iwl_rx_statistics(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb)
|
||||
@ -629,6 +630,9 @@ void iwl_rx_statistics(struct iwl_priv *priv,
|
||||
int combined_plcp_delta;
|
||||
unsigned int plcp_msec;
|
||||
unsigned long plcp_received_jiffies;
|
||||
int actual_ack_cnt_delta;
|
||||
int expected_ack_cnt_delta;
|
||||
int ba_timeout_delta;
|
||||
|
||||
IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n",
|
||||
(int)sizeof(priv->statistics),
|
||||
@ -643,6 +647,44 @@ void iwl_rx_statistics(struct iwl_priv *priv,
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats);
|
||||
#endif
|
||||
actual_ack_cnt_delta = le32_to_cpu(pkt->u.stats.tx.actual_ack_cnt) -
|
||||
le32_to_cpu(priv->statistics.tx.actual_ack_cnt);
|
||||
expected_ack_cnt_delta = le32_to_cpu(
|
||||
pkt->u.stats.tx.expected_ack_cnt) -
|
||||
le32_to_cpu(priv->statistics.tx.expected_ack_cnt);
|
||||
ba_timeout_delta = le32_to_cpu(
|
||||
pkt->u.stats.tx.agg.ba_timeout) -
|
||||
le32_to_cpu(priv->statistics.tx.agg.ba_timeout);
|
||||
if ((priv->agg_tids_count > 0) &&
|
||||
(expected_ack_cnt_delta > 0) &&
|
||||
(((actual_ack_cnt_delta * 100) / expected_ack_cnt_delta) <
|
||||
ACK_CNT_RATIO) &&
|
||||
(ba_timeout_delta > BA_TIMEOUT_CNT)) {
|
||||
IWL_DEBUG_RADIO(priv,
|
||||
"actual_ack_cnt delta = %d, expected_ack_cnt = %d\n",
|
||||
actual_ack_cnt_delta, expected_ack_cnt_delta);
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
IWL_DEBUG_RADIO(priv, "rx_detected_cnt delta = %d\n",
|
||||
priv->delta_statistics.tx.rx_detected_cnt);
|
||||
IWL_DEBUG_RADIO(priv,
|
||||
"ack_or_ba_timeout_collision delta = %d\n",
|
||||
priv->delta_statistics.tx.ack_or_ba_timeout_collision);
|
||||
#endif
|
||||
IWL_DEBUG_RADIO(priv, "agg ba_timeout delta = %d\n",
|
||||
ba_timeout_delta);
|
||||
if ((actual_ack_cnt_delta == 0) &&
|
||||
(ba_timeout_delta >=
|
||||
BA_TIMEOUT_MAX)) {
|
||||
IWL_DEBUG_RADIO(priv,
|
||||
"call iwl_force_reset(IWL_FW_RESET)\n");
|
||||
iwl_force_reset(priv, IWL_FW_RESET);
|
||||
} else {
|
||||
IWL_DEBUG_RADIO(priv,
|
||||
"call iwl_force_reset(IWL_RF_RESET)\n");
|
||||
iwl_force_reset(priv, IWL_RF_RESET);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* check for plcp_err and trigger radio reset if it exceeds
|
||||
* the plcp error threshold plcp_delta.
|
||||
@ -689,7 +731,7 @@ void iwl_rx_statistics(struct iwl_priv *priv,
|
||||
* Reset the RF radio due to the high plcp
|
||||
* error rate
|
||||
*/
|
||||
iwl_force_rf_reset(priv);
|
||||
iwl_force_reset(priv, IWL_RF_RESET);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -250,8 +250,6 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv,
|
||||
|
||||
if (!priv->is_internal_short_scan)
|
||||
priv->next_scan_jiffies = 0;
|
||||
else
|
||||
priv->last_internal_scan_jiffies = jiffies;
|
||||
|
||||
IWL_DEBUG_INFO(priv, "Setting scan to off\n");
|
||||
|
||||
@ -471,21 +469,6 @@ EXPORT_SYMBOL(iwl_init_scan_params);
|
||||
|
||||
static int iwl_scan_initiate(struct iwl_priv *priv)
|
||||
{
|
||||
if (!iwl_is_ready_rf(priv)) {
|
||||
IWL_DEBUG_SCAN(priv, "Aborting scan due to not ready.\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (test_bit(STATUS_SCANNING, &priv->status)) {
|
||||
IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
|
||||
IWL_DEBUG_SCAN(priv, "Scan request while abort pending\n");
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
IWL_DEBUG_INFO(priv, "Starting scan...\n");
|
||||
set_bit(STATUS_SCANNING, &priv->status);
|
||||
priv->is_internal_short_scan = false;
|
||||
@ -517,6 +500,18 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw,
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
if (test_bit(STATUS_SCANNING, &priv->status)) {
|
||||
IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
|
||||
ret = -EAGAIN;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
|
||||
IWL_DEBUG_SCAN(priv, "Scan request while abort pending\n");
|
||||
ret = -EAGAIN;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
/* We don't schedule scan within next_scan_jiffies period.
|
||||
* Avoid scanning during possible EAPOL exchange, return
|
||||
* success immediately.
|
||||
@ -551,8 +546,6 @@ EXPORT_SYMBOL(iwl_mac_hw_scan);
|
||||
* internal short scan, this function should only been called while associated.
|
||||
* It will reset and tune the radio to prevent possible RF related problem
|
||||
*/
|
||||
#define IWL_DELAY_NEXT_INTERNAL_SCAN (HZ*1)
|
||||
|
||||
int iwl_internal_short_hw_scan(struct iwl_priv *priv)
|
||||
{
|
||||
int ret = 0;
|
||||
@ -572,12 +565,6 @@ int iwl_internal_short_hw_scan(struct iwl_priv *priv)
|
||||
ret = -EAGAIN;
|
||||
goto out;
|
||||
}
|
||||
if (priv->last_internal_scan_jiffies &&
|
||||
time_after(priv->last_internal_scan_jiffies +
|
||||
IWL_DELAY_NEXT_INTERNAL_SCAN, jiffies)) {
|
||||
IWL_DEBUG_SCAN(priv, "internal scan rejected\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
priv->scan_bands = 0;
|
||||
if (priv->band == IEEE80211_BAND_5GHZ)
|
||||
|
@ -60,7 +60,8 @@ static const u16 default_tid_to_tx_fifo[] = {
|
||||
static inline int iwl_alloc_dma_ptr(struct iwl_priv *priv,
|
||||
struct iwl_dma_ptr *ptr, size_t size)
|
||||
{
|
||||
ptr->addr = pci_alloc_consistent(priv->pci_dev, size, &ptr->dma);
|
||||
ptr->addr = dma_alloc_coherent(&priv->pci_dev->dev, size, &ptr->dma,
|
||||
GFP_KERNEL);
|
||||
if (!ptr->addr)
|
||||
return -ENOMEM;
|
||||
ptr->size = size;
|
||||
@ -73,21 +74,20 @@ static inline void iwl_free_dma_ptr(struct iwl_priv *priv,
|
||||
if (unlikely(!ptr->addr))
|
||||
return;
|
||||
|
||||
pci_free_consistent(priv->pci_dev, ptr->size, ptr->addr, ptr->dma);
|
||||
dma_free_coherent(&priv->pci_dev->dev, ptr->size, ptr->addr, ptr->dma);
|
||||
memset(ptr, 0, sizeof(*ptr));
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl_txq_update_write_ptr - Send new write index to hardware
|
||||
*/
|
||||
int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq)
|
||||
void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq)
|
||||
{
|
||||
u32 reg = 0;
|
||||
int ret = 0;
|
||||
int txq_id = txq->q.id;
|
||||
|
||||
if (txq->need_update == 0)
|
||||
return ret;
|
||||
return;
|
||||
|
||||
/* if we're trying to save power */
|
||||
if (test_bit(STATUS_POWER_PMI, &priv->status)) {
|
||||
@ -101,7 +101,7 @@ int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq)
|
||||
txq_id, reg);
|
||||
iwl_set_bit(priv, CSR_GP_CNTRL,
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
|
||||
return ret;
|
||||
return;
|
||||
}
|
||||
|
||||
iwl_write_direct32(priv, HBUS_TARG_WRPTR,
|
||||
@ -114,8 +114,6 @@ int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq)
|
||||
txq->q.write_ptr | (txq_id << 8));
|
||||
|
||||
txq->need_update = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_txq_update_write_ptr);
|
||||
|
||||
@ -146,7 +144,7 @@ void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id)
|
||||
{
|
||||
struct iwl_tx_queue *txq = &priv->txq[txq_id];
|
||||
struct iwl_queue *q = &txq->q;
|
||||
struct pci_dev *dev = priv->pci_dev;
|
||||
struct device *dev = &priv->pci_dev->dev;
|
||||
int i;
|
||||
|
||||
if (q->n_bd == 0)
|
||||
@ -163,8 +161,8 @@ void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id)
|
||||
|
||||
/* De-alloc circular buffer of TFDs */
|
||||
if (txq->q.n_bd)
|
||||
pci_free_consistent(dev, priv->hw_params.tfd_size *
|
||||
txq->q.n_bd, txq->tfds, txq->q.dma_addr);
|
||||
dma_free_coherent(dev, priv->hw_params.tfd_size *
|
||||
txq->q.n_bd, txq->tfds, txq->q.dma_addr);
|
||||
|
||||
/* De-alloc array of per-TFD driver data */
|
||||
kfree(txq->txb);
|
||||
@ -193,7 +191,7 @@ void iwl_cmd_queue_free(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM];
|
||||
struct iwl_queue *q = &txq->q;
|
||||
struct pci_dev *dev = priv->pci_dev;
|
||||
struct device *dev = &priv->pci_dev->dev;
|
||||
int i;
|
||||
|
||||
if (q->n_bd == 0)
|
||||
@ -205,8 +203,8 @@ void iwl_cmd_queue_free(struct iwl_priv *priv)
|
||||
|
||||
/* De-alloc circular buffer of TFDs */
|
||||
if (txq->q.n_bd)
|
||||
pci_free_consistent(dev, priv->hw_params.tfd_size *
|
||||
txq->q.n_bd, txq->tfds, txq->q.dma_addr);
|
||||
dma_free_coherent(dev, priv->hw_params.tfd_size * txq->q.n_bd,
|
||||
txq->tfds, txq->q.dma_addr);
|
||||
|
||||
/* deallocate arrays */
|
||||
kfree(txq->cmd);
|
||||
@ -297,7 +295,7 @@ static int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q,
|
||||
static int iwl_tx_queue_alloc(struct iwl_priv *priv,
|
||||
struct iwl_tx_queue *txq, u32 id)
|
||||
{
|
||||
struct pci_dev *dev = priv->pci_dev;
|
||||
struct device *dev = &priv->pci_dev->dev;
|
||||
size_t tfd_sz = priv->hw_params.tfd_size * TFD_QUEUE_SIZE_MAX;
|
||||
|
||||
/* Driver private data, only for Tx (not command) queues,
|
||||
@ -316,8 +314,8 @@ static int iwl_tx_queue_alloc(struct iwl_priv *priv,
|
||||
|
||||
/* Circular buffer of transmit frame descriptors (TFDs),
|
||||
* shared with device */
|
||||
txq->tfds = pci_alloc_consistent(dev, tfd_sz, &txq->q.dma_addr);
|
||||
|
||||
txq->tfds = dma_alloc_coherent(dev, tfd_sz, &txq->q.dma_addr,
|
||||
GFP_KERNEL);
|
||||
if (!txq->tfds) {
|
||||
IWL_ERR(priv, "pci_alloc_consistent(%zd) failed\n", tfd_sz);
|
||||
goto error;
|
||||
@ -745,7 +743,6 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
||||
u8 tid = 0;
|
||||
u8 *qc = NULL;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
if (iwl_is_rfkill(priv)) {
|
||||
@ -820,8 +817,10 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
||||
hdr->seq_ctrl |= cpu_to_le16(seq_number);
|
||||
seq_number += 0x10;
|
||||
/* aggregation is on for this <sta,tid> */
|
||||
if (info->flags & IEEE80211_TX_CTL_AMPDU)
|
||||
if (info->flags & IEEE80211_TX_CTL_AMPDU &&
|
||||
priv->stations[sta_id].tid[tid].agg.state == IWL_AGG_ON) {
|
||||
txq_id = priv->stations[sta_id].tid[tid].agg.txq_id;
|
||||
}
|
||||
}
|
||||
|
||||
txq = &priv->txq[txq_id];
|
||||
@ -963,7 +962,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
||||
|
||||
/* Tell device the write index *just past* this latest filled TFD */
|
||||
q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
|
||||
ret = iwl_txq_update_write_ptr(priv, txq);
|
||||
iwl_txq_update_write_ptr(priv, txq);
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
/*
|
||||
@ -977,9 +976,6 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
||||
if (sta_priv && sta_priv->client)
|
||||
atomic_inc(&sta_priv->pending_frames);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if ((iwl_queue_space(q) < q->high_mark) && priv->mac80211_registered) {
|
||||
if (wait_write_ptr) {
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
@ -1018,7 +1014,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
|
||||
struct iwl_cmd_meta *out_meta;
|
||||
dma_addr_t phys_addr;
|
||||
unsigned long flags;
|
||||
int len, ret;
|
||||
int len;
|
||||
u32 idx;
|
||||
u16 fix_size;
|
||||
|
||||
@ -1115,10 +1111,10 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
|
||||
|
||||
/* Increment and update queue's write index */
|
||||
q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
|
||||
ret = iwl_txq_update_write_ptr(priv, txq);
|
||||
iwl_txq_update_write_ptr(priv, txq);
|
||||
|
||||
spin_unlock_irqrestore(&priv->hcmd_lock, flags);
|
||||
return ret ? ret : idx;
|
||||
return idx;
|
||||
}
|
||||
|
||||
static void iwl_tx_status(struct iwl_priv *priv, struct sk_buff *skb)
|
||||
@ -1260,6 +1256,8 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
|
||||
|
||||
if (!(meta->flags & CMD_ASYNC)) {
|
||||
clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
|
||||
IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command %s \n",
|
||||
get_cmd_string(cmd->hdr.cmd));
|
||||
wake_up_interruptible(&priv->wait_command_queue);
|
||||
}
|
||||
}
|
||||
@ -1346,7 +1344,7 @@ int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid)
|
||||
{
|
||||
int tx_fifo_id, txq_id, sta_id, ssn = -1;
|
||||
struct iwl_tid_data *tid_data;
|
||||
int ret, write_ptr, read_ptr;
|
||||
int write_ptr, read_ptr;
|
||||
unsigned long flags;
|
||||
|
||||
if (!ra) {
|
||||
@ -1398,13 +1396,17 @@ int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid)
|
||||
priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF;
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
ret = priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, ssn,
|
||||
/*
|
||||
* the only reason this call can fail is queue number out of range,
|
||||
* which can happen if uCode is reloaded and all the station
|
||||
* information are lost. if it is outside the range, there is no need
|
||||
* to deactivate the uCode queue, just return "success" to allow
|
||||
* mac80211 to clean up it own data.
|
||||
*/
|
||||
priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, ssn,
|
||||
tx_fifo_id);
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, ra, tid);
|
||||
|
||||
return 0;
|
||||
|
@ -53,8 +53,8 @@
|
||||
#include "iwl-commands.h"
|
||||
#include "iwl-sta.h"
|
||||
#include "iwl-3945.h"
|
||||
#include "iwl-helpers.h"
|
||||
#include "iwl-core.h"
|
||||
#include "iwl-helpers.h"
|
||||
#include "iwl-dev.h"
|
||||
#include "iwl-spectrum.h"
|
||||
|
||||
@ -352,10 +352,10 @@ static int iwl3945_send_beacon_cmd(struct iwl_priv *priv)
|
||||
static void iwl3945_unset_hw_params(struct iwl_priv *priv)
|
||||
{
|
||||
if (priv->shared_virt)
|
||||
pci_free_consistent(priv->pci_dev,
|
||||
sizeof(struct iwl3945_shared),
|
||||
priv->shared_virt,
|
||||
priv->shared_phys);
|
||||
dma_free_coherent(&priv->pci_dev->dev,
|
||||
sizeof(struct iwl3945_shared),
|
||||
priv->shared_virt,
|
||||
priv->shared_phys);
|
||||
}
|
||||
|
||||
static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
|
||||
@ -478,7 +478,6 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
||||
u8 wait_write_ptr = 0;
|
||||
u8 *qc = NULL;
|
||||
unsigned long flags;
|
||||
int rc;
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
if (iwl_is_rfkill(priv)) {
|
||||
@ -663,12 +662,9 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
||||
|
||||
/* Tell device the write index *just past* this latest filled TFD */
|
||||
q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
|
||||
rc = iwl_txq_update_write_ptr(priv, txq);
|
||||
iwl_txq_update_write_ptr(priv, txq);
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if ((iwl_queue_space(q) < q->high_mark)
|
||||
&& priv->mac80211_registered) {
|
||||
if (wait_write_ptr) {
|
||||
@ -1063,13 +1059,13 @@ static inline __le32 iwl3945_dma_addr2rbd_ptr(struct iwl_priv *priv,
|
||||
* also updates the memory address in the firmware to reference the new
|
||||
* target buffer.
|
||||
*/
|
||||
static int iwl3945_rx_queue_restock(struct iwl_priv *priv)
|
||||
static void iwl3945_rx_queue_restock(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_rx_queue *rxq = &priv->rxq;
|
||||
struct list_head *element;
|
||||
struct iwl_rx_mem_buffer *rxb;
|
||||
unsigned long flags;
|
||||
int write, rc;
|
||||
int write;
|
||||
|
||||
spin_lock_irqsave(&rxq->lock, flags);
|
||||
write = rxq->write & ~0x7;
|
||||
@ -1099,12 +1095,8 @@ static int iwl3945_rx_queue_restock(struct iwl_priv *priv)
|
||||
spin_lock_irqsave(&rxq->lock, flags);
|
||||
rxq->need_update = 1;
|
||||
spin_unlock_irqrestore(&rxq->lock, flags);
|
||||
rc = iwl_rx_queue_update_write_ptr(priv, rxq);
|
||||
if (rc)
|
||||
return rc;
|
||||
iwl_rx_queue_update_write_ptr(priv, rxq);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1249,10 +1241,10 @@ static void iwl3945_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rx
|
||||
}
|
||||
}
|
||||
|
||||
pci_free_consistent(priv->pci_dev, 4 * RX_QUEUE_SIZE, rxq->bd,
|
||||
rxq->dma_addr);
|
||||
pci_free_consistent(priv->pci_dev, sizeof(struct iwl_rb_status),
|
||||
rxq->rb_stts, rxq->rb_stts_dma);
|
||||
dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd,
|
||||
rxq->dma_addr);
|
||||
dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status),
|
||||
rxq->rb_stts, rxq->rb_stts_dma);
|
||||
rxq->bd = NULL;
|
||||
rxq->rb_stts = NULL;
|
||||
}
|
||||
@ -3855,6 +3847,7 @@ static int iwl3945_init_drv(struct iwl_priv *priv)
|
||||
INIT_LIST_HEAD(&priv->free_frames);
|
||||
|
||||
mutex_init(&priv->mutex);
|
||||
mutex_init(&priv->sync_cmd_mutex);
|
||||
|
||||
/* Clear the driver's (not device's) station table */
|
||||
iwl_clear_stations_table(priv);
|
||||
@ -4047,6 +4040,13 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
|
||||
spin_lock_init(&priv->reg_lock);
|
||||
spin_lock_init(&priv->lock);
|
||||
|
||||
/*
|
||||
* stop and reset the on-board processor just in case it is in a
|
||||
* strange state ... like being left stranded by a primary kernel
|
||||
* and this is now the kdump kernel trying to start up
|
||||
*/
|
||||
iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
|
||||
|
||||
/***********************
|
||||
* 4. Read EEPROM
|
||||
* ********************/
|
||||
|
@ -771,23 +771,41 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw,
|
||||
}
|
||||
}
|
||||
|
||||
static int mac80211_hwsim_sta_add(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
hwsim_check_magic(vif);
|
||||
hwsim_set_sta_magic(sta);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mac80211_hwsim_sta_remove(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
hwsim_check_magic(vif);
|
||||
hwsim_clear_sta_magic(sta);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mac80211_hwsim_sta_notify(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
enum sta_notify_cmd cmd,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
hwsim_check_magic(vif);
|
||||
|
||||
switch (cmd) {
|
||||
case STA_NOTIFY_ADD:
|
||||
hwsim_set_sta_magic(sta);
|
||||
break;
|
||||
case STA_NOTIFY_REMOVE:
|
||||
hwsim_clear_sta_magic(sta);
|
||||
break;
|
||||
case STA_NOTIFY_SLEEP:
|
||||
case STA_NOTIFY_AWAKE:
|
||||
/* TODO: make good use of these flags */
|
||||
break;
|
||||
default:
|
||||
WARN(1, "Invalid sta notify: %d\n", cmd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -958,6 +976,8 @@ static struct ieee80211_ops mac80211_hwsim_ops =
|
||||
.config = mac80211_hwsim_config,
|
||||
.configure_filter = mac80211_hwsim_configure_filter,
|
||||
.bss_info_changed = mac80211_hwsim_bss_info_changed,
|
||||
.sta_add = mac80211_hwsim_sta_add,
|
||||
.sta_remove = mac80211_hwsim_sta_remove,
|
||||
.sta_notify = mac80211_hwsim_sta_notify,
|
||||
.set_tim = mac80211_hwsim_set_tim,
|
||||
.conf_tx = mac80211_hwsim_conf_tx,
|
||||
|
@ -188,10 +188,6 @@ struct mwl8k_priv {
|
||||
bool sniffer_enabled;
|
||||
bool wmm_enabled;
|
||||
|
||||
struct work_struct sta_notify_worker;
|
||||
spinlock_t sta_notify_list_lock;
|
||||
struct list_head sta_notify_list;
|
||||
|
||||
/* XXX need to convert this to handle multiple interfaces */
|
||||
bool capture_beacon;
|
||||
u8 capture_bssid[ETH_ALEN];
|
||||
@ -3706,90 +3702,36 @@ static int mwl8k_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
|
||||
return mwl8k_cmd_set_rts_threshold(hw, value);
|
||||
}
|
||||
|
||||
struct mwl8k_sta_notify_item
|
||||
{
|
||||
struct list_head list;
|
||||
struct ieee80211_vif *vif;
|
||||
enum sta_notify_cmd cmd;
|
||||
struct ieee80211_sta sta;
|
||||
};
|
||||
|
||||
static void
|
||||
mwl8k_do_sta_notify(struct ieee80211_hw *hw, struct mwl8k_sta_notify_item *s)
|
||||
static int mwl8k_sta_remove(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
struct mwl8k_priv *priv = hw->priv;
|
||||
|
||||
/*
|
||||
* STA firmware uses UPDATE_STADB, AP firmware uses SET_NEW_STN.
|
||||
*/
|
||||
if (!priv->ap_fw && s->cmd == STA_NOTIFY_ADD) {
|
||||
int rc;
|
||||
if (priv->ap_fw)
|
||||
return mwl8k_cmd_set_new_stn_del(hw, vif, sta->addr);
|
||||
else
|
||||
return mwl8k_cmd_update_stadb_del(hw, vif, sta->addr);
|
||||
}
|
||||
|
||||
rc = mwl8k_cmd_update_stadb_add(hw, s->vif, &s->sta);
|
||||
if (rc >= 0) {
|
||||
struct ieee80211_sta *sta;
|
||||
static int mwl8k_sta_add(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
struct mwl8k_priv *priv = hw->priv;
|
||||
int ret;
|
||||
|
||||
rcu_read_lock();
|
||||
sta = ieee80211_find_sta(s->vif, s->sta.addr);
|
||||
if (sta != NULL)
|
||||
MWL8K_STA(sta)->peer_id = rc;
|
||||
rcu_read_unlock();
|
||||
if (!priv->ap_fw) {
|
||||
ret = mwl8k_cmd_update_stadb_add(hw, vif, sta);
|
||||
if (ret >= 0) {
|
||||
MWL8K_STA(sta)->peer_id = ret;
|
||||
return 0;
|
||||
}
|
||||
} else if (!priv->ap_fw && s->cmd == STA_NOTIFY_REMOVE) {
|
||||
mwl8k_cmd_update_stadb_del(hw, s->vif, s->sta.addr);
|
||||
} else if (priv->ap_fw && s->cmd == STA_NOTIFY_ADD) {
|
||||
mwl8k_cmd_set_new_stn_add(hw, s->vif, &s->sta);
|
||||
} else if (priv->ap_fw && s->cmd == STA_NOTIFY_REMOVE) {
|
||||
mwl8k_cmd_set_new_stn_del(hw, s->vif, s->sta.addr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
static void mwl8k_sta_notify_worker(struct work_struct *work)
|
||||
{
|
||||
struct mwl8k_priv *priv =
|
||||
container_of(work, struct mwl8k_priv, sta_notify_worker);
|
||||
struct ieee80211_hw *hw = priv->hw;
|
||||
|
||||
spin_lock_bh(&priv->sta_notify_list_lock);
|
||||
while (!list_empty(&priv->sta_notify_list)) {
|
||||
struct mwl8k_sta_notify_item *s;
|
||||
|
||||
s = list_entry(priv->sta_notify_list.next,
|
||||
struct mwl8k_sta_notify_item, list);
|
||||
list_del(&s->list);
|
||||
|
||||
spin_unlock_bh(&priv->sta_notify_list_lock);
|
||||
|
||||
mwl8k_do_sta_notify(hw, s);
|
||||
kfree(s);
|
||||
|
||||
spin_lock_bh(&priv->sta_notify_list_lock);
|
||||
}
|
||||
spin_unlock_bh(&priv->sta_notify_list_lock);
|
||||
}
|
||||
|
||||
static void
|
||||
mwl8k_sta_notify(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
enum sta_notify_cmd cmd, struct ieee80211_sta *sta)
|
||||
{
|
||||
struct mwl8k_priv *priv = hw->priv;
|
||||
struct mwl8k_sta_notify_item *s;
|
||||
|
||||
if (cmd != STA_NOTIFY_ADD && cmd != STA_NOTIFY_REMOVE)
|
||||
return;
|
||||
|
||||
s = kmalloc(sizeof(*s), GFP_ATOMIC);
|
||||
if (s != NULL) {
|
||||
s->vif = vif;
|
||||
s->cmd = cmd;
|
||||
s->sta = *sta;
|
||||
|
||||
spin_lock(&priv->sta_notify_list_lock);
|
||||
list_add_tail(&s->list, &priv->sta_notify_list);
|
||||
spin_unlock(&priv->sta_notify_list_lock);
|
||||
|
||||
ieee80211_queue_work(hw, &priv->sta_notify_worker);
|
||||
}
|
||||
return mwl8k_cmd_set_new_stn_add(hw, vif, sta);
|
||||
}
|
||||
|
||||
static int mwl8k_conf_tx(struct ieee80211_hw *hw, u16 queue,
|
||||
@ -3849,7 +3791,8 @@ static const struct ieee80211_ops mwl8k_ops = {
|
||||
.prepare_multicast = mwl8k_prepare_multicast,
|
||||
.configure_filter = mwl8k_configure_filter,
|
||||
.set_rts_threshold = mwl8k_set_rts_threshold,
|
||||
.sta_notify = mwl8k_sta_notify,
|
||||
.sta_add = mwl8k_sta_add,
|
||||
.sta_remove = mwl8k_sta_remove,
|
||||
.conf_tx = mwl8k_conf_tx,
|
||||
.get_stats = mwl8k_get_stats,
|
||||
.ampdu_action = mwl8k_ampdu_action,
|
||||
@ -4051,11 +3994,6 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
|
||||
priv->radio_on = 0;
|
||||
priv->radio_short_preamble = 0;
|
||||
|
||||
/* Station database handling */
|
||||
INIT_WORK(&priv->sta_notify_worker, mwl8k_sta_notify_worker);
|
||||
spin_lock_init(&priv->sta_notify_list_lock);
|
||||
INIT_LIST_HEAD(&priv->sta_notify_list);
|
||||
|
||||
/* Finalize join worker */
|
||||
INIT_WORK(&priv->finalize_join_worker, mwl8k_finalize_join_worker);
|
||||
|
||||
|
@ -407,7 +407,6 @@ static struct pcmcia_device_id orinoco_cs_ids[] = {
|
||||
PCMCIA_DEVICE_PROD_ID12("3Com", "3CRWE737A AirConnect Wireless LAN PC Card", 0x41240e5b, 0x56010af3),
|
||||
PCMCIA_DEVICE_PROD_ID12("ACTIONTEC", "PRISM Wireless LAN PC Card", 0x393089da, 0xa71e69d5),
|
||||
PCMCIA_DEVICE_PROD_ID12("Addtron", "AWP-100 Wireless PCMCIA", 0xe6ec52ce, 0x08649af2),
|
||||
PCMCIA_DEVICE_PROD_ID123("AIRVAST", "IEEE 802.11b Wireless PCMCIA Card", "HFA3863", 0xea569531, 0x4bcb9645, 0x355cb092),
|
||||
PCMCIA_DEVICE_PROD_ID12("Allied Telesyn", "AT-WCL452 Wireless PCMCIA Radio", 0x5cd01705, 0x4271660f),
|
||||
PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11b_PC_CARD_25", 0x78fc06ee, 0xdb9aa842),
|
||||
PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11B_CF_CARD_25", 0x78fc06ee, 0x45a50c1e),
|
||||
@ -417,7 +416,6 @@ static struct pcmcia_device_id orinoco_cs_ids[] = {
|
||||
PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-CF-S11G", 0x2decece3, 0x82067c18),
|
||||
PCMCIA_DEVICE_PROD_ID12("Cabletron", "RoamAbout 802.11 DS", 0x32d445f5, 0xedeffd90),
|
||||
PCMCIA_DEVICE_PROD_ID12("Compaq", "WL200_11Mbps_Wireless_PCI_Card", 0x54f7c49c, 0x15a75e5b),
|
||||
PCMCIA_DEVICE_PROD_ID123("corega", "WL PCCL-11", "ISL37300P", 0x0a21501a, 0x59868926, 0xc9049a39),
|
||||
PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCC-11", 0x5261440f, 0xa6405584),
|
||||
PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCCA-11", 0x5261440f, 0xdf6115f9),
|
||||
PCMCIA_DEVICE_PROD_ID12("corega_K.K.", "Wireless_LAN_PCCB-11", 0x29e33311, 0xee7a27ae),
|
||||
@ -432,7 +430,6 @@ static struct pcmcia_device_id orinoco_cs_ids[] = {
|
||||
PCMCIA_DEVICE_PROD_ID12("INTERSIL", "HFA384x/IEEE", 0x74c5e40d, 0xdb472a18),
|
||||
PCMCIA_DEVICE_PROD_ID12("INTERSIL", "I-GATE 11M PC Card / PC Card plus", 0x74c5e40d, 0x8304ff77),
|
||||
PCMCIA_DEVICE_PROD_ID12("Intersil", "PRISM 2_5 PCMCIA ADAPTER", 0x4b801a17, 0x6345a0bf),
|
||||
PCMCIA_DEVICE_PROD_ID123("Intersil", "PRISM Freedom PCMCIA Adapter", "ISL37100P", 0x4b801a17, 0xf222ec2d, 0x630d52b2),
|
||||
PCMCIA_DEVICE_PROD_ID12("LeArtery", "SYNCBYAIR 11Mbps Wireless LAN PC Card", 0x7e3b326a, 0x49893e92),
|
||||
PCMCIA_DEVICE_PROD_ID12("Linksys", "Wireless CompactFlash Card", 0x0733cc81, 0x0c52f395),
|
||||
PCMCIA_DEVICE_PROD_ID12("Lucent Technologies", "WaveLAN/IEEE", 0x23eb9949, 0xc562e72a),
|
||||
@ -445,7 +442,6 @@ static struct pcmcia_device_id orinoco_cs_ids[] = {
|
||||
PCMCIA_DEVICE_PROD_ID12("Nortel Networks", "emobility 802.11 Wireless LAN PC Card", 0x2d617ea0, 0x88cd5767),
|
||||
PCMCIA_DEVICE_PROD_ID12("OEM", "PRISM2 IEEE 802.11 PC-Card", 0xfea54c90, 0x48f2bdd6),
|
||||
PCMCIA_DEVICE_PROD_ID12("OTC", "Wireless AirEZY 2411-PCC WLAN Card", 0x4ac44287, 0x235a6bed),
|
||||
PCMCIA_DEVICE_PROD_ID123("PCMCIA", "11M WLAN Card v2.5", "ISL37300P", 0x281f1c5d, 0x6e440487, 0xc9049a39),
|
||||
PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-CF110", 0x209f40ab, 0xd9715264),
|
||||
PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-NS110", 0x209f40ab, 0x46263178),
|
||||
PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PC CARD HARMONY 80211B", 0xc6536a5e, 0x090c3cd9),
|
||||
@ -454,8 +450,11 @@ static struct pcmcia_device_id orinoco_cs_ids[] = {
|
||||
PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2532W-B EliteConnect Wireless Adapter", 0xc4f8b18b, 0x196bd757),
|
||||
PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2632W", 0xc4f8b18b, 0x474a1f2a),
|
||||
PCMCIA_DEVICE_PROD_ID12("Symbol Technologies", "LA4111 Spectrum24 Wireless LAN PC Card", 0x3f02b4d6, 0x3663cb0e),
|
||||
PCMCIA_DEVICE_PROD_ID123("The Linksys Group, Inc.", "Instant Wireless Network PC Card", "ISL37300P", 0xa5f472c2, 0x590eb502, 0xc9049a39),
|
||||
PCMCIA_DEVICE_PROD_ID12("ZoomAir 11Mbps High", "Rate wireless Networking", 0x273fe3db, 0x32a1eaee),
|
||||
PCMCIA_DEVICE_PROD_ID3("HFA3863", 0x355cb092),
|
||||
PCMCIA_DEVICE_PROD_ID3("ISL37100P", 0x630d52b2),
|
||||
PCMCIA_DEVICE_PROD_ID3("ISL37101P-10", 0xdd97a26b),
|
||||
PCMCIA_DEVICE_PROD_ID3("ISL37300P", 0xc9049a39),
|
||||
PCMCIA_DEVICE_NULL,
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pcmcia, orinoco_cs_ids);
|
||||
|
@ -33,21 +33,29 @@ MODULE_DESCRIPTION("Softmac Prism54 common code");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("prism54common");
|
||||
|
||||
static int p54_sta_add_remove(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
struct p54_common *priv = hw->priv;
|
||||
|
||||
/*
|
||||
* Notify the firmware that we don't want or we don't
|
||||
* need to buffer frames for this station anymore.
|
||||
*/
|
||||
|
||||
p54_sta_unlock(priv, sta->addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void p54_sta_notify(struct ieee80211_hw *dev, struct ieee80211_vif *vif,
|
||||
enum sta_notify_cmd notify_cmd,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
struct p54_common *priv = dev->priv;
|
||||
switch (notify_cmd) {
|
||||
case STA_NOTIFY_ADD:
|
||||
case STA_NOTIFY_REMOVE:
|
||||
/*
|
||||
* Notify the firmware that we don't want or we don't
|
||||
* need to buffer frames for this station anymore.
|
||||
*/
|
||||
|
||||
p54_sta_unlock(priv, sta->addr);
|
||||
break;
|
||||
switch (notify_cmd) {
|
||||
case STA_NOTIFY_AWAKE:
|
||||
/* update the firmware's filter table */
|
||||
p54_sta_unlock(priv, sta->addr);
|
||||
@ -506,6 +514,8 @@ static const struct ieee80211_ops p54_ops = {
|
||||
.remove_interface = p54_remove_interface,
|
||||
.set_tim = p54_set_tim,
|
||||
.sta_notify = p54_sta_notify,
|
||||
.sta_add = p54_sta_add_remove,
|
||||
.sta_remove = p54_sta_add_remove,
|
||||
.set_key = p54_set_key,
|
||||
.config = p54_config,
|
||||
.bss_info_changed = p54_bss_info_changed,
|
||||
|
@ -36,6 +36,7 @@ static struct usb_device_id p54u_table[] __devinitdata = {
|
||||
/* Version 1 devices (pci chip + net2280) */
|
||||
{USB_DEVICE(0x0506, 0x0a11)}, /* 3COM 3CRWE254G72 */
|
||||
{USB_DEVICE(0x0707, 0xee06)}, /* SMC 2862W-G */
|
||||
{USB_DEVICE(0x07aa, 0x001c)}, /* Corega CG-WLUSB2GT */
|
||||
{USB_DEVICE(0x083a, 0x4501)}, /* Accton 802.11g WN4501 USB */
|
||||
{USB_DEVICE(0x083a, 0x4502)}, /* Siemens Gigaset USB Adapter */
|
||||
{USB_DEVICE(0x083a, 0x5501)}, /* Phillips CPWUA054 */
|
||||
@ -60,6 +61,7 @@ static struct usb_device_id p54u_table[] __devinitdata = {
|
||||
{USB_DEVICE(0x06b9, 0x0121)}, /* Thomson SpeedTouch 121g */
|
||||
{USB_DEVICE(0x0707, 0xee13)}, /* SMC 2862W-G version 2 */
|
||||
{USB_DEVICE(0x083a, 0x4521)}, /* Siemens Gigaset USB Adapter 54 version 2 */
|
||||
{USB_DEVICE(0x083a, 0xf503)}, /* Accton FD7050E ver 1010ec */
|
||||
{USB_DEVICE(0x0846, 0x4240)}, /* Netgear WG111 (v2) */
|
||||
{USB_DEVICE(0x0915, 0x2000)}, /* Cohiba Proto board */
|
||||
{USB_DEVICE(0x0915, 0x2002)}, /* Cohiba Proto board */
|
||||
|
@ -186,7 +186,7 @@ static int p54_tx_qos_accounting_alloc(struct p54_common *priv,
|
||||
struct p54_tx_queue_stats *queue;
|
||||
unsigned long flags;
|
||||
|
||||
if (WARN_ON(p54_queue > P54_QUEUE_NUM))
|
||||
if (WARN_ON(p54_queue >= P54_QUEUE_NUM))
|
||||
return -EINVAL;
|
||||
|
||||
queue = &priv->tx_stats[p54_queue];
|
||||
|
@ -64,7 +64,7 @@ config RT2800PCI_SOC
|
||||
default y
|
||||
|
||||
config RT2800PCI
|
||||
tristate "Ralink rt2800 (PCI/PCMCIA) support (VERY EXPERIMENTAL)"
|
||||
tristate "Ralink rt28xx/rt30xx/rt35xx (PCI/PCIe/PCMCIA) support (EXPERIMENTAL)"
|
||||
depends on (RT2800PCI_PCI || RT2800PCI_SOC) && EXPERIMENTAL
|
||||
select RT2800_LIB
|
||||
select RT2X00_LIB_PCI if RT2800PCI_PCI
|
||||
@ -75,7 +75,7 @@ config RT2800PCI
|
||||
select CRC_CCITT
|
||||
select EEPROM_93CX6
|
||||
---help---
|
||||
This adds support for rt2800 wireless chipset family.
|
||||
This adds support for rt2800/rt3000/rt3500 wireless chipset family.
|
||||
Supported chips: RT2760, RT2790, RT2860, RT2880, RT2890 & RT3052
|
||||
|
||||
This driver is non-functional at the moment and is intended for
|
||||
@ -83,6 +83,32 @@ config RT2800PCI
|
||||
|
||||
When compiled as a module, this driver will be called "rt2800pci.ko".
|
||||
|
||||
if RT2800PCI
|
||||
|
||||
config RT2800PCI_RT30XX
|
||||
bool "rt2800pci - Include support for rt30xx (PCI/PCIe/PCMCIA) devices"
|
||||
default n
|
||||
---help---
|
||||
This adds support for rt30xx wireless chipset family to the
|
||||
rt2800pci driver.
|
||||
Supported chips: RT3090, RT3091 & RT3092
|
||||
|
||||
Support for these devices is non-functional at the moment and is
|
||||
intended for testers and developers.
|
||||
|
||||
config RT2800PCI_RT35XX
|
||||
bool "rt2800pci - Include support for rt35xx (PCI/PCIe/PCMCIA) devices"
|
||||
default n
|
||||
---help---
|
||||
This adds support for rt35xx wireless chipset family to the
|
||||
rt2800pci driver.
|
||||
Supported chips: RT3060, RT3062, RT3562, RT3592
|
||||
|
||||
Support for these devices is non-functional at the moment and is
|
||||
intended for testers and developers.
|
||||
|
||||
endif
|
||||
|
||||
config RT2500USB
|
||||
tristate "Ralink rt2500 (USB) support"
|
||||
depends on USB
|
||||
@ -126,6 +152,43 @@ config RT2800USB
|
||||
|
||||
When compiled as a module, this driver will be called "rt2800usb.ko".
|
||||
|
||||
if RT2800USB
|
||||
|
||||
config RT2800USB_RT30XX
|
||||
bool "rt2800usb - Include support for rt30xx (USB) devices"
|
||||
default n
|
||||
---help---
|
||||
This adds support for rt30xx wireless chipset family to the
|
||||
rt2800usb driver.
|
||||
Supported chips: RT3070, RT3071 & RT3072
|
||||
|
||||
Support for these devices is non-functional at the moment and is
|
||||
intended for testers and developers.
|
||||
|
||||
config RT2800USB_RT35XX
|
||||
bool "rt2800usb - Include support for rt35xx (USB) devices"
|
||||
default n
|
||||
---help---
|
||||
This adds support for rt35xx wireless chipset family to the
|
||||
rt2800usb driver.
|
||||
Supported chips: RT3572
|
||||
|
||||
Support for these devices is non-functional at the moment and is
|
||||
intended for testers and developers.
|
||||
|
||||
config RT2800USB_UNKNOWN
|
||||
bool "rt2800usb - Include support for unknown (USB) devices"
|
||||
default n
|
||||
---help---
|
||||
This adds support for rt2800 family devices that are known to
|
||||
have a rt2800 family chipset, but for which the exact chipset
|
||||
is unknown.
|
||||
|
||||
Support status for these devices is unknown, and enabling these
|
||||
devices may or may not work.
|
||||
|
||||
endif
|
||||
|
||||
config RT2800_LIB
|
||||
tristate
|
||||
|
||||
|
@ -1340,8 +1340,8 @@ static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
|
||||
*/
|
||||
value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
|
||||
rt2x00pci_register_read(rt2x00dev, CSR0, ®);
|
||||
rt2x00_set_chip_rf(rt2x00dev, value, reg);
|
||||
rt2x00_print_chip(rt2x00dev);
|
||||
rt2x00_set_chip(rt2x00dev, RT2460, value,
|
||||
rt2x00_get_field32(reg, CSR0_REVISION));
|
||||
|
||||
if (!rt2x00_rf(rt2x00dev, RF2420) && !rt2x00_rf(rt2x00dev, RF2421)) {
|
||||
ERROR(rt2x00dev, "Invalid RF chipset detected.\n");
|
||||
|
@ -65,6 +65,7 @@
|
||||
* CSR0: ASIC revision number.
|
||||
*/
|
||||
#define CSR0 0x0000
|
||||
#define CSR0_REVISION FIELD32(0x0000ffff)
|
||||
|
||||
/*
|
||||
* CSR1: System control register.
|
||||
|
@ -1503,8 +1503,8 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
|
||||
*/
|
||||
value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
|
||||
rt2x00pci_register_read(rt2x00dev, CSR0, ®);
|
||||
rt2x00_set_chip_rf(rt2x00dev, value, reg);
|
||||
rt2x00_print_chip(rt2x00dev);
|
||||
rt2x00_set_chip(rt2x00dev, RT2560, value,
|
||||
rt2x00_get_field32(reg, CSR0_REVISION));
|
||||
|
||||
if (!rt2x00_rf(rt2x00dev, RF2522) &&
|
||||
!rt2x00_rf(rt2x00dev, RF2523) &&
|
||||
|
@ -76,6 +76,7 @@
|
||||
* CSR0: ASIC revision number.
|
||||
*/
|
||||
#define CSR0 0x0000
|
||||
#define CSR0_REVISION FIELD32(0x0000ffff)
|
||||
|
||||
/*
|
||||
* CSR1: System control register.
|
||||
|
@ -1408,10 +1408,8 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
|
||||
value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
|
||||
rt2500usb_register_read(rt2x00dev, MAC_CSR0, ®);
|
||||
rt2x00_set_chip(rt2x00dev, RT2570, value, reg);
|
||||
rt2x00_print_chip(rt2x00dev);
|
||||
|
||||
if (!rt2x00_check_rev(rt2x00dev, 0x000ffff0, 0) ||
|
||||
rt2x00_check_rev(rt2x00dev, 0x0000000f, 0)) {
|
||||
if (((reg & 0xfff0) != 0) || ((reg & 0x0000000f) == 0)) {
|
||||
ERROR(rt2x00dev, "Invalid RT chipset detected.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
@ -60,11 +60,11 @@
|
||||
/*
|
||||
* Chipset version.
|
||||
*/
|
||||
#define RT2860C_VERSION 0x28600100
|
||||
#define RT2860D_VERSION 0x28600101
|
||||
#define RT2880E_VERSION 0x28720200
|
||||
#define RT2883_VERSION 0x28830300
|
||||
#define RT3070_VERSION 0x30700200
|
||||
#define RT2860C_VERSION 0x0100
|
||||
#define RT2860D_VERSION 0x0101
|
||||
#define RT2880E_VERSION 0x0200
|
||||
#define RT2883_VERSION 0x0300
|
||||
#define RT3070_VERSION 0x0200
|
||||
|
||||
/*
|
||||
* Signal information.
|
||||
@ -408,8 +408,8 @@
|
||||
* ASIC_VER: 2860 or 2870
|
||||
*/
|
||||
#define MAC_CSR0 0x1000
|
||||
#define MAC_CSR0_ASIC_REV FIELD32(0x0000ffff)
|
||||
#define MAC_CSR0_ASIC_VER FIELD32(0xffff0000)
|
||||
#define MAC_CSR0_REVISION FIELD32(0x0000ffff)
|
||||
#define MAC_CSR0_CHIPSET FIELD32(0xffff0000)
|
||||
|
||||
/*
|
||||
* MAC_SYS_CTRL:
|
||||
|
@ -40,6 +40,9 @@
|
||||
#if defined(CONFIG_RT2X00_LIB_USB) || defined(CONFIG_RT2X00_LIB_USB_MODULE)
|
||||
#include "rt2x00usb.h"
|
||||
#endif
|
||||
#if defined(CONFIG_RT2X00_LIB_PCI) || defined(CONFIG_RT2X00_LIB_PCI_MODULE)
|
||||
#include "rt2x00pci.h"
|
||||
#endif
|
||||
#include "rt2800lib.h"
|
||||
#include "rt2800.h"
|
||||
#include "rt2800usb.h"
|
||||
@ -89,7 +92,7 @@ static void rt2800_bbp_write(struct rt2x00_dev *rt2x00dev,
|
||||
rt2x00_set_field32(®, BBP_CSR_CFG_REGNUM, word);
|
||||
rt2x00_set_field32(®, BBP_CSR_CFG_BUSY, 1);
|
||||
rt2x00_set_field32(®, BBP_CSR_CFG_READ_CONTROL, 0);
|
||||
if (rt2x00_intf_is_pci(rt2x00dev))
|
||||
if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev))
|
||||
rt2x00_set_field32(®, BBP_CSR_CFG_BBP_RW_MODE, 1);
|
||||
|
||||
rt2800_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg);
|
||||
@ -118,7 +121,7 @@ static void rt2800_bbp_read(struct rt2x00_dev *rt2x00dev,
|
||||
rt2x00_set_field32(®, BBP_CSR_CFG_REGNUM, word);
|
||||
rt2x00_set_field32(®, BBP_CSR_CFG_BUSY, 1);
|
||||
rt2x00_set_field32(®, BBP_CSR_CFG_READ_CONTROL, 1);
|
||||
if (rt2x00_intf_is_pci(rt2x00dev))
|
||||
if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev))
|
||||
rt2x00_set_field32(®, BBP_CSR_CFG_BBP_RW_MODE, 1);
|
||||
|
||||
rt2800_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg);
|
||||
@ -218,9 +221,9 @@ void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev,
|
||||
u32 reg;
|
||||
|
||||
/*
|
||||
* RT2880 and RT3052 don't support MCU requests.
|
||||
* SOC devices don't support MCU requests.
|
||||
*/
|
||||
if (rt2x00_rt(rt2x00dev, RT2880) || rt2x00_rt(rt2x00dev, RT3052))
|
||||
if (rt2x00_is_soc(rt2x00dev))
|
||||
return;
|
||||
|
||||
mutex_lock(&rt2x00dev->csr_mutex);
|
||||
@ -660,7 +663,7 @@ void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant)
|
||||
switch ((int)ant->tx) {
|
||||
case 1:
|
||||
rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0);
|
||||
if (rt2x00_intf_is_pci(rt2x00dev))
|
||||
if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev))
|
||||
rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 0);
|
||||
break;
|
||||
case 2:
|
||||
@ -895,7 +898,8 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
|
||||
rt2x00_set_field8(&bbp, BBP3_HT40_PLUS, conf_is_ht40_plus(conf));
|
||||
rt2800_bbp_write(rt2x00dev, 3, bbp);
|
||||
|
||||
if (rt2x00_rev(rt2x00dev) == RT2860C_VERSION) {
|
||||
if (rt2x00_rt(rt2x00dev, RT2860) &&
|
||||
(rt2x00_rev(rt2x00dev) == RT2860C_VERSION)) {
|
||||
if (conf_is_ht40(conf)) {
|
||||
rt2800_bbp_write(rt2x00dev, 69, 0x1a);
|
||||
rt2800_bbp_write(rt2x00dev, 70, 0x0a);
|
||||
@ -1057,8 +1061,9 @@ EXPORT_SYMBOL_GPL(rt2800_link_stats);
|
||||
static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) {
|
||||
if (rt2x00_intf_is_usb(rt2x00dev) &&
|
||||
rt2x00_rev(rt2x00dev) == RT3070_VERSION)
|
||||
if (rt2x00_is_usb(rt2x00dev) &&
|
||||
rt2x00_rt(rt2x00dev, RT3070) &&
|
||||
(rt2x00_rev(rt2x00dev) == RT3070_VERSION))
|
||||
return 0x1c + (2 * rt2x00dev->lna_gain);
|
||||
else
|
||||
return 0x2e + rt2x00dev->lna_gain;
|
||||
@ -1089,7 +1094,8 @@ EXPORT_SYMBOL_GPL(rt2800_reset_tuner);
|
||||
void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual,
|
||||
const u32 count)
|
||||
{
|
||||
if (rt2x00_rev(rt2x00dev) == RT2860C_VERSION)
|
||||
if (rt2x00_rt(rt2x00dev, RT2860) &&
|
||||
(rt2x00_rev(rt2x00dev) == RT2860C_VERSION))
|
||||
return;
|
||||
|
||||
/*
|
||||
@ -1109,7 +1115,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
|
||||
u32 reg;
|
||||
unsigned int i;
|
||||
|
||||
if (rt2x00_intf_is_usb(rt2x00dev)) {
|
||||
if (rt2x00_is_usb(rt2x00dev)) {
|
||||
/*
|
||||
* Wait until BBP and RF are ready.
|
||||
*/
|
||||
@ -1128,7 +1134,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
|
||||
rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, ®);
|
||||
rt2800_register_write(rt2x00dev, PBF_SYS_CTRL,
|
||||
reg & ~0x00002000);
|
||||
} else if (rt2x00_intf_is_pci(rt2x00dev))
|
||||
} else if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev))
|
||||
rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003);
|
||||
|
||||
rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, ®);
|
||||
@ -1136,7 +1142,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
|
||||
rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_BBP, 1);
|
||||
rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
|
||||
|
||||
if (rt2x00_intf_is_usb(rt2x00dev)) {
|
||||
if (rt2x00_is_usb(rt2x00dev)) {
|
||||
rt2800_register_write(rt2x00dev, USB_DMA_CFG, 0x00000000);
|
||||
#if defined(CONFIG_RT2X00_LIB_USB) || defined(CONFIG_RT2X00_LIB_USB_MODULE)
|
||||
rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0,
|
||||
@ -1174,8 +1180,9 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
|
||||
rt2x00_set_field32(®, BCN_TIME_CFG_TX_TIME_COMPENSATE, 0);
|
||||
rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
|
||||
|
||||
if (rt2x00_intf_is_usb(rt2x00dev) &&
|
||||
rt2x00_rev(rt2x00dev) == RT3070_VERSION) {
|
||||
if (rt2x00_is_usb(rt2x00dev) &&
|
||||
rt2x00_rt(rt2x00dev, RT3070) &&
|
||||
(rt2x00_rev(rt2x00dev) == RT3070_VERSION)) {
|
||||
rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);
|
||||
rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
|
||||
rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000);
|
||||
@ -1202,8 +1209,14 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
|
||||
|
||||
rt2800_register_read(rt2x00dev, MAX_LEN_CFG, ®);
|
||||
rt2x00_set_field32(®, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE);
|
||||
if (rt2x00_rev(rt2x00dev) >= RT2880E_VERSION &&
|
||||
rt2x00_rev(rt2x00dev) < RT3070_VERSION)
|
||||
if ((rt2x00_rt(rt2x00dev, RT2872) &&
|
||||
(rt2x00_rev(rt2x00dev) >= RT2880E_VERSION)) ||
|
||||
rt2x00_rt(rt2x00dev, RT2880) ||
|
||||
rt2x00_rt(rt2x00dev, RT2883) ||
|
||||
rt2x00_rt(rt2x00dev, RT2890) ||
|
||||
rt2x00_rt(rt2x00dev, RT3052) ||
|
||||
(rt2x00_rt(rt2x00dev, RT3070) &&
|
||||
(rt2x00_rev(rt2x00dev) < RT3070_VERSION)))
|
||||
rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 2);
|
||||
else
|
||||
rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 1);
|
||||
@ -1293,7 +1306,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
|
||||
rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_GF40, 1);
|
||||
rt2800_register_write(rt2x00dev, GF40_PROT_CFG, reg);
|
||||
|
||||
if (rt2x00_intf_is_usb(rt2x00dev)) {
|
||||
if (rt2x00_is_usb(rt2x00dev)) {
|
||||
rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40006);
|
||||
|
||||
rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®);
|
||||
@ -1353,7 +1366,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
|
||||
rt2800_register_write(rt2x00dev, HW_BEACON_BASE6, 0);
|
||||
rt2800_register_write(rt2x00dev, HW_BEACON_BASE7, 0);
|
||||
|
||||
if (rt2x00_intf_is_usb(rt2x00dev)) {
|
||||
if (rt2x00_is_usb(rt2x00dev)) {
|
||||
rt2800_register_read(rt2x00dev, USB_CYC_CFG, ®);
|
||||
rt2x00_set_field32(®, USB_CYC_CFG_CLOCK_CYCLE, 30);
|
||||
rt2800_register_write(rt2x00dev, USB_CYC_CFG, reg);
|
||||
@ -1482,16 +1495,19 @@ int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
|
||||
rt2800_bbp_write(rt2x00dev, 103, 0x00);
|
||||
rt2800_bbp_write(rt2x00dev, 105, 0x05);
|
||||
|
||||
if (rt2x00_rev(rt2x00dev) == RT2860C_VERSION) {
|
||||
if (rt2x00_rt(rt2x00dev, RT2860) &&
|
||||
(rt2x00_rev(rt2x00dev) == RT2860C_VERSION)) {
|
||||
rt2800_bbp_write(rt2x00dev, 69, 0x16);
|
||||
rt2800_bbp_write(rt2x00dev, 73, 0x12);
|
||||
}
|
||||
|
||||
if (rt2x00_rev(rt2x00dev) > RT2860D_VERSION)
|
||||
if (rt2x00_rt(rt2x00dev, RT2860) &&
|
||||
(rt2x00_rev(rt2x00dev) > RT2860D_VERSION))
|
||||
rt2800_bbp_write(rt2x00dev, 84, 0x19);
|
||||
|
||||
if (rt2x00_intf_is_usb(rt2x00dev) &&
|
||||
rt2x00_rev(rt2x00dev) == RT3070_VERSION) {
|
||||
if (rt2x00_is_usb(rt2x00dev) &&
|
||||
rt2x00_rt(rt2x00dev, RT3070) &&
|
||||
(rt2x00_rev(rt2x00dev) == RT3070_VERSION)) {
|
||||
rt2800_bbp_write(rt2x00dev, 70, 0x0a);
|
||||
rt2800_bbp_write(rt2x00dev, 84, 0x99);
|
||||
rt2800_bbp_write(rt2x00dev, 105, 0x05);
|
||||
@ -1582,11 +1598,12 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
|
||||
u8 rfcsr;
|
||||
u8 bbp;
|
||||
|
||||
if (rt2x00_intf_is_usb(rt2x00dev) &&
|
||||
rt2x00_rev(rt2x00dev) != RT3070_VERSION)
|
||||
if (rt2x00_is_usb(rt2x00dev) &&
|
||||
rt2x00_rt(rt2x00dev, RT3070) &&
|
||||
(rt2x00_rev(rt2x00dev) != RT3070_VERSION))
|
||||
return 0;
|
||||
|
||||
if (rt2x00_intf_is_pci(rt2x00dev)) {
|
||||
if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev)) {
|
||||
if (!rt2x00_rf(rt2x00dev, RF3020) &&
|
||||
!rt2x00_rf(rt2x00dev, RF3021) &&
|
||||
!rt2x00_rf(rt2x00dev, RF3022))
|
||||
@ -1603,7 +1620,7 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
|
||||
rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 0);
|
||||
rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
|
||||
|
||||
if (rt2x00_intf_is_usb(rt2x00dev)) {
|
||||
if (rt2x00_is_usb(rt2x00dev)) {
|
||||
rt2800_rfcsr_write(rt2x00dev, 4, 0x40);
|
||||
rt2800_rfcsr_write(rt2x00dev, 5, 0x03);
|
||||
rt2800_rfcsr_write(rt2x00dev, 6, 0x02);
|
||||
@ -1624,7 +1641,7 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
|
||||
rt2800_rfcsr_write(rt2x00dev, 25, 0x01);
|
||||
rt2800_rfcsr_write(rt2x00dev, 27, 0x03);
|
||||
rt2800_rfcsr_write(rt2x00dev, 29, 0x1f);
|
||||
} else if (rt2x00_intf_is_pci(rt2x00dev)) {
|
||||
} else if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev)) {
|
||||
rt2800_rfcsr_write(rt2x00dev, 0, 0x50);
|
||||
rt2800_rfcsr_write(rt2x00dev, 1, 0x01);
|
||||
rt2800_rfcsr_write(rt2x00dev, 2, 0xf7);
|
||||
@ -1754,7 +1771,12 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
|
||||
rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2820);
|
||||
rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word);
|
||||
EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word);
|
||||
} else if (rt2x00_rev(rt2x00dev) < RT2883_VERSION) {
|
||||
} else if (rt2x00_rt(rt2x00dev, RT2860) ||
|
||||
rt2x00_rt(rt2x00dev, RT2870) ||
|
||||
rt2x00_rt(rt2x00dev, RT2872) ||
|
||||
rt2x00_rt(rt2x00dev, RT2880) ||
|
||||
(rt2x00_rt(rt2x00dev, RT2883) &&
|
||||
(rt2x00_rev(rt2x00dev) < RT2883_VERSION))) {
|
||||
/*
|
||||
* There is a max of 2 RX streams for RT28x0 series
|
||||
*/
|
||||
@ -1853,25 +1875,24 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
|
||||
value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
|
||||
rt2800_register_read(rt2x00dev, MAC_CSR0, ®);
|
||||
|
||||
rt2x00_set_chip_rf(rt2x00dev, value, reg);
|
||||
rt2x00_set_chip(rt2x00dev, rt2x00_get_field32(reg, MAC_CSR0_CHIPSET),
|
||||
value, rt2x00_get_field32(reg, MAC_CSR0_REVISION));
|
||||
|
||||
if (rt2x00_intf_is_usb(rt2x00dev)) {
|
||||
/*
|
||||
* The check for rt2860 is not a typo, some rt2870 hardware
|
||||
* identifies itself as rt2860 in the CSR register.
|
||||
*/
|
||||
if (rt2x00_check_rev(rt2x00dev, 0xfff00000, 0x28600000) ||
|
||||
rt2x00_check_rev(rt2x00dev, 0xfff00000, 0x28700000) ||
|
||||
rt2x00_check_rev(rt2x00dev, 0xfff00000, 0x28800000)) {
|
||||
rt2x00_set_chip_rt(rt2x00dev, RT2870);
|
||||
} else if (rt2x00_check_rev(rt2x00dev, 0xffff0000, 0x30700000)) {
|
||||
rt2x00_set_chip_rt(rt2x00dev, RT3070);
|
||||
} else {
|
||||
ERROR(rt2x00dev, "Invalid RT chipset detected.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
if (!rt2x00_rt(rt2x00dev, RT2860) &&
|
||||
!rt2x00_rt(rt2x00dev, RT2870) &&
|
||||
!rt2x00_rt(rt2x00dev, RT2872) &&
|
||||
!rt2x00_rt(rt2x00dev, RT2880) &&
|
||||
!rt2x00_rt(rt2x00dev, RT2883) &&
|
||||
!rt2x00_rt(rt2x00dev, RT2890) &&
|
||||
!rt2x00_rt(rt2x00dev, RT3052) &&
|
||||
!rt2x00_rt(rt2x00dev, RT3070) &&
|
||||
!rt2x00_rt(rt2x00dev, RT3071) &&
|
||||
!rt2x00_rt(rt2x00dev, RT3090) &&
|
||||
!rt2x00_rt(rt2x00dev, RT3390) &&
|
||||
!rt2x00_rt(rt2x00dev, RT3572)) {
|
||||
ERROR(rt2x00dev, "Invalid RT chipset detected.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
rt2x00_print_chip(rt2x00dev);
|
||||
|
||||
if (!rt2x00_rf(rt2x00dev, RF2820) &&
|
||||
!rt2x00_rf(rt2x00dev, RF2850) &&
|
||||
@ -2039,7 +2060,7 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
|
||||
/*
|
||||
* Disable powersaving as default on PCI devices.
|
||||
*/
|
||||
if (rt2x00_intf_is_pci(rt2x00dev))
|
||||
if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev))
|
||||
rt2x00dev->hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
|
||||
|
||||
/*
|
||||
|
@ -1041,18 +1041,12 @@ static int rt2800pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
|
||||
/*
|
||||
* Read EEPROM into buffer
|
||||
*/
|
||||
switch (rt2x00dev->chip.rt) {
|
||||
case RT2880:
|
||||
case RT3052:
|
||||
if (rt2x00_is_soc(rt2x00dev))
|
||||
rt2800pci_read_eeprom_soc(rt2x00dev);
|
||||
break;
|
||||
default:
|
||||
if (rt2800pci_efuse_detect(rt2x00dev))
|
||||
rt2800pci_read_eeprom_efuse(rt2x00dev);
|
||||
else
|
||||
rt2800pci_read_eeprom_pci(rt2x00dev);
|
||||
break;
|
||||
}
|
||||
else if (rt2800pci_efuse_detect(rt2x00dev))
|
||||
rt2800pci_read_eeprom_efuse(rt2x00dev);
|
||||
else
|
||||
rt2800pci_read_eeprom_pci(rt2x00dev);
|
||||
|
||||
return rt2800_validate_eeprom(rt2x00dev);
|
||||
}
|
||||
@ -1103,7 +1097,7 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)
|
||||
/*
|
||||
* This device requires firmware.
|
||||
*/
|
||||
if (!rt2x00_rt(rt2x00dev, RT2880) && !rt2x00_rt(rt2x00dev, RT3052))
|
||||
if (!rt2x00_is_soc(rt2x00dev))
|
||||
__set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
|
||||
__set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags);
|
||||
__set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags);
|
||||
@ -1191,7 +1185,10 @@ static const struct rt2x00_ops rt2800pci_ops = {
|
||||
* RT2800pci module information.
|
||||
*/
|
||||
static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = {
|
||||
{ PCI_DEVICE(0x1462, 0x891a), PCI_DEVICE_DATA(&rt2800pci_ops) },
|
||||
{ PCI_DEVICE(0x1814, 0x0601), PCI_DEVICE_DATA(&rt2800pci_ops) },
|
||||
{ PCI_DEVICE(0x1814, 0x0681), PCI_DEVICE_DATA(&rt2800pci_ops) },
|
||||
{ PCI_DEVICE(0x1814, 0x0701), PCI_DEVICE_DATA(&rt2800pci_ops) },
|
||||
{ PCI_DEVICE(0x1814, 0x0781), PCI_DEVICE_DATA(&rt2800pci_ops) },
|
||||
{ PCI_DEVICE(0x1432, 0x7708), PCI_DEVICE_DATA(&rt2800pci_ops) },
|
||||
{ PCI_DEVICE(0x1432, 0x7727), PCI_DEVICE_DATA(&rt2800pci_ops) },
|
||||
{ PCI_DEVICE(0x1432, 0x7728), PCI_DEVICE_DATA(&rt2800pci_ops) },
|
||||
@ -1199,18 +1196,19 @@ static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = {
|
||||
{ PCI_DEVICE(0x1432, 0x7748), PCI_DEVICE_DATA(&rt2800pci_ops) },
|
||||
{ PCI_DEVICE(0x1432, 0x7758), PCI_DEVICE_DATA(&rt2800pci_ops) },
|
||||
{ PCI_DEVICE(0x1432, 0x7768), PCI_DEVICE_DATA(&rt2800pci_ops) },
|
||||
{ PCI_DEVICE(0x1814, 0x0601), PCI_DEVICE_DATA(&rt2800pci_ops) },
|
||||
{ PCI_DEVICE(0x1814, 0x0681), PCI_DEVICE_DATA(&rt2800pci_ops) },
|
||||
{ PCI_DEVICE(0x1814, 0x0701), PCI_DEVICE_DATA(&rt2800pci_ops) },
|
||||
{ PCI_DEVICE(0x1814, 0x0781), PCI_DEVICE_DATA(&rt2800pci_ops) },
|
||||
{ PCI_DEVICE(0x1814, 0x3060), PCI_DEVICE_DATA(&rt2800pci_ops) },
|
||||
{ PCI_DEVICE(0x1814, 0x3062), PCI_DEVICE_DATA(&rt2800pci_ops) },
|
||||
{ PCI_DEVICE(0x1a3b, 0x1059), PCI_DEVICE_DATA(&rt2800pci_ops) },
|
||||
#ifdef CONFIG_RT2800PCI_RT30XX
|
||||
{ PCI_DEVICE(0x1814, 0x3090), PCI_DEVICE_DATA(&rt2800pci_ops) },
|
||||
{ PCI_DEVICE(0x1814, 0x3091), PCI_DEVICE_DATA(&rt2800pci_ops) },
|
||||
{ PCI_DEVICE(0x1814, 0x3092), PCI_DEVICE_DATA(&rt2800pci_ops) },
|
||||
{ PCI_DEVICE(0x1462, 0x891a), PCI_DEVICE_DATA(&rt2800pci_ops) },
|
||||
#endif
|
||||
#ifdef CONFIG_RT2800PCI_RT35XX
|
||||
{ PCI_DEVICE(0x1814, 0x3060), PCI_DEVICE_DATA(&rt2800pci_ops) },
|
||||
{ PCI_DEVICE(0x1814, 0x3062), PCI_DEVICE_DATA(&rt2800pci_ops) },
|
||||
{ PCI_DEVICE(0x1814, 0x3562), PCI_DEVICE_DATA(&rt2800pci_ops) },
|
||||
{ PCI_DEVICE(0x1814, 0x3592), PCI_DEVICE_DATA(&rt2800pci_ops) },
|
||||
{ PCI_DEVICE(0x1a3b, 0x1059), PCI_DEVICE_DATA(&rt2800pci_ops) },
|
||||
#endif
|
||||
{ 0, }
|
||||
};
|
||||
|
||||
@ -1225,11 +1223,10 @@ MODULE_DEVICE_TABLE(pci, rt2800pci_device_table);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
#ifdef CONFIG_RT2800PCI_SOC
|
||||
#if defined(CONFIG_RALINK_RT288X)
|
||||
__rt2x00soc_probe(RT2880, &rt2800pci_ops);
|
||||
#elif defined(CONFIG_RALINK_RT305X)
|
||||
__rt2x00soc_probe(RT3052, &rt2800pci_ops);
|
||||
#endif
|
||||
static int rt2800soc_probe(struct platform_device *pdev)
|
||||
{
|
||||
return rt2x00soc_probe(pdev, rt2800pci_ops);
|
||||
}
|
||||
|
||||
static struct platform_driver rt2800soc_driver = {
|
||||
.driver = {
|
||||
@ -1237,7 +1234,7 @@ static struct platform_driver rt2800soc_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.mod_name = KBUILD_MODNAME,
|
||||
},
|
||||
.probe = __rt2x00soc_probe,
|
||||
.probe = rt2800soc_probe,
|
||||
.remove = __devexit_p(rt2x00soc_remove),
|
||||
.suspend = rt2x00soc_suspend,
|
||||
.resume = rt2x00soc_resume,
|
||||
|
@ -92,7 +92,6 @@ static bool rt2800usb_check_crc(const u8 *data, const size_t len)
|
||||
static int rt2800usb_check_firmware(struct rt2x00_dev *rt2x00dev,
|
||||
const u8 *data, const size_t len)
|
||||
{
|
||||
u16 chipset = (rt2x00_rev(rt2x00dev) >> 16) & 0xffff;
|
||||
size_t offset = 0;
|
||||
|
||||
/*
|
||||
@ -111,9 +110,9 @@ static int rt2800usb_check_firmware(struct rt2x00_dev *rt2x00dev,
|
||||
* Check if we need the upper 4kb firmware data or not.
|
||||
*/
|
||||
if ((len == 4096) &&
|
||||
(chipset != 0x2860) &&
|
||||
(chipset != 0x2872) &&
|
||||
(chipset != 0x3070))
|
||||
!rt2x00_rt(rt2x00dev, RT2860) &&
|
||||
!rt2x00_rt(rt2x00dev, RT2872) &&
|
||||
!rt2x00_rt(rt2x00dev, RT3070))
|
||||
return FW_BAD_VERSION;
|
||||
|
||||
/*
|
||||
@ -138,14 +137,13 @@ static int rt2800usb_load_firmware(struct rt2x00_dev *rt2x00dev,
|
||||
u32 reg;
|
||||
u32 offset;
|
||||
u32 length;
|
||||
u16 chipset = (rt2x00_rev(rt2x00dev) >> 16) & 0xffff;
|
||||
|
||||
/*
|
||||
* Check which section of the firmware we need.
|
||||
*/
|
||||
if ((chipset == 0x2860) ||
|
||||
(chipset == 0x2872) ||
|
||||
(chipset == 0x3070)) {
|
||||
if (rt2x00_rt(rt2x00dev, RT2860) ||
|
||||
rt2x00_rt(rt2x00dev, RT2872) ||
|
||||
rt2x00_rt(rt2x00dev, RT3070)) {
|
||||
offset = 0;
|
||||
length = 4096;
|
||||
} else {
|
||||
@ -200,9 +198,9 @@ static int rt2800usb_load_firmware(struct rt2x00_dev *rt2x00dev,
|
||||
*/
|
||||
rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0xff, 0, 0);
|
||||
|
||||
if ((chipset == 0x3070) ||
|
||||
(chipset == 0x3071) ||
|
||||
(chipset == 0x3572)) {
|
||||
if (rt2x00_rt(rt2x00dev, RT3070) ||
|
||||
rt2x00_rt(rt2x00dev, RT3071) ||
|
||||
rt2x00_rt(rt2x00dev, RT3572)) {
|
||||
udelay(200);
|
||||
rt2800_mcu_request(rt2x00dev, MCU_CURRENT, 0, 0, 0);
|
||||
udelay(10);
|
||||
@ -807,51 +805,27 @@ static struct usb_device_id rt2800usb_device_table[] = {
|
||||
/* Abocom */
|
||||
{ USB_DEVICE(0x07b8, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x07b8, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x07b8, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x07b8, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x07b8, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x1482, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* AirTies */
|
||||
{ USB_DEVICE(0x1eda, 0x2310), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Amigo */
|
||||
{ USB_DEVICE(0x0e0b, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0e0b, 0x9041), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Amit */
|
||||
{ USB_DEVICE(0x15c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Askey */
|
||||
{ USB_DEVICE(0x1690, 0x0740), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x1690, 0x0744), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0930, 0x0a07), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* ASUS */
|
||||
{ USB_DEVICE(0x0b05, 0x1731), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0b05, 0x1732), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0b05, 0x1742), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0b05, 0x1760), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0b05, 0x1761), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0b05, 0x1784), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* AzureWave */
|
||||
{ USB_DEVICE(0x13d3, 0x3247), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x13d3, 0x3262), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x13d3, 0x3273), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x13d3, 0x3284), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x13d3, 0x3305), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Belkin */
|
||||
{ USB_DEVICE(0x050d, 0x8053), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x050d, 0x805c), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x050d, 0x815c), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x050d, 0x825a), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Buffalo */
|
||||
{ USB_DEVICE(0x0411, 0x00e8), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0411, 0x012e), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Cisco */
|
||||
{ USB_DEVICE(0x167b, 0x4001), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Conceptronic */
|
||||
{ USB_DEVICE(0x14b2, 0x3c06), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x14b2, 0x3c07), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x14b2, 0x3c08), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x14b2, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x14b2, 0x3c11), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x14b2, 0x3c12), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x14b2, 0x3c23), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x14b2, 0x3c25), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x14b2, 0x3c27), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
@ -860,103 +834,38 @@ static struct usb_device_id rt2800usb_device_table[] = {
|
||||
{ USB_DEVICE(0x07aa, 0x002f), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x07aa, 0x003c), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x07aa, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x07aa, 0x0041), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x07aa, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x18c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x18c5, 0x0012), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* D-Link */
|
||||
{ USB_DEVICE(0x07d1, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x07d1, 0x3c0a), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x07d1, 0x3c0b), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x07d1, 0x3c0d), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x07d1, 0x3c0e), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x07d1, 0x3c0f), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x07d1, 0x3c11), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x07d1, 0x3c13), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x07d1, 0x3c15), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Edimax */
|
||||
{ USB_DEVICE(0x7392, 0x7711), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x7392, 0x7717), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x7392, 0x7718), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Encore */
|
||||
{ USB_DEVICE(0x203d, 0x1480), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x203d, 0x14a1), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x203d, 0x14a9), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* EnGenius */
|
||||
{ USB_DEVICE(0X1740, 0x9701), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x1740, 0x9702), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x1740, 0x9703), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x1740, 0x9705), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x1740, 0x9706), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x1740, 0x9707), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x1740, 0x9708), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x1740, 0x9709), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x1740, 0x9801), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Gemtek */
|
||||
{ USB_DEVICE(0x15a9, 0x0010), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Gigabyte */
|
||||
{ USB_DEVICE(0x1044, 0x800b), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x1044, 0x800c), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x1044, 0x800d), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Hawking */
|
||||
{ USB_DEVICE(0x0e66, 0x0001), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0e66, 0x0003), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0e66, 0x0009), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0e66, 0x000b), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* I-O DATA */
|
||||
{ USB_DEVICE(0x04bb, 0x0944), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x04bb, 0x0945), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x04bb, 0x0947), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x04bb, 0x0948), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* LevelOne */
|
||||
{ USB_DEVICE(0x1740, 0x0605), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x1740, 0x0615), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Linksys */
|
||||
{ USB_DEVICE(0x1737, 0x0070), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x1737, 0x0071), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x1737, 0x0077), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x1737, 0x0079), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Logitec */
|
||||
{ USB_DEVICE(0x0789, 0x0162), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0789, 0x0163), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0789, 0x0164), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Motorola */
|
||||
{ USB_DEVICE(0x100d, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x100d, 0x9032), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* MSI */
|
||||
{ USB_DEVICE(0x0db0, 0x3820), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0db0, 0x3821), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0db0, 0x3870), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0db0, 0x6899), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0db0, 0x821a), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0db0, 0x870a), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0db0, 0x899a), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Ovislink */
|
||||
{ USB_DEVICE(0x1b75, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Para */
|
||||
{ USB_DEVICE(0x20b8, 0x8888), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Pegatron */
|
||||
{ USB_DEVICE(0x1d4d, 0x0002), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x1d4d, 0x000c), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x1d4d, 0x000e), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Philips */
|
||||
{ USB_DEVICE(0x0471, 0x200f), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Planex */
|
||||
{ USB_DEVICE(0x2019, 0xed06), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x2019, 0xab24), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x2019, 0xab25), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Qcom */
|
||||
{ USB_DEVICE(0x18e8, 0x6259), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Quanta */
|
||||
{ USB_DEVICE(0x1a32, 0x0304), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Ralink */
|
||||
{ USB_DEVICE(0x148f, 0x2070), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x148f, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x148f, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x148f, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x148f, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x148f, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x148f, 0x3572), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Samsung */
|
||||
{ USB_DEVICE(0x04e8, 0x2018), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Siemens */
|
||||
@ -967,36 +876,18 @@ static struct usb_device_id rt2800usb_device_table[] = {
|
||||
{ USB_DEVICE(0x0df6, 0x002c), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0df6, 0x002d), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0df6, 0x0039), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0df6, 0x003b), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0df6, 0x003c), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0df6, 0x003d), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0df6, 0x003e), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0df6, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0df6, 0x0040), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0df6, 0x0041), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0df6, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0df6, 0x0047), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0df6, 0x0048), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0df6, 0x004a), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0df6, 0x004d), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* SMC */
|
||||
{ USB_DEVICE(0x083a, 0x6618), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x083a, 0x7511), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x083a, 0x7512), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x083a, 0x7522), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x083a, 0x8522), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x083a, 0xa512), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x083a, 0xa618), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x083a, 0xa701), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x083a, 0xa702), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x083a, 0xb522), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x083a, 0xc522), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Sparklan */
|
||||
{ USB_DEVICE(0x15a9, 0x0006), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Sweex */
|
||||
{ USB_DEVICE(0x177f, 0x0153), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x177f, 0x0302), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x177f, 0x0313), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* U-Media*/
|
||||
{ USB_DEVICE(0x157e, 0x300e), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* ZCOM */
|
||||
@ -1005,12 +896,195 @@ static struct usb_device_id rt2800usb_device_table[] = {
|
||||
/* Zinwell */
|
||||
{ USB_DEVICE(0x5a57, 0x0280), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x5a57, 0x0282), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x5a57, 0x0283), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x5a57, 0x0284), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x5a57, 0x5257), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Zyxel */
|
||||
{ USB_DEVICE(0x0586, 0x3416), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
#ifdef CONFIG_RT2800USB_RT30XX
|
||||
/* Abocom */
|
||||
{ USB_DEVICE(0x07b8, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x07b8, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x07b8, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* AirTies */
|
||||
{ USB_DEVICE(0x1eda, 0x2310), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* AzureWave */
|
||||
{ USB_DEVICE(0x13d3, 0x3273), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Conceptronic */
|
||||
{ USB_DEVICE(0x14b2, 0x3c12), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Corega */
|
||||
{ USB_DEVICE(0x18c5, 0x0012), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* D-Link */
|
||||
{ USB_DEVICE(0x07d1, 0x3c0a), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x07d1, 0x3c0d), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x07d1, 0x3c0e), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x07d1, 0x3c0f), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Edimax */
|
||||
{ USB_DEVICE(0x7392, 0x7711), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Encore */
|
||||
{ USB_DEVICE(0x203d, 0x1480), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* EnGenius */
|
||||
{ USB_DEVICE(0x1740, 0x9703), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x1740, 0x9705), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x1740, 0x9706), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Gigabyte */
|
||||
{ USB_DEVICE(0x1044, 0x800d), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* I-O DATA */
|
||||
{ USB_DEVICE(0x04bb, 0x0945), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* MSI */
|
||||
{ USB_DEVICE(0x0db0, 0x3820), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Pegatron */
|
||||
{ USB_DEVICE(0x1d4d, 0x000c), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x1d4d, 0x000e), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Planex */
|
||||
{ USB_DEVICE(0x2019, 0xab25), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Quanta */
|
||||
{ USB_DEVICE(0x1a32, 0x0304), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Ralink */
|
||||
{ USB_DEVICE(0x148f, 0x2070), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x148f, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x148f, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x148f, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Sitecom */
|
||||
{ USB_DEVICE(0x0df6, 0x003e), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0df6, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* SMC */
|
||||
{ USB_DEVICE(0x083a, 0x7511), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Zinwell */
|
||||
{ USB_DEVICE(0x5a57, 0x0283), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x5a57, 0x5257), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
#endif
|
||||
#ifdef CONFIG_RT2800USB_RT35XX
|
||||
/* Askey */
|
||||
{ USB_DEVICE(0x1690, 0x0744), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Cisco */
|
||||
{ USB_DEVICE(0x167b, 0x4001), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* EnGenius */
|
||||
{ USB_DEVICE(0x1740, 0x9801), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* I-O DATA */
|
||||
{ USB_DEVICE(0x04bb, 0x0944), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Ralink */
|
||||
{ USB_DEVICE(0x148f, 0x3370), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x148f, 0x3572), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x148f, 0x8070), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Sitecom */
|
||||
{ USB_DEVICE(0x0df6, 0x0041), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Zinwell */
|
||||
{ USB_DEVICE(0x5a57, 0x0284), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
#endif
|
||||
#ifdef CONFIG_RT2800USB_UNKNOWN
|
||||
/*
|
||||
* Unclear what kind of devices these are (they aren't supported by the
|
||||
* vendor driver).
|
||||
*/
|
||||
/* Allwin */
|
||||
{ USB_DEVICE(0x8516, 0x2070), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x8516, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x8516, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x8516, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x8516, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x8516, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x8516, 0x3572), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Amigo */
|
||||
{ USB_DEVICE(0x0e0b, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0e0b, 0x9041), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Askey */
|
||||
{ USB_DEVICE(0x0930, 0x0a07), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* ASUS */
|
||||
{ USB_DEVICE(0x0b05, 0x1760), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0b05, 0x1761), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0b05, 0x1784), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0b05, 0x1790), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x1761, 0x0b05), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* AzureWave */
|
||||
{ USB_DEVICE(0x13d3, 0x3262), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x13d3, 0x3284), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x13d3, 0x3305), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Belkin */
|
||||
{ USB_DEVICE(0x050d, 0x825a), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Buffalo */
|
||||
{ USB_DEVICE(0x0411, 0x012e), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0411, 0x0148), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0411, 0x0150), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0411, 0x015d), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Conceptronic */
|
||||
{ USB_DEVICE(0x14b2, 0x3c08), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x14b2, 0x3c11), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Corega */
|
||||
{ USB_DEVICE(0x07aa, 0x0041), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x07aa, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x18c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* D-Link */
|
||||
{ USB_DEVICE(0x07d1, 0x3c0b), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x07d1, 0x3c13), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x07d1, 0x3c15), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x07d1, 0x3c16), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Encore */
|
||||
{ USB_DEVICE(0x203d, 0x14a1), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x203d, 0x14a9), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* EnGenius */
|
||||
{ USB_DEVICE(0x1740, 0x9707), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x1740, 0x9708), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x1740, 0x9709), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Gemtek */
|
||||
{ USB_DEVICE(0x15a9, 0x0010), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Gigabyte */
|
||||
{ USB_DEVICE(0x1044, 0x800c), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Hawking */
|
||||
{ USB_DEVICE(0x0e66, 0x0009), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0e66, 0x000b), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* I-O DATA */
|
||||
{ USB_DEVICE(0x04bb, 0x0947), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x04bb, 0x0948), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* LevelOne */
|
||||
{ USB_DEVICE(0x1740, 0x0605), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x1740, 0x0615), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Linksys */
|
||||
{ USB_DEVICE(0x1737, 0x0077), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x1737, 0x0078), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x1737, 0x0079), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Motorola */
|
||||
{ USB_DEVICE(0x100d, 0x9032), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* MSI */
|
||||
{ USB_DEVICE(0x0db0, 0x3821), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0db0, 0x3822), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0db0, 0x3870), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0db0, 0x3871), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0db0, 0x821a), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0db0, 0x822a), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0db0, 0x870a), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0db0, 0x871a), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0db0, 0x899a), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Ovislink */
|
||||
{ USB_DEVICE(0x1b75, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Para */
|
||||
{ USB_DEVICE(0x20b8, 0x8888), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Pegatron */
|
||||
{ USB_DEVICE(0x05a6, 0x0101), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x1d4d, 0x0002), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x1d4d, 0x0010), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Planex */
|
||||
{ USB_DEVICE(0x2019, 0xab24), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Qcom */
|
||||
{ USB_DEVICE(0x18e8, 0x6259), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Sitecom */
|
||||
{ USB_DEVICE(0x0df6, 0x003b), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0df6, 0x003c), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0df6, 0x003d), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0df6, 0x0040), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0df6, 0x0047), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0df6, 0x0048), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0df6, 0x004a), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x0df6, 0x004d), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* SMC */
|
||||
{ USB_DEVICE(0x083a, 0xa512), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x083a, 0xa701), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x083a, 0xa702), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x083a, 0xc522), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x083a, 0xd522), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Sweex */
|
||||
{ USB_DEVICE(0x177f, 0x0153), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
{ USB_DEVICE(0x177f, 0x0313), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
/* Zyxel */
|
||||
{ USB_DEVICE(0x0586, 0x341a), USB_DEVICE_DATA(&rt2800usb_ops) },
|
||||
#endif
|
||||
{ 0, }
|
||||
};
|
||||
|
||||
|
@ -160,6 +160,7 @@ struct avg_val {
|
||||
enum rt2x00_chip_intf {
|
||||
RT2X00_CHIP_INTF_PCI,
|
||||
RT2X00_CHIP_INTF_USB,
|
||||
RT2X00_CHIP_INTF_SOC,
|
||||
};
|
||||
|
||||
/*
|
||||
@ -169,25 +170,26 @@ enum rt2x00_chip_intf {
|
||||
*/
|
||||
struct rt2x00_chip {
|
||||
u16 rt;
|
||||
#define RT2460 0x0101
|
||||
#define RT2560 0x0201
|
||||
#define RT2570 0x1201
|
||||
#define RT2561s 0x0301 /* Turbo */
|
||||
#define RT2561 0x0302
|
||||
#define RT2661 0x0401
|
||||
#define RT2571 0x1300
|
||||
#define RT2860 0x0601 /* 2.4GHz PCI/CB */
|
||||
#define RT2860D 0x0681 /* 2.4GHz, 5GHz PCI/CB */
|
||||
#define RT2890 0x0701 /* 2.4GHz PCIe */
|
||||
#define RT2890D 0x0781 /* 2.4GHz, 5GHz PCIe */
|
||||
#define RT2460 0x2460
|
||||
#define RT2560 0x2560
|
||||
#define RT2570 0x2570
|
||||
#define RT2661 0x2661
|
||||
#define RT2573 0x2573
|
||||
#define RT2860 0x2860 /* 2.4GHz PCI/CB */
|
||||
#define RT2870 0x2870
|
||||
#define RT2872 0x2872
|
||||
#define RT2880 0x2880 /* WSOC */
|
||||
#define RT2883 0x2883 /* WSOC */
|
||||
#define RT2890 0x2890 /* 2.4GHz PCIe */
|
||||
#define RT3052 0x3052 /* WSOC */
|
||||
#define RT3070 0x3070
|
||||
#define RT3071 0x3071
|
||||
#define RT3090 0x3090 /* 2.4GHz PCIe */
|
||||
#define RT2870 0x1600
|
||||
#define RT3070 0x1800
|
||||
#define RT3390 0x3390
|
||||
#define RT3572 0x3572
|
||||
|
||||
u16 rf;
|
||||
u32 rev;
|
||||
u16 rev;
|
||||
|
||||
enum rt2x00_chip_intf intf;
|
||||
};
|
||||
@ -917,29 +919,14 @@ static inline void rt2x00_eeprom_write(struct rt2x00_dev *rt2x00dev,
|
||||
* Chipset handlers
|
||||
*/
|
||||
static inline void rt2x00_set_chip(struct rt2x00_dev *rt2x00dev,
|
||||
const u16 rt, const u16 rf, const u32 rev)
|
||||
const u16 rt, const u16 rf, const u16 rev)
|
||||
{
|
||||
rt2x00dev->chip.rt = rt;
|
||||
rt2x00dev->chip.rf = rf;
|
||||
rt2x00dev->chip.rev = rev;
|
||||
}
|
||||
|
||||
static inline void rt2x00_set_chip_rt(struct rt2x00_dev *rt2x00dev,
|
||||
const u16 rt)
|
||||
{
|
||||
rt2x00dev->chip.rt = rt;
|
||||
}
|
||||
|
||||
static inline void rt2x00_set_chip_rf(struct rt2x00_dev *rt2x00dev,
|
||||
const u16 rf, const u32 rev)
|
||||
{
|
||||
rt2x00_set_chip(rt2x00dev, rt2x00dev->chip.rt, rf, rev);
|
||||
}
|
||||
|
||||
static inline void rt2x00_print_chip(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
INFO(rt2x00dev,
|
||||
"Chipset detected - rt: %04x, rf: %04x, rev: %08x.\n",
|
||||
"Chipset detected - rt: %04x, rf: %04x, rev: %04x.\n",
|
||||
rt2x00dev->chip.rt, rt2x00dev->chip.rf, rt2x00dev->chip.rev);
|
||||
}
|
||||
|
||||
@ -953,17 +940,11 @@ static inline char rt2x00_rf(struct rt2x00_dev *rt2x00dev, const u16 rf)
|
||||
return (rt2x00dev->chip.rf == rf);
|
||||
}
|
||||
|
||||
static inline u32 rt2x00_rev(struct rt2x00_dev *rt2x00dev)
|
||||
static inline u16 rt2x00_rev(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
return rt2x00dev->chip.rev;
|
||||
}
|
||||
|
||||
static inline bool rt2x00_check_rev(struct rt2x00_dev *rt2x00dev,
|
||||
const u32 mask, const u32 rev)
|
||||
{
|
||||
return ((rt2x00dev->chip.rev & mask) == rev);
|
||||
}
|
||||
|
||||
static inline void rt2x00_set_chip_intf(struct rt2x00_dev *rt2x00dev,
|
||||
enum rt2x00_chip_intf intf)
|
||||
{
|
||||
@ -976,16 +957,21 @@ static inline bool rt2x00_intf(struct rt2x00_dev *rt2x00dev,
|
||||
return (rt2x00dev->chip.intf == intf);
|
||||
}
|
||||
|
||||
static inline bool rt2x00_intf_is_pci(struct rt2x00_dev *rt2x00dev)
|
||||
static inline bool rt2x00_is_pci(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
return rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_PCI);
|
||||
}
|
||||
|
||||
static inline bool rt2x00_intf_is_usb(struct rt2x00_dev *rt2x00dev)
|
||||
static inline bool rt2x00_is_usb(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
return rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_USB);
|
||||
}
|
||||
|
||||
static inline bool rt2x00_is_soc(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
return rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_SOC);
|
||||
}
|
||||
|
||||
/**
|
||||
* rt2x00queue_map_txskb - Map a skb into DMA for TX purposes.
|
||||
* @rt2x00dev: Pointer to &struct rt2x00_dev.
|
||||
|
@ -184,7 +184,7 @@ void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
|
||||
dump_hdr->data_length = cpu_to_le32(skb->len);
|
||||
dump_hdr->chip_rt = cpu_to_le16(rt2x00dev->chip.rt);
|
||||
dump_hdr->chip_rf = cpu_to_le16(rt2x00dev->chip.rf);
|
||||
dump_hdr->chip_rev = cpu_to_le32(rt2x00dev->chip.rev);
|
||||
dump_hdr->chip_rev = cpu_to_le16(rt2x00dev->chip.rev);
|
||||
dump_hdr->type = cpu_to_le16(type);
|
||||
dump_hdr->queue_index = desc->entry->queue->qid;
|
||||
dump_hdr->entry_index = desc->entry->entry_idx;
|
||||
@ -573,7 +573,7 @@ static struct dentry *rt2x00debug_create_file_chipset(const char *name,
|
||||
blob->data = data;
|
||||
data += sprintf(data, "rt chip:\t%04x\n", intf->rt2x00dev->chip.rt);
|
||||
data += sprintf(data, "rf chip:\t%04x\n", intf->rt2x00dev->chip.rf);
|
||||
data += sprintf(data, "revision:\t%08x\n", intf->rt2x00dev->chip.rev);
|
||||
data += sprintf(data, "revision:\t%04x\n", intf->rt2x00dev->chip.rev);
|
||||
data += sprintf(data, "\n");
|
||||
data += sprintf(data, "register\tbase\twords\twordsize\n");
|
||||
data += sprintf(data, "csr\t%d\t%d\t%d\n",
|
||||
|
@ -272,7 +272,6 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
|
||||
struct ieee80211_hw *hw;
|
||||
struct rt2x00_dev *rt2x00dev;
|
||||
int retval;
|
||||
u16 chip;
|
||||
|
||||
retval = pci_request_regions(pci_dev, pci_name(pci_dev));
|
||||
if (retval) {
|
||||
@ -315,12 +314,6 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
|
||||
|
||||
rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_PCI);
|
||||
|
||||
/*
|
||||
* Determine RT chipset by reading PCI header.
|
||||
*/
|
||||
pci_read_config_word(pci_dev, PCI_DEVICE_ID, &chip);
|
||||
rt2x00_set_chip_rt(rt2x00dev, chip);
|
||||
|
||||
retval = rt2x00pci_alloc_reg(rt2x00dev);
|
||||
if (retval)
|
||||
goto exit_free_device;
|
||||
|
@ -27,6 +27,7 @@
|
||||
#define RT2X00PCI_H
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
/*
|
||||
* This variable should be used with the
|
||||
|
@ -71,9 +71,7 @@ exit:
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
int rt2x00soc_probe(struct platform_device *pdev,
|
||||
const unsigned short chipset,
|
||||
const struct rt2x00_ops *ops)
|
||||
int rt2x00soc_probe(struct platform_device *pdev, const struct rt2x00_ops *ops)
|
||||
{
|
||||
struct ieee80211_hw *hw;
|
||||
struct rt2x00_dev *rt2x00dev;
|
||||
@ -94,12 +92,7 @@ int rt2x00soc_probe(struct platform_device *pdev,
|
||||
rt2x00dev->irq = platform_get_irq(pdev, 0);
|
||||
rt2x00dev->name = pdev->dev.driver->name;
|
||||
|
||||
/*
|
||||
* SoC devices mimic PCI behavior.
|
||||
*/
|
||||
rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_PCI);
|
||||
|
||||
rt2x00_set_chip_rt(rt2x00dev, chipset);
|
||||
rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_SOC);
|
||||
|
||||
retval = rt2x00soc_alloc_reg(rt2x00dev);
|
||||
if (retval)
|
||||
|
@ -28,18 +28,10 @@
|
||||
|
||||
#define KSEG1ADDR(__ptr) __ptr
|
||||
|
||||
#define __rt2x00soc_probe(__chipset, __ops) \
|
||||
static int __rt2x00soc_probe(struct platform_device *pdev) \
|
||||
{ \
|
||||
return rt2x00soc_probe(pdev, (__chipset), (__ops)); \
|
||||
}
|
||||
|
||||
/*
|
||||
* SoC driver handlers.
|
||||
*/
|
||||
int rt2x00soc_probe(struct platform_device *pdev,
|
||||
const unsigned short chipset,
|
||||
const struct rt2x00_ops *ops);
|
||||
int rt2x00soc_probe(struct platform_device *pdev, const struct rt2x00_ops *ops);
|
||||
int rt2x00soc_remove(struct platform_device *pdev);
|
||||
#ifdef CONFIG_PM
|
||||
int rt2x00soc_suspend(struct platform_device *pdev, pm_message_t state);
|
||||
|
@ -1131,16 +1131,18 @@ dynamic_cca_tune:
|
||||
*/
|
||||
static char *rt61pci_get_firmware_name(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
u16 chip;
|
||||
char *fw_name;
|
||||
|
||||
switch (rt2x00dev->chip.rt) {
|
||||
case RT2561:
|
||||
pci_read_config_word(to_pci_dev(rt2x00dev->dev), PCI_DEVICE_ID, &chip);
|
||||
switch (chip) {
|
||||
case RT2561_PCI_ID:
|
||||
fw_name = FIRMWARE_RT2561;
|
||||
break;
|
||||
case RT2561s:
|
||||
case RT2561s_PCI_ID:
|
||||
fw_name = FIRMWARE_RT2561s;
|
||||
break;
|
||||
case RT2661:
|
||||
case RT2661_PCI_ID:
|
||||
fw_name = FIRMWARE_RT2661;
|
||||
break;
|
||||
default:
|
||||
@ -2295,8 +2297,8 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
|
||||
*/
|
||||
value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
|
||||
rt2x00pci_register_read(rt2x00dev, MAC_CSR0, ®);
|
||||
rt2x00_set_chip_rf(rt2x00dev, value, reg);
|
||||
rt2x00_print_chip(rt2x00dev);
|
||||
rt2x00_set_chip(rt2x00dev, rt2x00_get_field32(reg, MAC_CSR0_CHIPSET),
|
||||
value, rt2x00_get_field32(reg, MAC_CSR0_REVISION));
|
||||
|
||||
if (!rt2x00_rf(rt2x00dev, RF5225) &&
|
||||
!rt2x00_rf(rt2x00dev, RF5325) &&
|
||||
|
@ -27,6 +27,13 @@
|
||||
#ifndef RT61PCI_H
|
||||
#define RT61PCI_H
|
||||
|
||||
/*
|
||||
* RT chip PCI IDs.
|
||||
*/
|
||||
#define RT2561s_PCI_ID 0x0301
|
||||
#define RT2561_PCI_ID 0x0302
|
||||
#define RT2661_PCI_ID 0x0401
|
||||
|
||||
/*
|
||||
* RF chip defines.
|
||||
*/
|
||||
@ -225,6 +232,8 @@ struct hw_pairwise_ta_entry {
|
||||
* MAC_CSR0: ASIC revision number.
|
||||
*/
|
||||
#define MAC_CSR0 0x3000
|
||||
#define MAC_CSR0_REVISION FIELD32(0x0000000f)
|
||||
#define MAC_CSR0_CHIPSET FIELD32(0x000ffff0)
|
||||
|
||||
/*
|
||||
* MAC_CSR1: System control register.
|
||||
|
@ -1820,11 +1820,10 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
|
||||
*/
|
||||
value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
|
||||
rt2x00usb_register_read(rt2x00dev, MAC_CSR0, ®);
|
||||
rt2x00_set_chip(rt2x00dev, RT2571, value, reg);
|
||||
rt2x00_print_chip(rt2x00dev);
|
||||
rt2x00_set_chip(rt2x00dev, rt2x00_get_field32(reg, MAC_CSR0_CHIPSET),
|
||||
value, rt2x00_get_field32(reg, MAC_CSR0_REVISION));
|
||||
|
||||
if (!rt2x00_check_rev(rt2x00dev, 0x000ffff0, 0x25730) ||
|
||||
rt2x00_check_rev(rt2x00dev, 0x0000000f, 0)) {
|
||||
if (!rt2x00_rt(rt2x00dev, RT2573) || (rt2x00_rev(rt2x00dev) == 0)) {
|
||||
ERROR(rt2x00dev, "Invalid RT chipset detected.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
@ -142,6 +142,8 @@ struct hw_pairwise_ta_entry {
|
||||
* MAC_CSR0: ASIC revision number.
|
||||
*/
|
||||
#define MAC_CSR0 0x3000
|
||||
#define MAC_CSR0_REVISION FIELD32(0x0000000f)
|
||||
#define MAC_CSR0_CHIPSET FIELD32(0x000ffff0)
|
||||
|
||||
/*
|
||||
* MAC_CSR1: System control register.
|
||||
|
@ -241,5 +241,5 @@ void rtl8187_leds_exit(struct ieee80211_hw *dev)
|
||||
cancel_delayed_work_sync(&priv->led_off);
|
||||
cancel_delayed_work_sync(&priv->led_on);
|
||||
}
|
||||
#endif /* def CONFIG_RTL8187_LED */
|
||||
#endif /* def CONFIG_RTL8187_LEDS */
|
||||
|
||||
|
@ -54,6 +54,6 @@ struct rtl8187_led {
|
||||
void rtl8187_leds_init(struct ieee80211_hw *dev, u16 code);
|
||||
void rtl8187_leds_exit(struct ieee80211_hw *dev);
|
||||
|
||||
#endif /* def CONFIG_RTL8187_LED */
|
||||
#endif /* def CONFIG_RTL8187_LEDS */
|
||||
|
||||
#endif /* RTL8187_LED_H */
|
||||
|
@ -10,5 +10,7 @@ obj-$(CONFIG_WL1251_SDIO) += wl1251_sdio.o
|
||||
wl1271-objs = wl1271_main.o wl1271_spi.o wl1271_cmd.o \
|
||||
wl1271_event.o wl1271_tx.o wl1271_rx.o \
|
||||
wl1271_ps.o wl1271_acx.o wl1271_boot.o \
|
||||
wl1271_init.o wl1271_debugfs.o
|
||||
wl1271_init.o wl1271_debugfs.o wl1271_io.o
|
||||
|
||||
wl1271-$(CONFIG_NL80211_TESTMODE) += wl1271_testmode.o
|
||||
obj-$(CONFIG_WL1271) += wl1271.o
|
||||
|
@ -43,7 +43,7 @@ enum {
|
||||
DEBUG_SPI = BIT(1),
|
||||
DEBUG_BOOT = BIT(2),
|
||||
DEBUG_MAILBOX = BIT(3),
|
||||
DEBUG_NETLINK = BIT(4),
|
||||
DEBUG_TESTMODE = BIT(4),
|
||||
DEBUG_EVENT = BIT(5),
|
||||
DEBUG_TX = BIT(6),
|
||||
DEBUG_RX = BIT(7),
|
||||
@ -109,7 +109,33 @@ enum {
|
||||
|
||||
#define WL1271_FW_NAME "wl1271-fw.bin"
|
||||
#define WL1271_NVS_NAME "wl1271-nvs.bin"
|
||||
#define WL1271_NVS_LEN 468
|
||||
|
||||
/* NVS data structure */
|
||||
#define WL1271_NVS_SECTION_SIZE 468
|
||||
|
||||
#define WL1271_NVS_GENERAL_PARAMS_SIZE 57
|
||||
#define WL1271_NVS_GENERAL_PARAMS_SIZE_PADDED \
|
||||
(WL1271_NVS_GENERAL_PARAMS_SIZE + 1)
|
||||
#define WL1271_NVS_STAT_RADIO_PARAMS_SIZE 17
|
||||
#define WL1271_NVS_STAT_RADIO_PARAMS_SIZE_PADDED \
|
||||
(WL1271_NVS_STAT_RADIO_PARAMS_SIZE + 1)
|
||||
#define WL1271_NVS_DYN_RADIO_PARAMS_SIZE 65
|
||||
#define WL1271_NVS_DYN_RADIO_PARAMS_SIZE_PADDED \
|
||||
(WL1271_NVS_DYN_RADIO_PARAMS_SIZE + 1)
|
||||
#define WL1271_NVS_FEM_COUNT 2
|
||||
#define WL1271_NVS_INI_SPARE_SIZE 124
|
||||
|
||||
struct wl1271_nvs_file {
|
||||
/* NVS section */
|
||||
u8 nvs[WL1271_NVS_SECTION_SIZE];
|
||||
|
||||
/* INI section */
|
||||
u8 general_params[WL1271_NVS_GENERAL_PARAMS_SIZE_PADDED];
|
||||
u8 stat_radio_params[WL1271_NVS_STAT_RADIO_PARAMS_SIZE_PADDED];
|
||||
u8 dyn_radio_params[WL1271_NVS_FEM_COUNT]
|
||||
[WL1271_NVS_DYN_RADIO_PARAMS_SIZE_PADDED];
|
||||
u8 ini_spare[WL1271_NVS_INI_SPARE_SIZE];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/*
|
||||
* Enable/disable 802.11a support for WL1273
|
||||
@ -342,8 +368,7 @@ struct wl1271 {
|
||||
|
||||
u8 *fw;
|
||||
size_t fw_len;
|
||||
u8 *nvs;
|
||||
size_t nvs_len;
|
||||
struct wl1271_nvs_file *nvs;
|
||||
|
||||
u8 bssid[ETH_ALEN];
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
@ -461,6 +486,7 @@ int wl1271_plt_stop(struct wl1271 *wl);
|
||||
|
||||
static inline bool wl1271_11a_enabled(void)
|
||||
{
|
||||
/* FIXME: this could be determined based on the NVS-INI file */
|
||||
#ifdef WL1271_80211A_ENABLED
|
||||
return true;
|
||||
#else
|
||||
|
@ -830,12 +830,14 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wl1271_acx_ac_cfg(struct wl1271 *wl)
|
||||
int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max,
|
||||
u8 aifsn, u16 txop)
|
||||
{
|
||||
struct acx_ac_cfg *acx;
|
||||
int i, ret = 0;
|
||||
int ret = 0;
|
||||
|
||||
wl1271_debug(DEBUG_ACX, "acx access category config");
|
||||
wl1271_debug(DEBUG_ACX, "acx ac cfg %d cw_ming %d cw_max %d "
|
||||
"aifs %d txop %d", ac, cw_min, cw_max, aifsn, txop);
|
||||
|
||||
acx = kzalloc(sizeof(*acx), GFP_KERNEL);
|
||||
|
||||
@ -844,21 +846,16 @@ int wl1271_acx_ac_cfg(struct wl1271 *wl)
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < wl->conf.tx.ac_conf_count; i++) {
|
||||
struct conf_tx_ac_category *c = &(wl->conf.tx.ac_conf[i]);
|
||||
acx->ac = c->ac;
|
||||
acx->cw_min = c->cw_min;
|
||||
acx->cw_max = cpu_to_le16(c->cw_max);
|
||||
acx->aifsn = c->aifsn;
|
||||
acx->reserved = 0;
|
||||
acx->tx_op_limit = cpu_to_le16(c->tx_op_limit);
|
||||
acx->ac = ac;
|
||||
acx->cw_min = cw_min;
|
||||
acx->cw_max = cpu_to_le16(cw_max);
|
||||
acx->aifsn = aifsn;
|
||||
acx->tx_op_limit = cpu_to_le16(txop);
|
||||
|
||||
ret = wl1271_cmd_configure(wl, ACX_AC_CFG, acx, sizeof(*acx));
|
||||
if (ret < 0) {
|
||||
wl1271_warning("Setting of access category "
|
||||
"config: %d", ret);
|
||||
goto out;
|
||||
}
|
||||
ret = wl1271_cmd_configure(wl, ACX_AC_CFG, acx, sizeof(*acx));
|
||||
if (ret < 0) {
|
||||
wl1271_warning("acx ac cfg failed: %d", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
@ -866,10 +863,12 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wl1271_acx_tid_cfg(struct wl1271 *wl)
|
||||
int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type,
|
||||
u8 tsid, u8 ps_scheme, u8 ack_policy,
|
||||
u32 apsd_conf0, u32 apsd_conf1)
|
||||
{
|
||||
struct acx_tid_config *acx;
|
||||
int i, ret = 0;
|
||||
int ret = 0;
|
||||
|
||||
wl1271_debug(DEBUG_ACX, "acx tid config");
|
||||
|
||||
@ -880,21 +879,18 @@ int wl1271_acx_tid_cfg(struct wl1271 *wl)
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < wl->conf.tx.tid_conf_count; i++) {
|
||||
struct conf_tx_tid *c = &(wl->conf.tx.tid_conf[i]);
|
||||
acx->queue_id = c->queue_id;
|
||||
acx->channel_type = c->channel_type;
|
||||
acx->tsid = c->tsid;
|
||||
acx->ps_scheme = c->ps_scheme;
|
||||
acx->ack_policy = c->ack_policy;
|
||||
acx->apsd_conf[0] = cpu_to_le32(c->apsd_conf[0]);
|
||||
acx->apsd_conf[1] = cpu_to_le32(c->apsd_conf[1]);
|
||||
acx->queue_id = queue_id;
|
||||
acx->channel_type = channel_type;
|
||||
acx->tsid = tsid;
|
||||
acx->ps_scheme = ps_scheme;
|
||||
acx->ack_policy = ack_policy;
|
||||
acx->apsd_conf[0] = cpu_to_le32(apsd_conf0);
|
||||
acx->apsd_conf[1] = cpu_to_le32(apsd_conf1);
|
||||
|
||||
ret = wl1271_cmd_configure(wl, ACX_TID_CFG, acx, sizeof(*acx));
|
||||
if (ret < 0) {
|
||||
wl1271_warning("Setting of tid config failed: %d", ret);
|
||||
goto out;
|
||||
}
|
||||
ret = wl1271_cmd_configure(wl, ACX_TID_CFG, acx, sizeof(*acx));
|
||||
if (ret < 0) {
|
||||
wl1271_warning("Setting of tid config failed: %d", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
|
@ -2,7 +2,7 @@
|
||||
* This file is part of wl1271
|
||||
*
|
||||
* Copyright (C) 1998-2009 Texas Instruments. All rights reserved.
|
||||
* Copyright (C) 2008-2009 Nokia Corporation
|
||||
* Copyright (C) 2008-2010 Nokia Corporation
|
||||
*
|
||||
* Contact: Luciano Coelho <luciano.coelho@nokia.com>
|
||||
*
|
||||
@ -348,7 +348,7 @@ struct acx_beacon_filter_option {
|
||||
* ACXBeaconFilterEntry (not 221)
|
||||
* Byte Offset Size (Bytes) Definition
|
||||
* =========== ============ ==========
|
||||
* 0 1 IE identifier
|
||||
* 0 1 IE identifier
|
||||
* 1 1 Treatment bit mask
|
||||
*
|
||||
* ACXBeaconFilterEntry (221)
|
||||
@ -381,8 +381,8 @@ struct acx_beacon_filter_ie_table {
|
||||
struct acx_header header;
|
||||
|
||||
u8 num_ie;
|
||||
u8 table[BEACON_FILTER_TABLE_MAX_SIZE];
|
||||
u8 pad[3];
|
||||
u8 table[BEACON_FILTER_TABLE_MAX_SIZE];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct acx_conn_monit_params {
|
||||
@ -1070,8 +1070,11 @@ int wl1271_acx_cts_protect(struct wl1271 *wl,
|
||||
enum acx_ctsprotect_type ctsprotect);
|
||||
int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats);
|
||||
int wl1271_acx_rate_policies(struct wl1271 *wl);
|
||||
int wl1271_acx_ac_cfg(struct wl1271 *wl);
|
||||
int wl1271_acx_tid_cfg(struct wl1271 *wl);
|
||||
int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max,
|
||||
u8 aifsn, u16 txop);
|
||||
int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type,
|
||||
u8 tsid, u8 ps_scheme, u8 ack_policy,
|
||||
u32 apsd_conf0, u32 apsd_conf1);
|
||||
int wl1271_acx_frag_threshold(struct wl1271 *wl);
|
||||
int wl1271_acx_tx_config_options(struct wl1271 *wl);
|
||||
int wl1271_acx_mem_cfg(struct wl1271 *wl);
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "wl1271_reg.h"
|
||||
#include "wl1271_boot.h"
|
||||
#include "wl1271_spi.h"
|
||||
#include "wl1271_io.h"
|
||||
#include "wl1271_event.h"
|
||||
|
||||
static struct wl1271_partition_set part_table[PART_TABLE_LEN] = {
|
||||
@ -93,19 +94,19 @@ static void wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag)
|
||||
u32 cpu_ctrl;
|
||||
|
||||
/* 10.5.0 run the firmware (I) */
|
||||
cpu_ctrl = wl1271_spi_read32(wl, ACX_REG_ECPU_CONTROL);
|
||||
cpu_ctrl = wl1271_read32(wl, ACX_REG_ECPU_CONTROL);
|
||||
|
||||
/* 10.5.1 run the firmware (II) */
|
||||
cpu_ctrl |= flag;
|
||||
wl1271_spi_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl);
|
||||
wl1271_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl);
|
||||
}
|
||||
|
||||
static void wl1271_boot_fw_version(struct wl1271 *wl)
|
||||
{
|
||||
struct wl1271_static_data static_data;
|
||||
|
||||
wl1271_spi_read(wl, wl->cmd_box_addr,
|
||||
&static_data, sizeof(static_data), false);
|
||||
wl1271_read(wl, wl->cmd_box_addr, &static_data, sizeof(static_data),
|
||||
false);
|
||||
|
||||
strncpy(wl->chip.fw_ver, static_data.fw_version,
|
||||
sizeof(wl->chip.fw_ver));
|
||||
@ -164,7 +165,7 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
|
||||
memcpy(chunk, p, CHUNK_SIZE);
|
||||
wl1271_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x",
|
||||
p, addr);
|
||||
wl1271_spi_write(wl, addr, chunk, CHUNK_SIZE, false);
|
||||
wl1271_write(wl, addr, chunk, CHUNK_SIZE, false);
|
||||
|
||||
chunk_num++;
|
||||
}
|
||||
@ -175,7 +176,7 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
|
||||
memcpy(chunk, p, fw_data_len % CHUNK_SIZE);
|
||||
wl1271_debug(DEBUG_BOOT, "uploading fw last chunk (%zd B) 0x%p to 0x%x",
|
||||
fw_data_len % CHUNK_SIZE, p, addr);
|
||||
wl1271_spi_write(wl, addr, chunk, fw_data_len % CHUNK_SIZE, false);
|
||||
wl1271_write(wl, addr, chunk, fw_data_len % CHUNK_SIZE, false);
|
||||
|
||||
kfree(chunk);
|
||||
return 0;
|
||||
@ -219,29 +220,14 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
|
||||
size_t nvs_len, burst_len;
|
||||
int i;
|
||||
u32 dest_addr, val;
|
||||
u8 *nvs_ptr, *nvs, *nvs_aligned;
|
||||
u8 *nvs_ptr, *nvs_aligned;
|
||||
|
||||
nvs = wl->nvs;
|
||||
if (nvs == NULL)
|
||||
if (wl->nvs == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
if (wl->nvs_len < WL1271_NVS_LEN)
|
||||
return -EINVAL;
|
||||
|
||||
nvs_ptr = nvs;
|
||||
|
||||
/* only the first part of the NVS needs to be uploaded */
|
||||
nvs_len = WL1271_NVS_LEN;
|
||||
|
||||
/* FIXME: read init settings from the remaining part of the NVS */
|
||||
|
||||
/* Update the device MAC address into the nvs */
|
||||
nvs[11] = wl->mac_addr[0];
|
||||
nvs[10] = wl->mac_addr[1];
|
||||
nvs[6] = wl->mac_addr[2];
|
||||
nvs[5] = wl->mac_addr[3];
|
||||
nvs[4] = wl->mac_addr[4];
|
||||
nvs[3] = wl->mac_addr[5];
|
||||
nvs_len = sizeof(wl->nvs->nvs);
|
||||
nvs_ptr = (u8 *)wl->nvs->nvs;
|
||||
|
||||
/*
|
||||
* Layout before the actual NVS tables:
|
||||
@ -271,7 +257,7 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
|
||||
wl1271_debug(DEBUG_BOOT,
|
||||
"nvs burst write 0x%x: 0x%x",
|
||||
dest_addr, val);
|
||||
wl1271_spi_write32(wl, dest_addr, val);
|
||||
wl1271_write32(wl, dest_addr, val);
|
||||
|
||||
nvs_ptr += 4;
|
||||
dest_addr += 4;
|
||||
@ -283,7 +269,7 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
|
||||
* is 7 bytes further.
|
||||
*/
|
||||
nvs_ptr += 7;
|
||||
nvs_len -= nvs_ptr - nvs;
|
||||
nvs_len -= nvs_ptr - (u8 *)wl->nvs->nvs;
|
||||
nvs_len = ALIGN(nvs_len, 4);
|
||||
|
||||
/* FIXME: The driver sets the partition here, but this is not needed,
|
||||
@ -292,15 +278,20 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
|
||||
wl1271_set_partition(wl, &part_table[PART_WORK]);
|
||||
|
||||
/* Copy the NVS tables to a new block to ensure alignment */
|
||||
nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL);
|
||||
if (!nvs_aligned)
|
||||
return -ENOMEM;
|
||||
/* FIXME: We jump 3 more bytes before uploading the NVS. It seems
|
||||
that our NVS files have three extra zeros here. I'm not sure whether
|
||||
the problem is in our NVS generation or we should really jumpt these
|
||||
3 bytes here */
|
||||
nvs_ptr += 3;
|
||||
|
||||
nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL); if
|
||||
(!nvs_aligned) return -ENOMEM;
|
||||
|
||||
/* And finally we upload the NVS tables */
|
||||
/* FIXME: In wl1271, we upload everything at once.
|
||||
No endianness handling needed here?! The ref driver doesn't do
|
||||
anything about it at this point */
|
||||
wl1271_spi_write(wl, CMD_MBOX_ADDRESS, nvs_aligned, nvs_len, false);
|
||||
wl1271_write(wl, CMD_MBOX_ADDRESS, nvs_aligned, nvs_len, false);
|
||||
|
||||
kfree(nvs_aligned);
|
||||
return 0;
|
||||
@ -309,9 +300,9 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
|
||||
static void wl1271_boot_enable_interrupts(struct wl1271 *wl)
|
||||
{
|
||||
enable_irq(wl->irq);
|
||||
wl1271_spi_write32(wl, ACX_REG_INTERRUPT_MASK,
|
||||
WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK));
|
||||
wl1271_spi_write32(wl, HI_CFG, HI_CFG_DEF_VAL);
|
||||
wl1271_write32(wl, ACX_REG_INTERRUPT_MASK,
|
||||
WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK));
|
||||
wl1271_write32(wl, HI_CFG, HI_CFG_DEF_VAL);
|
||||
}
|
||||
|
||||
static int wl1271_boot_soft_reset(struct wl1271 *wl)
|
||||
@ -320,13 +311,12 @@ static int wl1271_boot_soft_reset(struct wl1271 *wl)
|
||||
u32 boot_data;
|
||||
|
||||
/* perform soft reset */
|
||||
wl1271_spi_write32(wl, ACX_REG_SLV_SOFT_RESET,
|
||||
ACX_SLV_SOFT_RESET_BIT);
|
||||
wl1271_write32(wl, ACX_REG_SLV_SOFT_RESET, ACX_SLV_SOFT_RESET_BIT);
|
||||
|
||||
/* SOFT_RESET is self clearing */
|
||||
timeout = jiffies + usecs_to_jiffies(SOFT_RESET_MAX_TIME);
|
||||
while (1) {
|
||||
boot_data = wl1271_spi_read32(wl, ACX_REG_SLV_SOFT_RESET);
|
||||
boot_data = wl1271_read32(wl, ACX_REG_SLV_SOFT_RESET);
|
||||
wl1271_debug(DEBUG_BOOT, "soft reset bootdata 0x%x", boot_data);
|
||||
if ((boot_data & ACX_SLV_SOFT_RESET_BIT) == 0)
|
||||
break;
|
||||
@ -342,10 +332,10 @@ static int wl1271_boot_soft_reset(struct wl1271 *wl)
|
||||
}
|
||||
|
||||
/* disable Rx/Tx */
|
||||
wl1271_spi_write32(wl, ENABLE, 0x0);
|
||||
wl1271_write32(wl, ENABLE, 0x0);
|
||||
|
||||
/* disable auto calibration on start*/
|
||||
wl1271_spi_write32(wl, SPARE_A2, 0xffff);
|
||||
wl1271_write32(wl, SPARE_A2, 0xffff);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -357,7 +347,7 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)
|
||||
|
||||
wl1271_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT);
|
||||
|
||||
chip_id = wl1271_spi_read32(wl, CHIP_ID_B);
|
||||
chip_id = wl1271_read32(wl, CHIP_ID_B);
|
||||
|
||||
wl1271_debug(DEBUG_BOOT, "chip id after firmware boot: 0x%x", chip_id);
|
||||
|
||||
@ -370,8 +360,7 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)
|
||||
loop = 0;
|
||||
while (loop++ < INIT_LOOP) {
|
||||
udelay(INIT_LOOP_DELAY);
|
||||
interrupt = wl1271_spi_read32(wl,
|
||||
ACX_REG_INTERRUPT_NO_CLEAR);
|
||||
interrupt = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
|
||||
|
||||
if (interrupt == 0xffffffff) {
|
||||
wl1271_error("error reading hardware complete "
|
||||
@ -380,8 +369,8 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)
|
||||
}
|
||||
/* check that ACX_INTR_INIT_COMPLETE is enabled */
|
||||
else if (interrupt & WL1271_ACX_INTR_INIT_COMPLETE) {
|
||||
wl1271_spi_write32(wl, ACX_REG_INTERRUPT_ACK,
|
||||
WL1271_ACX_INTR_INIT_COMPLETE);
|
||||
wl1271_write32(wl, ACX_REG_INTERRUPT_ACK,
|
||||
WL1271_ACX_INTR_INIT_COMPLETE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -393,10 +382,10 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)
|
||||
}
|
||||
|
||||
/* get hardware config command mail box */
|
||||
wl->cmd_box_addr = wl1271_spi_read32(wl, REG_COMMAND_MAILBOX_PTR);
|
||||
wl->cmd_box_addr = wl1271_read32(wl, REG_COMMAND_MAILBOX_PTR);
|
||||
|
||||
/* get hardware config event mail box */
|
||||
wl->event_box_addr = wl1271_spi_read32(wl, REG_EVENT_MAILBOX_PTR);
|
||||
wl->event_box_addr = wl1271_read32(wl, REG_EVENT_MAILBOX_PTR);
|
||||
|
||||
/* set the working partition to its "running" mode offset */
|
||||
wl1271_set_partition(wl, &part_table[PART_WORK]);
|
||||
@ -469,9 +458,9 @@ int wl1271_boot(struct wl1271 *wl)
|
||||
wl1271_top_reg_write(wl, OCP_REG_CLK_POLARITY, val);
|
||||
}
|
||||
|
||||
wl1271_spi_write32(wl, PLL_PARAMETERS, clk);
|
||||
wl1271_write32(wl, PLL_PARAMETERS, clk);
|
||||
|
||||
pause = wl1271_spi_read32(wl, PLL_PARAMETERS);
|
||||
pause = wl1271_read32(wl, PLL_PARAMETERS);
|
||||
|
||||
wl1271_debug(DEBUG_BOOT, "pause1 0x%x", pause);
|
||||
|
||||
@ -480,10 +469,10 @@ int wl1271_boot(struct wl1271 *wl)
|
||||
* 0x3ff (magic number ). How does
|
||||
* this work?! */
|
||||
pause |= WU_COUNTER_PAUSE_VAL;
|
||||
wl1271_spi_write32(wl, WU_COUNTER_PAUSE, pause);
|
||||
wl1271_write32(wl, WU_COUNTER_PAUSE, pause);
|
||||
|
||||
/* Continue the ELP wake up sequence */
|
||||
wl1271_spi_write32(wl, WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL);
|
||||
wl1271_write32(wl, WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL);
|
||||
udelay(500);
|
||||
|
||||
wl1271_set_partition(wl, &part_table[PART_DRPW]);
|
||||
@ -493,18 +482,18 @@ int wl1271_boot(struct wl1271 *wl)
|
||||
before taking DRPw out of reset */
|
||||
|
||||
wl1271_debug(DEBUG_BOOT, "DRPW_SCRATCH_START %08x", DRPW_SCRATCH_START);
|
||||
clk = wl1271_spi_read32(wl, DRPW_SCRATCH_START);
|
||||
clk = wl1271_read32(wl, DRPW_SCRATCH_START);
|
||||
|
||||
wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk);
|
||||
|
||||
/* 2 */
|
||||
clk |= (REF_CLOCK << 1) << 4;
|
||||
wl1271_spi_write32(wl, DRPW_SCRATCH_START, clk);
|
||||
wl1271_write32(wl, DRPW_SCRATCH_START, clk);
|
||||
|
||||
wl1271_set_partition(wl, &part_table[PART_WORK]);
|
||||
|
||||
/* Disable interrupts */
|
||||
wl1271_spi_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL);
|
||||
wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL);
|
||||
|
||||
ret = wl1271_boot_soft_reset(wl);
|
||||
if (ret < 0)
|
||||
@ -519,23 +508,22 @@ int wl1271_boot(struct wl1271 *wl)
|
||||
* ACX_EEPROMLESS_IND_REG */
|
||||
wl1271_debug(DEBUG_BOOT, "ACX_EEPROMLESS_IND_REG");
|
||||
|
||||
wl1271_spi_write32(wl, ACX_EEPROMLESS_IND_REG,
|
||||
ACX_EEPROMLESS_IND_REG);
|
||||
wl1271_write32(wl, ACX_EEPROMLESS_IND_REG, ACX_EEPROMLESS_IND_REG);
|
||||
|
||||
tmp = wl1271_spi_read32(wl, CHIP_ID_B);
|
||||
tmp = wl1271_read32(wl, CHIP_ID_B);
|
||||
|
||||
wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp);
|
||||
|
||||
/* 6. read the EEPROM parameters */
|
||||
tmp = wl1271_spi_read32(wl, SCR_PAD2);
|
||||
tmp = wl1271_read32(wl, SCR_PAD2);
|
||||
|
||||
ret = wl1271_boot_write_irq_polarity(wl);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
/* FIXME: Need to check whether this is really what we want */
|
||||
wl1271_spi_write32(wl, ACX_REG_INTERRUPT_MASK,
|
||||
WL1271_ACX_ALL_EVENTS_VECTOR);
|
||||
wl1271_write32(wl, ACX_REG_INTERRUPT_MASK,
|
||||
WL1271_ACX_ALL_EVENTS_VECTOR);
|
||||
|
||||
/* WL1271: The reference driver skips steps 7 to 10 (jumps directly
|
||||
* to upload_fw) */
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "wl1271.h"
|
||||
#include "wl1271_reg.h"
|
||||
#include "wl1271_spi.h"
|
||||
#include "wl1271_io.h"
|
||||
#include "wl1271_acx.h"
|
||||
#include "wl12xx_80211.h"
|
||||
#include "wl1271_cmd.h"
|
||||
@ -57,13 +58,13 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
|
||||
|
||||
WARN_ON(len % 4 != 0);
|
||||
|
||||
wl1271_spi_write(wl, wl->cmd_box_addr, buf, len, false);
|
||||
wl1271_write(wl, wl->cmd_box_addr, buf, len, false);
|
||||
|
||||
wl1271_spi_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_CMD);
|
||||
wl1271_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_CMD);
|
||||
|
||||
timeout = jiffies + msecs_to_jiffies(WL1271_COMMAND_TIMEOUT);
|
||||
|
||||
intr = wl1271_spi_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
|
||||
intr = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
|
||||
while (!(intr & WL1271_ACX_INTR_CMD_COMPLETE)) {
|
||||
if (time_after(jiffies, timeout)) {
|
||||
wl1271_error("command complete timeout");
|
||||
@ -73,13 +74,13 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
|
||||
|
||||
msleep(1);
|
||||
|
||||
intr = wl1271_spi_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
|
||||
intr = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
|
||||
}
|
||||
|
||||
/* read back the status code of the command */
|
||||
if (res_len == 0)
|
||||
res_len = sizeof(struct wl1271_cmd_header);
|
||||
wl1271_spi_read(wl, wl->cmd_box_addr, cmd, res_len, false);
|
||||
wl1271_read(wl, wl->cmd_box_addr, cmd, res_len, false);
|
||||
|
||||
status = le16_to_cpu(cmd->status);
|
||||
if (status != CMD_STATUS_SUCCESS) {
|
||||
@ -87,8 +88,8 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
|
||||
ret = -EIO;
|
||||
}
|
||||
|
||||
wl1271_spi_write32(wl, ACX_REG_INTERRUPT_ACK,
|
||||
WL1271_ACX_INTR_CMD_COMPLETE);
|
||||
wl1271_write32(wl, ACX_REG_INTERRUPT_ACK,
|
||||
WL1271_ACX_INTR_CMD_COMPLETE);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
@ -191,43 +192,19 @@ static int wl1271_cmd_cal(struct wl1271 *wl)
|
||||
int wl1271_cmd_general_parms(struct wl1271 *wl)
|
||||
{
|
||||
struct wl1271_general_parms_cmd *gen_parms;
|
||||
struct conf_general_parms *g = &wl->conf.init.genparam;
|
||||
int ret;
|
||||
|
||||
if (!wl->nvs)
|
||||
return -ENODEV;
|
||||
|
||||
gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL);
|
||||
if (!gen_parms)
|
||||
return -ENOMEM;
|
||||
|
||||
gen_parms->test.id = TEST_CMD_INI_FILE_GENERAL_PARAM;
|
||||
|
||||
gen_parms->ref_clk = g->ref_clk;
|
||||
gen_parms->settling_time = g->settling_time;
|
||||
gen_parms->clk_valid_on_wakeup = g->clk_valid_on_wakeup;
|
||||
gen_parms->dc2dcmode = g->dc2dcmode;
|
||||
gen_parms->single_dual_band = g->single_dual_band;
|
||||
gen_parms->tx_bip_fem_autodetect = g->tx_bip_fem_autodetect;
|
||||
gen_parms->tx_bip_fem_manufacturer = g->tx_bip_fem_manufacturer;
|
||||
gen_parms->settings = g->settings;
|
||||
|
||||
gen_parms->sr_state = g->sr_state;
|
||||
|
||||
memcpy(gen_parms->srf1,
|
||||
g->srf1,
|
||||
CONF_MAX_SMART_REFLEX_PARAMS);
|
||||
memcpy(gen_parms->srf2,
|
||||
g->srf2,
|
||||
CONF_MAX_SMART_REFLEX_PARAMS);
|
||||
memcpy(gen_parms->srf3,
|
||||
g->srf3,
|
||||
CONF_MAX_SMART_REFLEX_PARAMS);
|
||||
memcpy(gen_parms->sr_debug_table,
|
||||
g->sr_debug_table,
|
||||
CONF_MAX_SMART_REFLEX_PARAMS);
|
||||
|
||||
gen_parms->sr_sen_n_p = g->sr_sen_n_p;
|
||||
gen_parms->sr_sen_n_p_gain = g->sr_sen_n_p_gain;
|
||||
gen_parms->sr_sen_nrn = g->sr_sen_nrn;
|
||||
gen_parms->sr_sen_prn = g->sr_sen_prn;
|
||||
memcpy(gen_parms->params, wl->nvs->general_params,
|
||||
WL1271_NVS_GENERAL_PARAMS_SIZE);
|
||||
|
||||
ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), 0);
|
||||
if (ret < 0)
|
||||
@ -240,8 +217,11 @@ int wl1271_cmd_general_parms(struct wl1271 *wl)
|
||||
int wl1271_cmd_radio_parms(struct wl1271 *wl)
|
||||
{
|
||||
struct wl1271_radio_parms_cmd *radio_parms;
|
||||
struct conf_radio_parms *r = &wl->conf.init.radioparam;
|
||||
int i, ret;
|
||||
struct conf_radio_parms *rparam = &wl->conf.init.radioparam;
|
||||
int ret;
|
||||
|
||||
if (!wl->nvs)
|
||||
return -ENODEV;
|
||||
|
||||
radio_parms = kzalloc(sizeof(*radio_parms), GFP_KERNEL);
|
||||
if (!radio_parms)
|
||||
@ -249,73 +229,13 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl)
|
||||
|
||||
radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM;
|
||||
|
||||
/* Static radio parameters */
|
||||
radio_parms->rx_trace_loss = r->rx_trace_loss;
|
||||
radio_parms->tx_trace_loss = r->tx_trace_loss;
|
||||
memcpy(radio_parms->rx_rssi_and_proc_compens,
|
||||
r->rx_rssi_and_proc_compens,
|
||||
CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE);
|
||||
memcpy(radio_parms->stat_radio_params, wl->nvs->stat_radio_params,
|
||||
WL1271_NVS_STAT_RADIO_PARAMS_SIZE);
|
||||
memcpy(radio_parms->dyn_radio_params,
|
||||
wl->nvs->dyn_radio_params[rparam->fem],
|
||||
WL1271_NVS_DYN_RADIO_PARAMS_SIZE);
|
||||
|
||||
memcpy(radio_parms->rx_trace_loss_5, r->rx_trace_loss_5,
|
||||
CONF_NUMBER_OF_SUB_BANDS_5);
|
||||
memcpy(radio_parms->tx_trace_loss_5, r->tx_trace_loss_5,
|
||||
CONF_NUMBER_OF_SUB_BANDS_5);
|
||||
memcpy(radio_parms->rx_rssi_and_proc_compens_5,
|
||||
r->rx_rssi_and_proc_compens_5,
|
||||
CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE);
|
||||
|
||||
/* Dynamic radio parameters */
|
||||
radio_parms->tx_ref_pd_voltage = cpu_to_le16(r->tx_ref_pd_voltage);
|
||||
radio_parms->tx_ref_power = r->tx_ref_power;
|
||||
radio_parms->tx_offset_db = r->tx_offset_db;
|
||||
|
||||
memcpy(radio_parms->tx_rate_limits_normal, r->tx_rate_limits_normal,
|
||||
CONF_NUMBER_OF_RATE_GROUPS);
|
||||
memcpy(radio_parms->tx_rate_limits_degraded, r->tx_rate_limits_degraded,
|
||||
CONF_NUMBER_OF_RATE_GROUPS);
|
||||
memcpy(radio_parms->tx_rate_limits_extreme, r->tx_rate_limits_extreme,
|
||||
CONF_NUMBER_OF_RATE_GROUPS);
|
||||
|
||||
memcpy(radio_parms->tx_channel_limits_11b, r->tx_channel_limits_11b,
|
||||
CONF_NUMBER_OF_CHANNELS_2_4);
|
||||
memcpy(radio_parms->tx_channel_limits_ofdm, r->tx_channel_limits_ofdm,
|
||||
CONF_NUMBER_OF_CHANNELS_2_4);
|
||||
memcpy(radio_parms->tx_pdv_rate_offsets, r->tx_pdv_rate_offsets,
|
||||
CONF_NUMBER_OF_RATE_GROUPS);
|
||||
memcpy(radio_parms->tx_ibias, r->tx_ibias, CONF_NUMBER_OF_RATE_GROUPS);
|
||||
|
||||
radio_parms->rx_fem_insertion_loss = r->rx_fem_insertion_loss;
|
||||
radio_parms->degraded_low_to_normal_threshold =
|
||||
r->degraded_low_to_normal_threshold;
|
||||
radio_parms->degraded_normal_to_high_threshold =
|
||||
r->degraded_normal_to_high_threshold;
|
||||
|
||||
|
||||
for (i = 0; i < CONF_NUMBER_OF_SUB_BANDS_5; i++)
|
||||
radio_parms->tx_ref_pd_voltage_5[i] =
|
||||
cpu_to_le16(r->tx_ref_pd_voltage_5[i]);
|
||||
memcpy(radio_parms->tx_ref_power_5, r->tx_ref_power_5,
|
||||
CONF_NUMBER_OF_SUB_BANDS_5);
|
||||
memcpy(radio_parms->tx_offset_db_5, r->tx_offset_db_5,
|
||||
CONF_NUMBER_OF_SUB_BANDS_5);
|
||||
memcpy(radio_parms->tx_rate_limits_normal_5,
|
||||
r->tx_rate_limits_normal_5, CONF_NUMBER_OF_RATE_GROUPS);
|
||||
memcpy(radio_parms->tx_rate_limits_degraded_5,
|
||||
r->tx_rate_limits_degraded_5, CONF_NUMBER_OF_RATE_GROUPS);
|
||||
memcpy(radio_parms->tx_rate_limits_extreme_5,
|
||||
r->tx_rate_limits_extreme_5, CONF_NUMBER_OF_RATE_GROUPS);
|
||||
memcpy(radio_parms->tx_channel_limits_ofdm_5,
|
||||
r->tx_channel_limits_ofdm_5, CONF_NUMBER_OF_CHANNELS_5);
|
||||
memcpy(radio_parms->tx_pdv_rate_offsets_5, r->tx_pdv_rate_offsets_5,
|
||||
CONF_NUMBER_OF_RATE_GROUPS);
|
||||
memcpy(radio_parms->tx_ibias_5, r->tx_ibias_5,
|
||||
CONF_NUMBER_OF_RATE_GROUPS);
|
||||
memcpy(radio_parms->rx_fem_insertion_loss_5,
|
||||
r->rx_fem_insertion_loss_5, CONF_NUMBER_OF_SUB_BANDS_5);
|
||||
radio_parms->degraded_low_to_normal_threshold_5 =
|
||||
r->degraded_low_to_normal_threshold_5;
|
||||
radio_parms->degraded_normal_to_high_threshold_5 =
|
||||
r->degraded_normal_to_high_threshold_5;
|
||||
/* FIXME: current NVS is missing 5GHz parameters */
|
||||
|
||||
wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ",
|
||||
radio_parms, sizeof(*radio_parms));
|
||||
@ -555,7 +475,7 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode)
|
||||
int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send)
|
||||
{
|
||||
struct wl1271_cmd_ps_params *ps_params = NULL;
|
||||
int ret = 0;
|
||||
@ -576,7 +496,7 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode)
|
||||
}
|
||||
|
||||
ps_params->ps_mode = ps_mode;
|
||||
ps_params->send_null_data = 1;
|
||||
ps_params->send_null_data = send;
|
||||
ps_params->retries = 5;
|
||||
ps_params->hang_over_period = 128;
|
||||
ps_params->null_data_rate = cpu_to_le32(1); /* 1 Mbps */
|
||||
@ -1022,7 +942,7 @@ int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
|
||||
ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd), 0);
|
||||
if (ret < 0) {
|
||||
wl1271_warning("could not set keys");
|
||||
goto out;
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
|
@ -38,7 +38,7 @@ int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer);
|
||||
int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len);
|
||||
int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len);
|
||||
int wl1271_cmd_data_path(struct wl1271 *wl, bool enable);
|
||||
int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode);
|
||||
int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send);
|
||||
int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer,
|
||||
size_t len);
|
||||
int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len,
|
||||
@ -428,90 +428,24 @@ struct wl1271_general_parms_cmd {
|
||||
|
||||
struct wl1271_cmd_test_header test;
|
||||
|
||||
u8 ref_clk;
|
||||
u8 settling_time;
|
||||
u8 clk_valid_on_wakeup;
|
||||
u8 dc2dcmode;
|
||||
u8 single_dual_band;
|
||||
|
||||
u8 tx_bip_fem_autodetect;
|
||||
u8 tx_bip_fem_manufacturer;
|
||||
u8 settings;
|
||||
|
||||
u8 sr_state;
|
||||
|
||||
s8 srf1[CONF_MAX_SMART_REFLEX_PARAMS];
|
||||
s8 srf2[CONF_MAX_SMART_REFLEX_PARAMS];
|
||||
s8 srf3[CONF_MAX_SMART_REFLEX_PARAMS];
|
||||
|
||||
s8 sr_debug_table[CONF_MAX_SMART_REFLEX_PARAMS];
|
||||
|
||||
u8 sr_sen_n_p;
|
||||
u8 sr_sen_n_p_gain;
|
||||
u8 sr_sen_nrn;
|
||||
u8 sr_sen_prn;
|
||||
|
||||
u8 padding[3];
|
||||
u8 params[WL1271_NVS_GENERAL_PARAMS_SIZE];
|
||||
s8 reserved[23];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#define WL1271_STAT_RADIO_PARAMS_5_SIZE 29
|
||||
#define WL1271_DYN_RADIO_PARAMS_5_SIZE 104
|
||||
|
||||
struct wl1271_radio_parms_cmd {
|
||||
struct wl1271_cmd_header header;
|
||||
|
||||
struct wl1271_cmd_test_header test;
|
||||
|
||||
/* Static radio parameters */
|
||||
/* 2.4GHz */
|
||||
u8 rx_trace_loss;
|
||||
u8 tx_trace_loss;
|
||||
s8 rx_rssi_and_proc_compens[CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE];
|
||||
u8 stat_radio_params[WL1271_NVS_STAT_RADIO_PARAMS_SIZE];
|
||||
u8 stat_radio_params_5[WL1271_STAT_RADIO_PARAMS_5_SIZE];
|
||||
|
||||
/* 5GHz */
|
||||
u8 rx_trace_loss_5[CONF_NUMBER_OF_SUB_BANDS_5];
|
||||
u8 tx_trace_loss_5[CONF_NUMBER_OF_SUB_BANDS_5];
|
||||
s8 rx_rssi_and_proc_compens_5[CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE];
|
||||
|
||||
/* Dynamic radio parameters */
|
||||
/* 2.4GHz */
|
||||
__le16 tx_ref_pd_voltage;
|
||||
u8 tx_ref_power;
|
||||
s8 tx_offset_db;
|
||||
|
||||
s8 tx_rate_limits_normal[CONF_NUMBER_OF_RATE_GROUPS];
|
||||
s8 tx_rate_limits_degraded[CONF_NUMBER_OF_RATE_GROUPS];
|
||||
s8 tx_rate_limits_extreme[CONF_NUMBER_OF_RATE_GROUPS];
|
||||
|
||||
s8 tx_channel_limits_11b[CONF_NUMBER_OF_CHANNELS_2_4];
|
||||
s8 tx_channel_limits_ofdm[CONF_NUMBER_OF_CHANNELS_2_4];
|
||||
s8 tx_pdv_rate_offsets[CONF_NUMBER_OF_RATE_GROUPS];
|
||||
|
||||
u8 tx_ibias[CONF_NUMBER_OF_RATE_GROUPS];
|
||||
u8 rx_fem_insertion_loss;
|
||||
|
||||
u8 degraded_low_to_normal_threshold;
|
||||
u8 degraded_normal_to_high_threshold;
|
||||
|
||||
u8 padding1; /* our own padding, not in ref driver */
|
||||
|
||||
/* 5GHz */
|
||||
__le16 tx_ref_pd_voltage_5[CONF_NUMBER_OF_SUB_BANDS_5];
|
||||
u8 tx_ref_power_5[CONF_NUMBER_OF_SUB_BANDS_5];
|
||||
s8 tx_offset_db_5[CONF_NUMBER_OF_SUB_BANDS_5];
|
||||
|
||||
s8 tx_rate_limits_normal_5[CONF_NUMBER_OF_RATE_GROUPS];
|
||||
s8 tx_rate_limits_degraded_5[CONF_NUMBER_OF_RATE_GROUPS];
|
||||
s8 tx_rate_limits_extreme_5[CONF_NUMBER_OF_RATE_GROUPS];
|
||||
|
||||
s8 tx_channel_limits_ofdm_5[CONF_NUMBER_OF_CHANNELS_5];
|
||||
s8 tx_pdv_rate_offsets_5[CONF_NUMBER_OF_RATE_GROUPS];
|
||||
|
||||
/* FIXME: this is inconsistent with the types for 2.4GHz */
|
||||
s8 tx_ibias_5[CONF_NUMBER_OF_RATE_GROUPS];
|
||||
s8 rx_fem_insertion_loss_5[CONF_NUMBER_OF_SUB_BANDS_5];
|
||||
|
||||
u8 degraded_low_to_normal_threshold_5;
|
||||
u8 degraded_normal_to_high_threshold_5;
|
||||
|
||||
u8 padding2[2];
|
||||
u8 dyn_radio_params[WL1271_NVS_DYN_RADIO_PARAMS_SIZE];
|
||||
u8 reserved;
|
||||
u8 dyn_radio_params_5[WL1271_DYN_RADIO_PARAMS_5_SIZE];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct wl1271_cmd_cal_channel_tune {
|
||||
|
@ -735,81 +735,6 @@ enum single_dual_band_enum {
|
||||
CONF_DUAL_BAND
|
||||
};
|
||||
|
||||
|
||||
#define CONF_MAX_SMART_REFLEX_PARAMS 16
|
||||
|
||||
struct conf_general_parms {
|
||||
/*
|
||||
* RF Reference Clock type / speed
|
||||
*
|
||||
* Range: CONF_REF_CLK_*
|
||||
*/
|
||||
u8 ref_clk;
|
||||
|
||||
/*
|
||||
* Settling time of the reference clock after boot.
|
||||
*
|
||||
* Range: u8
|
||||
*/
|
||||
u8 settling_time;
|
||||
|
||||
/*
|
||||
* Flag defining whether clock is valid on wakeup.
|
||||
*
|
||||
* Range: 0 - not valid on wakeup, 1 - valid on wakeup
|
||||
*/
|
||||
u8 clk_valid_on_wakeup;
|
||||
|
||||
/*
|
||||
* DC-to-DC mode.
|
||||
*
|
||||
* Range: Unknown
|
||||
*/
|
||||
u8 dc2dcmode;
|
||||
|
||||
/*
|
||||
* Flag defining whether used as single or dual-band.
|
||||
*
|
||||
* Range: CONF_SINGLE_BAND, CONF_DUAL_BAND
|
||||
*/
|
||||
u8 single_dual_band;
|
||||
|
||||
/*
|
||||
* TX bip fem autodetect flag.
|
||||
*
|
||||
* Range: Unknown
|
||||
*/
|
||||
u8 tx_bip_fem_autodetect;
|
||||
|
||||
/*
|
||||
* TX bip gem manufacturer.
|
||||
*
|
||||
* Range: Unknown
|
||||
*/
|
||||
u8 tx_bip_fem_manufacturer;
|
||||
|
||||
/*
|
||||
* Settings flags.
|
||||
*
|
||||
* Range: Unknown
|
||||
*/
|
||||
u8 settings;
|
||||
|
||||
/* Smart reflex settings */
|
||||
u8 sr_state;
|
||||
|
||||
s8 srf1[CONF_MAX_SMART_REFLEX_PARAMS];
|
||||
s8 srf2[CONF_MAX_SMART_REFLEX_PARAMS];
|
||||
s8 srf3[CONF_MAX_SMART_REFLEX_PARAMS];
|
||||
|
||||
s8 sr_debug_table[CONF_MAX_SMART_REFLEX_PARAMS];
|
||||
|
||||
u8 sr_sen_n_p;
|
||||
u8 sr_sen_n_p_gain;
|
||||
u8 sr_sen_nrn;
|
||||
u8 sr_sen_prn;
|
||||
};
|
||||
|
||||
#define CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE 15
|
||||
#define CONF_NUMBER_OF_SUB_BANDS_5 7
|
||||
#define CONF_NUMBER_OF_RATE_GROUPS 6
|
||||
@ -818,77 +743,14 @@ struct conf_general_parms {
|
||||
|
||||
struct conf_radio_parms {
|
||||
/*
|
||||
* Static radio parameters for 2.4GHz
|
||||
* FEM parameter set to use
|
||||
*
|
||||
* Range: unknown
|
||||
* Range: 0 or 1
|
||||
*/
|
||||
u8 rx_trace_loss;
|
||||
u8 tx_trace_loss;
|
||||
s8 rx_rssi_and_proc_compens[CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE];
|
||||
|
||||
/*
|
||||
* Static radio parameters for 5GHz
|
||||
*
|
||||
* Range: unknown
|
||||
*/
|
||||
u8 rx_trace_loss_5[CONF_NUMBER_OF_SUB_BANDS_5];
|
||||
u8 tx_trace_loss_5[CONF_NUMBER_OF_SUB_BANDS_5];
|
||||
s8 rx_rssi_and_proc_compens_5[CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE];
|
||||
|
||||
/*
|
||||
* Dynamic radio parameters for 2.4GHz
|
||||
*
|
||||
* Range: unknown
|
||||
*/
|
||||
u16 tx_ref_pd_voltage;
|
||||
u8 tx_ref_power;
|
||||
s8 tx_offset_db;
|
||||
|
||||
s8 tx_rate_limits_normal[CONF_NUMBER_OF_RATE_GROUPS];
|
||||
s8 tx_rate_limits_degraded[CONF_NUMBER_OF_RATE_GROUPS];
|
||||
s8 tx_rate_limits_extreme[CONF_NUMBER_OF_RATE_GROUPS];
|
||||
|
||||
s8 tx_channel_limits_11b[CONF_NUMBER_OF_CHANNELS_2_4];
|
||||
s8 tx_channel_limits_ofdm[CONF_NUMBER_OF_CHANNELS_2_4];
|
||||
s8 tx_pdv_rate_offsets[CONF_NUMBER_OF_RATE_GROUPS];
|
||||
|
||||
u8 tx_ibias[CONF_NUMBER_OF_RATE_GROUPS];
|
||||
u8 rx_fem_insertion_loss;
|
||||
|
||||
u8 degraded_low_to_normal_threshold;
|
||||
u8 degraded_normal_to_high_threshold;
|
||||
|
||||
|
||||
/*
|
||||
* Dynamic radio parameters for 5GHz
|
||||
*
|
||||
* Range: unknown
|
||||
*/
|
||||
u16 tx_ref_pd_voltage_5[CONF_NUMBER_OF_SUB_BANDS_5];
|
||||
u8 tx_ref_power_5[CONF_NUMBER_OF_SUB_BANDS_5];
|
||||
s8 tx_offset_db_5[CONF_NUMBER_OF_SUB_BANDS_5];
|
||||
|
||||
s8 tx_rate_limits_normal_5[CONF_NUMBER_OF_RATE_GROUPS];
|
||||
s8 tx_rate_limits_degraded_5[CONF_NUMBER_OF_RATE_GROUPS];
|
||||
s8 tx_rate_limits_extreme_5[CONF_NUMBER_OF_RATE_GROUPS];
|
||||
|
||||
s8 tx_channel_limits_ofdm_5[CONF_NUMBER_OF_CHANNELS_5];
|
||||
s8 tx_pdv_rate_offsets_5[CONF_NUMBER_OF_RATE_GROUPS];
|
||||
|
||||
/* FIXME: this is inconsistent with the types for 2.4GHz */
|
||||
s8 tx_ibias_5[CONF_NUMBER_OF_RATE_GROUPS];
|
||||
s8 rx_fem_insertion_loss_5[CONF_NUMBER_OF_SUB_BANDS_5];
|
||||
|
||||
u8 degraded_low_to_normal_threshold_5;
|
||||
u8 degraded_normal_to_high_threshold_5;
|
||||
u8 fem;
|
||||
};
|
||||
|
||||
struct conf_init_settings {
|
||||
/*
|
||||
* Configure general parameters.
|
||||
*/
|
||||
struct conf_general_parms genparam;
|
||||
|
||||
/*
|
||||
* Configure radio parameters.
|
||||
*/
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "wl1271.h"
|
||||
#include "wl1271_reg.h"
|
||||
#include "wl1271_spi.h"
|
||||
#include "wl1271_io.h"
|
||||
#include "wl1271_event.h"
|
||||
#include "wl1271_ps.h"
|
||||
#include "wl12xx_80211.h"
|
||||
@ -78,24 +79,61 @@ static int wl1271_event_ps_report(struct wl1271 *wl,
|
||||
|
||||
switch (mbox->ps_status) {
|
||||
case EVENT_ENTER_POWER_SAVE_FAIL:
|
||||
wl1271_debug(DEBUG_PSM, "PSM entry failed");
|
||||
|
||||
if (!test_bit(WL1271_FLAG_PSM, &wl->flags)) {
|
||||
/* remain in active mode */
|
||||
wl->psm_entry_retry = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (wl->psm_entry_retry < wl->conf.conn.psm_entry_retries) {
|
||||
wl->psm_entry_retry++;
|
||||
ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE);
|
||||
ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE,
|
||||
true);
|
||||
} else {
|
||||
wl1271_error("PSM entry failed, giving up.\n");
|
||||
/* FIXME: this may need to be reconsidered. for now it
|
||||
is not possible to indicate to the mac80211
|
||||
afterwards that PSM entry failed. To maximize
|
||||
functionality (receiving data and remaining
|
||||
associated) make sure that we are in sync with the
|
||||
AP in regard of PSM mode. */
|
||||
ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE,
|
||||
false);
|
||||
wl->psm_entry_retry = 0;
|
||||
}
|
||||
break;
|
||||
case EVENT_ENTER_POWER_SAVE_SUCCESS:
|
||||
wl->psm_entry_retry = 0;
|
||||
|
||||
/* enable beacon filtering */
|
||||
ret = wl1271_acx_beacon_filter_opt(wl, true);
|
||||
if (ret < 0)
|
||||
break;
|
||||
|
||||
/* enable beacon early termination */
|
||||
ret = wl1271_acx_bet_enable(wl, true);
|
||||
if (ret < 0)
|
||||
break;
|
||||
|
||||
/* go to extremely low power mode */
|
||||
wl1271_ps_elp_sleep(wl);
|
||||
if (ret < 0)
|
||||
break;
|
||||
break;
|
||||
case EVENT_EXIT_POWER_SAVE_FAIL:
|
||||
wl1271_info("PSM exit failed");
|
||||
wl1271_debug(DEBUG_PSM, "PSM exit failed");
|
||||
|
||||
if (test_bit(WL1271_FLAG_PSM, &wl->flags)) {
|
||||
wl->psm_entry_retry = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* make sure the firmware goes to active mode - the frame to
|
||||
be sent next will indicate to the AP, that we are active. */
|
||||
ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE,
|
||||
false);
|
||||
break;
|
||||
case EVENT_EXIT_POWER_SAVE_SUCCESS:
|
||||
default:
|
||||
@ -177,7 +215,7 @@ int wl1271_event_unmask(struct wl1271 *wl)
|
||||
|
||||
void wl1271_event_mbox_config(struct wl1271 *wl)
|
||||
{
|
||||
wl->mbox_ptr[0] = wl1271_spi_read32(wl, REG_EVENT_MAILBOX_PTR);
|
||||
wl->mbox_ptr[0] = wl1271_read32(wl, REG_EVENT_MAILBOX_PTR);
|
||||
wl->mbox_ptr[1] = wl->mbox_ptr[0] + sizeof(struct event_mailbox);
|
||||
|
||||
wl1271_debug(DEBUG_EVENT, "MBOX ptrs: 0x%x 0x%x",
|
||||
@ -195,8 +233,8 @@ int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num)
|
||||
return -EINVAL;
|
||||
|
||||
/* first we read the mbox descriptor */
|
||||
wl1271_spi_read(wl, wl->mbox_ptr[mbox_num], &mbox,
|
||||
sizeof(struct event_mailbox), false);
|
||||
wl1271_read(wl, wl->mbox_ptr[mbox_num], &mbox,
|
||||
sizeof(struct event_mailbox), false);
|
||||
|
||||
/* process the descriptor */
|
||||
ret = wl1271_event_process(wl, &mbox);
|
||||
@ -204,7 +242,7 @@ int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num)
|
||||
return ret;
|
||||
|
||||
/* then we let the firmware know it can go on...*/
|
||||
wl1271_spi_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_EVENT_ACK);
|
||||
wl1271_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_EVENT_ACK);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ static int wl1271_init_hwenc_config(struct wl1271 *wl)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wl1271_init_templates_config(struct wl1271 *wl)
|
||||
int wl1271_init_templates_config(struct wl1271 *wl)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@ -113,7 +113,7 @@ static int wl1271_init_rx_config(struct wl1271 *wl, u32 config, u32 filter)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wl1271_init_phy_config(struct wl1271 *wl)
|
||||
int wl1271_init_phy_config(struct wl1271 *wl)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@ -156,7 +156,7 @@ static int wl1271_init_beacon_filter(struct wl1271 *wl)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wl1271_init_pta(struct wl1271 *wl)
|
||||
int wl1271_init_pta(struct wl1271 *wl)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@ -171,7 +171,7 @@ static int wl1271_init_pta(struct wl1271 *wl)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wl1271_init_energy_detection(struct wl1271 *wl)
|
||||
int wl1271_init_energy_detection(struct wl1271 *wl)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@ -195,7 +195,9 @@ static int wl1271_init_beacon_broadcast(struct wl1271 *wl)
|
||||
|
||||
int wl1271_hw_init(struct wl1271 *wl)
|
||||
{
|
||||
int ret;
|
||||
struct conf_tx_ac_category *conf_ac;
|
||||
struct conf_tx_tid *conf_tid;
|
||||
int ret, i;
|
||||
|
||||
ret = wl1271_cmd_general_parms(wl);
|
||||
if (ret < 0)
|
||||
@ -274,14 +276,28 @@ int wl1271_hw_init(struct wl1271 *wl)
|
||||
goto out_free_memmap;
|
||||
|
||||
/* Default TID configuration */
|
||||
ret = wl1271_acx_tid_cfg(wl);
|
||||
if (ret < 0)
|
||||
goto out_free_memmap;
|
||||
for (i = 0; i < wl->conf.tx.tid_conf_count; i++) {
|
||||
conf_tid = &wl->conf.tx.tid_conf[i];
|
||||
ret = wl1271_acx_tid_cfg(wl, conf_tid->queue_id,
|
||||
conf_tid->channel_type,
|
||||
conf_tid->tsid,
|
||||
conf_tid->ps_scheme,
|
||||
conf_tid->ack_policy,
|
||||
conf_tid->apsd_conf[0],
|
||||
conf_tid->apsd_conf[1]);
|
||||
if (ret < 0)
|
||||
goto out_free_memmap;
|
||||
}
|
||||
|
||||
/* Default AC configuration */
|
||||
ret = wl1271_acx_ac_cfg(wl);
|
||||
if (ret < 0)
|
||||
goto out_free_memmap;
|
||||
for (i = 0; i < wl->conf.tx.ac_conf_count; i++) {
|
||||
conf_ac = &wl->conf.tx.ac_conf[i];
|
||||
ret = wl1271_acx_ac_cfg(wl, conf_ac->ac, conf_ac->cw_min,
|
||||
conf_ac->cw_max, conf_ac->aifsn,
|
||||
conf_ac->tx_op_limit);
|
||||
if (ret < 0)
|
||||
goto out_free_memmap;
|
||||
}
|
||||
|
||||
/* Configure TX rate classes */
|
||||
ret = wl1271_acx_rate_policies(wl);
|
||||
|
@ -27,6 +27,10 @@
|
||||
#include "wl1271.h"
|
||||
|
||||
int wl1271_hw_init_power_auth(struct wl1271 *wl);
|
||||
int wl1271_init_templates_config(struct wl1271 *wl);
|
||||
int wl1271_init_phy_config(struct wl1271 *wl);
|
||||
int wl1271_init_pta(struct wl1271 *wl);
|
||||
int wl1271_init_energy_detection(struct wl1271 *wl);
|
||||
int wl1271_hw_init(struct wl1271 *wl);
|
||||
|
||||
#endif
|
||||
|
213
drivers/net/wireless/wl12xx/wl1271_io.c
Normal file
213
drivers/net/wireless/wl12xx/wl1271_io.c
Normal file
@ -0,0 +1,213 @@
|
||||
/*
|
||||
* This file is part of wl1271
|
||||
*
|
||||
* Copyright (C) 2008-2010 Nokia Corporation
|
||||
*
|
||||
* Contact: Luciano Coelho <luciano.coelho@nokia.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 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 St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/crc7.h>
|
||||
#include <linux/spi/spi.h>
|
||||
|
||||
#include "wl1271.h"
|
||||
#include "wl12xx_80211.h"
|
||||
#include "wl1271_spi.h"
|
||||
#include "wl1271_io.h"
|
||||
|
||||
static int wl1271_translate_addr(struct wl1271 *wl, int addr)
|
||||
{
|
||||
/*
|
||||
* To translate, first check to which window of addresses the
|
||||
* particular address belongs. Then subtract the starting address
|
||||
* of that window from the address. Then, add offset of the
|
||||
* translated region.
|
||||
*
|
||||
* The translated regions occur next to each other in physical device
|
||||
* memory, so just add the sizes of the preceeding address regions to
|
||||
* get the offset to the new region.
|
||||
*
|
||||
* Currently, only the two first regions are addressed, and the
|
||||
* assumption is that all addresses will fall into either of those
|
||||
* two.
|
||||
*/
|
||||
if ((addr >= wl->part.reg.start) &&
|
||||
(addr < wl->part.reg.start + wl->part.reg.size))
|
||||
return addr - wl->part.reg.start + wl->part.mem.size;
|
||||
else
|
||||
return addr - wl->part.mem.start;
|
||||
}
|
||||
|
||||
/* Set the SPI partitions to access the chip addresses
|
||||
*
|
||||
* To simplify driver code, a fixed (virtual) memory map is defined for
|
||||
* register and memory addresses. Because in the chipset, in different stages
|
||||
* of operation, those addresses will move around, an address translation
|
||||
* mechanism is required.
|
||||
*
|
||||
* There are four partitions (three memory and one register partition),
|
||||
* which are mapped to two different areas of the hardware memory.
|
||||
*
|
||||
* Virtual address
|
||||
* space
|
||||
*
|
||||
* | |
|
||||
* ...+----+--> mem.start
|
||||
* Physical address ... | |
|
||||
* space ... | | [PART_0]
|
||||
* ... | |
|
||||
* 00000000 <--+----+... ...+----+--> mem.start + mem.size
|
||||
* | | ... | |
|
||||
* |MEM | ... | |
|
||||
* | | ... | |
|
||||
* mem.size <--+----+... | | {unused area)
|
||||
* | | ... | |
|
||||
* |REG | ... | |
|
||||
* mem.size | | ... | |
|
||||
* + <--+----+... ...+----+--> reg.start
|
||||
* reg.size | | ... | |
|
||||
* |MEM2| ... | | [PART_1]
|
||||
* | | ... | |
|
||||
* ...+----+--> reg.start + reg.size
|
||||
* | |
|
||||
*
|
||||
*/
|
||||
int wl1271_set_partition(struct wl1271 *wl,
|
||||
struct wl1271_partition_set *p)
|
||||
{
|
||||
/* copy partition info */
|
||||
memcpy(&wl->part, p, sizeof(*p));
|
||||
|
||||
wl1271_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
|
||||
p->mem.start, p->mem.size);
|
||||
wl1271_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
|
||||
p->reg.start, p->reg.size);
|
||||
wl1271_debug(DEBUG_SPI, "mem2_start %08X mem2_size %08X",
|
||||
p->mem2.start, p->mem2.size);
|
||||
wl1271_debug(DEBUG_SPI, "mem3_start %08X mem3_size %08X",
|
||||
p->mem3.start, p->mem3.size);
|
||||
|
||||
/* write partition info to the chipset */
|
||||
wl1271_raw_write32(wl, HW_PART0_START_ADDR, p->mem.start);
|
||||
wl1271_raw_write32(wl, HW_PART0_SIZE_ADDR, p->mem.size);
|
||||
wl1271_raw_write32(wl, HW_PART1_START_ADDR, p->reg.start);
|
||||
wl1271_raw_write32(wl, HW_PART1_SIZE_ADDR, p->reg.size);
|
||||
wl1271_raw_write32(wl, HW_PART2_START_ADDR, p->mem2.start);
|
||||
wl1271_raw_write32(wl, HW_PART2_SIZE_ADDR, p->mem2.size);
|
||||
wl1271_raw_write32(wl, HW_PART3_START_ADDR, p->mem3.start);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void wl1271_io_reset(struct wl1271 *wl)
|
||||
{
|
||||
wl1271_spi_reset(wl);
|
||||
}
|
||||
|
||||
void wl1271_io_init(struct wl1271 *wl)
|
||||
{
|
||||
wl1271_spi_init(wl);
|
||||
}
|
||||
|
||||
void wl1271_raw_write(struct wl1271 *wl, int addr, void *buf,
|
||||
size_t len, bool fixed)
|
||||
{
|
||||
wl1271_spi_raw_write(wl, addr, buf, len, fixed);
|
||||
}
|
||||
|
||||
void wl1271_raw_read(struct wl1271 *wl, int addr, void *buf,
|
||||
size_t len, bool fixed)
|
||||
{
|
||||
wl1271_spi_raw_read(wl, addr, buf, len, fixed);
|
||||
}
|
||||
|
||||
void wl1271_read(struct wl1271 *wl, int addr, void *buf, size_t len,
|
||||
bool fixed)
|
||||
{
|
||||
int physical;
|
||||
|
||||
physical = wl1271_translate_addr(wl, addr);
|
||||
|
||||
wl1271_spi_raw_read(wl, physical, buf, len, fixed);
|
||||
}
|
||||
|
||||
void wl1271_write(struct wl1271 *wl, int addr, void *buf, size_t len,
|
||||
bool fixed)
|
||||
{
|
||||
int physical;
|
||||
|
||||
physical = wl1271_translate_addr(wl, addr);
|
||||
|
||||
wl1271_spi_raw_write(wl, physical, buf, len, fixed);
|
||||
}
|
||||
|
||||
u32 wl1271_read32(struct wl1271 *wl, int addr)
|
||||
{
|
||||
return wl1271_raw_read32(wl, wl1271_translate_addr(wl, addr));
|
||||
}
|
||||
|
||||
void wl1271_write32(struct wl1271 *wl, int addr, u32 val)
|
||||
{
|
||||
wl1271_raw_write32(wl, wl1271_translate_addr(wl, addr), val);
|
||||
}
|
||||
|
||||
void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val)
|
||||
{
|
||||
/* write address >> 1 + 0x30000 to OCP_POR_CTR */
|
||||
addr = (addr >> 1) + 0x30000;
|
||||
wl1271_write32(wl, OCP_POR_CTR, addr);
|
||||
|
||||
/* write value to OCP_POR_WDATA */
|
||||
wl1271_write32(wl, OCP_DATA_WRITE, val);
|
||||
|
||||
/* write 1 to OCP_CMD */
|
||||
wl1271_write32(wl, OCP_CMD, OCP_CMD_WRITE);
|
||||
}
|
||||
|
||||
u16 wl1271_top_reg_read(struct wl1271 *wl, int addr)
|
||||
{
|
||||
u32 val;
|
||||
int timeout = OCP_CMD_LOOP;
|
||||
|
||||
/* write address >> 1 + 0x30000 to OCP_POR_CTR */
|
||||
addr = (addr >> 1) + 0x30000;
|
||||
wl1271_write32(wl, OCP_POR_CTR, addr);
|
||||
|
||||
/* write 2 to OCP_CMD */
|
||||
wl1271_write32(wl, OCP_CMD, OCP_CMD_READ);
|
||||
|
||||
/* poll for data ready */
|
||||
do {
|
||||
val = wl1271_read32(wl, OCP_DATA_READ);
|
||||
} while (!(val & OCP_READY_MASK) && --timeout);
|
||||
|
||||
if (!timeout) {
|
||||
wl1271_warning("Top register access timed out.");
|
||||
return 0xffff;
|
||||
}
|
||||
|
||||
/* check data status and return if OK */
|
||||
if ((val & OCP_STATUS_MASK) == OCP_STATUS_OK)
|
||||
return val & 0xffff;
|
||||
else {
|
||||
wl1271_warning("Top register access returned error.");
|
||||
return 0xffff;
|
||||
}
|
||||
}
|
||||
|
68
drivers/net/wireless/wl12xx/wl1271_io.h
Normal file
68
drivers/net/wireless/wl12xx/wl1271_io.h
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* This file is part of wl1271
|
||||
*
|
||||
* Copyright (C) 1998-2009 Texas Instruments. All rights reserved.
|
||||
* Copyright (C) 2008-2010 Nokia Corporation
|
||||
*
|
||||
* Contact: Luciano Coelho <luciano.coelho@nokia.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 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 St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __WL1271_IO_H__
|
||||
#define __WL1271_IO_H__
|
||||
|
||||
struct wl1271;
|
||||
|
||||
void wl1271_io_reset(struct wl1271 *wl);
|
||||
void wl1271_io_init(struct wl1271 *wl);
|
||||
|
||||
/* Raw target IO, address is not translated */
|
||||
void wl1271_raw_write(struct wl1271 *wl, int addr, void *buf,
|
||||
size_t len, bool fixed);
|
||||
void wl1271_raw_read(struct wl1271 *wl, int addr, void *buf,
|
||||
size_t len, bool fixed);
|
||||
|
||||
/* Translated target IO */
|
||||
void wl1271_read(struct wl1271 *wl, int addr, void *buf, size_t len,
|
||||
bool fixed);
|
||||
void wl1271_write(struct wl1271 *wl, int addr, void *buf, size_t len,
|
||||
bool fixed);
|
||||
u32 wl1271_read32(struct wl1271 *wl, int addr);
|
||||
void wl1271_write32(struct wl1271 *wl, int addr, u32 val);
|
||||
|
||||
/* Top Register IO */
|
||||
void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val);
|
||||
u16 wl1271_top_reg_read(struct wl1271 *wl, int addr);
|
||||
|
||||
int wl1271_set_partition(struct wl1271 *wl,
|
||||
struct wl1271_partition_set *p);
|
||||
|
||||
static inline u32 wl1271_raw_read32(struct wl1271 *wl, int addr)
|
||||
{
|
||||
wl1271_raw_read(wl, addr, &wl->buffer_32,
|
||||
sizeof(wl->buffer_32), false);
|
||||
|
||||
return wl->buffer_32;
|
||||
}
|
||||
|
||||
static inline void wl1271_raw_write32(struct wl1271 *wl, int addr, u32 val)
|
||||
{
|
||||
wl->buffer_32 = val;
|
||||
wl1271_raw_write(wl, addr, &wl->buffer_32,
|
||||
sizeof(wl->buffer_32), false);
|
||||
}
|
||||
#endif
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* This file is part of wl1271
|
||||
*
|
||||
* Copyright (C) 2008-2009 Nokia Corporation
|
||||
* Copyright (C) 2008-2010 Nokia Corporation
|
||||
*
|
||||
* Contact: Luciano Coelho <luciano.coelho@nokia.com>
|
||||
*
|
||||
@ -38,6 +38,7 @@
|
||||
#include "wl12xx_80211.h"
|
||||
#include "wl1271_reg.h"
|
||||
#include "wl1271_spi.h"
|
||||
#include "wl1271_io.h"
|
||||
#include "wl1271_event.h"
|
||||
#include "wl1271_tx.h"
|
||||
#include "wl1271_rx.h"
|
||||
@ -46,6 +47,7 @@
|
||||
#include "wl1271_debugfs.h"
|
||||
#include "wl1271_cmd.h"
|
||||
#include "wl1271_boot.h"
|
||||
#include "wl1271_testmode.h"
|
||||
|
||||
#define WL1271_BOOT_RETRIES 3
|
||||
|
||||
@ -229,93 +231,8 @@ static struct conf_drv_settings default_conf = {
|
||||
.psm_entry_retries = 3
|
||||
},
|
||||
.init = {
|
||||
.genparam = {
|
||||
.ref_clk = CONF_REF_CLK_38_4_E,
|
||||
.settling_time = 5,
|
||||
.clk_valid_on_wakeup = 0,
|
||||
.dc2dcmode = 0,
|
||||
.single_dual_band = CONF_SINGLE_BAND,
|
||||
.tx_bip_fem_autodetect = 1,
|
||||
.tx_bip_fem_manufacturer = 1,
|
||||
.settings = 1,
|
||||
.sr_state = 1,
|
||||
.srf1 = { 0x07, 0x03, 0x18, 0x10, 0x05, 0xfb, 0xf0,
|
||||
0xe8, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
.srf2 = { 0x07, 0x03, 0x18, 0x10, 0x05, 0xfb, 0xf0,
|
||||
0xe8, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
.srf3 = { 0x07, 0x03, 0x18, 0x10, 0x05, 0xfb, 0xf0,
|
||||
0xe8, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
.sr_debug_table = { 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0 },
|
||||
.sr_sen_n_p = 0,
|
||||
.sr_sen_n_p_gain = 0,
|
||||
.sr_sen_nrn = 0,
|
||||
.sr_sen_prn = 0,
|
||||
},
|
||||
.radioparam = {
|
||||
.rx_trace_loss = 0x24,
|
||||
.tx_trace_loss = 0x0,
|
||||
.rx_rssi_and_proc_compens = {
|
||||
0xec, 0xf6, 0x00, 0x0c, 0x18, 0xf8,
|
||||
0xfc, 0x00, 0x80, 0x10, 0xf0, 0xf8,
|
||||
0x00, 0x0a, 0x14 },
|
||||
.rx_trace_loss_5 = { 0, 0, 0, 0, 0, 0, 0 },
|
||||
.tx_trace_loss_5 = { 0, 0, 0, 0, 0, 0, 0 },
|
||||
.rx_rssi_and_proc_compens_5 = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00 },
|
||||
.tx_ref_pd_voltage = 0x1a9,
|
||||
.tx_ref_power = 0x80,
|
||||
.tx_offset_db = 0x0,
|
||||
.tx_rate_limits_normal = {
|
||||
0x1d, 0x1f, 0x24, 0x28, 0x28, 0x29 },
|
||||
.tx_rate_limits_degraded = {
|
||||
0x19, 0x1f, 0x22, 0x23, 0x27, 0x28 },
|
||||
.tx_rate_limits_extreme = {
|
||||
0x19, 0x1c, 0x1e, 0x20, 0x24, 0x25 },
|
||||
.tx_channel_limits_11b = {
|
||||
0x22, 0x50, 0x50, 0x50, 0x50, 0x50,
|
||||
0x50, 0x50, 0x50, 0x50, 0x22, 0x50,
|
||||
0x22, 0x50 },
|
||||
.tx_channel_limits_ofdm = {
|
||||
0x20, 0x50, 0x50, 0x50, 0x50, 0x50,
|
||||
0x50, 0x50, 0x50, 0x50, 0x20, 0x50,
|
||||
0x20, 0x50 },
|
||||
.tx_pdv_rate_offsets = {
|
||||
0x07, 0x08, 0x04, 0x02, 0x02, 0x00 },
|
||||
.tx_ibias = {
|
||||
0x11, 0x11, 0x15, 0x11, 0x15, 0x0f },
|
||||
.rx_fem_insertion_loss = 0x0e,
|
||||
.degraded_low_to_normal_threshold = 0x1e,
|
||||
.degraded_normal_to_high_threshold = 0x2d,
|
||||
.tx_ref_pd_voltage_5 = {
|
||||
0x0190, 0x01a4, 0x01c3, 0x01d8,
|
||||
0x020a, 0x021c },
|
||||
.tx_ref_power_5 = {
|
||||
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 },
|
||||
.tx_offset_db_5 = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
||||
.tx_rate_limits_normal_5 = {
|
||||
0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 },
|
||||
.tx_rate_limits_degraded_5 = {
|
||||
0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 },
|
||||
.tx_rate_limits_extreme_5 = {
|
||||
0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 },
|
||||
.tx_channel_limits_ofdm_5 = {
|
||||
0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50,
|
||||
0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50,
|
||||
0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50,
|
||||
0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50,
|
||||
0x50, 0x50, 0x50 },
|
||||
.tx_pdv_rate_offsets_5 = {
|
||||
0x01, 0x02, 0x02, 0x02, 0x02, 0x00 },
|
||||
.tx_ibias_5 = {
|
||||
0x10, 0x10, 0x10, 0x10, 0x10, 0x10 },
|
||||
.rx_fem_insertion_loss_5 = {
|
||||
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 },
|
||||
.degraded_low_to_normal_threshold_5 = 0x00,
|
||||
.degraded_normal_to_high_threshold_5 = 0x00
|
||||
.fem = 1,
|
||||
}
|
||||
},
|
||||
.itrim = {
|
||||
@ -345,15 +262,14 @@ static void wl1271_conf_init(struct wl1271 *wl)
|
||||
|
||||
/* apply driver default configuration */
|
||||
memcpy(&wl->conf, &default_conf, sizeof(default_conf));
|
||||
|
||||
if (wl1271_11a_enabled())
|
||||
wl->conf.init.genparam.single_dual_band = CONF_DUAL_BAND;
|
||||
}
|
||||
|
||||
|
||||
static int wl1271_plt_init(struct wl1271 *wl)
|
||||
{
|
||||
int ret;
|
||||
struct conf_tx_ac_category *conf_ac;
|
||||
struct conf_tx_tid *conf_tid;
|
||||
int ret, i;
|
||||
|
||||
ret = wl1271_cmd_general_parms(wl);
|
||||
if (ret < 0)
|
||||
@ -363,15 +279,89 @@ static int wl1271_plt_init(struct wl1271 *wl)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = wl1271_init_templates_config(wl);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = wl1271_acx_init_mem_config(wl);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* PHY layer config */
|
||||
ret = wl1271_init_phy_config(wl);
|
||||
if (ret < 0)
|
||||
goto out_free_memmap;
|
||||
|
||||
ret = wl1271_acx_dco_itrim_params(wl);
|
||||
if (ret < 0)
|
||||
goto out_free_memmap;
|
||||
|
||||
/* Initialize connection monitoring thresholds */
|
||||
ret = wl1271_acx_conn_monit_params(wl);
|
||||
if (ret < 0)
|
||||
goto out_free_memmap;
|
||||
|
||||
/* Bluetooth WLAN coexistence */
|
||||
ret = wl1271_init_pta(wl);
|
||||
if (ret < 0)
|
||||
goto out_free_memmap;
|
||||
|
||||
/* Energy detection */
|
||||
ret = wl1271_init_energy_detection(wl);
|
||||
if (ret < 0)
|
||||
goto out_free_memmap;
|
||||
|
||||
/* Default fragmentation threshold */
|
||||
ret = wl1271_acx_frag_threshold(wl);
|
||||
if (ret < 0)
|
||||
goto out_free_memmap;
|
||||
|
||||
/* Default TID configuration */
|
||||
for (i = 0; i < wl->conf.tx.tid_conf_count; i++) {
|
||||
conf_tid = &wl->conf.tx.tid_conf[i];
|
||||
ret = wl1271_acx_tid_cfg(wl, conf_tid->queue_id,
|
||||
conf_tid->channel_type,
|
||||
conf_tid->tsid,
|
||||
conf_tid->ps_scheme,
|
||||
conf_tid->ack_policy,
|
||||
conf_tid->apsd_conf[0],
|
||||
conf_tid->apsd_conf[1]);
|
||||
if (ret < 0)
|
||||
goto out_free_memmap;
|
||||
}
|
||||
|
||||
/* Default AC configuration */
|
||||
for (i = 0; i < wl->conf.tx.ac_conf_count; i++) {
|
||||
conf_ac = &wl->conf.tx.ac_conf[i];
|
||||
ret = wl1271_acx_ac_cfg(wl, conf_ac->ac, conf_ac->cw_min,
|
||||
conf_ac->cw_max, conf_ac->aifsn,
|
||||
conf_ac->tx_op_limit);
|
||||
if (ret < 0)
|
||||
goto out_free_memmap;
|
||||
}
|
||||
|
||||
/* Enable data path */
|
||||
ret = wl1271_cmd_data_path(wl, 1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
goto out_free_memmap;
|
||||
|
||||
/* Configure for CAM power saving (ie. always active) */
|
||||
ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM);
|
||||
if (ret < 0)
|
||||
goto out_free_memmap;
|
||||
|
||||
/* configure PM */
|
||||
ret = wl1271_acx_pm_config(wl);
|
||||
if (ret < 0)
|
||||
goto out_free_memmap;
|
||||
|
||||
return 0;
|
||||
|
||||
out_free_memmap:
|
||||
kfree(wl->target_mem_map);
|
||||
wl->target_mem_map = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void wl1271_disable_interrupts(struct wl1271 *wl)
|
||||
@ -397,8 +387,7 @@ static void wl1271_fw_status(struct wl1271 *wl,
|
||||
u32 total = 0;
|
||||
int i;
|
||||
|
||||
wl1271_spi_read(wl, FW_STATUS_ADDR, status,
|
||||
sizeof(*status), false);
|
||||
wl1271_read(wl, FW_STATUS_ADDR, status, sizeof(*status), false);
|
||||
|
||||
wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, "
|
||||
"drv_rx_counter = %d, tx_results_counter = %d)",
|
||||
@ -445,7 +434,7 @@ static void wl1271_irq_work(struct work_struct *work)
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
wl1271_spi_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL);
|
||||
wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL);
|
||||
|
||||
wl1271_fw_status(wl, wl->fw_status);
|
||||
intr = le32_to_cpu(wl->fw_status->intr);
|
||||
@ -487,8 +476,8 @@ static void wl1271_irq_work(struct work_struct *work)
|
||||
}
|
||||
|
||||
out_sleep:
|
||||
wl1271_spi_write32(wl, ACX_REG_INTERRUPT_MASK,
|
||||
WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK));
|
||||
wl1271_write32(wl, ACX_REG_INTERRUPT_MASK,
|
||||
WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK));
|
||||
wl1271_ps_elp_sleep(wl);
|
||||
|
||||
out:
|
||||
@ -555,6 +544,40 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int wl1271_update_mac_addr(struct wl1271 *wl)
|
||||
{
|
||||
int ret = 0;
|
||||
u8 *nvs_ptr = (u8 *)wl->nvs->nvs;
|
||||
|
||||
/* get mac address from the NVS */
|
||||
wl->mac_addr[0] = nvs_ptr[11];
|
||||
wl->mac_addr[1] = nvs_ptr[10];
|
||||
wl->mac_addr[2] = nvs_ptr[6];
|
||||
wl->mac_addr[3] = nvs_ptr[5];
|
||||
wl->mac_addr[4] = nvs_ptr[4];
|
||||
wl->mac_addr[5] = nvs_ptr[3];
|
||||
|
||||
/* FIXME: if it is a zero-address, we should bail out. Now, instead,
|
||||
we randomize an address */
|
||||
if (is_zero_ether_addr(wl->mac_addr)) {
|
||||
static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf};
|
||||
memcpy(wl->mac_addr, nokia_oui, 3);
|
||||
get_random_bytes(wl->mac_addr + 3, 3);
|
||||
|
||||
/* update this address to the NVS */
|
||||
nvs_ptr[11] = wl->mac_addr[0];
|
||||
nvs_ptr[10] = wl->mac_addr[1];
|
||||
nvs_ptr[6] = wl->mac_addr[2];
|
||||
nvs_ptr[5] = wl->mac_addr[3];
|
||||
nvs_ptr[4] = wl->mac_addr[4];
|
||||
nvs_ptr[3] = wl->mac_addr[5];
|
||||
}
|
||||
|
||||
SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int wl1271_fetch_nvs(struct wl1271 *wl)
|
||||
{
|
||||
const struct firmware *fw;
|
||||
@ -567,15 +590,14 @@ static int wl1271_fetch_nvs(struct wl1271 *wl)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (fw->size % 4) {
|
||||
wl1271_error("nvs size is not multiple of 32 bits: %zu",
|
||||
fw->size);
|
||||
if (fw->size != sizeof(struct wl1271_nvs_file)) {
|
||||
wl1271_error("nvs size is not as expected: %zu != %zu",
|
||||
fw->size, sizeof(struct wl1271_nvs_file));
|
||||
ret = -EILSEQ;
|
||||
goto out;
|
||||
}
|
||||
|
||||
wl->nvs_len = fw->size;
|
||||
wl->nvs = kmalloc(wl->nvs_len, GFP_KERNEL);
|
||||
wl->nvs = kmalloc(sizeof(struct wl1271_nvs_file), GFP_KERNEL);
|
||||
|
||||
if (!wl->nvs) {
|
||||
wl1271_error("could not allocate memory for the nvs file");
|
||||
@ -583,9 +605,9 @@ static int wl1271_fetch_nvs(struct wl1271 *wl)
|
||||
goto out;
|
||||
}
|
||||
|
||||
memcpy(wl->nvs, fw->data, wl->nvs_len);
|
||||
memcpy(wl->nvs, fw->data, sizeof(struct wl1271_nvs_file));
|
||||
|
||||
ret = 0;
|
||||
ret = wl1271_update_mac_addr(wl);
|
||||
|
||||
out:
|
||||
release_firmware(fw);
|
||||
@ -626,8 +648,8 @@ static int wl1271_chip_wakeup(struct wl1271 *wl)
|
||||
msleep(WL1271_PRE_POWER_ON_SLEEP);
|
||||
wl1271_power_on(wl);
|
||||
msleep(WL1271_POWER_ON_SLEEP);
|
||||
wl1271_spi_reset(wl);
|
||||
wl1271_spi_init(wl);
|
||||
wl1271_io_reset(wl);
|
||||
wl1271_io_init(wl);
|
||||
|
||||
/* We don't need a real memory partition here, because we only want
|
||||
* to use the registers at this point. */
|
||||
@ -642,7 +664,7 @@ static int wl1271_chip_wakeup(struct wl1271 *wl)
|
||||
/* whal_FwCtrl_BootSm() */
|
||||
|
||||
/* 0. read chip id from CHIP_ID */
|
||||
wl->chip.id = wl1271_spi_read32(wl, CHIP_ID_B);
|
||||
wl->chip.id = wl1271_read32(wl, CHIP_ID_B);
|
||||
|
||||
/* 1. check if chip id is valid */
|
||||
|
||||
@ -716,11 +738,6 @@ int wl1271_plt_start(struct wl1271 *wl)
|
||||
if (ret < 0)
|
||||
goto irq_disable;
|
||||
|
||||
/* Make sure power saving is disabled */
|
||||
ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM);
|
||||
if (ret < 0)
|
||||
goto irq_disable;
|
||||
|
||||
wl->state = WL1271_STATE_PLT;
|
||||
wl1271_notice("firmware booted in PLT mode (%s)",
|
||||
wl->chip.fw_ver);
|
||||
@ -1234,8 +1251,16 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
|
||||
}
|
||||
|
||||
/* if the channel changes while joined, join again */
|
||||
if (channel != wl->channel && test_bit(WL1271_FLAG_JOINED, &wl->flags))
|
||||
wl1271_join_channel(wl, channel);
|
||||
if (channel != wl->channel &&
|
||||
test_bit(WL1271_FLAG_JOINED, &wl->flags)) {
|
||||
wl->channel = channel;
|
||||
/* FIXME: maybe use CMD_CHANNEL_SWITCH for this? */
|
||||
ret = wl1271_cmd_join(wl);
|
||||
if (ret < 0)
|
||||
wl1271_warning("cmd join to update channel failed %d",
|
||||
ret);
|
||||
} else
|
||||
wl->channel = channel;
|
||||
|
||||
if (conf->flags & IEEE80211_CONF_PS &&
|
||||
!test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) {
|
||||
@ -1248,7 +1273,8 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
|
||||
*/
|
||||
if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) {
|
||||
wl1271_info("psm enabled");
|
||||
ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE);
|
||||
ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE,
|
||||
true);
|
||||
}
|
||||
} else if (!(conf->flags & IEEE80211_CONF_PS) &&
|
||||
test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) {
|
||||
@ -1257,7 +1283,8 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
|
||||
clear_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags);
|
||||
|
||||
if (test_bit(WL1271_FLAG_PSM, &wl->flags))
|
||||
ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE);
|
||||
ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE,
|
||||
true);
|
||||
}
|
||||
|
||||
if (conf->power_level != wl->power_level) {
|
||||
@ -1449,9 +1476,24 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
wl1271_error("Could not add or replace key");
|
||||
goto out_sleep;
|
||||
}
|
||||
|
||||
/* the default WEP key needs to be configured at least once */
|
||||
if (key_type == KEY_WEP) {
|
||||
ret = wl1271_cmd_set_default_wep_key(wl,
|
||||
wl->default_key);
|
||||
if (ret < 0)
|
||||
goto out_sleep;
|
||||
}
|
||||
break;
|
||||
|
||||
case DISABLE_KEY:
|
||||
/* The wl1271 does not allow to remove unicast keys - they
|
||||
will be cleared automatically on next CMD_JOIN. Ignore the
|
||||
request silently, as we dont want the mac80211 to emit
|
||||
an error message. */
|
||||
if (!is_broadcast_ether_addr(addr))
|
||||
break;
|
||||
|
||||
ret = wl1271_cmd_set_key(wl, KEY_REMOVE,
|
||||
key_conf->keyidx, key_type,
|
||||
key_conf->keylen, key_conf->key,
|
||||
@ -1539,6 +1581,23 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void wl1271_ssid_set(struct wl1271 *wl, struct sk_buff *beacon)
|
||||
{
|
||||
u8 *ptr = beacon->data +
|
||||
offsetof(struct ieee80211_mgmt, u.beacon.variable);
|
||||
|
||||
/* find the location of the ssid in the beacon */
|
||||
while (ptr < beacon->data + beacon->len) {
|
||||
if (ptr[0] == WLAN_EID_SSID) {
|
||||
wl->ssid_len = ptr[1];
|
||||
memcpy(wl->ssid, ptr+2, wl->ssid_len);
|
||||
return;
|
||||
}
|
||||
ptr += ptr[1];
|
||||
}
|
||||
wl1271_error("ad-hoc beacon template has no SSID!\n");
|
||||
}
|
||||
|
||||
static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_bss_conf *bss_conf,
|
||||
@ -1546,6 +1605,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
|
||||
{
|
||||
enum wl1271_cmd_ps_mode mode;
|
||||
struct wl1271 *wl = hw->priv;
|
||||
bool do_join = false;
|
||||
int ret;
|
||||
|
||||
wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed");
|
||||
@ -1556,40 +1616,17 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
if ((changed & BSS_CHANGED_BSSID) &&
|
||||
/*
|
||||
* Now we know the correct bssid, so we send a new join command
|
||||
* and enable the BSSID filter
|
||||
*/
|
||||
memcmp(wl->bssid, bss_conf->bssid, ETH_ALEN)) {
|
||||
wl->rx_config |= CFG_BSSID_FILTER_EN;
|
||||
memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN);
|
||||
ret = wl1271_cmd_build_null_data(wl);
|
||||
if (ret < 0) {
|
||||
wl1271_warning("cmd buld null data failed %d",
|
||||
ret);
|
||||
goto out_sleep;
|
||||
}
|
||||
ret = wl1271_cmd_join(wl);
|
||||
if (ret < 0) {
|
||||
wl1271_warning("cmd join failed %d", ret);
|
||||
goto out_sleep;
|
||||
}
|
||||
set_bit(WL1271_FLAG_JOINED, &wl->flags);
|
||||
}
|
||||
|
||||
if (wl->bss_type == BSS_TYPE_IBSS) {
|
||||
/* FIXME: This implements rudimentary ad-hoc support -
|
||||
proper templates are on the wish list and notification
|
||||
on when they change. This patch will update the templates
|
||||
on every call to this function. Also, the firmware will not
|
||||
answer to probe-requests as it does not have the proper
|
||||
SSID set in the JOIN command. The probe-response template
|
||||
is set nevertheless, as the FW will ASSERT without it */
|
||||
on every call to this function. */
|
||||
struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
|
||||
|
||||
if (beacon) {
|
||||
struct ieee80211_hdr *hdr;
|
||||
|
||||
wl1271_ssid_set(wl, beacon);
|
||||
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON,
|
||||
beacon->data,
|
||||
beacon->len);
|
||||
@ -1611,9 +1648,31 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
|
||||
dev_kfree_skb(beacon);
|
||||
if (ret < 0)
|
||||
goto out_sleep;
|
||||
|
||||
/* Need to update the SSID (for filtering etc) */
|
||||
do_join = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ((changed & BSS_CHANGED_BSSID) &&
|
||||
/*
|
||||
* Now we know the correct bssid, so we send a new join command
|
||||
* and enable the BSSID filter
|
||||
*/
|
||||
memcmp(wl->bssid, bss_conf->bssid, ETH_ALEN)) {
|
||||
wl->rx_config |= CFG_BSSID_FILTER_EN;
|
||||
memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN);
|
||||
ret = wl1271_cmd_build_null_data(wl);
|
||||
if (ret < 0) {
|
||||
wl1271_warning("cmd buld null data failed %d",
|
||||
ret);
|
||||
goto out_sleep;
|
||||
}
|
||||
|
||||
/* Need to update the BSSID (for filtering etc) */
|
||||
do_join = true;
|
||||
}
|
||||
|
||||
if (changed & BSS_CHANGED_ASSOC) {
|
||||
if (bss_conf->assoc) {
|
||||
wl->aid = bss_conf->aid;
|
||||
@ -1637,7 +1696,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
|
||||
if (test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags) &&
|
||||
!test_bit(WL1271_FLAG_PSM, &wl->flags)) {
|
||||
mode = STATION_POWER_SAVE_MODE;
|
||||
ret = wl1271_ps_set_mode(wl, mode);
|
||||
ret = wl1271_ps_set_mode(wl, mode, true);
|
||||
if (ret < 0)
|
||||
goto out_sleep;
|
||||
}
|
||||
@ -1678,6 +1737,15 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
|
||||
}
|
||||
}
|
||||
|
||||
if (do_join) {
|
||||
ret = wl1271_cmd_join(wl);
|
||||
if (ret < 0) {
|
||||
wl1271_warning("cmd join failed %d", ret);
|
||||
goto out_sleep;
|
||||
}
|
||||
set_bit(WL1271_FLAG_JOINED, &wl->flags);
|
||||
}
|
||||
|
||||
out_sleep:
|
||||
wl1271_ps_elp_sleep(wl);
|
||||
|
||||
@ -1685,6 +1753,43 @@ out:
|
||||
mutex_unlock(&wl->mutex);
|
||||
}
|
||||
|
||||
static int wl1271_op_conf_tx(struct ieee80211_hw *hw, u16 queue,
|
||||
const struct ieee80211_tx_queue_params *params)
|
||||
{
|
||||
struct wl1271 *wl = hw->priv;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
wl1271_debug(DEBUG_MAC80211, "mac80211 conf tx %d", queue);
|
||||
|
||||
ret = wl1271_ps_elp_wakeup(wl, false);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = wl1271_acx_ac_cfg(wl, wl1271_tx_get_queue(queue),
|
||||
params->cw_min, params->cw_max,
|
||||
params->aifs, params->txop);
|
||||
if (ret < 0)
|
||||
goto out_sleep;
|
||||
|
||||
ret = wl1271_acx_tid_cfg(wl, wl1271_tx_get_queue(queue),
|
||||
CONF_CHANNEL_TYPE_EDCF,
|
||||
wl1271_tx_get_queue(queue),
|
||||
CONF_PS_SCHEME_LEGACY_PSPOLL,
|
||||
CONF_ACK_POLICY_LEGACY, 0, 0);
|
||||
if (ret < 0)
|
||||
goto out_sleep;
|
||||
|
||||
out_sleep:
|
||||
wl1271_ps_elp_sleep(wl);
|
||||
|
||||
out:
|
||||
mutex_unlock(&wl->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* can't be const, mac80211 writes to this */
|
||||
static struct ieee80211_rate wl1271_rates[] = {
|
||||
@ -1850,6 +1955,8 @@ static const struct ieee80211_ops wl1271_ops = {
|
||||
.hw_scan = wl1271_op_hw_scan,
|
||||
.bss_info_changed = wl1271_op_bss_info_changed,
|
||||
.set_rts_threshold = wl1271_op_set_rts_threshold,
|
||||
.conf_tx = wl1271_op_conf_tx,
|
||||
CFG80211_TESTMODE_CMD(wl1271_tm_cmd)
|
||||
};
|
||||
|
||||
static int wl1271_register_hw(struct wl1271 *wl)
|
||||
@ -1918,24 +2025,17 @@ static struct platform_device wl1271_device = {
|
||||
};
|
||||
|
||||
#define WL1271_DEFAULT_CHANNEL 0
|
||||
static int __devinit wl1271_probe(struct spi_device *spi)
|
||||
|
||||
static struct ieee80211_hw *wl1271_alloc_hw(void)
|
||||
{
|
||||
struct wl12xx_platform_data *pdata;
|
||||
struct ieee80211_hw *hw;
|
||||
struct wl1271 *wl;
|
||||
int ret, i;
|
||||
static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf};
|
||||
|
||||
pdata = spi->dev.platform_data;
|
||||
if (!pdata) {
|
||||
wl1271_error("no platform data");
|
||||
return -ENODEV;
|
||||
}
|
||||
int i;
|
||||
|
||||
hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops);
|
||||
if (!hw) {
|
||||
wl1271_error("could not alloc ieee80211_hw");
|
||||
return -ENOMEM;
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
wl = hw->priv;
|
||||
@ -1944,8 +2044,6 @@ static int __devinit wl1271_probe(struct spi_device *spi)
|
||||
INIT_LIST_HEAD(&wl->list);
|
||||
|
||||
wl->hw = hw;
|
||||
dev_set_drvdata(&spi->dev, wl);
|
||||
wl->spi = spi;
|
||||
|
||||
skb_queue_head_init(&wl->tx_queue);
|
||||
|
||||
@ -1969,16 +2067,57 @@ static int __devinit wl1271_probe(struct spi_device *spi)
|
||||
|
||||
spin_lock_init(&wl->wl_lock);
|
||||
|
||||
/*
|
||||
* In case our MAC address is not correctly set,
|
||||
* we use a random but Nokia MAC.
|
||||
*/
|
||||
memcpy(wl->mac_addr, nokia_oui, 3);
|
||||
get_random_bytes(wl->mac_addr + 3, 3);
|
||||
|
||||
wl->state = WL1271_STATE_OFF;
|
||||
mutex_init(&wl->mutex);
|
||||
|
||||
/* Apply default driver configuration. */
|
||||
wl1271_conf_init(wl);
|
||||
|
||||
return hw;
|
||||
}
|
||||
|
||||
int wl1271_free_hw(struct wl1271 *wl)
|
||||
{
|
||||
ieee80211_unregister_hw(wl->hw);
|
||||
|
||||
wl1271_debugfs_exit(wl);
|
||||
|
||||
kfree(wl->target_mem_map);
|
||||
vfree(wl->fw);
|
||||
wl->fw = NULL;
|
||||
kfree(wl->nvs);
|
||||
wl->nvs = NULL;
|
||||
|
||||
kfree(wl->fw_status);
|
||||
kfree(wl->tx_res_if);
|
||||
|
||||
ieee80211_free_hw(wl->hw);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit wl1271_probe(struct spi_device *spi)
|
||||
{
|
||||
struct wl12xx_platform_data *pdata;
|
||||
struct ieee80211_hw *hw;
|
||||
struct wl1271 *wl;
|
||||
int ret;
|
||||
|
||||
pdata = spi->dev.platform_data;
|
||||
if (!pdata) {
|
||||
wl1271_error("no platform data");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
hw = wl1271_alloc_hw();
|
||||
if (IS_ERR(hw))
|
||||
return PTR_ERR(hw);
|
||||
|
||||
wl = hw->priv;
|
||||
|
||||
dev_set_drvdata(&spi->dev, wl);
|
||||
wl->spi = spi;
|
||||
|
||||
/* This is the only SPI value that we need to set here, the rest
|
||||
* comes from the board-peripherals file */
|
||||
spi->bits_per_word = 32;
|
||||
@ -2020,9 +2159,6 @@ static int __devinit wl1271_probe(struct spi_device *spi)
|
||||
}
|
||||
dev_set_drvdata(&wl1271_device.dev, wl);
|
||||
|
||||
/* Apply default driver configuration. */
|
||||
wl1271_conf_init(wl);
|
||||
|
||||
ret = wl1271_init_ieee80211(wl);
|
||||
if (ret)
|
||||
goto out_platform;
|
||||
@ -2053,21 +2189,10 @@ static int __devexit wl1271_remove(struct spi_device *spi)
|
||||
{
|
||||
struct wl1271 *wl = dev_get_drvdata(&spi->dev);
|
||||
|
||||
ieee80211_unregister_hw(wl->hw);
|
||||
|
||||
wl1271_debugfs_exit(wl);
|
||||
platform_device_unregister(&wl1271_device);
|
||||
free_irq(wl->irq, wl);
|
||||
kfree(wl->target_mem_map);
|
||||
vfree(wl->fw);
|
||||
wl->fw = NULL;
|
||||
kfree(wl->nvs);
|
||||
wl->nvs = NULL;
|
||||
|
||||
kfree(wl->fw_status);
|
||||
kfree(wl->tx_res_if);
|
||||
|
||||
ieee80211_free_hw(wl->hw);
|
||||
wl1271_free_hw(wl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "wl1271_reg.h"
|
||||
#include "wl1271_ps.h"
|
||||
#include "wl1271_spi.h"
|
||||
#include "wl1271_io.h"
|
||||
|
||||
#define WL1271_WAKEUP_TIMEOUT 500
|
||||
|
||||
@ -118,7 +119,8 @@ out:
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode)
|
||||
int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
|
||||
bool send)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@ -126,21 +128,7 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode)
|
||||
case STATION_POWER_SAVE_MODE:
|
||||
wl1271_debug(DEBUG_PSM, "entering psm");
|
||||
|
||||
/* enable beacon filtering */
|
||||
ret = wl1271_acx_beacon_filter_opt(wl, true);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* enable beacon early termination */
|
||||
ret = wl1271_acx_bet_enable(wl, true);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = wl1271_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
wl1271_ps_elp_sleep(wl);
|
||||
ret = wl1271_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE, send);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@ -163,7 +151,7 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = wl1271_cmd_ps_mode(wl, STATION_ACTIVE_MODE);
|
||||
ret = wl1271_cmd_ps_mode(wl, STATION_ACTIVE_MODE, send);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
@ -27,7 +27,8 @@
|
||||
#include "wl1271.h"
|
||||
#include "wl1271_acx.h"
|
||||
|
||||
int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode);
|
||||
int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
|
||||
bool send);
|
||||
void wl1271_ps_elp_sleep(struct wl1271 *wl);
|
||||
int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake);
|
||||
void wl1271_elp_work(struct work_struct *work);
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "wl1271_reg.h"
|
||||
#include "wl1271_rx.h"
|
||||
#include "wl1271_spi.h"
|
||||
#include "wl1271_io.h"
|
||||
|
||||
static u8 wl1271_rx_get_mem_block(struct wl1271_fw_status *status,
|
||||
u32 drv_rx_counter)
|
||||
@ -166,7 +167,7 @@ static void wl1271_rx_handle_data(struct wl1271 *wl, u32 length)
|
||||
}
|
||||
|
||||
buf = skb_put(skb, length);
|
||||
wl1271_spi_read(wl, WL1271_SLV_MEM_DATA, buf, length, true);
|
||||
wl1271_read(wl, WL1271_SLV_MEM_DATA, buf, length, true);
|
||||
|
||||
/* the data read starts with the descriptor */
|
||||
desc = (struct wl1271_rx_descriptor *) buf;
|
||||
@ -210,15 +211,13 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status)
|
||||
wl->rx_mem_pool_addr.addr + 4;
|
||||
|
||||
/* Choose the block we want to read */
|
||||
wl1271_spi_write(wl, WL1271_SLV_REG_DATA,
|
||||
&wl->rx_mem_pool_addr,
|
||||
sizeof(wl->rx_mem_pool_addr), false);
|
||||
wl1271_write(wl, WL1271_SLV_REG_DATA, &wl->rx_mem_pool_addr,
|
||||
sizeof(wl->rx_mem_pool_addr), false);
|
||||
|
||||
wl1271_rx_handle_data(wl, buf_size);
|
||||
|
||||
wl->rx_counter++;
|
||||
drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK;
|
||||
wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter);
|
||||
}
|
||||
|
||||
wl1271_spi_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter);
|
||||
}
|
||||
|
@ -30,28 +30,6 @@
|
||||
#include "wl12xx_80211.h"
|
||||
#include "wl1271_spi.h"
|
||||
|
||||
static int wl1271_translate_addr(struct wl1271 *wl, int addr)
|
||||
{
|
||||
/*
|
||||
* To translate, first check to which window of addresses the
|
||||
* particular address belongs. Then subtract the starting address
|
||||
* of that window from the address. Then, add offset of the
|
||||
* translated region.
|
||||
*
|
||||
* The translated regions occur next to each other in physical device
|
||||
* memory, so just add the sizes of the preceeding address regions to
|
||||
* get the offset to the new region.
|
||||
*
|
||||
* Currently, only the two first regions are addressed, and the
|
||||
* assumption is that all addresses will fall into either of those
|
||||
* two.
|
||||
*/
|
||||
if ((addr >= wl->part.reg.start) &&
|
||||
(addr < wl->part.reg.start + wl->part.reg.size))
|
||||
return addr - wl->part.reg.start + wl->part.mem.size;
|
||||
else
|
||||
return addr - wl->part.mem.start;
|
||||
}
|
||||
|
||||
void wl1271_spi_reset(struct wl1271 *wl)
|
||||
{
|
||||
@ -133,67 +111,6 @@ void wl1271_spi_init(struct wl1271 *wl)
|
||||
wl1271_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN);
|
||||
}
|
||||
|
||||
/* Set the SPI partitions to access the chip addresses
|
||||
*
|
||||
* To simplify driver code, a fixed (virtual) memory map is defined for
|
||||
* register and memory addresses. Because in the chipset, in different stages
|
||||
* of operation, those addresses will move around, an address translation
|
||||
* mechanism is required.
|
||||
*
|
||||
* There are four partitions (three memory and one register partition),
|
||||
* which are mapped to two different areas of the hardware memory.
|
||||
*
|
||||
* Virtual address
|
||||
* space
|
||||
*
|
||||
* | |
|
||||
* ...+----+--> mem.start
|
||||
* Physical address ... | |
|
||||
* space ... | | [PART_0]
|
||||
* ... | |
|
||||
* 00000000 <--+----+... ...+----+--> mem.start + mem.size
|
||||
* | | ... | |
|
||||
* |MEM | ... | |
|
||||
* | | ... | |
|
||||
* mem.size <--+----+... | | {unused area)
|
||||
* | | ... | |
|
||||
* |REG | ... | |
|
||||
* mem.size | | ... | |
|
||||
* + <--+----+... ...+----+--> reg.start
|
||||
* reg.size | | ... | |
|
||||
* |MEM2| ... | | [PART_1]
|
||||
* | | ... | |
|
||||
* ...+----+--> reg.start + reg.size
|
||||
* | |
|
||||
*
|
||||
*/
|
||||
int wl1271_set_partition(struct wl1271 *wl,
|
||||
struct wl1271_partition_set *p)
|
||||
{
|
||||
/* copy partition info */
|
||||
memcpy(&wl->part, p, sizeof(*p));
|
||||
|
||||
wl1271_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
|
||||
p->mem.start, p->mem.size);
|
||||
wl1271_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
|
||||
p->reg.start, p->reg.size);
|
||||
wl1271_debug(DEBUG_SPI, "mem2_start %08X mem2_size %08X",
|
||||
p->mem2.start, p->mem2.size);
|
||||
wl1271_debug(DEBUG_SPI, "mem3_start %08X mem3_size %08X",
|
||||
p->mem3.start, p->mem3.size);
|
||||
|
||||
/* write partition info to the chipset */
|
||||
wl1271_raw_write32(wl, HW_PART0_START_ADDR, p->mem.start);
|
||||
wl1271_raw_write32(wl, HW_PART0_SIZE_ADDR, p->mem.size);
|
||||
wl1271_raw_write32(wl, HW_PART1_START_ADDR, p->reg.start);
|
||||
wl1271_raw_write32(wl, HW_PART1_SIZE_ADDR, p->reg.size);
|
||||
wl1271_raw_write32(wl, HW_PART2_START_ADDR, p->mem2.start);
|
||||
wl1271_raw_write32(wl, HW_PART2_SIZE_ADDR, p->mem2.size);
|
||||
wl1271_raw_write32(wl, HW_PART3_START_ADDR, p->mem3.start);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define WL1271_BUSY_WORD_TIMEOUT 1000
|
||||
|
||||
/* FIXME: Check busy words, removed due to SPI bug */
|
||||
@ -338,77 +255,3 @@ void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf,
|
||||
wl1271_dump(DEBUG_SPI, "spi_write cmd -> ", cmd, sizeof(*cmd));
|
||||
wl1271_dump(DEBUG_SPI, "spi_write buf -> ", buf, len);
|
||||
}
|
||||
|
||||
void wl1271_spi_read(struct wl1271 *wl, int addr, void *buf, size_t len,
|
||||
bool fixed)
|
||||
{
|
||||
int physical;
|
||||
|
||||
physical = wl1271_translate_addr(wl, addr);
|
||||
|
||||
wl1271_spi_raw_read(wl, physical, buf, len, fixed);
|
||||
}
|
||||
|
||||
void wl1271_spi_write(struct wl1271 *wl, int addr, void *buf, size_t len,
|
||||
bool fixed)
|
||||
{
|
||||
int physical;
|
||||
|
||||
physical = wl1271_translate_addr(wl, addr);
|
||||
|
||||
wl1271_spi_raw_write(wl, physical, buf, len, fixed);
|
||||
}
|
||||
|
||||
u32 wl1271_spi_read32(struct wl1271 *wl, int addr)
|
||||
{
|
||||
return wl1271_raw_read32(wl, wl1271_translate_addr(wl, addr));
|
||||
}
|
||||
|
||||
void wl1271_spi_write32(struct wl1271 *wl, int addr, u32 val)
|
||||
{
|
||||
wl1271_raw_write32(wl, wl1271_translate_addr(wl, addr), val);
|
||||
}
|
||||
|
||||
void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val)
|
||||
{
|
||||
/* write address >> 1 + 0x30000 to OCP_POR_CTR */
|
||||
addr = (addr >> 1) + 0x30000;
|
||||
wl1271_spi_write32(wl, OCP_POR_CTR, addr);
|
||||
|
||||
/* write value to OCP_POR_WDATA */
|
||||
wl1271_spi_write32(wl, OCP_DATA_WRITE, val);
|
||||
|
||||
/* write 1 to OCP_CMD */
|
||||
wl1271_spi_write32(wl, OCP_CMD, OCP_CMD_WRITE);
|
||||
}
|
||||
|
||||
u16 wl1271_top_reg_read(struct wl1271 *wl, int addr)
|
||||
{
|
||||
u32 val;
|
||||
int timeout = OCP_CMD_LOOP;
|
||||
|
||||
/* write address >> 1 + 0x30000 to OCP_POR_CTR */
|
||||
addr = (addr >> 1) + 0x30000;
|
||||
wl1271_spi_write32(wl, OCP_POR_CTR, addr);
|
||||
|
||||
/* write 2 to OCP_CMD */
|
||||
wl1271_spi_write32(wl, OCP_CMD, OCP_CMD_READ);
|
||||
|
||||
/* poll for data ready */
|
||||
do {
|
||||
val = wl1271_spi_read32(wl, OCP_DATA_READ);
|
||||
} while (!(val & OCP_READY_MASK) && --timeout);
|
||||
|
||||
if (!timeout) {
|
||||
wl1271_warning("Top register access timed out.");
|
||||
return 0xffff;
|
||||
}
|
||||
|
||||
/* check data status and return if OK */
|
||||
if ((val & OCP_STATUS_MASK) == OCP_STATUS_OK)
|
||||
return val & 0xffff;
|
||||
else {
|
||||
wl1271_warning("Top register access returned error.");
|
||||
return 0xffff;
|
||||
}
|
||||
}
|
||||
|
@ -90,37 +90,7 @@ void wl1271_spi_raw_write(struct wl1271 *wl, int addr, void *buf,
|
||||
void wl1271_spi_raw_read(struct wl1271 *wl, int addr, void *buf,
|
||||
size_t len, bool fixed);
|
||||
|
||||
/* Translated target IO */
|
||||
void wl1271_spi_read(struct wl1271 *wl, int addr, void *buf, size_t len,
|
||||
bool fixed);
|
||||
void wl1271_spi_write(struct wl1271 *wl, int addr, void *buf, size_t len,
|
||||
bool fixed);
|
||||
u32 wl1271_spi_read32(struct wl1271 *wl, int addr);
|
||||
void wl1271_spi_write32(struct wl1271 *wl, int addr, u32 val);
|
||||
|
||||
/* Top Register IO */
|
||||
void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val);
|
||||
u16 wl1271_top_reg_read(struct wl1271 *wl, int addr);
|
||||
|
||||
/* INIT and RESET words */
|
||||
void wl1271_spi_reset(struct wl1271 *wl);
|
||||
void wl1271_spi_init(struct wl1271 *wl);
|
||||
int wl1271_set_partition(struct wl1271 *wl,
|
||||
struct wl1271_partition_set *p);
|
||||
|
||||
static inline u32 wl1271_raw_read32(struct wl1271 *wl, int addr)
|
||||
{
|
||||
wl1271_spi_raw_read(wl, addr, &wl->buffer_32,
|
||||
sizeof(wl->buffer_32), false);
|
||||
|
||||
return wl->buffer_32;
|
||||
}
|
||||
|
||||
static inline void wl1271_raw_write32(struct wl1271 *wl, int addr, u32 val)
|
||||
{
|
||||
wl->buffer_32 = val;
|
||||
wl1271_spi_raw_write(wl, addr, &wl->buffer_32,
|
||||
sizeof(wl->buffer_32), false);
|
||||
}
|
||||
|
||||
#endif /* __WL1271_SPI_H__ */
|
||||
|
283
drivers/net/wireless/wl12xx/wl1271_testmode.c
Normal file
283
drivers/net/wireless/wl12xx/wl1271_testmode.c
Normal file
@ -0,0 +1,283 @@
|
||||
/*
|
||||
* This file is part of wl1271
|
||||
*
|
||||
* Copyright (C) 2010 Nokia Corporation
|
||||
*
|
||||
* Contact: Luciano Coelho <luciano.coelho@nokia.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 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 St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
#include "wl1271_testmode.h"
|
||||
|
||||
#include <net/genetlink.h>
|
||||
|
||||
#include "wl1271.h"
|
||||
#include "wl1271_spi.h"
|
||||
#include "wl1271_acx.h"
|
||||
|
||||
#define WL1271_TM_MAX_DATA_LENGTH 1024
|
||||
|
||||
enum wl1271_tm_commands {
|
||||
WL1271_TM_CMD_UNSPEC,
|
||||
WL1271_TM_CMD_TEST,
|
||||
WL1271_TM_CMD_INTERROGATE,
|
||||
WL1271_TM_CMD_CONFIGURE,
|
||||
WL1271_TM_CMD_NVS_PUSH,
|
||||
WL1271_TM_CMD_SET_PLT_MODE,
|
||||
|
||||
__WL1271_TM_CMD_AFTER_LAST
|
||||
};
|
||||
#define WL1271_TM_CMD_MAX (__WL1271_TM_CMD_AFTER_LAST - 1)
|
||||
|
||||
enum wl1271_tm_attrs {
|
||||
WL1271_TM_ATTR_UNSPEC,
|
||||
WL1271_TM_ATTR_CMD_ID,
|
||||
WL1271_TM_ATTR_ANSWER,
|
||||
WL1271_TM_ATTR_DATA,
|
||||
WL1271_TM_ATTR_IE_ID,
|
||||
WL1271_TM_ATTR_PLT_MODE,
|
||||
|
||||
__WL1271_TM_ATTR_AFTER_LAST
|
||||
};
|
||||
#define WL1271_TM_ATTR_MAX (__WL1271_TM_ATTR_AFTER_LAST - 1)
|
||||
|
||||
static struct nla_policy wl1271_tm_policy[WL1271_TM_ATTR_MAX + 1] = {
|
||||
[WL1271_TM_ATTR_CMD_ID] = { .type = NLA_U32 },
|
||||
[WL1271_TM_ATTR_ANSWER] = { .type = NLA_U8 },
|
||||
[WL1271_TM_ATTR_DATA] = { .type = NLA_BINARY,
|
||||
.len = WL1271_TM_MAX_DATA_LENGTH },
|
||||
[WL1271_TM_ATTR_IE_ID] = { .type = NLA_U32 },
|
||||
[WL1271_TM_ATTR_PLT_MODE] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
|
||||
static int wl1271_tm_cmd_test(struct wl1271 *wl, struct nlattr *tb[])
|
||||
{
|
||||
int buf_len, ret, len;
|
||||
struct sk_buff *skb;
|
||||
void *buf;
|
||||
u8 answer = 0;
|
||||
|
||||
wl1271_debug(DEBUG_TESTMODE, "testmode cmd test");
|
||||
|
||||
if (!tb[WL1271_TM_ATTR_DATA])
|
||||
return -EINVAL;
|
||||
|
||||
buf = nla_data(tb[WL1271_TM_ATTR_DATA]);
|
||||
buf_len = nla_len(tb[WL1271_TM_ATTR_DATA]);
|
||||
|
||||
if (tb[WL1271_TM_ATTR_ANSWER])
|
||||
answer = nla_get_u8(tb[WL1271_TM_ATTR_ANSWER]);
|
||||
|
||||
if (buf_len > sizeof(struct wl1271_command))
|
||||
return -EMSGSIZE;
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
ret = wl1271_cmd_test(wl, buf, buf_len, answer);
|
||||
mutex_unlock(&wl->mutex);
|
||||
|
||||
if (ret < 0) {
|
||||
wl1271_warning("testmode cmd test failed: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (answer) {
|
||||
len = nla_total_size(buf_len);
|
||||
skb = cfg80211_testmode_alloc_reply_skb(wl->hw->wiphy, len);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
NLA_PUT(skb, WL1271_TM_ATTR_DATA, buf_len, buf);
|
||||
ret = cfg80211_testmode_reply(skb);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
kfree_skb(skb);
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
static int wl1271_tm_cmd_interrogate(struct wl1271 *wl, struct nlattr *tb[])
|
||||
{
|
||||
int ret;
|
||||
struct wl1271_command *cmd;
|
||||
struct sk_buff *skb;
|
||||
u8 ie_id;
|
||||
|
||||
wl1271_debug(DEBUG_TESTMODE, "testmode cmd interrogate");
|
||||
|
||||
if (!tb[WL1271_TM_ATTR_IE_ID])
|
||||
return -EINVAL;
|
||||
|
||||
ie_id = nla_get_u8(tb[WL1271_TM_ATTR_IE_ID]);
|
||||
|
||||
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
|
||||
if (!cmd)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
ret = wl1271_cmd_interrogate(wl, ie_id, cmd, sizeof(*cmd));
|
||||
mutex_unlock(&wl->mutex);
|
||||
|
||||
if (ret < 0) {
|
||||
wl1271_warning("testmode cmd interrogate failed: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
skb = cfg80211_testmode_alloc_reply_skb(wl->hw->wiphy, sizeof(*cmd));
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
NLA_PUT(skb, WL1271_TM_ATTR_DATA, sizeof(*cmd), cmd);
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
kfree_skb(skb);
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
static int wl1271_tm_cmd_configure(struct wl1271 *wl, struct nlattr *tb[])
|
||||
{
|
||||
int buf_len, ret;
|
||||
void *buf;
|
||||
u8 ie_id;
|
||||
|
||||
wl1271_debug(DEBUG_TESTMODE, "testmode cmd configure");
|
||||
|
||||
if (!tb[WL1271_TM_ATTR_DATA])
|
||||
return -EINVAL;
|
||||
if (!tb[WL1271_TM_ATTR_IE_ID])
|
||||
return -EINVAL;
|
||||
|
||||
ie_id = nla_get_u8(tb[WL1271_TM_ATTR_IE_ID]);
|
||||
buf = nla_data(tb[WL1271_TM_ATTR_DATA]);
|
||||
buf_len = nla_len(tb[WL1271_TM_ATTR_DATA]);
|
||||
|
||||
if (buf_len > sizeof(struct wl1271_command))
|
||||
return -EMSGSIZE;
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
ret = wl1271_cmd_configure(wl, ie_id, buf, buf_len);
|
||||
mutex_unlock(&wl->mutex);
|
||||
|
||||
if (ret < 0) {
|
||||
wl1271_warning("testmode cmd configure failed: %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wl1271_tm_cmd_nvs_push(struct wl1271 *wl, struct nlattr *tb[])
|
||||
{
|
||||
int ret = 0;
|
||||
size_t len;
|
||||
void *buf;
|
||||
|
||||
wl1271_debug(DEBUG_TESTMODE, "testmode cmd nvs push");
|
||||
|
||||
if (!tb[WL1271_TM_ATTR_DATA])
|
||||
return -EINVAL;
|
||||
|
||||
buf = nla_data(tb[WL1271_TM_ATTR_DATA]);
|
||||
len = nla_len(tb[WL1271_TM_ATTR_DATA]);
|
||||
|
||||
if (len != sizeof(struct wl1271_nvs_file)) {
|
||||
wl1271_error("nvs size is not as expected: %zu != %zu",
|
||||
len, sizeof(struct wl1271_nvs_file));
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
kfree(wl->nvs);
|
||||
|
||||
wl->nvs = kmalloc(sizeof(struct wl1271_nvs_file), GFP_KERNEL);
|
||||
if (!wl->nvs) {
|
||||
wl1271_error("could not allocate memory for the nvs file");
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
memcpy(wl->nvs, buf, len);
|
||||
|
||||
wl1271_debug(DEBUG_TESTMODE, "testmode pushed nvs");
|
||||
|
||||
out:
|
||||
mutex_unlock(&wl->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int wl1271_tm_cmd_set_plt_mode(struct wl1271 *wl, struct nlattr *tb[])
|
||||
{
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
wl1271_debug(DEBUG_TESTMODE, "testmode cmd set plt mode");
|
||||
|
||||
if (!tb[WL1271_TM_ATTR_PLT_MODE])
|
||||
return -EINVAL;
|
||||
|
||||
val = nla_get_u32(tb[WL1271_TM_ATTR_PLT_MODE]);
|
||||
|
||||
switch (val) {
|
||||
case 0:
|
||||
ret = wl1271_plt_stop(wl);
|
||||
break;
|
||||
case 1:
|
||||
ret = wl1271_plt_start(wl);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wl1271_tm_cmd(struct ieee80211_hw *hw, void *data, int len)
|
||||
{
|
||||
struct wl1271 *wl = hw->priv;
|
||||
struct nlattr *tb[WL1271_TM_ATTR_MAX + 1];
|
||||
int err;
|
||||
|
||||
err = nla_parse(tb, WL1271_TM_ATTR_MAX, data, len, wl1271_tm_policy);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (!tb[WL1271_TM_ATTR_CMD_ID])
|
||||
return -EINVAL;
|
||||
|
||||
switch (nla_get_u32(tb[WL1271_TM_ATTR_CMD_ID])) {
|
||||
case WL1271_TM_CMD_TEST:
|
||||
return wl1271_tm_cmd_test(wl, tb);
|
||||
case WL1271_TM_CMD_INTERROGATE:
|
||||
return wl1271_tm_cmd_interrogate(wl, tb);
|
||||
case WL1271_TM_CMD_CONFIGURE:
|
||||
return wl1271_tm_cmd_configure(wl, tb);
|
||||
case WL1271_TM_CMD_NVS_PUSH:
|
||||
return wl1271_tm_cmd_nvs_push(wl, tb);
|
||||
case WL1271_TM_CMD_SET_PLT_MODE:
|
||||
return wl1271_tm_cmd_set_plt_mode(wl, tb);
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
31
drivers/net/wireless/wl12xx/wl1271_testmode.h
Normal file
31
drivers/net/wireless/wl12xx/wl1271_testmode.h
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* This file is part of wl1271
|
||||
*
|
||||
* Copyright (C) 2010 Nokia Corporation
|
||||
*
|
||||
* Contact: Luciano Coelho <luciano.coelho@nokia.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 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 St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __WL1271_TESTMODE_H__
|
||||
#define __WL1271_TESTMODE_H__
|
||||
|
||||
#include <net/mac80211.h>
|
||||
|
||||
int wl1271_tm_cmd(struct ieee80211_hw *hw, void *data, int len);
|
||||
|
||||
#endif /* __WL1271_TESTMODE_H__ */
|
@ -26,6 +26,7 @@
|
||||
|
||||
#include "wl1271.h"
|
||||
#include "wl1271_spi.h"
|
||||
#include "wl1271_io.h"
|
||||
#include "wl1271_reg.h"
|
||||
#include "wl1271_ps.h"
|
||||
#include "wl1271_tx.h"
|
||||
@ -87,7 +88,7 @@ static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
|
||||
u32 extra, struct ieee80211_tx_info *control)
|
||||
{
|
||||
struct wl1271_tx_hw_descr *desc;
|
||||
int pad;
|
||||
int pad, ac;
|
||||
u16 tx_attr;
|
||||
|
||||
desc = (struct wl1271_tx_hw_descr *) skb->data;
|
||||
@ -107,9 +108,11 @@ static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
|
||||
|
||||
/* configure the tx attributes */
|
||||
tx_attr = wl->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER;
|
||||
/* FIXME: do we know the packet priority? can we identify mgmt
|
||||
packets, and use max prio for them at least? */
|
||||
desc->tid = 0;
|
||||
|
||||
/* queue */
|
||||
ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
|
||||
desc->tid = wl1271_tx_ac_to_tid(ac);
|
||||
|
||||
desc->aid = TX_HW_DEFAULT_AID;
|
||||
desc->reserved = 0;
|
||||
|
||||
@ -163,11 +166,11 @@ static int wl1271_tx_send_packet(struct wl1271 *wl, struct sk_buff *skb,
|
||||
len = WL1271_TX_ALIGN(skb->len);
|
||||
|
||||
/* perform a fixed address block write with the packet */
|
||||
wl1271_spi_write(wl, WL1271_SLV_MEM_DATA, skb->data, len, true);
|
||||
wl1271_write(wl, WL1271_SLV_MEM_DATA, skb->data, len, true);
|
||||
|
||||
/* write packet new counter into the write access register */
|
||||
wl->tx_packets_count++;
|
||||
wl1271_spi_write32(wl, WL1271_HOST_WR_ACCESS, wl->tx_packets_count);
|
||||
wl1271_write32(wl, WL1271_HOST_WR_ACCESS, wl->tx_packets_count);
|
||||
|
||||
desc = (struct wl1271_tx_hw_descr *) skb->data;
|
||||
wl1271_debug(DEBUG_TX, "tx id %u skb 0x%p payload %u (%u words)",
|
||||
@ -201,6 +204,7 @@ static int wl1271_tx_frame(struct wl1271 *wl, struct sk_buff *skb)
|
||||
ret = wl1271_cmd_set_default_wep_key(wl, idx);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
wl->default_key = idx;
|
||||
}
|
||||
}
|
||||
|
||||
@ -372,8 +376,8 @@ void wl1271_tx_complete(struct wl1271 *wl, u32 count)
|
||||
wl1271_debug(DEBUG_TX, "tx_complete received, packets: %d", count);
|
||||
|
||||
/* read the tx results from the chipset */
|
||||
wl1271_spi_read(wl, le32_to_cpu(memmap->tx_result),
|
||||
wl->tx_res_if, sizeof(*wl->tx_res_if), false);
|
||||
wl1271_read(wl, le32_to_cpu(memmap->tx_result),
|
||||
wl->tx_res_if, sizeof(*wl->tx_res_if), false);
|
||||
|
||||
/* verify that the result buffer is not getting overrun */
|
||||
if (count > TX_HW_RESULT_QUEUE_LEN) {
|
||||
@ -394,10 +398,10 @@ void wl1271_tx_complete(struct wl1271 *wl, u32 count)
|
||||
}
|
||||
|
||||
/* write host counter to chipset (to ack) */
|
||||
wl1271_spi_write32(wl, le32_to_cpu(memmap->tx_result) +
|
||||
offsetof(struct wl1271_tx_hw_res_if,
|
||||
tx_result_host_counter),
|
||||
le32_to_cpu(wl->tx_res_if->tx_result_fw_counter));
|
||||
wl1271_write32(wl, le32_to_cpu(memmap->tx_result) +
|
||||
offsetof(struct wl1271_tx_hw_res_if,
|
||||
tx_result_host_counter),
|
||||
le32_to_cpu(wl->tx_res_if->tx_result_fw_counter));
|
||||
}
|
||||
|
||||
/* caller must hold wl->mutex */
|
||||
|
@ -123,6 +123,42 @@ struct wl1271_tx_hw_res_if {
|
||||
struct wl1271_tx_hw_res_descr tx_results_queue[TX_HW_RESULT_QUEUE_LEN];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
static inline int wl1271_tx_get_queue(int queue)
|
||||
{
|
||||
/* FIXME: use best effort until WMM is enabled */
|
||||
return CONF_TX_AC_BE;
|
||||
|
||||
switch (queue) {
|
||||
case 0:
|
||||
return CONF_TX_AC_VO;
|
||||
case 1:
|
||||
return CONF_TX_AC_VI;
|
||||
case 2:
|
||||
return CONF_TX_AC_BE;
|
||||
case 3:
|
||||
return CONF_TX_AC_BK;
|
||||
default:
|
||||
return CONF_TX_AC_BE;
|
||||
}
|
||||
}
|
||||
|
||||
/* wl1271 tx descriptor needs the tid and we need to convert it from ac */
|
||||
static inline int wl1271_tx_ac_to_tid(int ac)
|
||||
{
|
||||
switch (ac) {
|
||||
case 0:
|
||||
return 0;
|
||||
case 1:
|
||||
return 2;
|
||||
case 2:
|
||||
return 4;
|
||||
case 3:
|
||||
return 6;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void wl1271_tx_work(struct work_struct *work);
|
||||
void wl1271_tx_complete(struct wl1271 *wl, u32 count);
|
||||
void wl1271_tx_flush(struct wl1271 *wl);
|
||||
|
@ -332,6 +332,12 @@ static void ssb_pmu_pll_init(struct ssb_chipcommon *cc)
|
||||
case 0x5354:
|
||||
ssb_pmu0_pllinit_r0(cc, crystalfreq);
|
||||
break;
|
||||
case 0x4322:
|
||||
if (cc->pmu.rev == 2) {
|
||||
chipco_write32(cc, SSB_CHIPCO_PLLCTL_ADDR, 0x0000000A);
|
||||
chipco_write32(cc, SSB_CHIPCO_PLLCTL_DATA, 0x380005C0);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ssb_printk(KERN_ERR PFX
|
||||
"ERROR: PLL init unknown for device %04X\n",
|
||||
@ -417,6 +423,7 @@ static void ssb_pmu_resources_init(struct ssb_chipcommon *cc)
|
||||
|
||||
switch (bus->chip_id) {
|
||||
case 0x4312:
|
||||
case 0x4322:
|
||||
/* We keep the default settings:
|
||||
* min_msk = 0xCBB
|
||||
* max_msk = 0x7FFFF
|
||||
|
@ -196,7 +196,7 @@ extern int ssb_devices_thaw(struct ssb_freeze_context *ctx);
|
||||
#ifdef CONFIG_SSB_B43_PCI_BRIDGE
|
||||
extern int __init b43_pci_ssb_bridge_init(void);
|
||||
extern void __exit b43_pci_ssb_bridge_exit(void);
|
||||
#else /* CONFIG_SSB_B43_PCI_BRIDGR */
|
||||
#else /* CONFIG_SSB_B43_PCI_BRIDGE */
|
||||
static inline int b43_pci_ssb_bridge_init(void)
|
||||
{
|
||||
return 0;
|
||||
@ -204,6 +204,6 @@ static inline int b43_pci_ssb_bridge_init(void)
|
||||
static inline void b43_pci_ssb_bridge_exit(void)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_SSB_PCIHOST */
|
||||
#endif /* CONFIG_SSB_B43_PCI_BRIDGE */
|
||||
|
||||
#endif /* LINUX_SSB_PRIVATE_H_ */
|
||||
|
@ -609,16 +609,6 @@ struct ieee80211_hdr_2addr {
|
||||
u8 payload[0];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct ieee80211_hdr_3addr {
|
||||
__le16 frame_ctl;
|
||||
__le16 duration_id;
|
||||
u8 addr1[ETH_ALEN];
|
||||
u8 addr2[ETH_ALEN];
|
||||
u8 addr3[ETH_ALEN];
|
||||
__le16 seq_ctl;
|
||||
u8 payload[0];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct ieee80211_hdr_4addr {
|
||||
__le16 frame_ctl;
|
||||
__le16 duration_id;
|
||||
@ -1672,7 +1662,7 @@ static inline u8 *ieee80211_get_payload(struct rtl_ieee80211_hdr *hdr)
|
||||
case IEEE80211_2ADDR_LEN:
|
||||
return ((struct ieee80211_hdr_2addr *)hdr)->payload;
|
||||
case IEEE80211_3ADDR_LEN:
|
||||
return ((struct ieee80211_hdr_3addr *)hdr)->payload;
|
||||
return (void *)hdr+sizeof(struct ieee80211_hdr_3addr);
|
||||
case IEEE80211_4ADDR_LEN:
|
||||
return ((struct ieee80211_hdr_4addr *)hdr)->payload;
|
||||
}
|
||||
|
@ -201,7 +201,7 @@ typedef union _frameqos {
|
||||
static inline u8 Frame_QoSTID(u8 *buf)
|
||||
{
|
||||
struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *)buf;
|
||||
u16 fc = le16_to_cpu(hdr->frame_ctl);
|
||||
u16 fc = le16_to_cpu(hdr->frame_control);
|
||||
|
||||
return (u8)((frameqos *)(buf +
|
||||
(((fc & IEEE80211_FCTL_TODS) &&
|
||||
|
@ -744,7 +744,7 @@ u8 parse_subframe(struct sk_buff *skb,
|
||||
struct ieee80211_rxb *rxb,u8* src,u8* dst)
|
||||
{
|
||||
struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr* )skb->data;
|
||||
u16 fc = le16_to_cpu(hdr->frame_ctl);
|
||||
u16 fc = le16_to_cpu(hdr->frame_control);
|
||||
|
||||
u16 LLCOffset= sizeof(struct ieee80211_hdr_3addr);
|
||||
u16 ChkLength;
|
||||
@ -756,7 +756,7 @@ u8 parse_subframe(struct sk_buff *skb,
|
||||
struct sk_buff *sub_skb;
|
||||
u8 *data_ptr;
|
||||
/* just for debug purpose */
|
||||
SeqNum = WLAN_GET_SEQ_SEQ(le16_to_cpu(hdr->seq_ctl));
|
||||
SeqNum = WLAN_GET_SEQ_SEQ(le16_to_cpu(hdr->seq_ctrl));
|
||||
|
||||
if((IEEE80211_QOS_HAS_SEQ(fc))&&\
|
||||
(((frameqos *)(skb->data + IEEE80211_3ADDR_LEN))->field.reserved)) {
|
||||
@ -2370,7 +2370,7 @@ static inline void ieee80211_process_probe_response(
|
||||
escape_essid(info_element->data,
|
||||
info_element->len),
|
||||
MAC_ARG(beacon->header.addr3),
|
||||
WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
|
||||
WLAN_FC_GET_STYPE(beacon->header.frame_control) ==
|
||||
IEEE80211_STYPE_PROBE_RESP ?
|
||||
"PROBE RESPONSE" : "BEACON");
|
||||
return;
|
||||
@ -2387,7 +2387,7 @@ static inline void ieee80211_process_probe_response(
|
||||
return;
|
||||
if(ieee->bGlobalDomain)
|
||||
{
|
||||
if (WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == IEEE80211_STYPE_PROBE_RESP)
|
||||
if (WLAN_FC_GET_STYPE(beacon->header.frame_control) == IEEE80211_STYPE_PROBE_RESP)
|
||||
{
|
||||
// Case 1: Country code
|
||||
if(IS_COUNTRY_IE_VALID(ieee) )
|
||||
@ -2454,7 +2454,7 @@ static inline void ieee80211_process_probe_response(
|
||||
else
|
||||
ieee->current_network.buseprotection = false;
|
||||
}
|
||||
if(is_beacon(beacon->header.frame_ctl))
|
||||
if(is_beacon(beacon->header.frame_control))
|
||||
{
|
||||
if(ieee->state == IEEE80211_LINKED)
|
||||
ieee->LinkDetectInfo.NumRecvBcnInPeriod++;
|
||||
@ -2496,7 +2496,7 @@ static inline void ieee80211_process_probe_response(
|
||||
escape_essid(network.ssid,
|
||||
network.ssid_len),
|
||||
MAC_ARG(network.bssid),
|
||||
WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
|
||||
WLAN_FC_GET_STYPE(beacon->header.frame_control) ==
|
||||
IEEE80211_STYPE_PROBE_RESP ?
|
||||
"PROBE RESPONSE" : "BEACON");
|
||||
#endif
|
||||
@ -2509,7 +2509,7 @@ static inline void ieee80211_process_probe_response(
|
||||
escape_essid(target->ssid,
|
||||
target->ssid_len),
|
||||
MAC_ARG(target->bssid),
|
||||
WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
|
||||
WLAN_FC_GET_STYPE(beacon->header.frame_control) ==
|
||||
IEEE80211_STYPE_PROBE_RESP ?
|
||||
"PROBE RESPONSE" : "BEACON");
|
||||
|
||||
@ -2519,7 +2519,7 @@ static inline void ieee80211_process_probe_response(
|
||||
*/
|
||||
renew = !time_after(target->last_scanned + ieee->scan_age, jiffies);
|
||||
//YJ,add,080819,for hidden ap
|
||||
if(is_beacon(beacon->header.frame_ctl) == 0)
|
||||
if(is_beacon(beacon->header.frame_control) == 0)
|
||||
network.flags = (~NETWORK_EMPTY_ESSID & network.flags)|(NETWORK_EMPTY_ESSID & target->flags);
|
||||
//if(strncmp(network.ssid, "linksys-c",9) == 0)
|
||||
// printk("====>2 network.ssid=%s FLAG=%d target.ssid=%s FLAG=%d\n", network.ssid, network.flags, target->ssid, target->flags);
|
||||
@ -2535,7 +2535,7 @@ static inline void ieee80211_process_probe_response(
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&ieee->lock, flags);
|
||||
if (is_beacon(beacon->header.frame_ctl)&&is_same_network(&ieee->current_network, &network, ieee)&&\
|
||||
if (is_beacon(beacon->header.frame_control)&&is_same_network(&ieee->current_network, &network, ieee)&&\
|
||||
(ieee->state == IEEE80211_LINKED)) {
|
||||
if(ieee->handle_beacon != NULL) {
|
||||
ieee->handle_beacon(ieee->dev,beacon,&ieee->current_network);
|
||||
|
@ -242,7 +242,7 @@ inline void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee
|
||||
if(ieee->queue_stop){
|
||||
enqueue_mgmt(ieee,skb);
|
||||
}else{
|
||||
header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0]<<4);
|
||||
header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0]<<4);
|
||||
|
||||
if (ieee->seq_ctrl[0] == 0xFFF)
|
||||
ieee->seq_ctrl[0] = 0;
|
||||
@ -260,7 +260,7 @@ inline void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee
|
||||
spin_unlock_irqrestore(&ieee->lock, flags);
|
||||
spin_lock_irqsave(&ieee->mgmt_tx_lock, flags);
|
||||
|
||||
header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
|
||||
header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
|
||||
|
||||
if (ieee->seq_ctrl[0] == 0xFFF)
|
||||
ieee->seq_ctrl[0] = 0;
|
||||
@ -302,7 +302,7 @@ inline void softmac_ps_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *i
|
||||
//printk("=============>%s()\n", __FUNCTION__);
|
||||
if(single){
|
||||
|
||||
header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
|
||||
header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
|
||||
|
||||
if (ieee->seq_ctrl[0] == 0xFFF)
|
||||
ieee->seq_ctrl[0] = 0;
|
||||
@ -315,7 +315,7 @@ inline void softmac_ps_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *i
|
||||
|
||||
}else{
|
||||
|
||||
header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
|
||||
header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
|
||||
|
||||
if (ieee->seq_ctrl[0] == 0xFFF)
|
||||
ieee->seq_ctrl[0] = 0;
|
||||
@ -347,7 +347,7 @@ inline struct sk_buff *ieee80211_probe_req(struct ieee80211_device *ieee)
|
||||
skb_reserve(skb, ieee->tx_headroom);
|
||||
|
||||
req = (struct ieee80211_probe_request *) skb_put(skb,sizeof(struct ieee80211_probe_request));
|
||||
req->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
|
||||
req->header.frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
|
||||
req->header.duration_id = 0; //FIXME: is this OK ?
|
||||
|
||||
memset(req->header.addr1, 0xff, ETH_ALEN);
|
||||
@ -662,8 +662,8 @@ inline struct sk_buff *ieee80211_authentication_req(struct ieee80211_network *be
|
||||
auth = (struct ieee80211_authentication *)
|
||||
skb_put(skb, sizeof(struct ieee80211_authentication));
|
||||
|
||||
auth->header.frame_ctl = IEEE80211_STYPE_AUTH;
|
||||
if (challengelen) auth->header.frame_ctl |= IEEE80211_FCTL_WEP;
|
||||
auth->header.frame_control = IEEE80211_STYPE_AUTH;
|
||||
if (challengelen) auth->header.frame_control |= IEEE80211_FCTL_WEP;
|
||||
|
||||
auth->header.duration_id = 0x013a; //FIXME
|
||||
|
||||
@ -801,7 +801,7 @@ static struct sk_buff* ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *d
|
||||
beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
|
||||
|
||||
|
||||
beacon_buf->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_RESP);
|
||||
beacon_buf->header.frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_RESP);
|
||||
beacon_buf->info_element[0].id = MFIE_TYPE_SSID;
|
||||
beacon_buf->info_element[0].len = ssid_len;
|
||||
|
||||
@ -880,7 +880,7 @@ struct sk_buff* ieee80211_assoc_resp(struct ieee80211_device *ieee, u8 *dest)
|
||||
assoc = (struct ieee80211_assoc_response_frame *)
|
||||
skb_put(skb,sizeof(struct ieee80211_assoc_response_frame));
|
||||
|
||||
assoc->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP);
|
||||
assoc->header.frame_control = cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP);
|
||||
memcpy(assoc->header.addr1, dest,ETH_ALEN);
|
||||
memcpy(assoc->header.addr3, ieee->dev->dev_addr, ETH_ALEN);
|
||||
memcpy(assoc->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
|
||||
@ -935,7 +935,7 @@ struct sk_buff* ieee80211_auth_resp(struct ieee80211_device *ieee,int status, u8
|
||||
memcpy(auth->header.addr3, ieee->dev->dev_addr, ETH_ALEN);
|
||||
memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
|
||||
memcpy(auth->header.addr1, dest, ETH_ALEN);
|
||||
auth->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_AUTH);
|
||||
auth->header.frame_control = cpu_to_le16(IEEE80211_STYPE_AUTH);
|
||||
return skb;
|
||||
|
||||
|
||||
@ -957,7 +957,7 @@ struct sk_buff* ieee80211_null_func(struct ieee80211_device *ieee,short pwr)
|
||||
memcpy(hdr->addr2, ieee->dev->dev_addr, ETH_ALEN);
|
||||
memcpy(hdr->addr3, ieee->current_network.bssid, ETH_ALEN);
|
||||
|
||||
hdr->frame_ctl = cpu_to_le16(IEEE80211_FTYPE_DATA |
|
||||
hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
|
||||
IEEE80211_STYPE_NULLFUNC | IEEE80211_FCTL_TODS |
|
||||
(pwr ? IEEE80211_FCTL_PM:0));
|
||||
|
||||
@ -1083,7 +1083,7 @@ inline struct sk_buff *ieee80211_association_req(struct ieee80211_network *beaco
|
||||
skb_put(skb, sizeof(struct ieee80211_assoc_request_frame)+2);
|
||||
|
||||
|
||||
hdr->header.frame_ctl = IEEE80211_STYPE_ASSOC_REQ;
|
||||
hdr->header.frame_control = IEEE80211_STYPE_ASSOC_REQ;
|
||||
hdr->header.duration_id= 37; //FIXME
|
||||
memcpy(hdr->header.addr1, beacon->bssid, ETH_ALEN);
|
||||
memcpy(hdr->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
|
||||
@ -1940,13 +1940,13 @@ ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
|
||||
if(!ieee->proto_started)
|
||||
return 0;
|
||||
|
||||
switch (WLAN_FC_GET_STYPE(header->frame_ctl)) {
|
||||
switch (WLAN_FC_GET_STYPE(header->frame_control)) {
|
||||
|
||||
case IEEE80211_STYPE_ASSOC_RESP:
|
||||
case IEEE80211_STYPE_REASSOC_RESP:
|
||||
|
||||
IEEE80211_DEBUG_MGMT("received [RE]ASSOCIATION RESPONSE (%d)\n",
|
||||
WLAN_FC_GET_STYPE(header->frame_ctl));
|
||||
WLAN_FC_GET_STYPE(header->frame_control));
|
||||
if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
|
||||
ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATED &&
|
||||
ieee->iw_mode == IW_MODE_INFRA){
|
||||
@ -2088,7 +2088,7 @@ ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
|
||||
if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
|
||||
ieee->state == IEEE80211_LINKED &&
|
||||
ieee->iw_mode == IW_MODE_INFRA){
|
||||
printk("==========>received disassoc/deauth(%x) frame, reason code:%x\n",WLAN_FC_GET_STYPE(header->frame_ctl), ((struct ieee80211_disassoc*)skb->data)->reason);
|
||||
printk("==========>received disassoc/deauth(%x) frame, reason code:%x\n",WLAN_FC_GET_STYPE(header->frame_control), ((struct ieee80211_disassoc*)skb->data)->reason);
|
||||
ieee->state = IEEE80211_ASSOCIATING;
|
||||
ieee->softmac_stats.reassoc++;
|
||||
ieee->is_roaming = true;
|
||||
@ -2239,7 +2239,7 @@ void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee)
|
||||
|
||||
header = (struct ieee80211_hdr_3addr *) skb->data;
|
||||
|
||||
header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
|
||||
header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
|
||||
|
||||
if (ieee->seq_ctrl[0] == 0xFFF)
|
||||
ieee->seq_ctrl[0] = 0;
|
||||
@ -2574,7 +2574,7 @@ struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee)
|
||||
return NULL;
|
||||
|
||||
b = (struct ieee80211_probe_response *) skb->data;
|
||||
b->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_BEACON);
|
||||
b->header.frame_control = cpu_to_le16(IEEE80211_STYPE_BEACON);
|
||||
|
||||
return skb;
|
||||
|
||||
@ -2590,7 +2590,7 @@ struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee)
|
||||
return NULL;
|
||||
|
||||
b = (struct ieee80211_probe_response *) skb->data;
|
||||
b->header.seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
|
||||
b->header.seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
|
||||
|
||||
if (ieee->seq_ctrl[0] == 0xFFF)
|
||||
ieee->seq_ctrl[0] = 0;
|
||||
@ -3139,7 +3139,7 @@ inline struct sk_buff *ieee80211_disassociate_skb(
|
||||
return NULL;
|
||||
|
||||
disass = (struct ieee80211_disassoc *) skb_put(skb,sizeof(struct ieee80211_disassoc));
|
||||
disass->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_DISASSOC);
|
||||
disass->header.frame_control = cpu_to_le16(IEEE80211_STYPE_DISASSOC);
|
||||
disass->header.duration_id = 0;
|
||||
|
||||
memcpy(disass->header.addr1, beacon->bssid, ETH_ALEN);
|
||||
|
@ -136,7 +136,7 @@ static struct sk_buff* ieee80211_ADDBA(struct ieee80211_device* ieee, u8* Dst, P
|
||||
|
||||
memcpy(BAReq->addr3, ieee->current_network.bssid, ETH_ALEN);
|
||||
|
||||
BAReq->frame_ctl = cpu_to_le16(IEEE80211_STYPE_MANAGE_ACT); //action frame
|
||||
BAReq->frame_control = cpu_to_le16(IEEE80211_STYPE_MANAGE_ACT); //action frame
|
||||
|
||||
//tag += sizeof( struct ieee80211_hdr_3addr); //move to action field
|
||||
tag = (u8*)skb_put(skb, 9);
|
||||
@ -221,7 +221,7 @@ static struct sk_buff* ieee80211_DELBA(
|
||||
memcpy(Delba->addr1, dst, ETH_ALEN);
|
||||
memcpy(Delba->addr2, ieee->dev->dev_addr, ETH_ALEN);
|
||||
memcpy(Delba->addr3, ieee->current_network.bssid, ETH_ALEN);
|
||||
Delba->frame_ctl = cpu_to_le16(IEEE80211_STYPE_MANAGE_ACT); //action frame
|
||||
Delba->frame_control = cpu_to_le16(IEEE80211_STYPE_MANAGE_ACT); //action frame
|
||||
|
||||
tag = (u8*)skb_put(skb, 6);
|
||||
|
||||
|
@ -6168,7 +6168,7 @@ void rtl8192_process_phyinfo(struct r8192_priv * priv,u8* buffer, struct ieee802
|
||||
u16 sc ;
|
||||
unsigned int frag,seq;
|
||||
hdr = (struct ieee80211_hdr_3addr *)buffer;
|
||||
sc = le16_to_cpu(hdr->seq_ctl);
|
||||
sc = le16_to_cpu(hdr->seq_ctrl);
|
||||
frag = WLAN_GET_SEQ_FRAG(sc);
|
||||
seq = WLAN_GET_SEQ_SEQ(sc);
|
||||
//cosa add 04292008 to record the sequence number
|
||||
@ -6827,7 +6827,7 @@ void rtl8192SU_TranslateRxSignalStuff(struct sk_buff *skb,
|
||||
tmp_buf = (u8*)skb->data;// + get_rxpacket_shiftbytes_819xusb(pstats);
|
||||
|
||||
hdr = (struct ieee80211_hdr_3addr *)tmp_buf;
|
||||
fc = le16_to_cpu(hdr->frame_ctl);
|
||||
fc = le16_to_cpu(hdr->frame_control);
|
||||
type = WLAN_FC_GET_TYPE(fc);
|
||||
praddr = hdr->addr1;
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
/*
|
||||
* 802.11 netlink interface public header
|
||||
*
|
||||
* Copyright 2006, 2007, 2008 Johannes Berg <johannes@sipsolutions.net>
|
||||
* Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
|
||||
* Copyright 2008 Michael Wu <flamingice@sourmilk.net>
|
||||
* Copyright 2008 Luis Carlos Cobo <luisca@cozybit.com>
|
||||
* Copyright 2008 Michael Buesch <mb@bu3sch.de>
|
||||
@ -299,6 +299,31 @@
|
||||
* rate selection. %NL80211_ATTR_IFINDEX is used to specify the interface
|
||||
* and @NL80211_ATTR_TX_RATES the set of allowed rates.
|
||||
*
|
||||
* @NL80211_CMD_REGISTER_ACTION: Register for receiving certain action frames
|
||||
* (via @NL80211_CMD_ACTION) for processing in userspace. This command
|
||||
* requires an interface index and a match attribute containing the first
|
||||
* few bytes of the frame that should match, e.g. a single byte for only
|
||||
* a category match or four bytes for vendor frames including the OUI.
|
||||
* The registration cannot be dropped, but is removed automatically
|
||||
* when the netlink socket is closed. Multiple registrations can be made.
|
||||
* @NL80211_CMD_ACTION: Action frame TX request and RX notification. This
|
||||
* command is used both as a request to transmit an Action frame and as an
|
||||
* event indicating reception of an Action frame that was not processed in
|
||||
* kernel code, but is for us (i.e., which may need to be processed in a
|
||||
* user space application). %NL80211_ATTR_FRAME is used to specify the
|
||||
* frame contents (including header). %NL80211_ATTR_WIPHY_FREQ (and
|
||||
* optionally %NL80211_ATTR_WIPHY_CHANNEL_TYPE) is used to indicate on
|
||||
* which channel the frame is to be transmitted or was received. This
|
||||
* channel has to be the current channel (remain-on-channel or the
|
||||
* operational channel). When called, this operation returns a cookie
|
||||
* (%NL80211_ATTR_COOKIE) that will be included with the TX status event
|
||||
* pertaining to the TX request.
|
||||
* @NL80211_CMD_ACTION_TX_STATUS: Report TX status of an Action frame
|
||||
* transmitted with %NL80211_CMD_ACTION. %NL80211_ATTR_COOKIE identifies
|
||||
* the TX command and %NL80211_ATTR_FRAME includes the contents of the
|
||||
* frame. %NL80211_ATTR_ACK flag is included if the recipient acknowledged
|
||||
* the frame.
|
||||
*
|
||||
* @NL80211_CMD_MAX: highest used command number
|
||||
* @__NL80211_CMD_AFTER_LAST: internal use
|
||||
*/
|
||||
@ -387,6 +412,13 @@ enum nl80211_commands {
|
||||
|
||||
NL80211_CMD_SET_TX_BITRATE_MASK,
|
||||
|
||||
NL80211_CMD_REGISTER_ACTION,
|
||||
NL80211_CMD_ACTION,
|
||||
NL80211_CMD_ACTION_TX_STATUS,
|
||||
|
||||
NL80211_CMD_SET_POWER_SAVE,
|
||||
NL80211_CMD_GET_POWER_SAVE,
|
||||
|
||||
/* add new commands above here */
|
||||
|
||||
/* used to define NL80211_CMD_MAX below */
|
||||
@ -653,6 +685,12 @@ enum nl80211_commands {
|
||||
* rates based on negotiated supported rates information. This attribute
|
||||
* is used with %NL80211_CMD_SET_TX_BITRATE_MASK.
|
||||
*
|
||||
* @NL80211_ATTR_FRAME_MATCH: A binary attribute which typically must contain
|
||||
* at least one byte, currently used with @NL80211_CMD_REGISTER_ACTION.
|
||||
*
|
||||
* @NL80211_ATTR_ACK: Flag attribute indicating that the frame was
|
||||
* acknowledged by the recipient.
|
||||
*
|
||||
* @NL80211_ATTR_MAX: highest attribute number currently defined
|
||||
* @__NL80211_ATTR_AFTER_LAST: internal use
|
||||
*/
|
||||
@ -798,6 +836,12 @@ enum nl80211_attrs {
|
||||
|
||||
NL80211_ATTR_TX_RATES,
|
||||
|
||||
NL80211_ATTR_FRAME_MATCH,
|
||||
|
||||
NL80211_ATTR_ACK,
|
||||
|
||||
NL80211_ATTR_PS_STATE,
|
||||
|
||||
/* add attributes here, update the policy in nl80211.c */
|
||||
|
||||
__NL80211_ATTR_AFTER_LAST,
|
||||
@ -1534,4 +1578,9 @@ enum nl80211_band {
|
||||
NL80211_BAND_5GHZ,
|
||||
};
|
||||
|
||||
enum nl80211_ps_state {
|
||||
NL80211_PS_DISABLED,
|
||||
NL80211_PS_ENABLED,
|
||||
};
|
||||
|
||||
#endif /* __LINUX_NL80211_H */
|
||||
|
@ -3,7 +3,7 @@
|
||||
/*
|
||||
* 802.11 device and configuration interface
|
||||
*
|
||||
* Copyright 2006-2009 Johannes Berg <johannes@sipsolutions.net>
|
||||
* Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@ -998,6 +998,7 @@ struct cfg80211_pmksa {
|
||||
* @cancel_remain_on_channel: Cancel an on-going remain-on-channel operation.
|
||||
* This allows the operation to be terminated prior to timeout based on
|
||||
* the duration value.
|
||||
* @action: Transmit an action frame
|
||||
*
|
||||
* @testmode_cmd: run a test mode command
|
||||
*
|
||||
@ -1144,7 +1145,11 @@ struct cfg80211_ops {
|
||||
struct net_device *dev,
|
||||
u64 cookie);
|
||||
|
||||
/* some temporary stuff to finish wext */
|
||||
int (*action)(struct wiphy *wiphy, struct net_device *dev,
|
||||
struct ieee80211_channel *chan,
|
||||
enum nl80211_channel_type channel_type,
|
||||
const u8 *buf, size_t len, u64 *cookie);
|
||||
|
||||
int (*set_power_mgmt)(struct wiphy *wiphy, struct net_device *dev,
|
||||
bool enabled, int timeout);
|
||||
};
|
||||
@ -1445,6 +1450,8 @@ struct cfg80211_cached_keys;
|
||||
* set by driver (if supported) on add_interface BEFORE registering the
|
||||
* netdev and may otherwise be used by driver read-only, will be update
|
||||
* by cfg80211 on change_interface
|
||||
* @action_registrations: list of registrations for action frames
|
||||
* @action_registrations_lock: lock for the list
|
||||
*/
|
||||
struct wireless_dev {
|
||||
struct wiphy *wiphy;
|
||||
@ -1454,6 +1461,9 @@ struct wireless_dev {
|
||||
struct list_head list;
|
||||
struct net_device *netdev;
|
||||
|
||||
struct list_head action_registrations;
|
||||
spinlock_t action_registrations_lock;
|
||||
|
||||
struct mutex mtx;
|
||||
|
||||
struct work_struct cleanup_work;
|
||||
@ -1478,6 +1488,9 @@ struct wireless_dev {
|
||||
struct cfg80211_internal_bss *auth_bsses[MAX_AUTH_BSSES];
|
||||
struct cfg80211_internal_bss *current_bss; /* associated / joined */
|
||||
|
||||
bool ps;
|
||||
int ps_timeout;
|
||||
|
||||
#ifdef CONFIG_CFG80211_WEXT
|
||||
/* wext data */
|
||||
struct {
|
||||
@ -1489,8 +1502,7 @@ struct wireless_dev {
|
||||
u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN];
|
||||
u8 ssid[IEEE80211_MAX_SSID_LEN];
|
||||
s8 default_key, default_mgmt_key;
|
||||
bool ps, prev_bssid_valid;
|
||||
int ps_timeout;
|
||||
bool prev_bssid_valid;
|
||||
} wext;
|
||||
#endif
|
||||
};
|
||||
@ -2291,4 +2303,38 @@ void cfg80211_remain_on_channel_expired(struct net_device *dev,
|
||||
void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr,
|
||||
struct station_info *sinfo, gfp_t gfp);
|
||||
|
||||
/**
|
||||
* cfg80211_rx_action - notification of received, unprocessed Action frame
|
||||
* @dev: network device
|
||||
* @freq: Frequency on which the frame was received in MHz
|
||||
* @buf: Action frame (header + body)
|
||||
* @len: length of the frame data
|
||||
* @gfp: context flags
|
||||
* Returns %true if a user space application is responsible for rejecting the
|
||||
* unrecognized Action frame; %false if no such application is registered
|
||||
* (i.e., the driver is responsible for rejecting the unrecognized Action
|
||||
* frame)
|
||||
*
|
||||
* This function is called whenever an Action frame is received for a station
|
||||
* mode interface, but is not processed in kernel.
|
||||
*/
|
||||
bool cfg80211_rx_action(struct net_device *dev, int freq, const u8 *buf,
|
||||
size_t len, gfp_t gfp);
|
||||
|
||||
/**
|
||||
* cfg80211_action_tx_status - notification of TX status for Action frame
|
||||
* @dev: network device
|
||||
* @cookie: Cookie returned by cfg80211_ops::action()
|
||||
* @buf: Action frame (header + body)
|
||||
* @len: length of the frame data
|
||||
* @ack: Whether frame was acknowledged
|
||||
* @gfp: context flags
|
||||
*
|
||||
* This function is called whenever an Action frame was requested to be
|
||||
* transmitted with cfg80211_ops::action() to report the TX status of the
|
||||
* transmission attempt.
|
||||
*/
|
||||
void cfg80211_action_tx_status(struct net_device *dev, u64 cookie,
|
||||
const u8 *buf, size_t len, bool ack, gfp_t gfp);
|
||||
|
||||
#endif /* __NET_CFG80211_H */
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* Copyright 2002-2005, Devicescape Software, Inc.
|
||||
* Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
|
||||
* Copyright 2007-2008 Johannes Berg <johannes@sipsolutions.net>
|
||||
* Copyright 2007-2010 Johannes Berg <johannes@sipsolutions.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@ -264,6 +264,9 @@ struct ieee80211_bss_conf {
|
||||
* be modified again (no seqno assignment, crypto, etc.)
|
||||
* @IEEE80211_TX_INTFL_HAS_RADIOTAP: This frame was injected and still
|
||||
* has a radiotap header at skb->data.
|
||||
* @IEEE80211_TX_INTFL_NL80211_FRAME_TX: Frame was requested through nl80211
|
||||
* MLME command (internal to mac80211 to figure out whether to send TX
|
||||
* status to user space)
|
||||
*/
|
||||
enum mac80211_tx_control_flags {
|
||||
IEEE80211_TX_CTL_REQ_TX_STATUS = BIT(0),
|
||||
@ -286,6 +289,7 @@ enum mac80211_tx_control_flags {
|
||||
IEEE80211_TX_CTL_MORE_FRAMES = BIT(18),
|
||||
IEEE80211_TX_INTFL_RETRANSMISSION = BIT(19),
|
||||
IEEE80211_TX_INTFL_HAS_RADIOTAP = BIT(20),
|
||||
IEEE80211_TX_INTFL_NL80211_FRAME_TX = BIT(21),
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -34,6 +34,11 @@
|
||||
.prod_id = { NULL, (v2), NULL, NULL }, \
|
||||
.prod_id_hash = { 0, (vh2), 0, 0 }, }
|
||||
|
||||
#define PCMCIA_DEVICE_PROD_ID3(v3, vh3) { \
|
||||
.match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID3, \
|
||||
.prod_id = { NULL, NULL, (v3), NULL }, \
|
||||
.prod_id_hash = { 0, 0, (vh3), 0 }, }
|
||||
|
||||
#define PCMCIA_DEVICE_PROD_ID12(v1, v2, vh1, vh2) { \
|
||||
.match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \
|
||||
PCMCIA_DEV_ID_MATCH_PROD_ID2, \
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* mac80211 configuration hooks for cfg80211
|
||||
*
|
||||
* Copyright 2006, 2007 Johannes Berg <johannes@sipsolutions.net>
|
||||
* Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
|
||||
*
|
||||
* This file is GPLv2 as found in COPYING.
|
||||
*/
|
||||
@ -1448,6 +1448,15 @@ static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy,
|
||||
return ieee80211_wk_cancel_remain_on_channel(sdata, cookie);
|
||||
}
|
||||
|
||||
static int ieee80211_action(struct wiphy *wiphy, struct net_device *dev,
|
||||
struct ieee80211_channel *chan,
|
||||
enum nl80211_channel_type channel_type,
|
||||
const u8 *buf, size_t len, u64 *cookie)
|
||||
{
|
||||
return ieee80211_mgd_action(IEEE80211_DEV_TO_SUB_IF(dev), chan,
|
||||
channel_type, buf, len, cookie);
|
||||
}
|
||||
|
||||
struct cfg80211_ops mac80211_config_ops = {
|
||||
.add_virtual_intf = ieee80211_add_iface,
|
||||
.del_virtual_intf = ieee80211_del_iface,
|
||||
@ -1496,4 +1505,5 @@ struct cfg80211_ops mac80211_config_ops = {
|
||||
.set_bitrate_mask = ieee80211_set_bitrate_mask,
|
||||
.remain_on_channel = ieee80211_remain_on_channel,
|
||||
.cancel_remain_on_channel = ieee80211_cancel_remain_on_channel,
|
||||
.action = ieee80211_action,
|
||||
};
|
||||
|
@ -2,7 +2,7 @@
|
||||
* Copyright 2002-2005, Instant802 Networks, Inc.
|
||||
* Copyright 2005, Devicescape Software, Inc.
|
||||
* Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
|
||||
* Copyright 2007-2008 Johannes Berg <johannes@sipsolutions.net>
|
||||
* Copyright 2007-2010 Johannes Berg <johannes@sipsolutions.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@ -966,6 +966,10 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
|
||||
int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
|
||||
struct cfg80211_disassoc_request *req,
|
||||
void *cookie);
|
||||
int ieee80211_mgd_action(struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_channel *chan,
|
||||
enum nl80211_channel_type channel_type,
|
||||
const u8 *buf, size_t len, u64 *cookie);
|
||||
ieee80211_rx_result ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata,
|
||||
struct sk_buff *skb);
|
||||
void ieee80211_send_pspoll(struct ieee80211_local *local,
|
||||
|
@ -1031,7 +1031,7 @@ static int netdev_notify(struct notifier_block *nb,
|
||||
|
||||
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||
|
||||
memcpy(sdata->name, sdata->name, IFNAMSIZ);
|
||||
memcpy(sdata->name, dev->name, IFNAMSIZ);
|
||||
|
||||
ieee80211_debugfs_rename_netdev(sdata);
|
||||
return 0;
|
||||
|
@ -2084,3 +2084,38 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ieee80211_mgd_action(struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_channel *chan,
|
||||
enum nl80211_channel_type channel_type,
|
||||
const u8 *buf, size_t len, u64 *cookie)
|
||||
{
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
|
||||
struct sk_buff *skb;
|
||||
|
||||
/* Check that we are on the requested channel for transmission */
|
||||
if ((chan != local->tmp_channel ||
|
||||
channel_type != local->tmp_channel_type) &&
|
||||
(chan != local->oper_channel ||
|
||||
channel_type != local->oper_channel_type))
|
||||
return -EBUSY;
|
||||
|
||||
skb = dev_alloc_skb(local->hw.extra_tx_headroom + len);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
skb_reserve(skb, local->hw.extra_tx_headroom);
|
||||
|
||||
memcpy(skb_put(skb, len), buf, len);
|
||||
|
||||
if (!(ifmgd->flags & IEEE80211_STA_MFP_ENABLED))
|
||||
IEEE80211_SKB_CB(skb)->flags |=
|
||||
IEEE80211_TX_INTFL_DONT_ENCRYPT;
|
||||
IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_NL80211_FRAME_TX |
|
||||
IEEE80211_TX_CTL_REQ_TX_STATUS;
|
||||
skb->dev = sdata->dev;
|
||||
ieee80211_tx_skb(sdata, skb);
|
||||
|
||||
*cookie = (unsigned long) skb;
|
||||
return 0;
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
* Copyright 2002-2005, Instant802 Networks, Inc.
|
||||
* Copyright 2005-2006, Devicescape Software, Inc.
|
||||
* Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
|
||||
* Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
|
||||
* Copyright 2007-2010 Johannes Berg <johannes@sipsolutions.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@ -1397,6 +1397,21 @@ ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx, __le16 fc)
|
||||
ieee80211_is_data(fc) &&
|
||||
(rx->key || rx->sdata->drop_unencrypted)))
|
||||
return -EACCES;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx)
|
||||
{
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
|
||||
__le16 fc = hdr->frame_control;
|
||||
int res;
|
||||
|
||||
res = ieee80211_drop_unencrypted(rx, fc);
|
||||
if (unlikely(res))
|
||||
return res;
|
||||
|
||||
if (rx->sta && test_sta_flags(rx->sta, WLAN_STA_MFP)) {
|
||||
if (unlikely(ieee80211_is_unicast_robust_mgmt_frame(rx->skb) &&
|
||||
rx->key))
|
||||
@ -1855,23 +1870,25 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
|
||||
struct ieee80211_local *local = rx->local;
|
||||
struct ieee80211_sub_if_data *sdata = rx->sdata;
|
||||
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data;
|
||||
struct sk_buff *nskb;
|
||||
struct ieee80211_rx_status *status;
|
||||
int len = rx->skb->len;
|
||||
|
||||
if (!ieee80211_is_action(mgmt->frame_control))
|
||||
return RX_CONTINUE;
|
||||
|
||||
if (!rx->sta)
|
||||
return RX_DROP_MONITOR;
|
||||
/* drop too small frames */
|
||||
if (len < IEEE80211_MIN_ACTION_SIZE)
|
||||
return RX_DROP_UNUSABLE;
|
||||
|
||||
if (!rx->sta && mgmt->u.action.category != WLAN_CATEGORY_PUBLIC)
|
||||
return RX_DROP_UNUSABLE;
|
||||
|
||||
if (!(rx->flags & IEEE80211_RX_RA_MATCH))
|
||||
return RX_DROP_MONITOR;
|
||||
return RX_DROP_UNUSABLE;
|
||||
|
||||
if (ieee80211_drop_unencrypted(rx, mgmt->frame_control))
|
||||
return RX_DROP_MONITOR;
|
||||
|
||||
/* all categories we currently handle have action_code */
|
||||
if (len < IEEE80211_MIN_ACTION_SIZE + 1)
|
||||
return RX_DROP_MONITOR;
|
||||
if (ieee80211_drop_unencrypted_mgmt(rx))
|
||||
return RX_DROP_UNUSABLE;
|
||||
|
||||
switch (mgmt->u.action.category) {
|
||||
case WLAN_CATEGORY_BACK:
|
||||
@ -1884,7 +1901,11 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
|
||||
if (sdata->vif.type != NL80211_IFTYPE_STATION &&
|
||||
sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
|
||||
sdata->vif.type != NL80211_IFTYPE_AP)
|
||||
return RX_DROP_MONITOR;
|
||||
break;
|
||||
|
||||
/* verify action_code is present */
|
||||
if (len < IEEE80211_MIN_ACTION_SIZE + 1)
|
||||
break;
|
||||
|
||||
switch (mgmt->u.action.u.addba_req.action_code) {
|
||||
case WLAN_ACTION_ADDBA_REQ:
|
||||
@ -1892,45 +1913,49 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
|
||||
sizeof(mgmt->u.action.u.addba_req)))
|
||||
return RX_DROP_MONITOR;
|
||||
ieee80211_process_addba_request(local, rx->sta, mgmt, len);
|
||||
break;
|
||||
goto handled;
|
||||
case WLAN_ACTION_ADDBA_RESP:
|
||||
if (len < (IEEE80211_MIN_ACTION_SIZE +
|
||||
sizeof(mgmt->u.action.u.addba_resp)))
|
||||
return RX_DROP_MONITOR;
|
||||
break;
|
||||
ieee80211_process_addba_resp(local, rx->sta, mgmt, len);
|
||||
break;
|
||||
goto handled;
|
||||
case WLAN_ACTION_DELBA:
|
||||
if (len < (IEEE80211_MIN_ACTION_SIZE +
|
||||
sizeof(mgmt->u.action.u.delba)))
|
||||
return RX_DROP_MONITOR;
|
||||
break;
|
||||
ieee80211_process_delba(sdata, rx->sta, mgmt, len);
|
||||
break;
|
||||
goto handled;
|
||||
}
|
||||
break;
|
||||
case WLAN_CATEGORY_SPECTRUM_MGMT:
|
||||
if (local->hw.conf.channel->band != IEEE80211_BAND_5GHZ)
|
||||
return RX_DROP_MONITOR;
|
||||
break;
|
||||
|
||||
if (sdata->vif.type != NL80211_IFTYPE_STATION)
|
||||
return RX_DROP_MONITOR;
|
||||
break;
|
||||
|
||||
/* verify action_code is present */
|
||||
if (len < IEEE80211_MIN_ACTION_SIZE + 1)
|
||||
break;
|
||||
|
||||
switch (mgmt->u.action.u.measurement.action_code) {
|
||||
case WLAN_ACTION_SPCT_MSR_REQ:
|
||||
if (len < (IEEE80211_MIN_ACTION_SIZE +
|
||||
sizeof(mgmt->u.action.u.measurement)))
|
||||
return RX_DROP_MONITOR;
|
||||
break;
|
||||
ieee80211_process_measurement_req(sdata, mgmt, len);
|
||||
break;
|
||||
goto handled;
|
||||
case WLAN_ACTION_SPCT_CHL_SWITCH:
|
||||
if (len < (IEEE80211_MIN_ACTION_SIZE +
|
||||
sizeof(mgmt->u.action.u.chan_switch)))
|
||||
return RX_DROP_MONITOR;
|
||||
break;
|
||||
|
||||
if (sdata->vif.type != NL80211_IFTYPE_STATION)
|
||||
return RX_DROP_MONITOR;
|
||||
break;
|
||||
|
||||
if (memcmp(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN))
|
||||
return RX_DROP_MONITOR;
|
||||
break;
|
||||
|
||||
return ieee80211_sta_rx_mgmt(sdata, rx->skb);
|
||||
}
|
||||
@ -1938,30 +1963,64 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
|
||||
case WLAN_CATEGORY_SA_QUERY:
|
||||
if (len < (IEEE80211_MIN_ACTION_SIZE +
|
||||
sizeof(mgmt->u.action.u.sa_query)))
|
||||
return RX_DROP_MONITOR;
|
||||
break;
|
||||
|
||||
switch (mgmt->u.action.u.sa_query.action) {
|
||||
case WLAN_ACTION_SA_QUERY_REQUEST:
|
||||
if (sdata->vif.type != NL80211_IFTYPE_STATION)
|
||||
return RX_DROP_MONITOR;
|
||||
break;
|
||||
ieee80211_process_sa_query_req(sdata, mgmt, len);
|
||||
break;
|
||||
case WLAN_ACTION_SA_QUERY_RESPONSE:
|
||||
/*
|
||||
* SA Query response is currently only used in AP mode
|
||||
* and it is processed in user space.
|
||||
*/
|
||||
return RX_CONTINUE;
|
||||
goto handled;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* do not process rejected action frames */
|
||||
if (mgmt->u.action.category & 0x80)
|
||||
return RX_DROP_MONITOR;
|
||||
|
||||
return RX_CONTINUE;
|
||||
}
|
||||
|
||||
rx->sta->rx_packets++;
|
||||
/*
|
||||
* For AP mode, hostapd is responsible for handling any action
|
||||
* frames that we didn't handle, including returning unknown
|
||||
* ones. For all other modes we will return them to the sender,
|
||||
* setting the 0x80 bit in the action category, as required by
|
||||
* 802.11-2007 7.3.1.11.
|
||||
*/
|
||||
if (sdata->vif.type == NL80211_IFTYPE_AP ||
|
||||
sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
|
||||
return RX_DROP_MONITOR;
|
||||
|
||||
/*
|
||||
* Getting here means the kernel doesn't know how to handle
|
||||
* it, but maybe userspace does ... include returned frames
|
||||
* so userspace can register for those to know whether ones
|
||||
* it transmitted were processed or returned.
|
||||
*/
|
||||
status = IEEE80211_SKB_RXCB(rx->skb);
|
||||
|
||||
if (sdata->vif.type == NL80211_IFTYPE_STATION &&
|
||||
cfg80211_rx_action(rx->sdata->dev, status->freq,
|
||||
rx->skb->data, rx->skb->len,
|
||||
GFP_ATOMIC))
|
||||
goto handled;
|
||||
|
||||
/* do not return rejected action frames */
|
||||
if (mgmt->u.action.category & 0x80)
|
||||
return RX_DROP_UNUSABLE;
|
||||
|
||||
nskb = skb_copy_expand(rx->skb, local->hw.extra_tx_headroom, 0,
|
||||
GFP_ATOMIC);
|
||||
if (nskb) {
|
||||
struct ieee80211_mgmt *mgmt = (void *)nskb->data;
|
||||
|
||||
mgmt->u.action.category |= 0x80;
|
||||
memcpy(mgmt->da, mgmt->sa, ETH_ALEN);
|
||||
memcpy(mgmt->sa, rx->sdata->vif.addr, ETH_ALEN);
|
||||
|
||||
memset(nskb->cb, 0, sizeof(nskb->cb));
|
||||
|
||||
ieee80211_tx_skb(rx->sdata, nskb);
|
||||
}
|
||||
|
||||
handled:
|
||||
if (rx->sta)
|
||||
rx->sta->rx_packets++;
|
||||
dev_kfree_skb(rx->skb);
|
||||
return RX_QUEUED;
|
||||
}
|
||||
@ -1970,14 +2029,13 @@ static ieee80211_rx_result debug_noinline
|
||||
ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = rx->sdata;
|
||||
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data;
|
||||
ieee80211_rx_result rxs;
|
||||
|
||||
if (!(rx->flags & IEEE80211_RX_RA_MATCH))
|
||||
return RX_DROP_MONITOR;
|
||||
|
||||
if (ieee80211_drop_unencrypted(rx, mgmt->frame_control))
|
||||
return RX_DROP_MONITOR;
|
||||
if (ieee80211_drop_unencrypted_mgmt(rx))
|
||||
return RX_DROP_UNUSABLE;
|
||||
|
||||
rxs = ieee80211_work_rx_mgmt(rx->sdata, rx->skb);
|
||||
if (rxs != RX_CONTINUE)
|
||||
|
@ -2,7 +2,7 @@
|
||||
* Copyright 2002-2005, Instant802 Networks, Inc.
|
||||
* Copyright 2005-2006, Devicescape Software, Inc.
|
||||
* Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
|
||||
* Copyright 2008-2009 Johannes Berg <johannes@sipsolutions.net>
|
||||
* Copyright 2008-2010 Johannes Berg <johannes@sipsolutions.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@ -288,6 +288,11 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
|
||||
msecs_to_jiffies(10));
|
||||
}
|
||||
|
||||
if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX)
|
||||
cfg80211_action_tx_status(
|
||||
skb->dev, (unsigned long) skb, skb->data, skb->len,
|
||||
!!(info->flags & IEEE80211_TX_STAT_ACK), GFP_ATOMIC);
|
||||
|
||||
/* this was a transmitted frame, but now we want to reuse it */
|
||||
skb_orphan(skb);
|
||||
|
||||
|
@ -677,6 +677,9 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
|
||||
INIT_WORK(&wdev->cleanup_work, wdev_cleanup_work);
|
||||
INIT_LIST_HEAD(&wdev->event_list);
|
||||
spin_lock_init(&wdev->event_lock);
|
||||
INIT_LIST_HEAD(&wdev->action_registrations);
|
||||
spin_lock_init(&wdev->action_registrations_lock);
|
||||
|
||||
mutex_lock(&rdev->devlist_mtx);
|
||||
list_add_rcu(&wdev->list, &rdev->netdev_list);
|
||||
rdev->devlist_generation++;
|
||||
@ -695,19 +698,21 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
|
||||
wdev->wext.default_key = -1;
|
||||
wdev->wext.default_mgmt_key = -1;
|
||||
wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
|
||||
#endif
|
||||
|
||||
if (wdev->wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT)
|
||||
wdev->wext.ps = true;
|
||||
wdev->ps = true;
|
||||
else
|
||||
wdev->wext.ps = false;
|
||||
wdev->wext.ps_timeout = 100;
|
||||
wdev->ps = false;
|
||||
wdev->ps_timeout = 100;
|
||||
if (rdev->ops->set_power_mgmt)
|
||||
if (rdev->ops->set_power_mgmt(wdev->wiphy, dev,
|
||||
wdev->wext.ps,
|
||||
wdev->wext.ps_timeout)) {
|
||||
wdev->ps,
|
||||
wdev->ps_timeout)) {
|
||||
/* assume this means it's off */
|
||||
wdev->wext.ps = false;
|
||||
wdev->ps = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!dev->ethtool_ops)
|
||||
dev->ethtool_ops = &cfg80211_ethtool_ops;
|
||||
|
||||
@ -792,6 +797,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
|
||||
sysfs_remove_link(&dev->dev.kobj, "phy80211");
|
||||
list_del_rcu(&wdev->list);
|
||||
rdev->devlist_generation++;
|
||||
cfg80211_mlme_purge_actions(wdev);
|
||||
#ifdef CONFIG_CFG80211_WEXT
|
||||
kfree(wdev->wext.keys);
|
||||
#endif
|
||||
|
@ -329,6 +329,15 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
|
||||
const u8 *resp_ie, size_t resp_ie_len,
|
||||
u16 status, bool wextev,
|
||||
struct cfg80211_bss *bss);
|
||||
int cfg80211_mlme_register_action(struct wireless_dev *wdev, u32 snd_pid,
|
||||
const u8 *match_data, int match_len);
|
||||
void cfg80211_mlme_unregister_actions(struct wireless_dev *wdev, u32 nlpid);
|
||||
void cfg80211_mlme_purge_actions(struct wireless_dev *wdev);
|
||||
int cfg80211_mlme_action(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev,
|
||||
struct ieee80211_channel *chan,
|
||||
enum nl80211_channel_type channel_type,
|
||||
const u8 *buf, size_t len, u64 *cookie);
|
||||
|
||||
/* SME */
|
||||
int __cfg80211_connect(struct cfg80211_registered_device *rdev,
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user