Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
This commit is contained in:
commit
ed3f2e40f3
|
@ -1086,7 +1086,6 @@ F: include/net/ax25.h
|
|||
F: net/ax25/
|
||||
|
||||
B43 WIRELESS DRIVER
|
||||
M: Michael Buesch <mb@bu3sch.de>
|
||||
M: Stefano Brivio <stefano.brivio@polimi.it>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
W: http://linuxwireless.org/en/users/Drivers/b43
|
||||
|
|
|
@ -5660,7 +5660,8 @@ static int airo_pci_suspend(struct pci_dev *pdev, pm_message_t state)
|
|||
|
||||
pci_enable_wake(pdev, pci_choose_state(pdev, state), 1);
|
||||
pci_save_state(pdev);
|
||||
return pci_set_power_state(pdev, pci_choose_state(pdev, state));
|
||||
pci_set_power_state(pdev, pci_choose_state(pdev, state));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int airo_pci_resume(struct pci_dev *pdev)
|
||||
|
|
|
@ -231,7 +231,7 @@ struct ar9170 {
|
|||
struct sk_buff_head tx_status_ampdu;
|
||||
spinlock_t tx_ampdu_list_lock;
|
||||
struct list_head tx_ampdu_list;
|
||||
unsigned int tx_ampdu_pending;
|
||||
atomic_t tx_ampdu_pending;
|
||||
|
||||
/* rxstream mpdu merge */
|
||||
struct ar9170_rxstream_mpdu_merge rx_mpdu;
|
||||
|
|
|
@ -152,14 +152,14 @@ enum ar9170_cmd {
|
|||
#define AR9170_MAC_REG_FTF_BIT14 BIT(14)
|
||||
#define AR9170_MAC_REG_FTF_BIT15 BIT(15)
|
||||
#define AR9170_MAC_REG_FTF_BAR BIT(24)
|
||||
#define AR9170_MAC_REG_FTF_BIT25 BIT(25)
|
||||
#define AR9170_MAC_REG_FTF_BA BIT(25)
|
||||
#define AR9170_MAC_REG_FTF_PSPOLL BIT(26)
|
||||
#define AR9170_MAC_REG_FTF_RTS BIT(27)
|
||||
#define AR9170_MAC_REG_FTF_CTS BIT(28)
|
||||
#define AR9170_MAC_REG_FTF_ACK BIT(29)
|
||||
#define AR9170_MAC_REG_FTF_CFE BIT(30)
|
||||
#define AR9170_MAC_REG_FTF_CFE_ACK BIT(31)
|
||||
#define AR9170_MAC_REG_FTF_DEFAULTS 0x0500ffff
|
||||
#define AR9170_MAC_REG_FTF_DEFAULTS 0x0700ffff
|
||||
#define AR9170_MAC_REG_FTF_MONITOR 0xfd00ffff
|
||||
|
||||
#define AR9170_MAC_REG_RX_TOTAL (AR9170_MAC_REG_BASE + 0x6A0)
|
||||
|
|
|
@ -414,9 +414,9 @@ static void ar9170_tx_ampdu_callback(struct ar9170 *ar, struct sk_buff *skb)
|
|||
|
||||
skb_queue_tail(&ar->tx_status_ampdu, skb);
|
||||
ar9170_tx_fake_ampdu_status(ar);
|
||||
ar->tx_ampdu_pending--;
|
||||
|
||||
if (!list_empty(&ar->tx_ampdu_list) && !ar->tx_ampdu_pending)
|
||||
if (atomic_dec_and_test(&ar->tx_ampdu_pending) &&
|
||||
!list_empty(&ar->tx_ampdu_list))
|
||||
ar9170_tx_ampdu(ar);
|
||||
}
|
||||
|
||||
|
@ -1248,6 +1248,7 @@ static int ar9170_op_start(struct ieee80211_hw *hw)
|
|||
ar->global_ampdu_density = 6;
|
||||
ar->global_ampdu_factor = 3;
|
||||
|
||||
atomic_set(&ar->tx_ampdu_pending, 0);
|
||||
ar->bad_hw_nagger = jiffies;
|
||||
|
||||
err = ar->open(ar);
|
||||
|
@ -1773,7 +1774,7 @@ static void ar9170_tx(struct ar9170 *ar)
|
|||
msecs_to_jiffies(AR9170_TX_TIMEOUT);
|
||||
|
||||
if (arinfo->flags == AR9170_TX_FLAG_BLOCK_ACK)
|
||||
ar->tx_ampdu_pending++;
|
||||
atomic_inc(&ar->tx_ampdu_pending);
|
||||
|
||||
#ifdef AR9170_QUEUE_DEBUG
|
||||
printk(KERN_DEBUG "%s: send frame q:%d =>\n",
|
||||
|
@ -1784,7 +1785,7 @@ static void ar9170_tx(struct ar9170 *ar)
|
|||
err = ar->tx(ar, skb);
|
||||
if (unlikely(err)) {
|
||||
if (arinfo->flags == AR9170_TX_FLAG_BLOCK_ACK)
|
||||
ar->tx_ampdu_pending--;
|
||||
atomic_dec(&ar->tx_ampdu_pending);
|
||||
|
||||
frames_failed++;
|
||||
dev_kfree_skb_any(skb);
|
||||
|
@ -1931,7 +1932,7 @@ int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
|
|||
if (info->flags & IEEE80211_TX_CTL_AMPDU) {
|
||||
bool run = ar9170_tx_ampdu_queue(ar, skb);
|
||||
|
||||
if (run || !ar->tx_ampdu_pending)
|
||||
if (run || !atomic_read(&ar->tx_ampdu_pending))
|
||||
ar9170_tx_ampdu(ar);
|
||||
} else {
|
||||
unsigned int queue = skb_get_queue_mapping(skb);
|
||||
|
|
|
@ -108,15 +108,15 @@ static void ar9170_usb_submit_urb(struct ar9170_usb *aru)
|
|||
return ;
|
||||
|
||||
spin_lock_irqsave(&aru->tx_urb_lock, flags);
|
||||
if (aru->tx_submitted_urbs >= AR9170_NUM_TX_URBS) {
|
||||
if (atomic_read(&aru->tx_submitted_urbs) >= AR9170_NUM_TX_URBS) {
|
||||
spin_unlock_irqrestore(&aru->tx_urb_lock, flags);
|
||||
return ;
|
||||
}
|
||||
aru->tx_submitted_urbs++;
|
||||
atomic_inc(&aru->tx_submitted_urbs);
|
||||
|
||||
urb = usb_get_from_anchor(&aru->tx_pending);
|
||||
if (!urb) {
|
||||
aru->tx_submitted_urbs--;
|
||||
atomic_dec(&aru->tx_submitted_urbs);
|
||||
spin_unlock_irqrestore(&aru->tx_urb_lock, flags);
|
||||
|
||||
return ;
|
||||
|
@ -133,7 +133,7 @@ static void ar9170_usb_submit_urb(struct ar9170_usb *aru)
|
|||
err);
|
||||
|
||||
usb_unanchor_urb(urb);
|
||||
aru->tx_submitted_urbs--;
|
||||
atomic_dec(&aru->tx_submitted_urbs);
|
||||
ar9170_tx_callback(&aru->common, urb->context);
|
||||
}
|
||||
|
||||
|
@ -151,7 +151,7 @@ static void ar9170_usb_tx_urb_complete_frame(struct urb *urb)
|
|||
return ;
|
||||
}
|
||||
|
||||
aru->tx_submitted_urbs--;
|
||||
atomic_dec(&aru->tx_submitted_urbs);
|
||||
|
||||
ar9170_tx_callback(&aru->common, skb);
|
||||
|
||||
|
@ -794,7 +794,7 @@ static int ar9170_usb_probe(struct usb_interface *intf,
|
|||
spin_lock_init(&aru->tx_urb_lock);
|
||||
|
||||
aru->tx_pending_urbs = 0;
|
||||
aru->tx_submitted_urbs = 0;
|
||||
atomic_set(&aru->tx_submitted_urbs, 0);
|
||||
|
||||
aru->common.stop = ar9170_usb_stop;
|
||||
aru->common.flush = ar9170_usb_flush;
|
||||
|
|
|
@ -67,7 +67,7 @@ struct ar9170_usb {
|
|||
bool req_one_stage_fw;
|
||||
|
||||
spinlock_t tx_urb_lock;
|
||||
unsigned int tx_submitted_urbs;
|
||||
atomic_t tx_submitted_urbs;
|
||||
unsigned int tx_pending_urbs;
|
||||
|
||||
struct completion cmd_wait;
|
||||
|
|
|
@ -198,6 +198,7 @@
|
|||
#define AR5K_TUNE_CWMAX_11B 1023
|
||||
#define AR5K_TUNE_CWMAX_XR 7
|
||||
#define AR5K_TUNE_NOISE_FLOOR -72
|
||||
#define AR5K_TUNE_CCA_MAX_GOOD_VALUE -95
|
||||
#define AR5K_TUNE_MAX_TXPOWER 63
|
||||
#define AR5K_TUNE_DEFAULT_TXPOWER 25
|
||||
#define AR5K_TUNE_TPC_TXPOWER false
|
||||
|
@ -1006,6 +1007,14 @@ struct ath5k_capabilities {
|
|||
} cap_queues;
|
||||
};
|
||||
|
||||
/* size of noise floor history (keep it a power of two) */
|
||||
#define ATH5K_NF_CAL_HIST_MAX 8
|
||||
struct ath5k_nfcal_hist
|
||||
{
|
||||
s16 index; /* current index into nfval */
|
||||
s16 nfval[ATH5K_NF_CAL_HIST_MAX]; /* last few noise floors */
|
||||
};
|
||||
|
||||
|
||||
/***************************************\
|
||||
HARDWARE ABSTRACTION LAYER STRUCTURE
|
||||
|
@ -1112,6 +1121,8 @@ struct ath5k_hw {
|
|||
struct ieee80211_channel r_last_channel;
|
||||
} ah_radar;
|
||||
|
||||
struct ath5k_nfcal_hist ah_nfcal_hist;
|
||||
|
||||
/* noise floor from last periodic calibration */
|
||||
s32 ah_noise_floor;
|
||||
|
||||
|
@ -1274,8 +1285,10 @@ extern int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah);
|
|||
extern bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags);
|
||||
extern int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel);
|
||||
/* PHY calibration */
|
||||
void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah);
|
||||
extern int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, struct ieee80211_channel *channel);
|
||||
extern int ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq);
|
||||
extern s16 ath5k_hw_get_noise_floor(struct ath5k_hw *ah);
|
||||
extern void ath5k_hw_calibration_poll(struct ath5k_hw *ah);
|
||||
/* Spur mitigation */
|
||||
bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah,
|
||||
|
|
|
@ -331,6 +331,8 @@ int ath5k_hw_attach(struct ath5k_softc *sc)
|
|||
|
||||
ath5k_hw_rfgain_opt_init(ah);
|
||||
|
||||
ath5k_hw_init_nfcal_hist(ah);
|
||||
|
||||
/* turn on HW LEDs */
|
||||
ath5k_hw_set_ledstate(ah, AR5K_LED_INIT);
|
||||
|
||||
|
|
|
@ -1124,77 +1124,148 @@ ath5k_hw_calibration_poll(struct ath5k_hw *ah)
|
|||
ah->ah_swi_mask = AR5K_SWI_FULL_CALIBRATION;
|
||||
AR5K_REG_ENABLE_BITS(ah, AR5K_CR, AR5K_CR_SWI);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* ath5k_hw_noise_floor_calibration - perform PHY noise floor calibration
|
||||
*
|
||||
* @ah: struct ath5k_hw pointer we are operating on
|
||||
* @freq: the channel frequency, just used for error logging
|
||||
*
|
||||
* This function performs a noise floor calibration of the PHY and waits for
|
||||
* it to complete. Then the noise floor value is compared to some maximum
|
||||
* noise floor we consider valid.
|
||||
*
|
||||
* Note that this is different from what the madwifi HAL does: it reads the
|
||||
* noise floor and afterwards initiates the calibration. Since the noise floor
|
||||
* calibration can take some time to finish, depending on the current channel
|
||||
* use, that avoids the occasional timeout warnings we are seeing now.
|
||||
*
|
||||
* See the following link for an Atheros patent on noise floor calibration:
|
||||
* http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&Sect2=HITOFF&d=PALL \
|
||||
* &p=1&u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&r=1&f=G&l=50&s1=7245893.PN.&OS=PN/7
|
||||
*
|
||||
* XXX: Since during noise floor calibration antennas are detached according to
|
||||
* the patent, we should stop tx queues here.
|
||||
*/
|
||||
int
|
||||
ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq)
|
||||
static int sign_extend(int val, const int nbits)
|
||||
{
|
||||
int ret;
|
||||
unsigned int i;
|
||||
s32 noise_floor;
|
||||
int order = BIT(nbits-1);
|
||||
return (val ^ order) - order;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable noise floor calibration
|
||||
*/
|
||||
AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
|
||||
AR5K_PHY_AGCCTL_NF);
|
||||
static s32 ath5k_hw_read_measured_noise_floor(struct ath5k_hw *ah)
|
||||
{
|
||||
s32 val;
|
||||
|
||||
ret = ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
|
||||
AR5K_PHY_AGCCTL_NF, 0, false);
|
||||
if (ret) {
|
||||
ATH5K_ERR(ah->ah_sc,
|
||||
"noise floor calibration timeout (%uMHz)\n", freq);
|
||||
return -EAGAIN;
|
||||
}
|
||||
val = ath5k_hw_reg_read(ah, AR5K_PHY_NF);
|
||||
return sign_extend(AR5K_REG_MS(val, AR5K_PHY_NF_MINCCA_PWR), 9);
|
||||
}
|
||||
|
||||
/* Wait until the noise floor is calibrated and read the value */
|
||||
for (i = 20; i > 0; i--) {
|
||||
mdelay(1);
|
||||
noise_floor = ath5k_hw_reg_read(ah, AR5K_PHY_NF);
|
||||
noise_floor = AR5K_PHY_NF_RVAL(noise_floor);
|
||||
if (noise_floor & AR5K_PHY_NF_ACTIVE) {
|
||||
noise_floor = AR5K_PHY_NF_AVAL(noise_floor);
|
||||
void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (noise_floor <= AR5K_TUNE_NOISE_FLOOR)
|
||||
break;
|
||||
ah->ah_nfcal_hist.index = 0;
|
||||
for (i = 0; i < ATH5K_NF_CAL_HIST_MAX; i++)
|
||||
ah->ah_nfcal_hist.nfval[i] = AR5K_TUNE_CCA_MAX_GOOD_VALUE;
|
||||
}
|
||||
|
||||
static void ath5k_hw_update_nfcal_hist(struct ath5k_hw *ah, s16 noise_floor)
|
||||
{
|
||||
struct ath5k_nfcal_hist *hist = &ah->ah_nfcal_hist;
|
||||
hist->index = (hist->index + 1) & (ATH5K_NF_CAL_HIST_MAX-1);
|
||||
hist->nfval[hist->index] = noise_floor;
|
||||
}
|
||||
|
||||
static s16 ath5k_hw_get_median_noise_floor(struct ath5k_hw *ah)
|
||||
{
|
||||
s16 sort[ATH5K_NF_CAL_HIST_MAX];
|
||||
s16 tmp;
|
||||
int i, j;
|
||||
|
||||
memcpy(sort, ah->ah_nfcal_hist.nfval, sizeof(sort));
|
||||
for (i = 0; i < ATH5K_NF_CAL_HIST_MAX - 1; i++) {
|
||||
for (j = 1; j < ATH5K_NF_CAL_HIST_MAX - i; j++) {
|
||||
if (sort[j] > sort[j-1]) {
|
||||
tmp = sort[j];
|
||||
sort[j] = sort[j-1];
|
||||
sort[j-1] = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i = 0; i < ATH5K_NF_CAL_HIST_MAX; i++) {
|
||||
ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
|
||||
"cal %d:%d\n", i, sort[i]);
|
||||
}
|
||||
return sort[(ATH5K_NF_CAL_HIST_MAX-1) / 2];
|
||||
}
|
||||
|
||||
ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
|
||||
"noise floor %d\n", noise_floor);
|
||||
/*
|
||||
* When we tell the hardware to perform a noise floor calibration
|
||||
* by setting the AR5K_PHY_AGCCTL_NF bit, it will periodically
|
||||
* sample-and-hold the minimum noise level seen at the antennas.
|
||||
* This value is then stored in a ring buffer of recently measured
|
||||
* noise floor values so we have a moving window of the last few
|
||||
* samples.
|
||||
*
|
||||
* The median of the values in the history is then loaded into the
|
||||
* hardware for its own use for RSSI and CCA measurements.
|
||||
*/
|
||||
void ath5k_hw_update_noise_floor(struct ath5k_hw *ah)
|
||||
{
|
||||
struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
|
||||
u32 val;
|
||||
s16 nf, threshold;
|
||||
u8 ee_mode;
|
||||
|
||||
if (noise_floor > AR5K_TUNE_NOISE_FLOOR) {
|
||||
ATH5K_ERR(ah->ah_sc,
|
||||
"noise floor calibration failed (%uMHz)\n", freq);
|
||||
return -EAGAIN;
|
||||
/* keep last value if calibration hasn't completed */
|
||||
if (ath5k_hw_reg_read(ah, AR5K_PHY_AGCCTL) & AR5K_PHY_AGCCTL_NF) {
|
||||
ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
|
||||
"NF did not complete in calibration window\n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ah->ah_noise_floor = noise_floor;
|
||||
switch (ah->ah_current_channel->hw_value & CHANNEL_MODES) {
|
||||
case CHANNEL_A:
|
||||
case CHANNEL_T:
|
||||
case CHANNEL_XR:
|
||||
ee_mode = AR5K_EEPROM_MODE_11A;
|
||||
break;
|
||||
case CHANNEL_G:
|
||||
case CHANNEL_TG:
|
||||
ee_mode = AR5K_EEPROM_MODE_11G;
|
||||
break;
|
||||
default:
|
||||
case CHANNEL_B:
|
||||
ee_mode = AR5K_EEPROM_MODE_11B;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
/* completed NF calibration, test threshold */
|
||||
nf = ath5k_hw_read_measured_noise_floor(ah);
|
||||
threshold = ee->ee_noise_floor_thr[ee_mode];
|
||||
|
||||
if (nf > threshold) {
|
||||
ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
|
||||
"noise floor failure detected; "
|
||||
"read %d, threshold %d\n",
|
||||
nf, threshold);
|
||||
|
||||
nf = AR5K_TUNE_CCA_MAX_GOOD_VALUE;
|
||||
}
|
||||
|
||||
ath5k_hw_update_nfcal_hist(ah, nf);
|
||||
nf = ath5k_hw_get_median_noise_floor(ah);
|
||||
|
||||
/* load noise floor (in .5 dBm) so the hardware will use it */
|
||||
val = ath5k_hw_reg_read(ah, AR5K_PHY_NF) & ~AR5K_PHY_NF_M;
|
||||
val |= (nf * 2) & AR5K_PHY_NF_M;
|
||||
ath5k_hw_reg_write(ah, val, AR5K_PHY_NF);
|
||||
|
||||
AR5K_REG_MASKED_BITS(ah, AR5K_PHY_AGCCTL, AR5K_PHY_AGCCTL_NF,
|
||||
~(AR5K_PHY_AGCCTL_NF_EN | AR5K_PHY_AGCCTL_NF_NOUPDATE));
|
||||
|
||||
ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL, AR5K_PHY_AGCCTL_NF,
|
||||
0, false);
|
||||
|
||||
/*
|
||||
* Load a high max CCA Power value (-50 dBm in .5 dBm units)
|
||||
* so that we're not capped by the median we just loaded.
|
||||
* This will be used as the initial value for the next noise
|
||||
* floor calibration.
|
||||
*/
|
||||
val = (val & ~AR5K_PHY_NF_M) | ((-50 * 2) & AR5K_PHY_NF_M);
|
||||
ath5k_hw_reg_write(ah, val, AR5K_PHY_NF);
|
||||
AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
|
||||
AR5K_PHY_AGCCTL_NF_EN |
|
||||
AR5K_PHY_AGCCTL_NF_NOUPDATE |
|
||||
AR5K_PHY_AGCCTL_NF);
|
||||
|
||||
ah->ah_noise_floor = nf;
|
||||
|
||||
ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
|
||||
"noise floor calibrated: %d\n", nf);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1287,7 +1358,7 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah,
|
|||
return ret;
|
||||
}
|
||||
|
||||
ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
|
||||
ath5k_hw_update_noise_floor(ah);
|
||||
|
||||
/*
|
||||
* Re-enable RX/TX and beacons
|
||||
|
@ -1360,7 +1431,7 @@ done:
|
|||
* since noise floor calibration interrupts rx path while I/Q
|
||||
* calibration doesn't. We don't need to run noise floor calibration
|
||||
* as often as I/Q calibration.*/
|
||||
ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
|
||||
ath5k_hw_update_noise_floor(ah);
|
||||
|
||||
/* Initiate a gain_F calibration */
|
||||
ath5k_hw_request_rfgain_probe(ah);
|
||||
|
|
|
@ -2033,17 +2033,14 @@
|
|||
#define AR5K_PHY_AGCCTL_NF_NOUPDATE 0x00020000 /* Don't update nf automaticaly */
|
||||
|
||||
/*
|
||||
* PHY noise floor status register
|
||||
* PHY noise floor status register (CCA = Clear Channel Assessment)
|
||||
*/
|
||||
#define AR5K_PHY_NF 0x9864 /* Register address */
|
||||
#define AR5K_PHY_NF_M 0x000001ff /* Noise floor mask */
|
||||
#define AR5K_PHY_NF_ACTIVE 0x00000100 /* Noise floor calibration still active */
|
||||
#define AR5K_PHY_NF_RVAL(_n) (((_n) >> 19) & AR5K_PHY_NF_M)
|
||||
#define AR5K_PHY_NF_AVAL(_n) (-((_n) ^ AR5K_PHY_NF_M) + 1)
|
||||
#define AR5K_PHY_NF_SVAL(_n) (((_n) & AR5K_PHY_NF_M) | (1 << 9))
|
||||
#define AR5K_PHY_NF_M 0x000001ff /* Noise floor, written to hardware in 1/2 dBm units */
|
||||
#define AR5K_PHY_NF_SVAL(_n) (((_n) & AR5K_PHY_NF_M) | (1 << 9))
|
||||
#define AR5K_PHY_NF_THRESH62 0x0007f000 /* Thresh62 -check ANI patent- (field) */
|
||||
#define AR5K_PHY_NF_THRESH62_S 12
|
||||
#define AR5K_PHY_NF_MINCCA_PWR 0x0ff80000 /* ??? */
|
||||
#define AR5K_PHY_NF_MINCCA_PWR 0x0ff80000 /* Minimum measured noise level, read from hardware in 1 dBm units */
|
||||
#define AR5K_PHY_NF_MINCCA_PWR_S 19
|
||||
|
||||
/*
|
||||
|
|
|
@ -1293,7 +1293,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
|
|||
* out and/or noise floor calibration might timeout.
|
||||
*/
|
||||
AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
|
||||
AR5K_PHY_AGCCTL_CAL);
|
||||
AR5K_PHY_AGCCTL_CAL | AR5K_PHY_AGCCTL_NF);
|
||||
|
||||
/* At the same time start I/Q calibration for QAM constellation
|
||||
* -no need for CCK- */
|
||||
|
@ -1314,21 +1314,6 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
|
|||
channel->center_freq);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we run NF calibration before AGC, it always times out.
|
||||
* Binary HAL starts NF and AGC calibration at the same time
|
||||
* and only waits for AGC to finish. Also if AGC or NF cal.
|
||||
* times out, reset doesn't fail on binary HAL. I believe
|
||||
* that's wrong because since rx path is routed to a detector,
|
||||
* if cal. doesn't finish we won't have RX. Sam's HAL for AR5210/5211
|
||||
* enables noise floor calibration after offset calibration and if noise
|
||||
* floor calibration fails, reset fails. I believe that's
|
||||
* a better approach, we just need to find a polling interval
|
||||
* that suits best, even if reset continues we need to make
|
||||
* sure that rx path is ready.
|
||||
*/
|
||||
ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
|
||||
|
||||
/* Restore antenna mode */
|
||||
ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode);
|
||||
|
||||
|
|
|
@ -29,15 +29,13 @@ static void ath_ahb_read_cachesize(struct ath_common *common, int *csz)
|
|||
|
||||
static void ath_ahb_cleanup(struct ath_common *common)
|
||||
{
|
||||
struct ath_hw *ah = (struct ath_hw *) common->ah;
|
||||
struct ath_softc *sc = ah->ah_sc;
|
||||
struct ath_softc *sc = (struct ath_softc *)common->priv;
|
||||
iounmap(sc->mem);
|
||||
}
|
||||
|
||||
static bool ath_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data)
|
||||
{
|
||||
struct ath_hw *ah = (struct ath_hw *) common->ah;
|
||||
struct ath_softc *sc = ah->ah_sc;
|
||||
struct ath_softc *sc = (struct ath_softc *)common->priv;
|
||||
struct platform_device *pdev = to_platform_device(sc->dev);
|
||||
struct ath9k_platform_data *pdata;
|
||||
|
||||
|
|
|
@ -813,7 +813,7 @@ static void ath9k_olc_temp_compensation(struct ath_hw *ah)
|
|||
}
|
||||
}
|
||||
|
||||
static void ath9k_hw_9271_pa_cal(struct ath_hw *ah)
|
||||
static void ath9k_hw_9271_pa_cal(struct ath_hw *ah, bool is_reset)
|
||||
{
|
||||
u32 regVal;
|
||||
unsigned int i;
|
||||
|
@ -889,10 +889,19 @@ static void ath9k_hw_9271_pa_cal(struct ath_hw *ah)
|
|||
REG_WRITE(ah, 0x7834, regVal);
|
||||
}
|
||||
|
||||
/* Empirical offset correction */
|
||||
#if 0
|
||||
REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9271_AN_RF2G6_OFFS, 0x20);
|
||||
#endif
|
||||
regVal = (regVal >>20) & 0x7f;
|
||||
|
||||
/* Update PA cal info */
|
||||
if ((!is_reset) && (ah->pacal_info.prev_offset == regVal)) {
|
||||
if (ah->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT)
|
||||
ah->pacal_info.max_skipcount =
|
||||
2 * ah->pacal_info.max_skipcount;
|
||||
ah->pacal_info.skipcount = ah->pacal_info.max_skipcount;
|
||||
} else {
|
||||
ah->pacal_info.max_skipcount = 1;
|
||||
ah->pacal_info.skipcount = 0;
|
||||
ah->pacal_info.prev_offset = regVal;
|
||||
}
|
||||
|
||||
regVal = REG_READ(ah, 0x7834);
|
||||
regVal |= 0x1;
|
||||
|
@ -1043,7 +1052,7 @@ bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
|
|||
if (longcal) {
|
||||
/* Do periodic PAOffset Cal */
|
||||
if (AR_SREV_9271(ah))
|
||||
ath9k_hw_9271_pa_cal(ah);
|
||||
ath9k_hw_9271_pa_cal(ah, false);
|
||||
else if (AR_SREV_9285_11_OR_LATER(ah)) {
|
||||
if (!ah->pacal_info.skipcount)
|
||||
ath9k_hw_9285_pa_cal(ah, false);
|
||||
|
@ -1070,6 +1079,7 @@ bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
|
|||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_calibrate);
|
||||
|
||||
/* Carrier leakage Calibration fix */
|
||||
static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
|
@ -1115,7 +1125,7 @@ bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
|
|||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
|
||||
if (AR_SREV_9285_12_OR_LATER(ah)) {
|
||||
if (AR_SREV_9271(ah) || AR_SREV_9285_12_OR_LATER(ah)) {
|
||||
if (!ar9285_clc(ah, chan))
|
||||
return false;
|
||||
} else {
|
||||
|
@ -1151,7 +1161,9 @@ bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
|
|||
}
|
||||
|
||||
/* Do PA Calibration */
|
||||
if (AR_SREV_9285_11_OR_LATER(ah))
|
||||
if (AR_SREV_9271(ah))
|
||||
ath9k_hw_9271_pa_cal(ah, true);
|
||||
else if (AR_SREV_9285_11_OR_LATER(ah))
|
||||
ath9k_hw_9285_pa_cal(ah, true);
|
||||
|
||||
/* Do NF Calibration after DC offset and other calibrations */
|
||||
|
|
|
@ -2079,7 +2079,9 @@ static void ath_tx_complete_poll_work(struct work_struct *work)
|
|||
if (needreset) {
|
||||
ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_RESET,
|
||||
"tx hung, resetting the chip\n");
|
||||
ath9k_ps_wakeup(sc);
|
||||
ath_reset(sc, false);
|
||||
ath9k_ps_restore(sc);
|
||||
}
|
||||
|
||||
ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work,
|
||||
|
|
|
@ -65,10 +65,13 @@ enum CountryCode {
|
|||
CTRY_ALGERIA = 12,
|
||||
CTRY_ARGENTINA = 32,
|
||||
CTRY_ARMENIA = 51,
|
||||
CTRY_ARUBA = 533,
|
||||
CTRY_AUSTRALIA = 36,
|
||||
CTRY_AUSTRIA = 40,
|
||||
CTRY_AZERBAIJAN = 31,
|
||||
CTRY_BAHRAIN = 48,
|
||||
CTRY_BANGLADESH = 50,
|
||||
CTRY_BARBADOS = 52,
|
||||
CTRY_BELARUS = 112,
|
||||
CTRY_BELGIUM = 56,
|
||||
CTRY_BELIZE = 84,
|
||||
|
@ -77,6 +80,7 @@ enum CountryCode {
|
|||
CTRY_BRAZIL = 76,
|
||||
CTRY_BRUNEI_DARUSSALAM = 96,
|
||||
CTRY_BULGARIA = 100,
|
||||
CTRY_CAMBODIA = 116,
|
||||
CTRY_CANADA = 124,
|
||||
CTRY_CHILE = 152,
|
||||
CTRY_CHINA = 156,
|
||||
|
@ -97,7 +101,11 @@ enum CountryCode {
|
|||
CTRY_GEORGIA = 268,
|
||||
CTRY_GERMANY = 276,
|
||||
CTRY_GREECE = 300,
|
||||
CTRY_GREENLAND = 304,
|
||||
CTRY_GRENEDA = 308,
|
||||
CTRY_GUAM = 316,
|
||||
CTRY_GUATEMALA = 320,
|
||||
CTRY_HAITI = 332,
|
||||
CTRY_HONDURAS = 340,
|
||||
CTRY_HONG_KONG = 344,
|
||||
CTRY_HUNGARY = 348,
|
||||
|
|
|
@ -288,13 +288,16 @@ static struct country_code_to_enum_rd allCountries[] = {
|
|||
{CTRY_DEFAULT, FCC1_FCCA, "CO"},
|
||||
{CTRY_ALBANIA, NULL1_WORLD, "AL"},
|
||||
{CTRY_ALGERIA, NULL1_WORLD, "DZ"},
|
||||
{CTRY_ARGENTINA, APL3_WORLD, "AR"},
|
||||
{CTRY_ARGENTINA, FCC3_WORLD, "AR"},
|
||||
{CTRY_ARMENIA, ETSI4_WORLD, "AM"},
|
||||
{CTRY_ARUBA, ETSI1_WORLD, "AW"},
|
||||
{CTRY_AUSTRALIA, FCC2_WORLD, "AU"},
|
||||
{CTRY_AUSTRALIA2, FCC6_WORLD, "AU"},
|
||||
{CTRY_AUSTRIA, ETSI1_WORLD, "AT"},
|
||||
{CTRY_AZERBAIJAN, ETSI4_WORLD, "AZ"},
|
||||
{CTRY_BAHRAIN, APL6_WORLD, "BH"},
|
||||
{CTRY_BANGLADESH, NULL1_WORLD, "BD"},
|
||||
{CTRY_BARBADOS, FCC2_WORLD, "BB"},
|
||||
{CTRY_BELARUS, ETSI1_WORLD, "BY"},
|
||||
{CTRY_BELGIUM, ETSI1_WORLD, "BE"},
|
||||
{CTRY_BELGIUM2, ETSI4_WORLD, "BL"},
|
||||
|
@ -304,13 +307,14 @@ static struct country_code_to_enum_rd allCountries[] = {
|
|||
{CTRY_BRAZIL, FCC3_WORLD, "BR"},
|
||||
{CTRY_BRUNEI_DARUSSALAM, APL1_WORLD, "BN"},
|
||||
{CTRY_BULGARIA, ETSI6_WORLD, "BG"},
|
||||
{CTRY_CANADA, FCC2_FCCA, "CA"},
|
||||
{CTRY_CAMBODIA, ETSI1_WORLD, "KH"},
|
||||
{CTRY_CANADA, FCC3_FCCA, "CA"},
|
||||
{CTRY_CANADA2, FCC6_FCCA, "CA"},
|
||||
{CTRY_CHILE, APL6_WORLD, "CL"},
|
||||
{CTRY_CHINA, APL1_WORLD, "CN"},
|
||||
{CTRY_COLOMBIA, FCC1_FCCA, "CO"},
|
||||
{CTRY_COSTA_RICA, FCC1_WORLD, "CR"},
|
||||
{CTRY_CROATIA, ETSI3_WORLD, "HR"},
|
||||
{CTRY_CROATIA, ETSI1_WORLD, "HR"},
|
||||
{CTRY_CYPRUS, ETSI1_WORLD, "CY"},
|
||||
{CTRY_CZECH, ETSI3_WORLD, "CZ"},
|
||||
{CTRY_DENMARK, ETSI1_WORLD, "DK"},
|
||||
|
@ -324,18 +328,22 @@ static struct country_code_to_enum_rd allCountries[] = {
|
|||
{CTRY_GEORGIA, ETSI4_WORLD, "GE"},
|
||||
{CTRY_GERMANY, ETSI1_WORLD, "DE"},
|
||||
{CTRY_GREECE, ETSI1_WORLD, "GR"},
|
||||
{CTRY_GREENLAND, ETSI1_WORLD, "GL"},
|
||||
{CTRY_GRENEDA, FCC3_FCCA, "GD"},
|
||||
{CTRY_GUAM, FCC1_FCCA, "GU"},
|
||||
{CTRY_GUATEMALA, FCC1_FCCA, "GT"},
|
||||
{CTRY_HAITI, ETSI1_WORLD, "HT"},
|
||||
{CTRY_HONDURAS, NULL1_WORLD, "HN"},
|
||||
{CTRY_HONG_KONG, FCC2_WORLD, "HK"},
|
||||
{CTRY_HONG_KONG, FCC3_WORLD, "HK"},
|
||||
{CTRY_HUNGARY, ETSI1_WORLD, "HU"},
|
||||
{CTRY_ICELAND, ETSI1_WORLD, "IS"},
|
||||
{CTRY_INDIA, APL6_WORLD, "IN"},
|
||||
{CTRY_INDONESIA, APL1_WORLD, "ID"},
|
||||
{CTRY_INDONESIA, NULL1_WORLD, "ID"},
|
||||
{CTRY_IRAN, APL1_WORLD, "IR"},
|
||||
{CTRY_IRELAND, ETSI1_WORLD, "IE"},
|
||||
{CTRY_ISRAEL, NULL1_WORLD, "IL"},
|
||||
{CTRY_ITALY, ETSI1_WORLD, "IT"},
|
||||
{CTRY_JAMAICA, ETSI1_WORLD, "JM"},
|
||||
{CTRY_JAMAICA, FCC3_WORLD, "JM"},
|
||||
|
||||
{CTRY_JAPAN, MKK1_MKKA, "JP"},
|
||||
{CTRY_JAPAN1, MKK1_MKKB, "JP"},
|
||||
|
@ -402,7 +410,7 @@ static struct country_code_to_enum_rd allCountries[] = {
|
|||
{CTRY_KOREA_ROC, APL9_WORLD, "KR"},
|
||||
{CTRY_KOREA_ROC2, APL2_WORLD, "K2"},
|
||||
{CTRY_KOREA_ROC3, APL9_WORLD, "K3"},
|
||||
{CTRY_KUWAIT, NULL1_WORLD, "KW"},
|
||||
{CTRY_KUWAIT, ETSI3_WORLD, "KW"},
|
||||
{CTRY_LATVIA, ETSI1_WORLD, "LV"},
|
||||
{CTRY_LEBANON, NULL1_WORLD, "LB"},
|
||||
{CTRY_LIECHTENSTEIN, ETSI1_WORLD, "LI"},
|
||||
|
@ -414,13 +422,13 @@ static struct country_code_to_enum_rd allCountries[] = {
|
|||
{CTRY_MALTA, ETSI1_WORLD, "MT"},
|
||||
{CTRY_MEXICO, FCC1_FCCA, "MX"},
|
||||
{CTRY_MONACO, ETSI4_WORLD, "MC"},
|
||||
{CTRY_MOROCCO, NULL1_WORLD, "MA"},
|
||||
{CTRY_MOROCCO, APL4_WORLD, "MA"},
|
||||
{CTRY_NEPAL, APL1_WORLD, "NP"},
|
||||
{CTRY_NETHERLANDS, ETSI1_WORLD, "NL"},
|
||||
{CTRY_NETHERLANDS_ANTILLES, ETSI1_WORLD, "AN"},
|
||||
{CTRY_NEW_ZEALAND, FCC2_ETSIC, "NZ"},
|
||||
{CTRY_NORWAY, ETSI1_WORLD, "NO"},
|
||||
{CTRY_OMAN, APL6_WORLD, "OM"},
|
||||
{CTRY_OMAN, FCC3_WORLD, "OM"},
|
||||
{CTRY_PAKISTAN, NULL1_WORLD, "PK"},
|
||||
{CTRY_PANAMA, FCC1_FCCA, "PA"},
|
||||
{CTRY_PAPUA_NEW_GUINEA, FCC1_WORLD, "PG"},
|
||||
|
@ -429,7 +437,7 @@ static struct country_code_to_enum_rd allCountries[] = {
|
|||
{CTRY_POLAND, ETSI1_WORLD, "PL"},
|
||||
{CTRY_PORTUGAL, ETSI1_WORLD, "PT"},
|
||||
{CTRY_PUERTO_RICO, FCC1_FCCA, "PR"},
|
||||
{CTRY_QATAR, NULL1_WORLD, "QA"},
|
||||
{CTRY_QATAR, APL1_WORLD, "QA"},
|
||||
{CTRY_ROMANIA, NULL1_WORLD, "RO"},
|
||||
{CTRY_RUSSIA, NULL1_WORLD, "RU"},
|
||||
{CTRY_SAUDI_ARABIA, NULL1_WORLD, "SA"},
|
||||
|
@ -445,7 +453,7 @@ static struct country_code_to_enum_rd allCountries[] = {
|
|||
{CTRY_SYRIA, NULL1_WORLD, "SY"},
|
||||
{CTRY_TAIWAN, APL3_FCCA, "TW"},
|
||||
{CTRY_THAILAND, FCC3_WORLD, "TH"},
|
||||
{CTRY_TRINIDAD_Y_TOBAGO, ETSI4_WORLD, "TT"},
|
||||
{CTRY_TRINIDAD_Y_TOBAGO, FCC3_WORLD, "TT"},
|
||||
{CTRY_TUNISIA, ETSI3_WORLD, "TN"},
|
||||
{CTRY_TURKEY, ETSI3_WORLD, "TR"},
|
||||
{CTRY_UKRAINE, NULL1_WORLD, "UA"},
|
||||
|
@ -456,7 +464,7 @@ static struct country_code_to_enum_rd allCountries[] = {
|
|||
* would need to assign new special alpha2 to CRDA db as with the world
|
||||
* regdomain and use another alpha2 */
|
||||
{CTRY_UNITED_STATES_FCC49, FCC4_FCCA, "PS"},
|
||||
{CTRY_URUGUAY, APL2_WORLD, "UY"},
|
||||
{CTRY_URUGUAY, FCC3_WORLD, "UY"},
|
||||
{CTRY_UZBEKISTAN, FCC3_FCCA, "UZ"},
|
||||
{CTRY_VENEZUELA, APL2_ETSIC, "VE"},
|
||||
{CTRY_VIET_NAM, NULL1_WORLD, "VN"},
|
||||
|
|
|
@ -749,12 +749,6 @@ struct b43_wldev {
|
|||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* Include goes here to avoid a dependency problem.
|
||||
* A better fix would be to integrate xmit.h into b43.h.
|
||||
*/
|
||||
#include "xmit.h"
|
||||
|
||||
/* Data structure for the WLAN parts (802.11 cores) of the b43 chip. */
|
||||
struct b43_wl {
|
||||
/* Pointer to the active wireless device on this chip */
|
||||
|
@ -830,13 +824,9 @@ struct b43_wl {
|
|||
struct b43_leds leds;
|
||||
|
||||
#ifdef CONFIG_B43_PIO
|
||||
/*
|
||||
* RX/TX header/tail buffers used by the frame transmit functions.
|
||||
*/
|
||||
struct b43_rxhdr_fw4 rxhdr;
|
||||
struct b43_txhdr txhdr;
|
||||
u8 rx_tail[4];
|
||||
u8 tx_tail[4];
|
||||
/* Kmalloc'ed scratch space for PIO TX/RX. Protected by wl->mutex. */
|
||||
u8 pio_scratchspace[110] __attribute__((__aligned__(8)));
|
||||
u8 pio_tailspace[4] __attribute__((__aligned__(8)));
|
||||
#endif /* CONFIG_B43_PIO */
|
||||
};
|
||||
|
||||
|
|
|
@ -4671,7 +4671,7 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
|
|||
{
|
||||
struct b43_wl *wl = dev->wl;
|
||||
struct ssb_bus *bus = dev->dev->bus;
|
||||
struct pci_dev *pdev = bus->host_pci;
|
||||
struct pci_dev *pdev = (bus->bustype == SSB_BUSTYPE_PCI) ? bus->host_pci : NULL;
|
||||
int err;
|
||||
bool have_2ghz_phy = 0, have_5ghz_phy = 0;
|
||||
u32 tmp;
|
||||
|
@ -4804,7 +4804,7 @@ static int b43_one_core_attach(struct ssb_device *dev, struct b43_wl *wl)
|
|||
|
||||
if (!list_empty(&wl->devlist)) {
|
||||
/* We are not the first core on this chip. */
|
||||
pdev = dev->bus->host_pci;
|
||||
pdev = (dev->bus->bustype == SSB_BUSTYPE_PCI) ? dev->bus->host_pci : NULL;
|
||||
/* Only special chips support more than one wireless
|
||||
* core, although some of the other chips have more than
|
||||
* one wireless core as well. Check for this and
|
||||
|
|
|
@ -341,12 +341,15 @@ static u16 tx_write_2byte_queue(struct b43_pio_txqueue *q,
|
|||
q->mmio_base + B43_PIO_TXDATA,
|
||||
sizeof(u16));
|
||||
if (data_len & 1) {
|
||||
u8 *tail = wl->pio_tailspace;
|
||||
BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 2);
|
||||
|
||||
/* Write the last byte. */
|
||||
ctl &= ~B43_PIO_TXCTL_WRITEHI;
|
||||
b43_piotx_write16(q, B43_PIO_TXCTL, ctl);
|
||||
wl->tx_tail[0] = data[data_len - 1];
|
||||
wl->tx_tail[1] = 0;
|
||||
ssb_block_write(dev->dev, wl->tx_tail, 2,
|
||||
tail[0] = data[data_len - 1];
|
||||
tail[1] = 0;
|
||||
ssb_block_write(dev->dev, tail, 2,
|
||||
q->mmio_base + B43_PIO_TXDATA,
|
||||
sizeof(u16));
|
||||
}
|
||||
|
@ -392,31 +395,31 @@ static u32 tx_write_4byte_queue(struct b43_pio_txqueue *q,
|
|||
q->mmio_base + B43_PIO8_TXDATA,
|
||||
sizeof(u32));
|
||||
if (data_len & 3) {
|
||||
wl->tx_tail[3] = 0;
|
||||
u8 *tail = wl->pio_tailspace;
|
||||
BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 4);
|
||||
|
||||
memset(tail, 0, 4);
|
||||
/* Write the last few bytes. */
|
||||
ctl &= ~(B43_PIO8_TXCTL_8_15 | B43_PIO8_TXCTL_16_23 |
|
||||
B43_PIO8_TXCTL_24_31);
|
||||
switch (data_len & 3) {
|
||||
case 3:
|
||||
ctl |= B43_PIO8_TXCTL_16_23 | B43_PIO8_TXCTL_8_15;
|
||||
wl->tx_tail[0] = data[data_len - 3];
|
||||
wl->tx_tail[1] = data[data_len - 2];
|
||||
wl->tx_tail[2] = data[data_len - 1];
|
||||
tail[0] = data[data_len - 3];
|
||||
tail[1] = data[data_len - 2];
|
||||
tail[2] = data[data_len - 1];
|
||||
break;
|
||||
case 2:
|
||||
ctl |= B43_PIO8_TXCTL_8_15;
|
||||
wl->tx_tail[0] = data[data_len - 2];
|
||||
wl->tx_tail[1] = data[data_len - 1];
|
||||
wl->tx_tail[2] = 0;
|
||||
tail[0] = data[data_len - 2];
|
||||
tail[1] = data[data_len - 1];
|
||||
break;
|
||||
case 1:
|
||||
wl->tx_tail[0] = data[data_len - 1];
|
||||
wl->tx_tail[1] = 0;
|
||||
wl->tx_tail[2] = 0;
|
||||
tail[0] = data[data_len - 1];
|
||||
break;
|
||||
}
|
||||
b43_piotx_write32(q, B43_PIO8_TXCTL, ctl);
|
||||
ssb_block_write(dev->dev, wl->tx_tail, 4,
|
||||
ssb_block_write(dev->dev, tail, 4,
|
||||
q->mmio_base + B43_PIO8_TXDATA,
|
||||
sizeof(u32));
|
||||
}
|
||||
|
@ -455,6 +458,7 @@ static int pio_tx_frame(struct b43_pio_txqueue *q,
|
|||
int err;
|
||||
unsigned int hdrlen;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct b43_txhdr *txhdr = (struct b43_txhdr *)wl->pio_scratchspace;
|
||||
|
||||
B43_WARN_ON(list_empty(&q->packets_list));
|
||||
pack = list_entry(q->packets_list.next,
|
||||
|
@ -462,7 +466,9 @@ static int pio_tx_frame(struct b43_pio_txqueue *q,
|
|||
|
||||
cookie = generate_cookie(q, pack);
|
||||
hdrlen = b43_txhdr_size(dev);
|
||||
err = b43_generate_txhdr(dev, (u8 *)&wl->txhdr, skb,
|
||||
BUILD_BUG_ON(sizeof(wl->pio_scratchspace) < sizeof(struct b43_txhdr));
|
||||
B43_WARN_ON(sizeof(wl->pio_scratchspace) < hdrlen);
|
||||
err = b43_generate_txhdr(dev, (u8 *)txhdr, skb,
|
||||
info, cookie);
|
||||
if (err)
|
||||
return err;
|
||||
|
@ -476,9 +482,9 @@ static int pio_tx_frame(struct b43_pio_txqueue *q,
|
|||
|
||||
pack->skb = skb;
|
||||
if (q->rev >= 8)
|
||||
pio_tx_frame_4byte_queue(pack, (const u8 *)&wl->txhdr, hdrlen);
|
||||
pio_tx_frame_4byte_queue(pack, (const u8 *)txhdr, hdrlen);
|
||||
else
|
||||
pio_tx_frame_2byte_queue(pack, (const u8 *)&wl->txhdr, hdrlen);
|
||||
pio_tx_frame_2byte_queue(pack, (const u8 *)txhdr, hdrlen);
|
||||
|
||||
/* Remove it from the list of available packet slots.
|
||||
* It will be put back when we receive the status report. */
|
||||
|
@ -624,8 +630,11 @@ static bool pio_rx_frame(struct b43_pio_rxqueue *q)
|
|||
unsigned int i, padding;
|
||||
struct sk_buff *skb;
|
||||
const char *err_msg = NULL;
|
||||
struct b43_rxhdr_fw4 *rxhdr =
|
||||
(struct b43_rxhdr_fw4 *)wl->pio_scratchspace;
|
||||
|
||||
memset(&wl->rxhdr, 0, sizeof(wl->rxhdr));
|
||||
BUILD_BUG_ON(sizeof(wl->pio_scratchspace) < sizeof(*rxhdr));
|
||||
memset(rxhdr, 0, sizeof(*rxhdr));
|
||||
|
||||
/* Check if we have data and wait for it to get ready. */
|
||||
if (q->rev >= 8) {
|
||||
|
@ -663,16 +672,16 @@ data_ready:
|
|||
|
||||
/* Get the preamble (RX header) */
|
||||
if (q->rev >= 8) {
|
||||
ssb_block_read(dev->dev, &wl->rxhdr, sizeof(wl->rxhdr),
|
||||
ssb_block_read(dev->dev, rxhdr, sizeof(*rxhdr),
|
||||
q->mmio_base + B43_PIO8_RXDATA,
|
||||
sizeof(u32));
|
||||
} else {
|
||||
ssb_block_read(dev->dev, &wl->rxhdr, sizeof(wl->rxhdr),
|
||||
ssb_block_read(dev->dev, rxhdr, sizeof(*rxhdr),
|
||||
q->mmio_base + B43_PIO_RXDATA,
|
||||
sizeof(u16));
|
||||
}
|
||||
/* Sanity checks. */
|
||||
len = le16_to_cpu(wl->rxhdr.frame_len);
|
||||
len = le16_to_cpu(rxhdr->frame_len);
|
||||
if (unlikely(len > 0x700)) {
|
||||
err_msg = "len > 0x700";
|
||||
goto rx_error;
|
||||
|
@ -682,7 +691,7 @@ data_ready:
|
|||
goto rx_error;
|
||||
}
|
||||
|
||||
macstat = le32_to_cpu(wl->rxhdr.mac_status);
|
||||
macstat = le32_to_cpu(rxhdr->mac_status);
|
||||
if (macstat & B43_RX_MAC_FCSERR) {
|
||||
if (!(q->dev->wl->filter_flags & FIF_FCSFAIL)) {
|
||||
/* Drop frames with failed FCS. */
|
||||
|
@ -707,22 +716,25 @@ data_ready:
|
|||
q->mmio_base + B43_PIO8_RXDATA,
|
||||
sizeof(u32));
|
||||
if (len & 3) {
|
||||
u8 *tail = wl->pio_tailspace;
|
||||
BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 4);
|
||||
|
||||
/* Read the last few bytes. */
|
||||
ssb_block_read(dev->dev, wl->rx_tail, 4,
|
||||
ssb_block_read(dev->dev, tail, 4,
|
||||
q->mmio_base + B43_PIO8_RXDATA,
|
||||
sizeof(u32));
|
||||
switch (len & 3) {
|
||||
case 3:
|
||||
skb->data[len + padding - 3] = wl->rx_tail[0];
|
||||
skb->data[len + padding - 2] = wl->rx_tail[1];
|
||||
skb->data[len + padding - 1] = wl->rx_tail[2];
|
||||
skb->data[len + padding - 3] = tail[0];
|
||||
skb->data[len + padding - 2] = tail[1];
|
||||
skb->data[len + padding - 1] = tail[2];
|
||||
break;
|
||||
case 2:
|
||||
skb->data[len + padding - 2] = wl->rx_tail[0];
|
||||
skb->data[len + padding - 1] = wl->rx_tail[1];
|
||||
skb->data[len + padding - 2] = tail[0];
|
||||
skb->data[len + padding - 1] = tail[1];
|
||||
break;
|
||||
case 1:
|
||||
skb->data[len + padding - 1] = wl->rx_tail[0];
|
||||
skb->data[len + padding - 1] = tail[0];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -731,15 +743,18 @@ data_ready:
|
|||
q->mmio_base + B43_PIO_RXDATA,
|
||||
sizeof(u16));
|
||||
if (len & 1) {
|
||||
u8 *tail = wl->pio_tailspace;
|
||||
BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 2);
|
||||
|
||||
/* Read the last byte. */
|
||||
ssb_block_read(dev->dev, wl->rx_tail, 2,
|
||||
ssb_block_read(dev->dev, tail, 2,
|
||||
q->mmio_base + B43_PIO_RXDATA,
|
||||
sizeof(u16));
|
||||
skb->data[len + padding - 1] = wl->rx_tail[0];
|
||||
skb->data[len + padding - 1] = tail[0];
|
||||
}
|
||||
}
|
||||
|
||||
b43_rx(q->dev, skb, &wl->rxhdr);
|
||||
b43_rx(q->dev, skb, rxhdr);
|
||||
|
||||
return 1;
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
|
||||
*/
|
||||
|
||||
#include "b43.h"
|
||||
#include "xmit.h"
|
||||
#include "phy_common.h"
|
||||
#include "dma.h"
|
||||
#include "pio.h"
|
||||
|
@ -690,10 +690,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
|
|||
}
|
||||
|
||||
memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
|
||||
|
||||
local_bh_disable();
|
||||
ieee80211_rx(dev->wl->hw, skb);
|
||||
local_bh_enable();
|
||||
ieee80211_rx_ni(dev->wl->hw, skb);
|
||||
|
||||
#if B43_DEBUG
|
||||
dev->rx_count++;
|
||||
|
|
|
@ -3592,7 +3592,7 @@ static int b43legacy_wireless_core_attach(struct b43legacy_wldev *dev)
|
|||
{
|
||||
struct b43legacy_wl *wl = dev->wl;
|
||||
struct ssb_bus *bus = dev->dev->bus;
|
||||
struct pci_dev *pdev = bus->host_pci;
|
||||
struct pci_dev *pdev = (bus->bustype == SSB_BUSTYPE_PCI) ? bus->host_pci : NULL;
|
||||
int err;
|
||||
int have_bphy = 0;
|
||||
int have_gphy = 0;
|
||||
|
@ -3706,7 +3706,7 @@ static int b43legacy_one_core_attach(struct ssb_device *dev,
|
|||
|
||||
if (!list_empty(&wl->devlist)) {
|
||||
/* We are not the first core on this chip. */
|
||||
pdev = dev->bus->host_pci;
|
||||
pdev = (dev->bus->bustype == SSB_BUSTYPE_PCI) ? dev->bus->host_pci : NULL;
|
||||
/* Only special chips support more than one wireless
|
||||
* core, although some of the other chips have more than
|
||||
* one wireless core as well. Check for this and
|
||||
|
|
|
@ -110,8 +110,7 @@ static struct iwl_lib_ops iwl1000_lib = {
|
|||
.send_tx_power = iwl5000_send_tx_power,
|
||||
.update_chain_flags = iwl_update_chain_flags,
|
||||
.apm_ops = {
|
||||
.init = iwl5000_apm_init,
|
||||
.reset = iwl5000_apm_reset,
|
||||
.init = iwl_apm_init,
|
||||
.stop = iwl_apm_stop,
|
||||
.config = iwl1000_nic_config,
|
||||
.set_pwr_src = iwl_set_pwr_src,
|
||||
|
@ -159,15 +158,20 @@ struct iwl_cfg iwl1000_bgn_cfg = {
|
|||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
.eeprom_ver = EEPROM_1000_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
|
||||
.num_of_queues = IWL50_NUM_QUEUES,
|
||||
.num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES,
|
||||
.mod_params = &iwl50_mod_params,
|
||||
.valid_tx_ant = ANT_A,
|
||||
.valid_rx_ant = ANT_AB,
|
||||
.need_pll_cfg = true,
|
||||
.pll_cfg_val = CSR50_ANA_PLL_CFG_VAL,
|
||||
.set_l0s = false,
|
||||
.use_bsm = false,
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_1000,
|
||||
.shadow_ram_support = false,
|
||||
.ht_greenfield_support = true,
|
||||
.led_compensation = 51,
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
.support_ct_kill_exit = true,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl1000_bg_cfg = {
|
||||
|
@ -180,15 +184,20 @@ struct iwl_cfg iwl1000_bg_cfg = {
|
|||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
.eeprom_ver = EEPROM_1000_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
|
||||
.num_of_queues = IWL50_NUM_QUEUES,
|
||||
.num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES,
|
||||
.mod_params = &iwl50_mod_params,
|
||||
.valid_tx_ant = ANT_A,
|
||||
.valid_rx_ant = ANT_AB,
|
||||
.need_pll_cfg = true,
|
||||
.pll_cfg_val = CSR50_ANA_PLL_CFG_VAL,
|
||||
.set_l0s = false,
|
||||
.use_bsm = false,
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_1000,
|
||||
.shadow_ram_support = false,
|
||||
.ht_greenfield_support = true,
|
||||
.led_compensation = 51,
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
.support_ct_kill_exit = true,
|
||||
};
|
||||
|
||||
MODULE_FIRMWARE(IWL1000_MODULE_FIRMWARE(IWL1000_UCODE_API_MAX));
|
||||
|
|
|
@ -71,12 +71,6 @@
|
|||
|
||||
#include "iwl-eeprom.h"
|
||||
|
||||
/*
|
||||
* uCode queue management definitions ...
|
||||
* Queue #4 is the command queue for 3945 and 4965.
|
||||
*/
|
||||
#define IWL_CMD_QUEUE_NUM 4
|
||||
|
||||
/* Time constants */
|
||||
#define SHORT_SLOT_TIME 9
|
||||
#define LONG_SLOT_TIME 20
|
||||
|
@ -254,12 +248,6 @@ struct iwl3945_eeprom {
|
|||
#define TFD_CTL_PAD_SET(n) (n << 28)
|
||||
#define TFD_CTL_PAD_GET(ctl) (ctl >> 28)
|
||||
|
||||
/*
|
||||
* RX related structures and functions
|
||||
*/
|
||||
#define RX_FREE_BUFFERS 64
|
||||
#define RX_LOW_WATERMARK 8
|
||||
|
||||
/* Sizes and addresses for instruction and data memory (SRAM) in
|
||||
* 3945's embedded processor. Driver access is via HBUS_TARG_MEM_* regs. */
|
||||
#define IWL39_RTC_INST_LOWER_BOUND (0x000000)
|
||||
|
|
|
@ -293,7 +293,7 @@ static void iwl3945_tx_queue_reclaim(struct iwl_priv *priv,
|
|||
static void iwl3945_rx_reply_tx(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
u16 sequence = le16_to_cpu(pkt->hdr.sequence);
|
||||
int txq_id = SEQ_TO_QUEUE(sequence);
|
||||
int index = SEQ_TO_INDEX(sequence);
|
||||
|
@ -353,16 +353,12 @@ static void iwl3945_rx_reply_tx(struct iwl_priv *priv,
|
|||
void iwl3945_hw_rx_statistics(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n",
|
||||
(int)sizeof(struct iwl3945_notif_statistics),
|
||||
le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK);
|
||||
|
||||
memcpy(&priv->statistics_39, pkt->u.raw, sizeof(priv->statistics_39));
|
||||
|
||||
iwl_leds_background(priv);
|
||||
|
||||
priv->last_statistics_time = jiffies;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
|
@ -545,14 +541,18 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv,
|
|||
struct iwl_rx_mem_buffer *rxb,
|
||||
struct ieee80211_rx_status *stats)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)IWL_RX_DATA(pkt);
|
||||
struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
|
||||
struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt);
|
||||
short len = le16_to_cpu(rx_hdr->len);
|
||||
u16 len = le16_to_cpu(rx_hdr->len);
|
||||
struct sk_buff *skb;
|
||||
int ret;
|
||||
__le16 fc = hdr->frame_control;
|
||||
|
||||
/* We received data from the HW, so stop the watchdog */
|
||||
if (unlikely((len + IWL39_RX_FRAME_SIZE) > skb_tailroom(rxb->skb))) {
|
||||
if (unlikely(len + IWL39_RX_FRAME_SIZE >
|
||||
PAGE_SIZE << priv->hw_params.rx_page_order)) {
|
||||
IWL_DEBUG_DROP(priv, "Corruption detected!\n");
|
||||
return;
|
||||
}
|
||||
|
@ -564,20 +564,49 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv,
|
|||
return;
|
||||
}
|
||||
|
||||
skb_reserve(rxb->skb, (void *)rx_hdr->payload - (void *)pkt);
|
||||
/* Set the size of the skb to the size of the frame */
|
||||
skb_put(rxb->skb, le16_to_cpu(rx_hdr->len));
|
||||
skb = alloc_skb(IWL_LINK_HDR_MAX, GFP_ATOMIC);
|
||||
if (!skb) {
|
||||
IWL_ERR(priv, "alloc_skb failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!iwl3945_mod_params.sw_crypto)
|
||||
iwl_set_decrypted_flag(priv,
|
||||
(struct ieee80211_hdr *)rxb->skb->data,
|
||||
(struct ieee80211_hdr *)rxb_addr(rxb),
|
||||
le32_to_cpu(rx_end->status), stats);
|
||||
|
||||
iwl_update_stats(priv, false, hdr->frame_control, len);
|
||||
skb_add_rx_frag(skb, 0, rxb->page,
|
||||
(void *)rx_hdr->payload - (void *)pkt, len);
|
||||
|
||||
memcpy(IEEE80211_SKB_RXCB(rxb->skb), stats, sizeof(*stats));
|
||||
ieee80211_rx_irqsafe(priv->hw, rxb->skb);
|
||||
rxb->skb = NULL;
|
||||
/* mac80211 currently doesn't support paged SKB. Convert it to
|
||||
* linear SKB for management frame and data frame requires
|
||||
* software decryption or software defragementation. */
|
||||
if (ieee80211_is_mgmt(fc) ||
|
||||
ieee80211_has_protected(fc) ||
|
||||
ieee80211_has_morefrags(fc) ||
|
||||
le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG)
|
||||
ret = skb_linearize(skb);
|
||||
else
|
||||
ret = __pskb_pull_tail(skb, min_t(u16, IWL_LINK_HDR_MAX, len)) ?
|
||||
0 : -ENOMEM;
|
||||
|
||||
if (ret) {
|
||||
kfree_skb(skb);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX: We cannot touch the page and its virtual memory (pkt) after
|
||||
* here. It might have already been freed by the above skb change.
|
||||
*/
|
||||
|
||||
iwl_update_stats(priv, false, fc, len);
|
||||
memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
|
||||
|
||||
ieee80211_rx(priv->hw, skb);
|
||||
out:
|
||||
priv->alloc_rxb_page--;
|
||||
rxb->page = NULL;
|
||||
}
|
||||
|
||||
#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6)
|
||||
|
@ -587,7 +616,7 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv,
|
|||
{
|
||||
struct ieee80211_hdr *header;
|
||||
struct ieee80211_rx_status rx_status;
|
||||
struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt);
|
||||
struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
|
||||
struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt);
|
||||
|
@ -787,29 +816,31 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv,
|
|||
u8 data_retry_limit;
|
||||
__le32 tx_flags;
|
||||
__le16 fc = hdr->frame_control;
|
||||
struct iwl3945_tx_cmd *tx = (struct iwl3945_tx_cmd *)cmd->cmd.payload;
|
||||
struct iwl3945_tx_cmd *tx_cmd = (struct iwl3945_tx_cmd *)cmd->cmd.payload;
|
||||
|
||||
rate = iwl3945_rates[rate_index].plcp;
|
||||
tx_flags = tx->tx_flags;
|
||||
tx_flags = tx_cmd->tx_flags;
|
||||
|
||||
/* We need to figure out how to get the sta->supp_rates while
|
||||
* in this running context */
|
||||
rate_mask = IWL_RATES_MASK;
|
||||
|
||||
|
||||
/* Set retry limit on DATA packets and Probe Responses*/
|
||||
if (ieee80211_is_probe_resp(fc))
|
||||
data_retry_limit = 3;
|
||||
else
|
||||
data_retry_limit = IWL_DEFAULT_TX_RETRY;
|
||||
tx_cmd->data_retry_limit = data_retry_limit;
|
||||
|
||||
if (tx_id >= IWL_CMD_QUEUE_NUM)
|
||||
rts_retry_limit = 3;
|
||||
else
|
||||
rts_retry_limit = 7;
|
||||
|
||||
if (ieee80211_is_probe_resp(fc)) {
|
||||
data_retry_limit = 3;
|
||||
if (data_retry_limit < rts_retry_limit)
|
||||
rts_retry_limit = data_retry_limit;
|
||||
} else
|
||||
data_retry_limit = IWL_DEFAULT_TX_RETRY;
|
||||
|
||||
if (priv->data_retry_limit != -1)
|
||||
data_retry_limit = priv->data_retry_limit;
|
||||
if (data_retry_limit < rts_retry_limit)
|
||||
rts_retry_limit = data_retry_limit;
|
||||
tx_cmd->rts_retry_limit = rts_retry_limit;
|
||||
|
||||
if (ieee80211_is_mgmt(fc)) {
|
||||
switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
|
||||
|
@ -827,22 +858,20 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv,
|
|||
}
|
||||
}
|
||||
|
||||
tx->rts_retry_limit = rts_retry_limit;
|
||||
tx->data_retry_limit = data_retry_limit;
|
||||
tx->rate = rate;
|
||||
tx->tx_flags = tx_flags;
|
||||
tx_cmd->rate = rate;
|
||||
tx_cmd->tx_flags = tx_flags;
|
||||
|
||||
/* OFDM */
|
||||
tx->supp_rates[0] =
|
||||
tx_cmd->supp_rates[0] =
|
||||
((rate_mask & IWL_OFDM_RATES_MASK) >> IWL_FIRST_OFDM_RATE) & 0xFF;
|
||||
|
||||
/* CCK */
|
||||
tx->supp_rates[1] = (rate_mask & 0xF);
|
||||
tx_cmd->supp_rates[1] = (rate_mask & 0xF);
|
||||
|
||||
IWL_DEBUG_RATE(priv, "Tx sta id: %d, rate: %d (plcp), flags: 0x%4X "
|
||||
"cck/ofdm mask: 0x%x/0x%x\n", sta_id,
|
||||
tx->rate, le32_to_cpu(tx->tx_flags),
|
||||
tx->supp_rates[1], tx->supp_rates[0]);
|
||||
tx_cmd->rate, le32_to_cpu(tx_cmd->tx_flags),
|
||||
tx_cmd->supp_rates[1], tx_cmd->supp_rates[0]);
|
||||
}
|
||||
|
||||
u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, u16 tx_rate, u8 flags)
|
||||
|
@ -958,6 +987,11 @@ static int iwl3945_txq_ctx_reset(struct iwl_priv *priv)
|
|||
|
||||
iwl3945_hw_txq_ctx_free(priv);
|
||||
|
||||
/* allocate tx queue structure */
|
||||
rc = iwl_alloc_txq_mem(priv);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
/* Tx CMD queue */
|
||||
rc = iwl3945_tx_reset(priv);
|
||||
if (rc)
|
||||
|
@ -982,42 +1016,25 @@ static int iwl3945_txq_ctx_reset(struct iwl_priv *priv)
|
|||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Start up 3945's basic functionality after it has been reset
|
||||
* (e.g. after platform boot, or shutdown via iwl_apm_stop())
|
||||
* NOTE: This does not load uCode nor start the embedded processor
|
||||
*/
|
||||
static int iwl3945_apm_init(struct iwl_priv *priv)
|
||||
{
|
||||
int ret;
|
||||
int ret = iwl_apm_init(priv);
|
||||
|
||||
iwl_power_initialize(priv);
|
||||
/* Clear APMG (NIC's internal power management) interrupts */
|
||||
iwl_write_prph(priv, APMG_RTC_INT_MSK_REG, 0x0);
|
||||
iwl_write_prph(priv, APMG_RTC_INT_STT_REG, 0xFFFFFFFF);
|
||||
|
||||
iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS,
|
||||
CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
|
||||
/* Reset radio chip */
|
||||
iwl_set_bits_prph(priv, APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_RESET_REQ);
|
||||
udelay(5);
|
||||
iwl_clear_bits_prph(priv, APMG_PS_CTRL_REG, APMG_PS_CTRL_VAL_RESET_REQ);
|
||||
|
||||
/* disable L0s without affecting L1 :don't wait for ICH L0s bug W/A) */
|
||||
iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS,
|
||||
CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX);
|
||||
|
||||
/* set "initialization complete" bit to move adapter
|
||||
* D0U* --> D0A* state */
|
||||
iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
|
||||
|
||||
ret = iwl_poll_bit(priv, CSR_GP_CNTRL,
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
|
||||
if (ret < 0) {
|
||||
IWL_DEBUG_INFO(priv, "Failed to init the card\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* enable DMA */
|
||||
iwl_write_prph(priv, APMG_CLK_CTRL_REG, APMG_CLK_VAL_DMA_CLK_RQT |
|
||||
APMG_CLK_VAL_BSM_CLK_RQT);
|
||||
|
||||
udelay(20);
|
||||
|
||||
/* disable L1-Active */
|
||||
iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG,
|
||||
APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1142,12 +1159,16 @@ void iwl3945_hw_txq_ctx_free(struct iwl_priv *priv)
|
|||
int txq_id;
|
||||
|
||||
/* Tx queues */
|
||||
for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
|
||||
if (txq_id == IWL_CMD_QUEUE_NUM)
|
||||
iwl_cmd_queue_free(priv);
|
||||
else
|
||||
iwl_tx_queue_free(priv, txq_id);
|
||||
if (priv->txq)
|
||||
for (txq_id = 0; txq_id < priv->hw_params.max_txq_num;
|
||||
txq_id++)
|
||||
if (txq_id == IWL_CMD_QUEUE_NUM)
|
||||
iwl_cmd_queue_free(priv);
|
||||
else
|
||||
iwl_tx_queue_free(priv, txq_id);
|
||||
|
||||
/* free tx queue structure */
|
||||
iwl_free_txq_mem(priv);
|
||||
}
|
||||
|
||||
void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv)
|
||||
|
@ -1156,6 +1177,7 @@ void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv)
|
|||
|
||||
/* stop SCD */
|
||||
iwl_write_prph(priv, ALM_SCD_MODE_REG, 0);
|
||||
iwl_write_prph(priv, ALM_SCD_TXFACT_REG, 0);
|
||||
|
||||
/* reset TFD queues */
|
||||
for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
|
||||
|
@ -1168,47 +1190,6 @@ void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv)
|
|||
iwl3945_hw_txq_ctx_free(priv);
|
||||
}
|
||||
|
||||
static int iwl3945_apm_reset(struct iwl_priv *priv)
|
||||
{
|
||||
iwl_apm_stop_master(priv);
|
||||
|
||||
|
||||
iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
|
||||
udelay(10);
|
||||
|
||||
iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
|
||||
|
||||
iwl_poll_bit(priv, CSR_GP_CNTRL,
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
|
||||
|
||||
iwl_write_prph(priv, APMG_CLK_CTRL_REG,
|
||||
APMG_CLK_VAL_BSM_CLK_RQT);
|
||||
|
||||
iwl_write_prph(priv, APMG_RTC_INT_MSK_REG, 0x0);
|
||||
iwl_write_prph(priv, APMG_RTC_INT_STT_REG,
|
||||
0xFFFFFFFF);
|
||||
|
||||
/* enable DMA */
|
||||
iwl_write_prph(priv, APMG_CLK_EN_REG,
|
||||
APMG_CLK_VAL_DMA_CLK_RQT |
|
||||
APMG_CLK_VAL_BSM_CLK_RQT);
|
||||
udelay(10);
|
||||
|
||||
iwl_set_bits_prph(priv, APMG_PS_CTRL_REG,
|
||||
APMG_PS_CTRL_VAL_RESET_REQ);
|
||||
udelay(5);
|
||||
iwl_clear_bits_prph(priv, APMG_PS_CTRL_REG,
|
||||
APMG_PS_CTRL_VAL_RESET_REQ);
|
||||
|
||||
/* Clear the 'host command active' bit... */
|
||||
clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
|
||||
|
||||
wake_up_interruptible(&priv->wait_command_queue);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl3945_hw_reg_adjust_power_by_temp
|
||||
* return index delta into power gain settings table
|
||||
|
@ -1817,7 +1798,7 @@ int iwl3945_hw_reg_set_txpower(struct iwl_priv *priv, s8 power)
|
|||
static int iwl3945_send_rxon_assoc(struct iwl_priv *priv)
|
||||
{
|
||||
int rc = 0;
|
||||
struct iwl_rx_packet *res = NULL;
|
||||
struct iwl_rx_packet *pkt;
|
||||
struct iwl3945_rxon_assoc_cmd rxon_assoc;
|
||||
struct iwl_host_cmd cmd = {
|
||||
.id = REPLY_RXON_ASSOC,
|
||||
|
@ -1846,14 +1827,14 @@ static int iwl3945_send_rxon_assoc(struct iwl_priv *priv)
|
|||
if (rc)
|
||||
return rc;
|
||||
|
||||
res = (struct iwl_rx_packet *)cmd.reply_skb->data;
|
||||
if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
|
||||
pkt = (struct iwl_rx_packet *)cmd.reply_page;
|
||||
if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
|
||||
IWL_ERR(priv, "Bad return from REPLY_RXON_ASSOC command\n");
|
||||
rc = -EIO;
|
||||
}
|
||||
|
||||
priv->alloc_rxb_skb--;
|
||||
dev_kfree_skb_any(cmd.reply_skb);
|
||||
priv->alloc_rxb_page--;
|
||||
free_pages(cmd.reply_page, priv->hw_params.rx_page_order);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
@ -2001,12 +1982,6 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* will add 3945 channel switch cmd handling later */
|
||||
int iwl3945_hw_channel_switch(struct iwl_priv *priv, u16 channel)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl3945_reg_txpower_periodic - called when time to check our temperature.
|
||||
*
|
||||
|
@ -2516,11 +2491,10 @@ int iwl3945_hw_set_hw_params(struct iwl_priv *priv)
|
|||
}
|
||||
|
||||
/* Assign number of Usable TX queues */
|
||||
priv->hw_params.max_txq_num = IWL39_NUM_QUEUES;
|
||||
priv->hw_params.max_txq_num = priv->cfg->num_of_queues;
|
||||
|
||||
priv->hw_params.tfd_size = sizeof(struct iwl3945_tfd);
|
||||
priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_3K;
|
||||
priv->hw_params.max_pkt_size = 2342;
|
||||
priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_3K);
|
||||
priv->hw_params.max_rxq_size = RX_QUEUE_SIZE;
|
||||
priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG;
|
||||
priv->hw_params.max_stations = IWL3945_STATION_COUNT;
|
||||
|
@ -2803,7 +2777,6 @@ static struct iwl_lib_ops iwl3945_lib = {
|
|||
.dump_nic_error_log = iwl3945_dump_nic_error_log,
|
||||
.apm_ops = {
|
||||
.init = iwl3945_apm_init,
|
||||
.reset = iwl3945_apm_reset,
|
||||
.stop = iwl_apm_stop,
|
||||
.config = iwl3945_nic_config,
|
||||
.set_pwr_src = iwl3945_set_pwr_src,
|
||||
|
@ -2833,6 +2806,7 @@ static struct iwl_lib_ops iwl3945_lib = {
|
|||
static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = {
|
||||
.get_hcmd_size = iwl3945_get_hcmd_size,
|
||||
.build_addsta_hcmd = iwl3945_build_addsta_hcmd,
|
||||
.rts_tx_cmd_flag = iwlcore_rts_tx_cmd_flag,
|
||||
};
|
||||
|
||||
static struct iwl_ops iwl3945_ops = {
|
||||
|
@ -2852,7 +2826,11 @@ static struct iwl_cfg iwl3945_bg_cfg = {
|
|||
.eeprom_size = IWL3945_EEPROM_IMG_SIZE,
|
||||
.eeprom_ver = EEPROM_3945_EEPROM_VERSION,
|
||||
.ops = &iwl3945_ops,
|
||||
.num_of_queues = IWL39_NUM_QUEUES,
|
||||
.mod_params = &iwl3945_mod_params,
|
||||
.pll_cfg_val = CSR39_ANA_PLL_CFG_VAL,
|
||||
.set_l0s = false,
|
||||
.use_bsm = true,
|
||||
.use_isr_legacy = true,
|
||||
.ht_greenfield_support = false,
|
||||
.led_compensation = 64,
|
||||
|
@ -2867,6 +2845,7 @@ static struct iwl_cfg iwl3945_abg_cfg = {
|
|||
.eeprom_size = IWL3945_EEPROM_IMG_SIZE,
|
||||
.eeprom_ver = EEPROM_3945_EEPROM_VERSION,
|
||||
.ops = &iwl3945_ops,
|
||||
.num_of_queues = IWL39_NUM_QUEUES,
|
||||
.mod_params = &iwl3945_mod_params,
|
||||
.use_isr_legacy = true,
|
||||
.ht_greenfield_support = false,
|
||||
|
|
|
@ -130,12 +130,6 @@ struct iwl3945_frame {
|
|||
#define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ)
|
||||
#define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4)
|
||||
|
||||
/*
|
||||
* RX related structures and functions
|
||||
*/
|
||||
#define RX_FREE_BUFFERS 64
|
||||
#define RX_LOW_WATERMARK 8
|
||||
|
||||
#define SUP_RATE_11A_MAX_NUM_CHANNELS 8
|
||||
#define SUP_RATE_11B_MAX_NUM_CHANNELS 4
|
||||
#define SUP_RATE_11G_MAX_NUM_CHANNELS 12
|
||||
|
@ -280,8 +274,6 @@ extern void iwl3945_config_ap(struct iwl_priv *priv);
|
|||
*/
|
||||
extern u8 iwl3945_hw_find_station(struct iwl_priv *priv, const u8 *bssid);
|
||||
|
||||
extern int iwl3945_hw_channel_switch(struct iwl_priv *priv, u16 channel);
|
||||
|
||||
/*
|
||||
* Forward declare iwl-3945.c functions for iwl-base.c
|
||||
*/
|
||||
|
|
|
@ -76,12 +76,9 @@
|
|||
|
||||
/*
|
||||
* uCode queue management definitions ...
|
||||
* Queue #4 is the command queue for 3945 and 4965; map it to Tx FIFO chnl 4.
|
||||
* The first queue used for block-ack aggregation is #7 (4965 only).
|
||||
* All block-ack aggregation queues should map to Tx DMA/FIFO channel 7.
|
||||
*/
|
||||
#define IWL_CMD_QUEUE_NUM 4
|
||||
#define IWL_CMD_FIFO_NUM 4
|
||||
#define IWL49_FIRST_AMPDU_QUEUE 7
|
||||
|
||||
/* Time constants */
|
||||
|
|
|
@ -62,8 +62,6 @@ static int iwl4965_hw_get_temperature(struct iwl_priv *priv);
|
|||
|
||||
/* module parameters */
|
||||
static struct iwl_mod_params iwl4965_mod_params = {
|
||||
.num_of_queues = IWL49_NUM_QUEUES,
|
||||
.num_of_ampdu_queues = IWL49_NUM_AMPDU_QUEUES,
|
||||
.amsdu_size_8K = 1,
|
||||
.restart_fw = 1,
|
||||
/* the rest are 0 by default */
|
||||
|
@ -319,64 +317,13 @@ static void iwl4965_txq_set_sched(struct iwl_priv *priv, u32 mask)
|
|||
iwl_write_prph(priv, IWL49_SCD_TXFACT, mask);
|
||||
}
|
||||
|
||||
static int iwl4965_apm_init(struct iwl_priv *priv)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS,
|
||||
CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
|
||||
|
||||
/* disable L0s without affecting L1 :don't wait for ICH L0s bug W/A) */
|
||||
iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS,
|
||||
CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX);
|
||||
|
||||
/* set "initialization complete" bit to move adapter
|
||||
* D0U* --> D0A* state */
|
||||
iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
|
||||
|
||||
/* wait for clock stabilization */
|
||||
ret = iwl_poll_bit(priv, CSR_GP_CNTRL,
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
|
||||
if (ret < 0) {
|
||||
IWL_DEBUG_INFO(priv, "Failed to init the card\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* enable DMA */
|
||||
iwl_write_prph(priv, APMG_CLK_CTRL_REG, APMG_CLK_VAL_DMA_CLK_RQT |
|
||||
APMG_CLK_VAL_BSM_CLK_RQT);
|
||||
|
||||
udelay(20);
|
||||
|
||||
/* disable L1-Active */
|
||||
iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG,
|
||||
APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static void iwl4965_nic_config(struct iwl_priv *priv)
|
||||
{
|
||||
unsigned long flags;
|
||||
u16 radio_cfg;
|
||||
u16 lctl;
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
|
||||
lctl = iwl_pcie_link_ctl(priv);
|
||||
|
||||
/* HW bug W/A - negligible power consumption */
|
||||
/* L1-ASPM is enabled by BIOS */
|
||||
if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) == PCI_CFG_LINK_CTRL_VAL_L1_EN)
|
||||
/* L1-ASPM enabled: disable L0S */
|
||||
iwl_set_bit(priv, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED);
|
||||
else
|
||||
/* L1-ASPM disabled: enable L0S */
|
||||
iwl_clear_bit(priv, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED);
|
||||
|
||||
radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG);
|
||||
|
||||
/* write radio config values to register */
|
||||
|
@ -397,46 +344,6 @@ static void iwl4965_nic_config(struct iwl_priv *priv)
|
|||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
}
|
||||
|
||||
static int iwl4965_apm_reset(struct iwl_priv *priv)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
iwl_apm_stop_master(priv);
|
||||
|
||||
|
||||
iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
|
||||
|
||||
udelay(10);
|
||||
|
||||
/* FIXME: put here L1A -L0S w/a */
|
||||
|
||||
iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
|
||||
|
||||
ret = iwl_poll_bit(priv, CSR_GP_CNTRL,
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
udelay(10);
|
||||
|
||||
/* Enable DMA and BSM Clock */
|
||||
iwl_write_prph(priv, APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT |
|
||||
APMG_CLK_VAL_BSM_CLK_RQT);
|
||||
|
||||
udelay(10);
|
||||
|
||||
/* disable L1A */
|
||||
iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG,
|
||||
APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
|
||||
|
||||
clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
|
||||
wake_up_interruptible(&priv->wait_command_queue);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Reset differential Rx gains in NIC to prepare for chain noise calibration.
|
||||
* Called after every association, but this runs only once!
|
||||
* ... once chain noise is calibrated the first time, it's good forever. */
|
||||
|
@ -526,18 +433,6 @@ static void iwl4965_gain_computation(struct iwl_priv *priv,
|
|||
data->beacon_count = 0;
|
||||
}
|
||||
|
||||
static void iwl4965_rts_tx_cmd_flag(struct ieee80211_tx_info *info,
|
||||
__le32 *tx_flags)
|
||||
{
|
||||
if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) {
|
||||
*tx_flags |= TX_CMD_FLG_RTS_MSK;
|
||||
*tx_flags &= ~TX_CMD_FLG_CTS_MSK;
|
||||
} else if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
|
||||
*tx_flags &= ~TX_CMD_FLG_RTS_MSK;
|
||||
*tx_flags |= TX_CMD_FLG_CTS_MSK;
|
||||
}
|
||||
}
|
||||
|
||||
static void iwl4965_bg_txpower_work(struct work_struct *work)
|
||||
{
|
||||
struct iwl_priv *priv = container_of(work, struct iwl_priv,
|
||||
|
@ -718,6 +613,10 @@ static struct iwl_sensitivity_ranges iwl4965_sensitivity = {
|
|||
|
||||
.nrg_th_cck = 100,
|
||||
.nrg_th_ofdm = 100,
|
||||
|
||||
.barker_corr_th_min = 190,
|
||||
.barker_corr_th_min_mrc = 390,
|
||||
.nrg_th_cca = 62,
|
||||
};
|
||||
|
||||
static void iwl4965_set_ct_threshold(struct iwl_priv *priv)
|
||||
|
@ -734,19 +633,16 @@ static void iwl4965_set_ct_threshold(struct iwl_priv *priv)
|
|||
*/
|
||||
static int iwl4965_hw_set_hw_params(struct iwl_priv *priv)
|
||||
{
|
||||
if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES &&
|
||||
priv->cfg->mod_params->num_of_queues <= IWL49_NUM_QUEUES)
|
||||
priv->cfg->num_of_queues =
|
||||
priv->cfg->mod_params->num_of_queues;
|
||||
|
||||
if ((priv->cfg->mod_params->num_of_queues > IWL49_NUM_QUEUES) ||
|
||||
(priv->cfg->mod_params->num_of_queues < IWL_MIN_NUM_QUEUES)) {
|
||||
IWL_ERR(priv,
|
||||
"invalid queues_num, should be between %d and %d\n",
|
||||
IWL_MIN_NUM_QUEUES, IWL49_NUM_QUEUES);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues;
|
||||
priv->hw_params.max_txq_num = priv->cfg->num_of_queues;
|
||||
priv->hw_params.dma_chnl_num = FH49_TCSR_CHNL_NUM;
|
||||
priv->hw_params.scd_bc_tbls_size =
|
||||
IWL49_NUM_QUEUES * sizeof(struct iwl4965_scd_bc_tbl);
|
||||
priv->cfg->num_of_queues *
|
||||
sizeof(struct iwl4965_scd_bc_tbl);
|
||||
priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
|
||||
priv->hw_params.max_stations = IWL4965_STATION_COUNT;
|
||||
priv->hw_params.bcast_sta_id = IWL4965_BROADCAST_ID;
|
||||
|
@ -757,10 +653,10 @@ static int iwl4965_hw_set_hw_params(struct iwl_priv *priv)
|
|||
|
||||
priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR;
|
||||
|
||||
priv->hw_params.tx_chains_num = 2;
|
||||
priv->hw_params.rx_chains_num = 2;
|
||||
priv->hw_params.valid_tx_ant = ANT_A | ANT_B;
|
||||
priv->hw_params.valid_rx_ant = ANT_A | ANT_B;
|
||||
priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
|
||||
priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant);
|
||||
priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant;
|
||||
priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant;
|
||||
if (priv->cfg->ops->lib->temp_ops.set_ct_kill)
|
||||
priv->cfg->ops->lib->temp_ops.set_ct_kill(priv);
|
||||
|
||||
|
@ -1537,14 +1433,13 @@ static int iwl4965_send_rxon_assoc(struct iwl_priv *priv)
|
|||
return ret;
|
||||
}
|
||||
|
||||
#ifdef IEEE80211_CONF_CHANNEL_SWITCH
|
||||
static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel)
|
||||
{
|
||||
int rc;
|
||||
u8 band = 0;
|
||||
bool is_ht40 = false;
|
||||
u8 ctrl_chan_high = 0;
|
||||
struct iwl4965_channel_switch_cmd cmd = { 0 };
|
||||
struct iwl4965_channel_switch_cmd cmd;
|
||||
const struct iwl_channel_info *ch_info;
|
||||
|
||||
band = priv->band == IEEE80211_BAND_2GHZ;
|
||||
|
@ -1565,8 +1460,11 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel)
|
|||
cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
|
||||
if (ch_info)
|
||||
cmd.expect_beacon = is_channel_radar(ch_info);
|
||||
else
|
||||
cmd.expect_beacon = 1;
|
||||
else {
|
||||
IWL_ERR(priv, "invalid channel switch from %u to %u\n",
|
||||
priv->active_rxon.channel, channel);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
rc = iwl4965_fill_txpower_tbl(priv, band, channel, is_ht40,
|
||||
ctrl_chan_high, &cmd.tx_power);
|
||||
|
@ -1578,7 +1476,6 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel)
|
|||
rc = iwl_send_cmd_pdu(priv, REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd);
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* iwl4965_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array
|
||||
|
@ -1775,11 +1672,13 @@ static int iwl4965_txq_agg_disable(struct iwl_priv *priv, u16 txq_id,
|
|||
u16 ssn_idx, u8 tx_fifo)
|
||||
{
|
||||
if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) ||
|
||||
(IWL49_FIRST_AMPDU_QUEUE + IWL49_NUM_AMPDU_QUEUES <= txq_id)) {
|
||||
(IWL49_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues
|
||||
<= txq_id)) {
|
||||
IWL_WARN(priv,
|
||||
"queue number out of range: %d, must be %d to %d\n",
|
||||
txq_id, IWL49_FIRST_AMPDU_QUEUE,
|
||||
IWL49_FIRST_AMPDU_QUEUE + IWL49_NUM_AMPDU_QUEUES - 1);
|
||||
IWL49_FIRST_AMPDU_QUEUE +
|
||||
priv->cfg->num_of_ampdu_queues - 1);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -1840,11 +1739,13 @@ static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id,
|
|||
u16 ra_tid;
|
||||
|
||||
if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) ||
|
||||
(IWL49_FIRST_AMPDU_QUEUE + IWL49_NUM_AMPDU_QUEUES <= txq_id)) {
|
||||
(IWL49_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues
|
||||
<= txq_id)) {
|
||||
IWL_WARN(priv,
|
||||
"queue number out of range: %d, must be %d to %d\n",
|
||||
txq_id, IWL49_FIRST_AMPDU_QUEUE,
|
||||
IWL49_FIRST_AMPDU_QUEUE + IWL49_NUM_AMPDU_QUEUES - 1);
|
||||
IWL49_FIRST_AMPDU_QUEUE +
|
||||
priv->cfg->num_of_ampdu_queues - 1);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -2048,7 +1949,7 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv,
|
|||
static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
u16 sequence = le16_to_cpu(pkt->hdr.sequence);
|
||||
int txq_id = SEQ_TO_QUEUE(sequence);
|
||||
int index = SEQ_TO_INDEX(sequence);
|
||||
|
@ -2249,7 +2150,7 @@ static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = {
|
|||
.build_addsta_hcmd = iwl4965_build_addsta_hcmd,
|
||||
.chain_noise_reset = iwl4965_chain_noise_reset,
|
||||
.gain_computation = iwl4965_gain_computation,
|
||||
.rts_tx_cmd_flag = iwl4965_rts_tx_cmd_flag,
|
||||
.rts_tx_cmd_flag = iwlcore_rts_tx_cmd_flag,
|
||||
.calc_rssi = iwl4965_calc_rssi,
|
||||
};
|
||||
|
||||
|
@ -2271,9 +2172,9 @@ static struct iwl_lib_ops iwl4965_lib = {
|
|||
.load_ucode = iwl4965_load_bsm,
|
||||
.dump_nic_event_log = iwl_dump_nic_event_log,
|
||||
.dump_nic_error_log = iwl_dump_nic_error_log,
|
||||
.set_channel_switch = iwl4965_hw_channel_switch,
|
||||
.apm_ops = {
|
||||
.init = iwl4965_apm_init,
|
||||
.reset = iwl4965_apm_reset,
|
||||
.init = iwl_apm_init,
|
||||
.stop = iwl_apm_stop,
|
||||
.config = iwl4965_nic_config,
|
||||
.set_pwr_src = iwl_set_pwr_src,
|
||||
|
@ -2323,7 +2224,14 @@ struct iwl_cfg iwl4965_agn_cfg = {
|
|||
.eeprom_ver = EEPROM_4965_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_4965_TX_POWER_VERSION,
|
||||
.ops = &iwl4965_ops,
|
||||
.num_of_queues = IWL49_NUM_QUEUES,
|
||||
.num_of_ampdu_queues = IWL49_NUM_AMPDU_QUEUES,
|
||||
.mod_params = &iwl4965_mod_params,
|
||||
.valid_tx_ant = ANT_AB,
|
||||
.valid_rx_ant = ANT_AB,
|
||||
.pll_cfg_val = 0,
|
||||
.set_l0s = true,
|
||||
.use_bsm = true,
|
||||
.use_isr_legacy = true,
|
||||
.ht_greenfield_support = false,
|
||||
.broken_powersave = true,
|
||||
|
|
|
@ -72,115 +72,14 @@ static const u16 iwl5000_default_queue_to_tx_fifo[] = {
|
|||
IWL_TX_FIFO_HCCA_2
|
||||
};
|
||||
|
||||
int iwl5000_apm_init(struct iwl_priv *priv)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS,
|
||||
CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
|
||||
|
||||
/* disable L0s without affecting L1 :don't wait for ICH L0s bug W/A) */
|
||||
iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS,
|
||||
CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX);
|
||||
|
||||
/* Set FH wait threshold to maximum (HW error during stress W/A) */
|
||||
iwl_set_bit(priv, CSR_DBG_HPET_MEM_REG, CSR_DBG_HPET_MEM_REG_VAL);
|
||||
|
||||
/* enable HAP INTA to move device L1a -> L0s */
|
||||
iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
|
||||
CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A);
|
||||
|
||||
if (priv->cfg->need_pll_cfg)
|
||||
iwl_set_bit(priv, CSR_ANA_PLL_CFG, CSR50_ANA_PLL_CFG_VAL);
|
||||
|
||||
/* set "initialization complete" bit to move adapter
|
||||
* D0U* --> D0A* state */
|
||||
iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
|
||||
|
||||
/* wait for clock stabilization */
|
||||
ret = iwl_poll_bit(priv, CSR_GP_CNTRL,
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
|
||||
if (ret < 0) {
|
||||
IWL_DEBUG_INFO(priv, "Failed to init the card\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* enable DMA */
|
||||
iwl_write_prph(priv, APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT);
|
||||
|
||||
udelay(20);
|
||||
|
||||
/* disable L1-Active */
|
||||
iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG,
|
||||
APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int iwl5000_apm_reset(struct iwl_priv *priv)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
iwl_apm_stop_master(priv);
|
||||
|
||||
iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
|
||||
|
||||
udelay(10);
|
||||
|
||||
|
||||
/* FIXME: put here L1A -L0S w/a */
|
||||
|
||||
if (priv->cfg->need_pll_cfg)
|
||||
iwl_set_bit(priv, CSR_ANA_PLL_CFG, CSR50_ANA_PLL_CFG_VAL);
|
||||
|
||||
/* set "initialization complete" bit to move adapter
|
||||
* D0U* --> D0A* state */
|
||||
iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
|
||||
|
||||
/* wait for clock stabilization */
|
||||
ret = iwl_poll_bit(priv, CSR_GP_CNTRL,
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
|
||||
if (ret < 0) {
|
||||
IWL_DEBUG_INFO(priv, "Failed to init the card\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* enable DMA */
|
||||
iwl_write_prph(priv, APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT);
|
||||
|
||||
udelay(20);
|
||||
|
||||
/* disable L1-Active */
|
||||
iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG,
|
||||
APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
|
||||
out:
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* NIC configuration for 5000 series */
|
||||
void iwl5000_nic_config(struct iwl_priv *priv)
|
||||
{
|
||||
unsigned long flags;
|
||||
u16 radio_cfg;
|
||||
u16 lctl;
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
|
||||
lctl = iwl_pcie_link_ctl(priv);
|
||||
|
||||
/* HW bug W/A */
|
||||
/* L1-ASPM is enabled by BIOS */
|
||||
if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) == PCI_CFG_LINK_CTRL_VAL_L1_EN)
|
||||
/* L1-APSM enabled: disable L0S */
|
||||
iwl_set_bit(priv, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED);
|
||||
else
|
||||
/* L1-ASPM disabled: enable L0S */
|
||||
iwl_clear_bit(priv, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED);
|
||||
|
||||
radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG);
|
||||
|
||||
/* write radio config values to register */
|
||||
|
@ -279,7 +178,7 @@ static void iwl5000_gain_computation(struct iwl_priv *priv,
|
|||
data->delta_gain_code[i] = 0;
|
||||
continue;
|
||||
}
|
||||
delta_g = (1000 * ((s32)average_noise[0] -
|
||||
delta_g = (1000 * ((s32)average_noise[default_chain] -
|
||||
(s32)average_noise[i])) / 1500;
|
||||
/* bound gain by 2 bits value max, 3rd bit is sign */
|
||||
data->delta_gain_code[i] =
|
||||
|
@ -372,6 +271,10 @@ static struct iwl_sensitivity_ranges iwl5000_sensitivity = {
|
|||
.auto_corr_max_cck_mrc = 400,
|
||||
.nrg_th_cck = 95,
|
||||
.nrg_th_ofdm = 95,
|
||||
|
||||
.barker_corr_th_min = 190,
|
||||
.barker_corr_th_min_mrc = 390,
|
||||
.nrg_th_cca = 62,
|
||||
};
|
||||
|
||||
static struct iwl_sensitivity_ranges iwl5150_sensitivity = {
|
||||
|
@ -394,6 +297,10 @@ static struct iwl_sensitivity_ranges iwl5150_sensitivity = {
|
|||
.auto_corr_max_cck_mrc = 400,
|
||||
.nrg_th_cck = 95,
|
||||
.nrg_th_ofdm = 95,
|
||||
|
||||
.barker_corr_th_min = 190,
|
||||
.barker_corr_th_min_mrc = 390,
|
||||
.nrg_th_cca = 62,
|
||||
};
|
||||
|
||||
const u8 *iwl5000_eeprom_query_addr(const struct iwl_priv *priv,
|
||||
|
@ -458,7 +365,7 @@ static int iwl5000_send_calib_cfg(struct iwl_priv *priv)
|
|||
static void iwl5000_rx_calib_result(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_calib_hdr *hdr = (struct iwl_calib_hdr *)pkt->u.raw;
|
||||
int len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
|
||||
int index;
|
||||
|
@ -784,18 +691,16 @@ int iwl5000_alive_notify(struct iwl_priv *priv)
|
|||
|
||||
int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
|
||||
{
|
||||
if ((priv->cfg->mod_params->num_of_queues > IWL50_NUM_QUEUES) ||
|
||||
(priv->cfg->mod_params->num_of_queues < IWL_MIN_NUM_QUEUES)) {
|
||||
IWL_ERR(priv,
|
||||
"invalid queues_num, should be between %d and %d\n",
|
||||
IWL_MIN_NUM_QUEUES, IWL50_NUM_QUEUES);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES &&
|
||||
priv->cfg->mod_params->num_of_queues <= IWL50_NUM_QUEUES)
|
||||
priv->cfg->num_of_queues =
|
||||
priv->cfg->mod_params->num_of_queues;
|
||||
|
||||
priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues;
|
||||
priv->hw_params.max_txq_num = priv->cfg->num_of_queues;
|
||||
priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM;
|
||||
priv->hw_params.scd_bc_tbls_size =
|
||||
IWL50_NUM_QUEUES * sizeof(struct iwl5000_scd_bc_tbl);
|
||||
priv->cfg->num_of_queues *
|
||||
sizeof(struct iwl5000_scd_bc_tbl);
|
||||
priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
|
||||
priv->hw_params.max_stations = IWL5000_STATION_COUNT;
|
||||
priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID;
|
||||
|
@ -947,11 +852,13 @@ int iwl5000_txq_agg_enable(struct iwl_priv *priv, int txq_id,
|
|||
u16 ra_tid;
|
||||
|
||||
if ((IWL50_FIRST_AMPDU_QUEUE > txq_id) ||
|
||||
(IWL50_FIRST_AMPDU_QUEUE + IWL50_NUM_AMPDU_QUEUES <= txq_id)) {
|
||||
(IWL50_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues
|
||||
<= txq_id)) {
|
||||
IWL_WARN(priv,
|
||||
"queue number out of range: %d, must be %d to %d\n",
|
||||
txq_id, IWL50_FIRST_AMPDU_QUEUE,
|
||||
IWL50_FIRST_AMPDU_QUEUE + IWL50_NUM_AMPDU_QUEUES - 1);
|
||||
IWL50_FIRST_AMPDU_QUEUE +
|
||||
priv->cfg->num_of_ampdu_queues - 1);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -1005,11 +912,13 @@ int iwl5000_txq_agg_disable(struct iwl_priv *priv, u16 txq_id,
|
|||
u16 ssn_idx, u8 tx_fifo)
|
||||
{
|
||||
if ((IWL50_FIRST_AMPDU_QUEUE > txq_id) ||
|
||||
(IWL50_FIRST_AMPDU_QUEUE + IWL50_NUM_AMPDU_QUEUES <= txq_id)) {
|
||||
(IWL50_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues
|
||||
<= txq_id)) {
|
||||
IWL_ERR(priv,
|
||||
"queue number out of range: %d, must be %d to %d\n",
|
||||
txq_id, IWL50_FIRST_AMPDU_QUEUE,
|
||||
IWL50_FIRST_AMPDU_QUEUE + IWL50_NUM_AMPDU_QUEUES - 1);
|
||||
IWL50_FIRST_AMPDU_QUEUE +
|
||||
priv->cfg->num_of_ampdu_queues - 1);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -1176,7 +1085,7 @@ static int iwl5000_tx_status_reply_tx(struct iwl_priv *priv,
|
|||
static void iwl5000_rx_reply_tx(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
u16 sequence = le16_to_cpu(pkt->hdr.sequence);
|
||||
int txq_id = SEQ_TO_QUEUE(sequence);
|
||||
int index = SEQ_TO_INDEX(sequence);
|
||||
|
@ -1473,6 +1382,36 @@ IWL5000_UCODE_GET(init_size);
|
|||
IWL5000_UCODE_GET(init_data_size);
|
||||
IWL5000_UCODE_GET(boot_size);
|
||||
|
||||
static int iwl5000_hw_channel_switch(struct iwl_priv *priv, u16 channel)
|
||||
{
|
||||
struct iwl5000_channel_switch_cmd cmd;
|
||||
const struct iwl_channel_info *ch_info;
|
||||
struct iwl_host_cmd hcmd = {
|
||||
.id = REPLY_CHANNEL_SWITCH,
|
||||
.len = sizeof(cmd),
|
||||
.flags = CMD_SIZE_HUGE,
|
||||
.data = &cmd,
|
||||
};
|
||||
|
||||
IWL_DEBUG_11H(priv, "channel switch from %d to %d\n",
|
||||
priv->active_rxon.channel, channel);
|
||||
cmd.band = priv->band == IEEE80211_BAND_2GHZ;
|
||||
cmd.channel = cpu_to_le16(channel);
|
||||
cmd.rxon_flags = priv->active_rxon.flags;
|
||||
cmd.rxon_filter_flags = priv->active_rxon.filter_flags;
|
||||
cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
|
||||
ch_info = iwl_get_channel_info(priv, priv->band, channel);
|
||||
if (ch_info)
|
||||
cmd.expect_beacon = is_channel_radar(ch_info);
|
||||
else {
|
||||
IWL_ERR(priv, "invalid channel switch from %u to %u\n",
|
||||
priv->active_rxon.channel, channel);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
return iwl_send_cmd_sync(priv, &hcmd);
|
||||
}
|
||||
|
||||
struct iwl_hcmd_ops iwl5000_hcmd = {
|
||||
.rxon_assoc = iwl5000_send_rxon_assoc,
|
||||
.commit_rxon = iwl_commit_rxon,
|
||||
|
@ -1520,9 +1459,9 @@ struct iwl_lib_ops iwl5000_lib = {
|
|||
.alive_notify = iwl5000_alive_notify,
|
||||
.send_tx_power = iwl5000_send_tx_power,
|
||||
.update_chain_flags = iwl_update_chain_flags,
|
||||
.set_channel_switch = iwl5000_hw_channel_switch,
|
||||
.apm_ops = {
|
||||
.init = iwl5000_apm_init,
|
||||
.reset = iwl5000_apm_reset,
|
||||
.init = iwl_apm_init,
|
||||
.stop = iwl_apm_stop,
|
||||
.config = iwl5000_nic_config,
|
||||
.set_pwr_src = iwl_set_pwr_src,
|
||||
|
@ -1572,9 +1511,9 @@ static struct iwl_lib_ops iwl5150_lib = {
|
|||
.alive_notify = iwl5000_alive_notify,
|
||||
.send_tx_power = iwl5000_send_tx_power,
|
||||
.update_chain_flags = iwl_update_chain_flags,
|
||||
.set_channel_switch = iwl5000_hw_channel_switch,
|
||||
.apm_ops = {
|
||||
.init = iwl5000_apm_init,
|
||||
.reset = iwl5000_apm_reset,
|
||||
.init = iwl_apm_init,
|
||||
.stop = iwl_apm_stop,
|
||||
.config = iwl5000_nic_config,
|
||||
.set_pwr_src = iwl_set_pwr_src,
|
||||
|
@ -1621,8 +1560,6 @@ static struct iwl_ops iwl5150_ops = {
|
|||
};
|
||||
|
||||
struct iwl_mod_params iwl50_mod_params = {
|
||||
.num_of_queues = IWL50_NUM_QUEUES,
|
||||
.num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES,
|
||||
.amsdu_size_8K = 1,
|
||||
.restart_fw = 1,
|
||||
/* the rest are 0 by default */
|
||||
|
@ -1639,10 +1576,14 @@ struct iwl_cfg iwl5300_agn_cfg = {
|
|||
.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
|
||||
.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
|
||||
.num_of_queues = IWL50_NUM_QUEUES,
|
||||
.num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES,
|
||||
.mod_params = &iwl50_mod_params,
|
||||
.valid_tx_ant = ANT_ABC,
|
||||
.valid_rx_ant = ANT_ABC,
|
||||
.need_pll_cfg = true,
|
||||
.pll_cfg_val = CSR50_ANA_PLL_CFG_VAL,
|
||||
.set_l0s = true,
|
||||
.use_bsm = false,
|
||||
.ht_greenfield_support = true,
|
||||
.led_compensation = 51,
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
|
@ -1658,10 +1599,14 @@ struct iwl_cfg iwl5100_bg_cfg = {
|
|||
.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
|
||||
.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
|
||||
.num_of_queues = IWL50_NUM_QUEUES,
|
||||
.num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES,
|
||||
.mod_params = &iwl50_mod_params,
|
||||
.valid_tx_ant = ANT_B,
|
||||
.valid_rx_ant = ANT_AB,
|
||||
.need_pll_cfg = true,
|
||||
.pll_cfg_val = CSR50_ANA_PLL_CFG_VAL,
|
||||
.set_l0s = true,
|
||||
.use_bsm = false,
|
||||
.ht_greenfield_support = true,
|
||||
.led_compensation = 51,
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
|
@ -1677,10 +1622,14 @@ struct iwl_cfg iwl5100_abg_cfg = {
|
|||
.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
|
||||
.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
|
||||
.num_of_queues = IWL50_NUM_QUEUES,
|
||||
.num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES,
|
||||
.mod_params = &iwl50_mod_params,
|
||||
.valid_tx_ant = ANT_B,
|
||||
.valid_rx_ant = ANT_AB,
|
||||
.need_pll_cfg = true,
|
||||
.pll_cfg_val = CSR50_ANA_PLL_CFG_VAL,
|
||||
.set_l0s = true,
|
||||
.use_bsm = false,
|
||||
.ht_greenfield_support = true,
|
||||
.led_compensation = 51,
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
|
@ -1696,10 +1645,14 @@ struct iwl_cfg iwl5100_agn_cfg = {
|
|||
.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
|
||||
.eeprom_ver = EEPROM_5000_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
|
||||
.num_of_queues = IWL50_NUM_QUEUES,
|
||||
.num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES,
|
||||
.mod_params = &iwl50_mod_params,
|
||||
.valid_tx_ant = ANT_B,
|
||||
.valid_rx_ant = ANT_AB,
|
||||
.need_pll_cfg = true,
|
||||
.pll_cfg_val = CSR50_ANA_PLL_CFG_VAL,
|
||||
.set_l0s = true,
|
||||
.use_bsm = false,
|
||||
.ht_greenfield_support = true,
|
||||
.led_compensation = 51,
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
|
@ -1715,10 +1668,14 @@ struct iwl_cfg iwl5350_agn_cfg = {
|
|||
.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
|
||||
.eeprom_ver = EEPROM_5050_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION,
|
||||
.num_of_queues = IWL50_NUM_QUEUES,
|
||||
.num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES,
|
||||
.mod_params = &iwl50_mod_params,
|
||||
.valid_tx_ant = ANT_ABC,
|
||||
.valid_rx_ant = ANT_ABC,
|
||||
.need_pll_cfg = true,
|
||||
.pll_cfg_val = CSR50_ANA_PLL_CFG_VAL,
|
||||
.set_l0s = true,
|
||||
.use_bsm = false,
|
||||
.ht_greenfield_support = true,
|
||||
.led_compensation = 51,
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
|
@ -1734,10 +1691,14 @@ struct iwl_cfg iwl5150_agn_cfg = {
|
|||
.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
|
||||
.eeprom_ver = EEPROM_5050_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION,
|
||||
.num_of_queues = IWL50_NUM_QUEUES,
|
||||
.num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES,
|
||||
.mod_params = &iwl50_mod_params,
|
||||
.valid_tx_ant = ANT_A,
|
||||
.valid_rx_ant = ANT_AB,
|
||||
.need_pll_cfg = true,
|
||||
.pll_cfg_val = CSR50_ANA_PLL_CFG_VAL,
|
||||
.set_l0s = true,
|
||||
.use_bsm = false,
|
||||
.ht_greenfield_support = true,
|
||||
.led_compensation = 51,
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
|
|
|
@ -52,8 +52,8 @@
|
|||
#define IWL6050_UCODE_API_MAX 4
|
||||
|
||||
/* Lowest firmware API version supported */
|
||||
#define IWL6000_UCODE_API_MIN 1
|
||||
#define IWL6050_UCODE_API_MIN 1
|
||||
#define IWL6000_UCODE_API_MIN 4
|
||||
#define IWL6050_UCODE_API_MIN 4
|
||||
|
||||
#define IWL6000_FW_PRE "iwlwifi-6000-"
|
||||
#define _IWL6000_MODULE_FIRMWARE(api) IWL6000_FW_PRE #api ".ucode"
|
||||
|
@ -121,22 +121,24 @@ static struct iwl_sensitivity_ranges iwl6000_sensitivity = {
|
|||
.auto_corr_max_cck_mrc = 310,
|
||||
.nrg_th_cck = 97,
|
||||
.nrg_th_ofdm = 100,
|
||||
|
||||
.barker_corr_th_min = 190,
|
||||
.barker_corr_th_min_mrc = 390,
|
||||
.nrg_th_cca = 62,
|
||||
};
|
||||
|
||||
static int iwl6000_hw_set_hw_params(struct iwl_priv *priv)
|
||||
{
|
||||
if ((priv->cfg->mod_params->num_of_queues > IWL50_NUM_QUEUES) ||
|
||||
(priv->cfg->mod_params->num_of_queues < IWL_MIN_NUM_QUEUES)) {
|
||||
IWL_ERR(priv,
|
||||
"invalid queues_num, should be between %d and %d\n",
|
||||
IWL_MIN_NUM_QUEUES, IWL50_NUM_QUEUES);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES &&
|
||||
priv->cfg->mod_params->num_of_queues <= IWL50_NUM_QUEUES)
|
||||
priv->cfg->num_of_queues =
|
||||
priv->cfg->mod_params->num_of_queues;
|
||||
|
||||
priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues;
|
||||
priv->hw_params.max_txq_num = priv->cfg->num_of_queues;
|
||||
priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM;
|
||||
priv->hw_params.scd_bc_tbls_size =
|
||||
IWL50_NUM_QUEUES * sizeof(struct iwl5000_scd_bc_tbl);
|
||||
priv->cfg->num_of_queues *
|
||||
sizeof(struct iwl5000_scd_bc_tbl);
|
||||
priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
|
||||
priv->hw_params.max_stations = IWL5000_STATION_COUNT;
|
||||
priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID;
|
||||
|
@ -170,6 +172,37 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int iwl6000_hw_channel_switch(struct iwl_priv *priv, u16 channel)
|
||||
{
|
||||
struct iwl6000_channel_switch_cmd cmd;
|
||||
const struct iwl_channel_info *ch_info;
|
||||
struct iwl_host_cmd hcmd = {
|
||||
.id = REPLY_CHANNEL_SWITCH,
|
||||
.len = sizeof(cmd),
|
||||
.flags = CMD_SIZE_HUGE,
|
||||
.data = &cmd,
|
||||
};
|
||||
|
||||
IWL_DEBUG_11H(priv, "channel switch from %d to %d\n",
|
||||
priv->active_rxon.channel, channel);
|
||||
|
||||
cmd.band = priv->band == IEEE80211_BAND_2GHZ;
|
||||
cmd.channel = cpu_to_le16(channel);
|
||||
cmd.rxon_flags = priv->active_rxon.flags;
|
||||
cmd.rxon_filter_flags = priv->active_rxon.filter_flags;
|
||||
cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
|
||||
ch_info = iwl_get_channel_info(priv, priv->band, channel);
|
||||
if (ch_info)
|
||||
cmd.expect_beacon = is_channel_radar(ch_info);
|
||||
else {
|
||||
IWL_ERR(priv, "invalid channel switch from %u to %u\n",
|
||||
priv->active_rxon.channel, channel);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
return iwl_send_cmd_sync(priv, &hcmd);
|
||||
}
|
||||
|
||||
static struct iwl_lib_ops iwl6000_lib = {
|
||||
.set_hw_params = iwl6000_hw_set_hw_params,
|
||||
.txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl,
|
||||
|
@ -190,9 +223,9 @@ static struct iwl_lib_ops iwl6000_lib = {
|
|||
.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 = iwl5000_apm_init,
|
||||
.reset = iwl5000_apm_reset,
|
||||
.init = iwl_apm_init,
|
||||
.stop = iwl_apm_stop,
|
||||
.config = iwl6000_nic_config,
|
||||
.set_pwr_src = iwl_set_pwr_src,
|
||||
|
@ -231,6 +264,21 @@ static struct iwl_ops iwl6000_ops = {
|
|||
.led = &iwlagn_led_ops,
|
||||
};
|
||||
|
||||
static struct iwl_hcmd_utils_ops iwl6050_hcmd_utils = {
|
||||
.get_hcmd_size = iwl5000_get_hcmd_size,
|
||||
.build_addsta_hcmd = iwl5000_build_addsta_hcmd,
|
||||
.rts_tx_cmd_flag = iwl5000_rts_tx_cmd_flag,
|
||||
.calc_rssi = iwl5000_calc_rssi,
|
||||
};
|
||||
|
||||
static struct iwl_ops iwl6050_ops = {
|
||||
.ucode = &iwl5000_ucode,
|
||||
.lib = &iwl6000_lib,
|
||||
.hcmd = &iwl5000_hcmd,
|
||||
.utils = &iwl6050_hcmd_utils,
|
||||
.led = &iwlagn_led_ops,
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* "h": Hybrid configuration, use both internal and external Power Amplifier
|
||||
|
@ -245,10 +293,14 @@ struct iwl_cfg iwl6000h_2agn_cfg = {
|
|||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
.eeprom_ver = EEPROM_6000_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
|
||||
.num_of_queues = IWL50_NUM_QUEUES,
|
||||
.num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES,
|
||||
.mod_params = &iwl50_mod_params,
|
||||
.valid_tx_ant = ANT_AB,
|
||||
.valid_rx_ant = ANT_AB,
|
||||
.need_pll_cfg = false,
|
||||
.pll_cfg_val = 0,
|
||||
.set_l0s = false,
|
||||
.use_bsm = false,
|
||||
.pa_type = IWL_PA_HYBRID,
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
|
||||
.shadow_ram_support = true,
|
||||
|
@ -257,6 +309,8 @@ struct iwl_cfg iwl6000h_2agn_cfg = {
|
|||
.use_rts_for_ht = true, /* use rts/cts protection */
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
.supports_idle = true,
|
||||
.adv_thermal_throttle = true,
|
||||
.support_ct_kill_exit = true,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6000h_2abg_cfg = {
|
||||
|
@ -269,10 +323,14 @@ struct iwl_cfg iwl6000h_2abg_cfg = {
|
|||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
.eeprom_ver = EEPROM_6000_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
|
||||
.num_of_queues = IWL50_NUM_QUEUES,
|
||||
.num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES,
|
||||
.mod_params = &iwl50_mod_params,
|
||||
.valid_tx_ant = ANT_AB,
|
||||
.valid_rx_ant = ANT_AB,
|
||||
.need_pll_cfg = false,
|
||||
.pll_cfg_val = 0,
|
||||
.set_l0s = false,
|
||||
.use_bsm = false,
|
||||
.pa_type = IWL_PA_HYBRID,
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
|
||||
.shadow_ram_support = true,
|
||||
|
@ -280,6 +338,8 @@ struct iwl_cfg iwl6000h_2abg_cfg = {
|
|||
.led_compensation = 51,
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
.supports_idle = true,
|
||||
.adv_thermal_throttle = true,
|
||||
.support_ct_kill_exit = true,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6000h_2bg_cfg = {
|
||||
|
@ -292,10 +352,14 @@ struct iwl_cfg iwl6000h_2bg_cfg = {
|
|||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
.eeprom_ver = EEPROM_6000_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
|
||||
.num_of_queues = IWL50_NUM_QUEUES,
|
||||
.num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES,
|
||||
.mod_params = &iwl50_mod_params,
|
||||
.valid_tx_ant = ANT_AB,
|
||||
.valid_rx_ant = ANT_AB,
|
||||
.need_pll_cfg = false,
|
||||
.pll_cfg_val = 0,
|
||||
.set_l0s = false,
|
||||
.use_bsm = false,
|
||||
.pa_type = IWL_PA_HYBRID,
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
|
||||
.shadow_ram_support = true,
|
||||
|
@ -303,6 +367,8 @@ struct iwl_cfg iwl6000h_2bg_cfg = {
|
|||
.led_compensation = 51,
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
.supports_idle = true,
|
||||
.adv_thermal_throttle = true,
|
||||
.support_ct_kill_exit = true,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -318,10 +384,14 @@ struct iwl_cfg iwl6000i_2agn_cfg = {
|
|||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
.eeprom_ver = EEPROM_6000_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
|
||||
.num_of_queues = IWL50_NUM_QUEUES,
|
||||
.num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES,
|
||||
.mod_params = &iwl50_mod_params,
|
||||
.valid_tx_ant = ANT_BC,
|
||||
.valid_rx_ant = ANT_BC,
|
||||
.need_pll_cfg = false,
|
||||
.pll_cfg_val = 0,
|
||||
.set_l0s = false,
|
||||
.use_bsm = false,
|
||||
.pa_type = IWL_PA_INTERNAL,
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
|
||||
.shadow_ram_support = true,
|
||||
|
@ -330,6 +400,8 @@ struct iwl_cfg iwl6000i_2agn_cfg = {
|
|||
.use_rts_for_ht = true, /* use rts/cts protection */
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
.supports_idle = true,
|
||||
.adv_thermal_throttle = true,
|
||||
.support_ct_kill_exit = true,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6000i_2abg_cfg = {
|
||||
|
@ -342,10 +414,14 @@ struct iwl_cfg iwl6000i_2abg_cfg = {
|
|||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
.eeprom_ver = EEPROM_6000_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
|
||||
.num_of_queues = IWL50_NUM_QUEUES,
|
||||
.num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES,
|
||||
.mod_params = &iwl50_mod_params,
|
||||
.valid_tx_ant = ANT_BC,
|
||||
.valid_rx_ant = ANT_BC,
|
||||
.need_pll_cfg = false,
|
||||
.pll_cfg_val = 0,
|
||||
.set_l0s = false,
|
||||
.use_bsm = false,
|
||||
.pa_type = IWL_PA_INTERNAL,
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
|
||||
.shadow_ram_support = true,
|
||||
|
@ -353,6 +429,8 @@ struct iwl_cfg iwl6000i_2abg_cfg = {
|
|||
.led_compensation = 51,
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
.supports_idle = true,
|
||||
.adv_thermal_throttle = true,
|
||||
.support_ct_kill_exit = true,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6000i_2bg_cfg = {
|
||||
|
@ -365,10 +443,14 @@ struct iwl_cfg iwl6000i_2bg_cfg = {
|
|||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
.eeprom_ver = EEPROM_6000_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
|
||||
.num_of_queues = IWL50_NUM_QUEUES,
|
||||
.num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES,
|
||||
.mod_params = &iwl50_mod_params,
|
||||
.valid_tx_ant = ANT_BC,
|
||||
.valid_rx_ant = ANT_BC,
|
||||
.need_pll_cfg = false,
|
||||
.pll_cfg_val = 0,
|
||||
.set_l0s = false,
|
||||
.use_bsm = false,
|
||||
.pa_type = IWL_PA_INTERNAL,
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
|
||||
.shadow_ram_support = true,
|
||||
|
@ -376,6 +458,8 @@ struct iwl_cfg iwl6000i_2bg_cfg = {
|
|||
.led_compensation = 51,
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
.supports_idle = true,
|
||||
.adv_thermal_throttle = true,
|
||||
.support_ct_kill_exit = true,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6050_2agn_cfg = {
|
||||
|
@ -384,22 +468,28 @@ 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_6000_EEPROM_VERSION,
|
||||
.eeprom_ver = EEPROM_6050_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
|
||||
.num_of_queues = IWL50_NUM_QUEUES,
|
||||
.num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES,
|
||||
.mod_params = &iwl50_mod_params,
|
||||
.valid_tx_ant = ANT_AB,
|
||||
.valid_rx_ant = ANT_AB,
|
||||
.need_pll_cfg = false,
|
||||
.pll_cfg_val = 0,
|
||||
.set_l0s = false,
|
||||
.use_bsm = false,
|
||||
.pa_type = IWL_PA_SYSTEM,
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_6x50,
|
||||
.shadow_ram_support = true,
|
||||
.ht_greenfield_support = true,
|
||||
.led_compensation = 51,
|
||||
.use_rts_for_ht = true, /* use rts/cts protection */
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
.supports_idle = true,
|
||||
.adv_thermal_throttle = true,
|
||||
.support_ct_kill_exit = true,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6050_2abg_cfg = {
|
||||
|
@ -408,21 +498,27 @@ 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_6000_EEPROM_VERSION,
|
||||
.eeprom_ver = EEPROM_6050_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
|
||||
.num_of_queues = IWL50_NUM_QUEUES,
|
||||
.num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES,
|
||||
.mod_params = &iwl50_mod_params,
|
||||
.valid_tx_ant = ANT_AB,
|
||||
.valid_rx_ant = ANT_AB,
|
||||
.need_pll_cfg = false,
|
||||
.pll_cfg_val = 0,
|
||||
.set_l0s = false,
|
||||
.use_bsm = false,
|
||||
.pa_type = IWL_PA_SYSTEM,
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_6x50,
|
||||
.shadow_ram_support = true,
|
||||
.ht_greenfield_support = true,
|
||||
.led_compensation = 51,
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
.supports_idle = true,
|
||||
.adv_thermal_throttle = true,
|
||||
.support_ct_kill_exit = true,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6000_3agn_cfg = {
|
||||
|
@ -435,10 +531,14 @@ struct iwl_cfg iwl6000_3agn_cfg = {
|
|||
.eeprom_size = OTP_LOW_IMAGE_SIZE,
|
||||
.eeprom_ver = EEPROM_6000_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
|
||||
.num_of_queues = IWL50_NUM_QUEUES,
|
||||
.num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES,
|
||||
.mod_params = &iwl50_mod_params,
|
||||
.valid_tx_ant = ANT_ABC,
|
||||
.valid_rx_ant = ANT_ABC,
|
||||
.need_pll_cfg = false,
|
||||
.pll_cfg_val = 0,
|
||||
.set_l0s = false,
|
||||
.use_bsm = false,
|
||||
.pa_type = IWL_PA_SYSTEM,
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
|
||||
.shadow_ram_support = true,
|
||||
|
@ -447,6 +547,8 @@ struct iwl_cfg iwl6000_3agn_cfg = {
|
|||
.use_rts_for_ht = true, /* use rts/cts protection */
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
.supports_idle = true,
|
||||
.adv_thermal_throttle = true,
|
||||
.support_ct_kill_exit = true,
|
||||
};
|
||||
|
||||
struct iwl_cfg iwl6050_3agn_cfg = {
|
||||
|
@ -455,22 +557,28 @@ struct iwl_cfg iwl6050_3agn_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_6000_EEPROM_VERSION,
|
||||
.eeprom_ver = EEPROM_6050_EEPROM_VERSION,
|
||||
.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
|
||||
.num_of_queues = IWL50_NUM_QUEUES,
|
||||
.num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES,
|
||||
.mod_params = &iwl50_mod_params,
|
||||
.valid_tx_ant = ANT_ABC,
|
||||
.valid_rx_ant = ANT_ABC,
|
||||
.need_pll_cfg = false,
|
||||
.pll_cfg_val = 0,
|
||||
.set_l0s = false,
|
||||
.use_bsm = false,
|
||||
.pa_type = IWL_PA_SYSTEM,
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
|
||||
.max_ll_items = OTP_MAX_LL_ITEMS_6x50,
|
||||
.shadow_ram_support = true,
|
||||
.ht_greenfield_support = true,
|
||||
.led_compensation = 51,
|
||||
.use_rts_for_ht = true, /* use rts/cts protection */
|
||||
.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
|
||||
.supports_idle = true,
|
||||
.adv_thermal_throttle = true,
|
||||
.support_ct_kill_exit = true,
|
||||
};
|
||||
|
||||
MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX));
|
||||
|
|
|
@ -75,106 +75,6 @@ static const u8 ant_toggle_lookup[] = {
|
|||
/*ANT_ABC -> */ ANT_ABC,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_rate_scale_data -- tx success history for one rate
|
||||
*/
|
||||
struct iwl_rate_scale_data {
|
||||
u64 data; /* bitmap of successful frames */
|
||||
s32 success_counter; /* number of frames successful */
|
||||
s32 success_ratio; /* per-cent * 128 */
|
||||
s32 counter; /* number of frames attempted */
|
||||
s32 average_tpt; /* success ratio * expected throughput */
|
||||
unsigned long stamp;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_scale_tbl_info -- tx params and success history for all rates
|
||||
*
|
||||
* There are two of these in struct iwl_lq_sta,
|
||||
* one for "active", and one for "search".
|
||||
*/
|
||||
struct iwl_scale_tbl_info {
|
||||
enum iwl_table_type lq_type;
|
||||
u8 ant_type;
|
||||
u8 is_SGI; /* 1 = short guard interval */
|
||||
u8 is_ht40; /* 1 = 40 MHz channel width */
|
||||
u8 is_dup; /* 1 = duplicated data streams */
|
||||
u8 action; /* change modulation; IWL_[LEGACY/SISO/MIMO]_SWITCH_* */
|
||||
u8 max_search; /* maximun number of tables we can search */
|
||||
s32 *expected_tpt; /* throughput metrics; expected_tpt_G, etc. */
|
||||
u32 current_rate; /* rate_n_flags, uCode API format */
|
||||
struct iwl_rate_scale_data win[IWL_RATE_COUNT]; /* rate histories */
|
||||
};
|
||||
|
||||
struct iwl_traffic_load {
|
||||
unsigned long time_stamp; /* age of the oldest statistics */
|
||||
u32 packet_count[TID_QUEUE_MAX_SIZE]; /* packet count in this time
|
||||
* slice */
|
||||
u32 total; /* total num of packets during the
|
||||
* last TID_MAX_TIME_DIFF */
|
||||
u8 queue_count; /* number of queues that has
|
||||
* been used since the last cleanup */
|
||||
u8 head; /* start of the circular buffer */
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_lq_sta -- driver's rate scaling private structure
|
||||
*
|
||||
* Pointer to this gets passed back and forth between driver and mac80211.
|
||||
*/
|
||||
struct iwl_lq_sta {
|
||||
u8 active_tbl; /* index of active table, range 0-1 */
|
||||
u8 enable_counter; /* indicates HT mode */
|
||||
u8 stay_in_tbl; /* 1: disallow, 0: allow search for new mode */
|
||||
u8 search_better_tbl; /* 1: currently trying alternate mode */
|
||||
s32 last_tpt;
|
||||
|
||||
/* The following determine when to search for a new mode */
|
||||
u32 table_count_limit;
|
||||
u32 max_failure_limit; /* # failed frames before new search */
|
||||
u32 max_success_limit; /* # successful frames before new search */
|
||||
u32 table_count;
|
||||
u32 total_failed; /* total failed frames, any/all rates */
|
||||
u32 total_success; /* total successful frames, any/all rates */
|
||||
u64 flush_timer; /* time staying in mode before new search */
|
||||
|
||||
u8 action_counter; /* # mode-switch actions tried */
|
||||
u8 is_green;
|
||||
u8 is_dup;
|
||||
enum ieee80211_band band;
|
||||
u8 ibss_sta_added;
|
||||
|
||||
/* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */
|
||||
u32 supp_rates;
|
||||
u16 active_legacy_rate;
|
||||
u16 active_siso_rate;
|
||||
u16 active_mimo2_rate;
|
||||
u16 active_mimo3_rate;
|
||||
u16 active_rate_basic;
|
||||
s8 max_rate_idx; /* Max rate set by user */
|
||||
u8 missed_rate_counter;
|
||||
|
||||
struct iwl_link_quality_cmd lq;
|
||||
struct iwl_scale_tbl_info lq_info[LQ_SIZE]; /* "active", "search" */
|
||||
struct iwl_traffic_load load[TID_MAX_LOAD_COUNT];
|
||||
u8 tx_agg_tid_en;
|
||||
#ifdef CONFIG_MAC80211_DEBUGFS
|
||||
struct dentry *rs_sta_dbgfs_scale_table_file;
|
||||
struct dentry *rs_sta_dbgfs_stats_table_file;
|
||||
struct dentry *rs_sta_dbgfs_rate_scale_data_file;
|
||||
struct dentry *rs_sta_dbgfs_tx_agg_tid_en_file;
|
||||
u32 dbg_fixed_rate;
|
||||
#endif
|
||||
struct iwl_priv *drv;
|
||||
|
||||
/* used to be in sta_info */
|
||||
int last_txrate_idx;
|
||||
/* last tx rate_n_flags */
|
||||
u32 last_rate_n_flags;
|
||||
/* packets destined for this STA are aggregated */
|
||||
u8 is_agg;
|
||||
};
|
||||
|
||||
static void rs_rate_scale_perform(struct iwl_priv *priv,
|
||||
struct sk_buff *skb,
|
||||
struct ieee80211_sta *sta,
|
||||
|
@ -2575,19 +2475,17 @@ static void *rs_alloc_sta(void *priv_rate, struct ieee80211_sta *sta,
|
|||
gfp_t gfp)
|
||||
{
|
||||
struct iwl_lq_sta *lq_sta;
|
||||
struct iwl_station_priv *sta_priv = (struct iwl_station_priv *) sta->drv_priv;
|
||||
struct iwl_priv *priv;
|
||||
int i, j;
|
||||
|
||||
priv = (struct iwl_priv *)priv_rate;
|
||||
IWL_DEBUG_RATE(priv, "create station rate scale window\n");
|
||||
|
||||
lq_sta = kzalloc(sizeof(struct iwl_lq_sta), gfp);
|
||||
lq_sta = &sta_priv->lq_sta;
|
||||
|
||||
if (lq_sta == NULL)
|
||||
return NULL;
|
||||
lq_sta->lq.sta_id = 0xff;
|
||||
|
||||
|
||||
for (j = 0; j < LQ_SIZE; j++)
|
||||
for (i = 0; i < IWL_RATE_COUNT; i++)
|
||||
rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]);
|
||||
|
@ -2819,11 +2717,9 @@ static void rs_free(void *priv_rate)
|
|||
static void rs_free_sta(void *priv_r, struct ieee80211_sta *sta,
|
||||
void *priv_sta)
|
||||
{
|
||||
struct iwl_lq_sta *lq_sta = priv_sta;
|
||||
struct iwl_priv *priv __maybe_unused = priv_r;
|
||||
|
||||
IWL_DEBUG_RATE(priv, "enter\n");
|
||||
kfree(lq_sta);
|
||||
IWL_DEBUG_RATE(priv, "leave\n");
|
||||
}
|
||||
|
||||
|
|
|
@ -54,6 +54,7 @@ struct iwl3945_rate_info {
|
|||
u8 prev_table_rs; /* prev in rate table cmd */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* These serve as indexes into
|
||||
* struct iwl_rate_info iwl_rates[IWL_RATE_COUNT];
|
||||
|
@ -335,6 +336,106 @@ struct iwl_rate_mcs_info {
|
|||
char mcs[IWL_MAX_MCS_DISPLAY_SIZE];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_rate_scale_data -- tx success history for one rate
|
||||
*/
|
||||
struct iwl_rate_scale_data {
|
||||
u64 data; /* bitmap of successful frames */
|
||||
s32 success_counter; /* number of frames successful */
|
||||
s32 success_ratio; /* per-cent * 128 */
|
||||
s32 counter; /* number of frames attempted */
|
||||
s32 average_tpt; /* success ratio * expected throughput */
|
||||
unsigned long stamp;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_scale_tbl_info -- tx params and success history for all rates
|
||||
*
|
||||
* There are two of these in struct iwl_lq_sta,
|
||||
* one for "active", and one for "search".
|
||||
*/
|
||||
struct iwl_scale_tbl_info {
|
||||
enum iwl_table_type lq_type;
|
||||
u8 ant_type;
|
||||
u8 is_SGI; /* 1 = short guard interval */
|
||||
u8 is_ht40; /* 1 = 40 MHz channel width */
|
||||
u8 is_dup; /* 1 = duplicated data streams */
|
||||
u8 action; /* change modulation; IWL_[LEGACY/SISO/MIMO]_SWITCH_* */
|
||||
u8 max_search; /* maximun number of tables we can search */
|
||||
s32 *expected_tpt; /* throughput metrics; expected_tpt_G, etc. */
|
||||
u32 current_rate; /* rate_n_flags, uCode API format */
|
||||
struct iwl_rate_scale_data win[IWL_RATE_COUNT]; /* rate histories */
|
||||
};
|
||||
|
||||
struct iwl_traffic_load {
|
||||
unsigned long time_stamp; /* age of the oldest statistics */
|
||||
u32 packet_count[TID_QUEUE_MAX_SIZE]; /* packet count in this time
|
||||
* slice */
|
||||
u32 total; /* total num of packets during the
|
||||
* last TID_MAX_TIME_DIFF */
|
||||
u8 queue_count; /* number of queues that has
|
||||
* been used since the last cleanup */
|
||||
u8 head; /* start of the circular buffer */
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_lq_sta -- driver's rate scaling private structure
|
||||
*
|
||||
* Pointer to this gets passed back and forth between driver and mac80211.
|
||||
*/
|
||||
struct iwl_lq_sta {
|
||||
u8 active_tbl; /* index of active table, range 0-1 */
|
||||
u8 enable_counter; /* indicates HT mode */
|
||||
u8 stay_in_tbl; /* 1: disallow, 0: allow search for new mode */
|
||||
u8 search_better_tbl; /* 1: currently trying alternate mode */
|
||||
s32 last_tpt;
|
||||
|
||||
/* The following determine when to search for a new mode */
|
||||
u32 table_count_limit;
|
||||
u32 max_failure_limit; /* # failed frames before new search */
|
||||
u32 max_success_limit; /* # successful frames before new search */
|
||||
u32 table_count;
|
||||
u32 total_failed; /* total failed frames, any/all rates */
|
||||
u32 total_success; /* total successful frames, any/all rates */
|
||||
u64 flush_timer; /* time staying in mode before new search */
|
||||
|
||||
u8 action_counter; /* # mode-switch actions tried */
|
||||
u8 is_green;
|
||||
u8 is_dup;
|
||||
enum ieee80211_band band;
|
||||
u8 ibss_sta_added;
|
||||
|
||||
/* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */
|
||||
u32 supp_rates;
|
||||
u16 active_legacy_rate;
|
||||
u16 active_siso_rate;
|
||||
u16 active_mimo2_rate;
|
||||
u16 active_mimo3_rate;
|
||||
u16 active_rate_basic;
|
||||
s8 max_rate_idx; /* Max rate set by user */
|
||||
u8 missed_rate_counter;
|
||||
|
||||
struct iwl_link_quality_cmd lq;
|
||||
struct iwl_scale_tbl_info lq_info[LQ_SIZE]; /* "active", "search" */
|
||||
struct iwl_traffic_load load[TID_MAX_LOAD_COUNT];
|
||||
u8 tx_agg_tid_en;
|
||||
#ifdef CONFIG_MAC80211_DEBUGFS
|
||||
struct dentry *rs_sta_dbgfs_scale_table_file;
|
||||
struct dentry *rs_sta_dbgfs_stats_table_file;
|
||||
struct dentry *rs_sta_dbgfs_rate_scale_data_file;
|
||||
struct dentry *rs_sta_dbgfs_tx_agg_tid_en_file;
|
||||
u32 dbg_fixed_rate;
|
||||
#endif
|
||||
struct iwl_priv *drv;
|
||||
|
||||
/* used to be in sta_info */
|
||||
int last_txrate_idx;
|
||||
/* last tx rate_n_flags */
|
||||
u32 last_rate_n_flags;
|
||||
/* packets destined for this STA are aggregated */
|
||||
u8 is_agg;
|
||||
};
|
||||
|
||||
static inline u8 num_of_ant(u8 mask)
|
||||
{
|
||||
return !!((mask) & ANT_A) +
|
||||
|
|
|
@ -524,7 +524,7 @@ int iwl_hw_tx_queue_init(struct iwl_priv *priv,
|
|||
static void iwl_rx_reply_alive(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_alive_resp *palive;
|
||||
struct delayed_work *pwork;
|
||||
|
||||
|
@ -610,7 +610,7 @@ static void iwl_rx_beacon_notif(struct iwl_priv *priv,
|
|||
struct iwl_rx_mem_buffer *rxb)
|
||||
{
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl4965_beacon_notif *beacon =
|
||||
(struct iwl4965_beacon_notif *)pkt->u.raw;
|
||||
u8 rate = iwl_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags);
|
||||
|
@ -634,7 +634,7 @@ static void iwl_rx_beacon_notif(struct iwl_priv *priv,
|
|||
static void iwl_rx_card_state_notif(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
|
||||
unsigned long status = priv->status;
|
||||
|
||||
|
@ -769,7 +769,7 @@ void iwl_rx_handle(struct iwl_priv *priv)
|
|||
IWL_DEBUG_RX(priv, "r = %d, i = %d\n", r, i);
|
||||
|
||||
/* calculate total frames need to be restock after handling RX */
|
||||
total_empty = r - priv->rxq.write_actual;
|
||||
total_empty = r - rxq->write_actual;
|
||||
if (total_empty < 0)
|
||||
total_empty += RX_QUEUE_SIZE;
|
||||
|
||||
|
@ -786,10 +786,10 @@ void iwl_rx_handle(struct iwl_priv *priv)
|
|||
|
||||
rxq->queue[i] = NULL;
|
||||
|
||||
pci_unmap_single(priv->pci_dev, rxb->real_dma_addr,
|
||||
priv->hw_params.rx_buf_size + 256,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
pkt = (struct iwl_rx_packet *)rxb->skb->data;
|
||||
pci_unmap_page(priv->pci_dev, rxb->page_dma,
|
||||
PAGE_SIZE << priv->hw_params.rx_page_order,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
pkt = rxb_addr(rxb);
|
||||
|
||||
trace_iwlwifi_dev_rx(priv, pkt,
|
||||
le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK);
|
||||
|
@ -814,8 +814,8 @@ void iwl_rx_handle(struct iwl_priv *priv)
|
|||
if (priv->rx_handlers[pkt->hdr.cmd]) {
|
||||
IWL_DEBUG_RX(priv, "r = %d, i = %d, %s, 0x%02x\n", r,
|
||||
i, get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
|
||||
priv->rx_handlers[pkt->hdr.cmd] (priv, rxb);
|
||||
priv->isr_stats.rx_handlers[pkt->hdr.cmd]++;
|
||||
priv->rx_handlers[pkt->hdr.cmd] (priv, rxb);
|
||||
} else {
|
||||
/* No handling needed */
|
||||
IWL_DEBUG_RX(priv,
|
||||
|
@ -824,35 +824,45 @@ void iwl_rx_handle(struct iwl_priv *priv)
|
|||
pkt->hdr.cmd);
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX: After here, we should always check rxb->page
|
||||
* against NULL before touching it or its virtual
|
||||
* memory (pkt). Because some rx_handler might have
|
||||
* already taken or freed the pages.
|
||||
*/
|
||||
|
||||
if (reclaim) {
|
||||
/* Invoke any callbacks, transfer the skb to caller, and
|
||||
* fire off the (possibly) blocking iwl_send_cmd()
|
||||
/* Invoke any callbacks, transfer the buffer to caller,
|
||||
* and fire off the (possibly) blocking iwl_send_cmd()
|
||||
* as we reclaim the driver command queue */
|
||||
if (rxb && rxb->skb)
|
||||
if (rxb->page)
|
||||
iwl_tx_cmd_complete(priv, rxb);
|
||||
else
|
||||
IWL_WARN(priv, "Claim null rxb?\n");
|
||||
}
|
||||
|
||||
/* For now we just don't re-use anything. We can tweak this
|
||||
* later to try and re-use notification packets and SKBs that
|
||||
* fail to Rx correctly */
|
||||
if (rxb->skb != NULL) {
|
||||
priv->alloc_rxb_skb--;
|
||||
dev_kfree_skb_any(rxb->skb);
|
||||
rxb->skb = NULL;
|
||||
}
|
||||
|
||||
/* Reuse the page if possible. For notification packets and
|
||||
* SKBs that fail to Rx correctly, add them back into the
|
||||
* rx_free list for reuse later. */
|
||||
spin_lock_irqsave(&rxq->lock, flags);
|
||||
list_add_tail(&rxb->list, &priv->rxq.rx_used);
|
||||
if (rxb->page != NULL) {
|
||||
rxb->page_dma = pci_map_page(priv->pci_dev, rxb->page,
|
||||
0, PAGE_SIZE << priv->hw_params.rx_page_order,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
list_add_tail(&rxb->list, &rxq->rx_free);
|
||||
rxq->free_count++;
|
||||
} else
|
||||
list_add_tail(&rxb->list, &rxq->rx_used);
|
||||
|
||||
spin_unlock_irqrestore(&rxq->lock, flags);
|
||||
|
||||
i = (i + 1) & RX_QUEUE_MASK;
|
||||
/* If there are a lot of unused frames,
|
||||
* restock the Rx queue so ucode wont assert. */
|
||||
if (fill_rx) {
|
||||
count++;
|
||||
if (count >= 8) {
|
||||
priv->rxq.read = i;
|
||||
rxq->read = i;
|
||||
iwl_rx_replenish_now(priv);
|
||||
count = 0;
|
||||
}
|
||||
|
@ -860,7 +870,7 @@ void iwl_rx_handle(struct iwl_priv *priv)
|
|||
}
|
||||
|
||||
/* Backtrack one entry */
|
||||
priv->rxq.read = i;
|
||||
rxq->read = i;
|
||||
if (fill_rx)
|
||||
iwl_rx_replenish_now(priv);
|
||||
else
|
||||
|
@ -907,6 +917,8 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv)
|
|||
}
|
||||
#endif
|
||||
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
/* Since CSR_INT and CSR_FH_INT_STATUS reads and clears are not
|
||||
* atomic, make sure that inta covers all the interrupts that
|
||||
* we've discovered, even if FH interrupt came in just after
|
||||
|
@ -928,8 +940,6 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv)
|
|||
|
||||
handled |= CSR_INT_BIT_HW_ERR;
|
||||
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1019,6 +1029,7 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv)
|
|||
if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) {
|
||||
iwl_rx_handle(priv);
|
||||
priv->isr_stats.rx++;
|
||||
iwl_leds_background(priv);
|
||||
handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX);
|
||||
}
|
||||
|
||||
|
@ -1056,7 +1067,6 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv)
|
|||
"flags 0x%08lx\n", inta, inta_mask, inta_fh, flags);
|
||||
}
|
||||
#endif
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
}
|
||||
|
||||
/* tasklet for iwlagn interrupt */
|
||||
|
@ -1086,6 +1096,9 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
|
|||
inta, inta_mask);
|
||||
}
|
||||
#endif
|
||||
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
/* saved interrupt in inta variable now we can reset priv->inta */
|
||||
priv->inta = 0;
|
||||
|
||||
|
@ -1101,8 +1114,6 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
|
|||
|
||||
handled |= CSR_INT_BIT_HW_ERR;
|
||||
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1220,6 +1231,7 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
|
|||
CSR_INT_PERIODIC_ENA);
|
||||
|
||||
priv->isr_stats.rx++;
|
||||
iwl_leds_background(priv);
|
||||
}
|
||||
|
||||
if (inta & CSR_INT_BIT_FH_TX) {
|
||||
|
@ -1242,14 +1254,10 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
|
|||
inta & ~priv->inta_mask);
|
||||
}
|
||||
|
||||
|
||||
/* Re-enable all interrupts */
|
||||
/* only Re-enable if diabled by irq */
|
||||
if (test_bit(STATUS_INT_ENABLED, &priv->status))
|
||||
iwl_enable_interrupts(priv);
|
||||
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -1899,11 +1907,9 @@ static void __iwl_down(struct iwl_priv *priv)
|
|||
|
||||
udelay(5);
|
||||
|
||||
/* FIXME: apm_ops.suspend(priv) */
|
||||
if (exit_pending)
|
||||
priv->cfg->ops->lib->apm_ops.stop(priv);
|
||||
else
|
||||
priv->cfg->ops->lib->apm_ops.reset(priv);
|
||||
/* Stop the device, and put it in low power state */
|
||||
priv->cfg->ops->lib->apm_ops.stop(priv);
|
||||
|
||||
exit:
|
||||
memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp));
|
||||
|
||||
|
@ -2290,6 +2296,69 @@ void iwl_post_associate(struct iwl_priv *priv)
|
|||
|
||||
#define UCODE_READY_TIMEOUT (4 * HZ)
|
||||
|
||||
/*
|
||||
* Not a mac80211 entry point function, but it fits in with all the
|
||||
* other mac80211 functions grouped here.
|
||||
*/
|
||||
static int iwl_setup_mac(struct iwl_priv *priv)
|
||||
{
|
||||
int ret;
|
||||
struct ieee80211_hw *hw = priv->hw;
|
||||
hw->rate_control_algorithm = "iwl-agn-rs";
|
||||
|
||||
/* Tell mac80211 our characteristics */
|
||||
hw->flags = IEEE80211_HW_SIGNAL_DBM |
|
||||
IEEE80211_HW_NOISE_DBM |
|
||||
IEEE80211_HW_AMPDU_AGGREGATION |
|
||||
IEEE80211_HW_SPECTRUM_MGMT;
|
||||
|
||||
if (!priv->cfg->broken_powersave)
|
||||
hw->flags |= IEEE80211_HW_SUPPORTS_PS |
|
||||
IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
|
||||
|
||||
hw->sta_data_size = sizeof(struct iwl_station_priv);
|
||||
hw->wiphy->interface_modes =
|
||||
BIT(NL80211_IFTYPE_STATION) |
|
||||
BIT(NL80211_IFTYPE_ADHOC);
|
||||
|
||||
hw->wiphy->custom_regulatory = true;
|
||||
|
||||
/* Firmware does not support this */
|
||||
hw->wiphy->disable_beacon_hints = true;
|
||||
|
||||
/*
|
||||
* For now, disable PS by default because it affects
|
||||
* RX performance significantly.
|
||||
*/
|
||||
hw->wiphy->ps_default = false;
|
||||
|
||||
hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX;
|
||||
/* we create the 802.11 header and a zero-length SSID element */
|
||||
hw->wiphy->max_scan_ie_len = IWL_MAX_PROBE_REQUEST - 24 - 2;
|
||||
|
||||
/* Default value; 4 EDCA QOS priorities */
|
||||
hw->queues = 4;
|
||||
|
||||
hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL;
|
||||
|
||||
if (priv->bands[IEEE80211_BAND_2GHZ].n_channels)
|
||||
priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
|
||||
&priv->bands[IEEE80211_BAND_2GHZ];
|
||||
if (priv->bands[IEEE80211_BAND_5GHZ].n_channels)
|
||||
priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
|
||||
&priv->bands[IEEE80211_BAND_5GHZ];
|
||||
|
||||
ret = ieee80211_register_hw(priv->hw);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Failed to register hw (error %d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
priv->mac80211_registered = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int iwl_mac_start(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct iwl_priv *priv = hw->priv;
|
||||
|
@ -3187,6 +3256,15 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
|
|||
iwl_down(priv);
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure device is reset to low power before unloading driver.
|
||||
* This may be redundant with iwl_down(), but there are paths to
|
||||
* run iwl_down() without calling apm_ops.stop(), and there are
|
||||
* paths to avoid running iwl_down() at all before leaving driver.
|
||||
* This (inexpensive) call *makes sure* device is reset.
|
||||
*/
|
||||
priv->cfg->ops->lib->apm_ops.stop(priv);
|
||||
|
||||
iwl_tt_exit(priv);
|
||||
|
||||
/* make sure we flush any pending irq or
|
||||
|
|
|
@ -447,11 +447,11 @@ static int iwl_sensitivity_write(struct iwl_priv *priv)
|
|||
cpu_to_le16((u16)data->nrg_th_ofdm);
|
||||
|
||||
cmd.table[HD_BARKER_CORR_TH_ADD_MIN_INDEX] =
|
||||
cpu_to_le16(190);
|
||||
cpu_to_le16(data->barker_corr_th_min);
|
||||
cmd.table[HD_BARKER_CORR_TH_ADD_MIN_MRC_INDEX] =
|
||||
cpu_to_le16(390);
|
||||
cpu_to_le16(data->barker_corr_th_min_mrc);
|
||||
cmd.table[HD_OFDM_ENERGY_TH_IN_INDEX] =
|
||||
cpu_to_le16(62);
|
||||
cpu_to_le16(data->nrg_th_cca);
|
||||
|
||||
IWL_DEBUG_CALIB(priv, "ofdm: ac %u mrc %u x1 %u mrc_x1 %u thresh %u\n",
|
||||
data->auto_corr_ofdm, data->auto_corr_ofdm_mrc,
|
||||
|
@ -524,6 +524,9 @@ void iwl_init_sensitivity(struct iwl_priv *priv)
|
|||
data->auto_corr_cck_mrc = ranges->auto_corr_min_cck_mrc;
|
||||
data->nrg_th_cck = ranges->nrg_th_cck;
|
||||
data->nrg_th_ofdm = ranges->nrg_th_ofdm;
|
||||
data->barker_corr_th_min = ranges->barker_corr_th_min;
|
||||
data->barker_corr_th_min_mrc = ranges->barker_corr_th_min_mrc;
|
||||
data->nrg_th_cca = ranges->nrg_th_cca;
|
||||
|
||||
data->last_bad_plcp_cnt_ofdm = 0;
|
||||
data->last_fa_cnt_ofdm = 0;
|
||||
|
|
|
@ -109,11 +109,12 @@ enum {
|
|||
REPLY_TX_LINK_QUALITY_CMD = 0x4e, /* 4965 only */
|
||||
|
||||
/* WiMAX coexistence */
|
||||
COEX_PRIORITY_TABLE_CMD = 0x5a, /*5000 only */
|
||||
COEX_PRIORITY_TABLE_CMD = 0x5a, /* for 5000 series and up */
|
||||
COEX_MEDIUM_NOTIFICATION = 0x5b,
|
||||
COEX_EVENT_CMD = 0x5c,
|
||||
|
||||
/* Calibration */
|
||||
TEMPERATURE_NOTIFICATION = 0x62,
|
||||
CALIBRATION_CFG_CMD = 0x65,
|
||||
CALIBRATION_RES_NOTIFICATION = 0x66,
|
||||
CALIBRATION_COMPLETE_NOTIFICATION = 0x67,
|
||||
|
@ -353,6 +354,9 @@ struct iwl3945_power_per_rate {
|
|||
#define POWER_TABLE_NUM_HT_OFDM_ENTRIES 32
|
||||
#define POWER_TABLE_CCK_ENTRY 32
|
||||
|
||||
#define IWL_PWR_NUM_HT_OFDM_ENTRIES 24
|
||||
#define IWL_PWR_CCK_ENTRIES 2
|
||||
|
||||
/**
|
||||
* union iwl4965_tx_power_dual_stream
|
||||
*
|
||||
|
@ -803,7 +807,7 @@ struct iwl3945_channel_switch_cmd {
|
|||
struct iwl3945_power_per_rate power[IWL_MAX_RATES];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct iwl_channel_switch_cmd {
|
||||
struct iwl4965_channel_switch_cmd {
|
||||
u8 band;
|
||||
u8 expect_beacon;
|
||||
__le16 channel;
|
||||
|
@ -813,6 +817,48 @@ struct iwl_channel_switch_cmd {
|
|||
struct iwl4965_tx_power_db tx_power;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/**
|
||||
* struct iwl5000_channel_switch_cmd
|
||||
* @band: 0- 5.2GHz, 1- 2.4GHz
|
||||
* @expect_beacon: 0- resume transmits after channel switch
|
||||
* 1- wait for beacon to resume transmits
|
||||
* @channel: new channel number
|
||||
* @rxon_flags: Rx on flags
|
||||
* @rxon_filter_flags: filtering parameters
|
||||
* @switch_time: switch time in extended beacon format
|
||||
* @reserved: reserved bytes
|
||||
*/
|
||||
struct iwl5000_channel_switch_cmd {
|
||||
u8 band;
|
||||
u8 expect_beacon;
|
||||
__le16 channel;
|
||||
__le32 rxon_flags;
|
||||
__le32 rxon_filter_flags;
|
||||
__le32 switch_time;
|
||||
__le32 reserved[2][IWL_PWR_NUM_HT_OFDM_ENTRIES + IWL_PWR_CCK_ENTRIES];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/**
|
||||
* struct iwl6000_channel_switch_cmd
|
||||
* @band: 0- 5.2GHz, 1- 2.4GHz
|
||||
* @expect_beacon: 0- resume transmits after channel switch
|
||||
* 1- wait for beacon to resume transmits
|
||||
* @channel: new channel number
|
||||
* @rxon_flags: Rx on flags
|
||||
* @rxon_filter_flags: filtering parameters
|
||||
* @switch_time: switch time in extended beacon format
|
||||
* @reserved: reserved bytes
|
||||
*/
|
||||
struct iwl6000_channel_switch_cmd {
|
||||
u8 band;
|
||||
u8 expect_beacon;
|
||||
__le16 channel;
|
||||
__le32 rxon_flags;
|
||||
__le32 rxon_filter_flags;
|
||||
__le32 switch_time;
|
||||
__le32 reserved[3][IWL_PWR_NUM_HT_OFDM_ENTRIES + IWL_PWR_CCK_ENTRIES];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/*
|
||||
* CHANNEL_SWITCH_NOTIFICATION = 0x73 (notification only, not a command)
|
||||
*/
|
||||
|
@ -2172,6 +2218,19 @@ struct iwl_link_quality_cmd {
|
|||
__le32 reserved2;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#define BT_COEX_DISABLE (0x0)
|
||||
#define BT_COEX_MODE_2W (0x1)
|
||||
#define BT_COEX_MODE_3W (0x2)
|
||||
#define BT_COEX_MODE_4W (0x3)
|
||||
|
||||
#define BT_LEAD_TIME_MIN (0x0)
|
||||
#define BT_LEAD_TIME_DEF (0x1E)
|
||||
#define BT_LEAD_TIME_MAX (0xFF)
|
||||
|
||||
#define BT_MAX_KILL_MIN (0x1)
|
||||
#define BT_MAX_KILL_DEF (0x5)
|
||||
#define BT_MAX_KILL_MAX (0xFF)
|
||||
|
||||
/*
|
||||
* REPLY_BT_CONFIG = 0x9b (command, has simple generic response)
|
||||
*
|
||||
|
@ -3247,12 +3306,6 @@ struct iwl_missed_beacon_notif {
|
|||
* Lower values mean higher energy; this means making sure that the value
|
||||
* in HD_MIN_ENERGY_CCK_DET_INDEX is at or *above* "Max cck energy".
|
||||
*
|
||||
* Driver should set the following entries to fixed values:
|
||||
*
|
||||
* HD_MIN_ENERGY_OFDM_DET_INDEX 100
|
||||
* HD_BARKER_CORR_TH_ADD_MIN_INDEX 190
|
||||
* HD_BARKER_CORR_TH_ADD_MIN_MRC_INDEX 390
|
||||
* HD_OFDM_ENERGY_TH_IN_INDEX 62
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -3505,6 +3558,16 @@ struct iwl_wimax_coex_cmd {
|
|||
*****************************************************************************/
|
||||
|
||||
struct iwl_rx_packet {
|
||||
/*
|
||||
* The first 4 bytes of the RX frame header contain both the RX frame
|
||||
* size and some flags.
|
||||
* Bit fields:
|
||||
* 31: flag flush RB request
|
||||
* 30: flag ignore TC (terminal counter) request
|
||||
* 29: flag fast IRQ request
|
||||
* 28-14: Reserved
|
||||
* 13-00: RX frame size
|
||||
*/
|
||||
__le32 len_n_flags;
|
||||
struct iwl_cmd_header hdr;
|
||||
union {
|
||||
|
|
|
@ -604,6 +604,23 @@ void iwlcore_free_geos(struct iwl_priv *priv)
|
|||
}
|
||||
EXPORT_SYMBOL(iwlcore_free_geos);
|
||||
|
||||
/*
|
||||
* iwlcore_rts_tx_cmd_flag: Set rts/cts. 3945 and 4965 only share this
|
||||
* function.
|
||||
*/
|
||||
void iwlcore_rts_tx_cmd_flag(struct ieee80211_tx_info *info,
|
||||
__le32 *tx_flags)
|
||||
{
|
||||
if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) {
|
||||
*tx_flags |= TX_CMD_FLG_RTS_MSK;
|
||||
*tx_flags &= ~TX_CMD_FLG_CTS_MSK;
|
||||
} else if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
|
||||
*tx_flags &= ~TX_CMD_FLG_RTS_MSK;
|
||||
*tx_flags |= TX_CMD_FLG_CTS_MSK;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(iwlcore_rts_tx_cmd_flag);
|
||||
|
||||
static bool is_single_rx_stream(struct iwl_priv *priv)
|
||||
{
|
||||
return !priv->current_ht_config.is_ht ||
|
||||
|
@ -1264,13 +1281,18 @@ static void iwl_set_rate(struct iwl_priv *priv)
|
|||
|
||||
void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_rxon_cmd *rxon = (void *)&priv->active_rxon;
|
||||
struct iwl_csa_notification *csa = &(pkt->u.csa_notif);
|
||||
IWL_DEBUG_11H(priv, "CSA notif: channel %d, status %d\n",
|
||||
le16_to_cpu(csa->channel), le32_to_cpu(csa->status));
|
||||
rxon->channel = csa->channel;
|
||||
priv->staging_rxon.channel = csa->channel;
|
||||
|
||||
if (!le32_to_cpu(csa->status)) {
|
||||
rxon->channel = csa->channel;
|
||||
priv->staging_rxon.channel = csa->channel;
|
||||
IWL_DEBUG_11H(priv, "CSA notif: channel %d\n",
|
||||
le16_to_cpu(csa->channel));
|
||||
} else
|
||||
IWL_ERR(priv, "CSA notif (fail) : channel %d\n",
|
||||
le16_to_cpu(csa->channel));
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_rx_csa);
|
||||
|
||||
|
@ -1352,6 +1374,8 @@ void iwl_apm_stop(struct iwl_priv *priv)
|
|||
{
|
||||
unsigned long flags;
|
||||
|
||||
IWL_DEBUG_INFO(priv, "Stop card, put in low power state\n");
|
||||
|
||||
iwl_apm_stop_master(priv);
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
|
@ -1365,6 +1389,118 @@ void iwl_apm_stop(struct iwl_priv *priv)
|
|||
}
|
||||
EXPORT_SYMBOL(iwl_apm_stop);
|
||||
|
||||
|
||||
/*
|
||||
* Start up NIC's basic functionality after it has been reset
|
||||
* (e.g. after platform boot, or shutdown via iwl_apm_stop())
|
||||
* NOTE: This does not load uCode nor start the embedded processor
|
||||
*/
|
||||
int iwl_apm_init(struct iwl_priv *priv)
|
||||
{
|
||||
int ret = 0;
|
||||
u16 lctl;
|
||||
|
||||
IWL_DEBUG_INFO(priv, "Init card's basic functions\n");
|
||||
|
||||
/*
|
||||
* Use "set_bit" below rather than "write", to preserve any hardware
|
||||
* bits already set by default after reset.
|
||||
*/
|
||||
|
||||
/* Disable L0S exit timer (platform NMI Work/Around) */
|
||||
iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS,
|
||||
CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
|
||||
|
||||
/*
|
||||
* Disable L0s without affecting L1;
|
||||
* don't wait for ICH L0s (ICH bug W/A)
|
||||
*/
|
||||
iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS,
|
||||
CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX);
|
||||
|
||||
/* Set FH wait threshold to maximum (HW error during stress W/A) */
|
||||
iwl_set_bit(priv, CSR_DBG_HPET_MEM_REG, CSR_DBG_HPET_MEM_REG_VAL);
|
||||
|
||||
/*
|
||||
* Enable HAP INTA (interrupt from management bus) to
|
||||
* wake device's PCI Express link L1a -> L0s
|
||||
* NOTE: This is no-op for 3945 (non-existant bit)
|
||||
*/
|
||||
iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
|
||||
CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A);
|
||||
|
||||
/*
|
||||
* HW bug W/A - costs negligible power consumption ...
|
||||
* Check if BIOS (or OS) enabled L1-ASPM on this device
|
||||
*/
|
||||
if (priv->cfg->set_l0s) {
|
||||
lctl = iwl_pcie_link_ctl(priv);
|
||||
if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) ==
|
||||
PCI_CFG_LINK_CTRL_VAL_L1_EN) {
|
||||
/* L1-ASPM enabled; disable(!) L0S */
|
||||
iwl_set_bit(priv, CSR_GIO_REG,
|
||||
CSR_GIO_REG_VAL_L0S_ENABLED);
|
||||
IWL_DEBUG_POWER(priv, "L1 Enabled; Disabling L0S\n");
|
||||
} else {
|
||||
/* L1-ASPM disabled; enable(!) L0S */
|
||||
iwl_clear_bit(priv, CSR_GIO_REG,
|
||||
CSR_GIO_REG_VAL_L0S_ENABLED);
|
||||
IWL_DEBUG_POWER(priv, "L1 Disabled; Enabling L0S\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* Configure analog phase-lock-loop before activating to D0A */
|
||||
if (priv->cfg->pll_cfg_val)
|
||||
iwl_set_bit(priv, CSR_ANA_PLL_CFG, priv->cfg->pll_cfg_val);
|
||||
|
||||
/*
|
||||
* Set "initialization complete" bit to move adapter from
|
||||
* D0U* --> D0A* (powered-up active) state.
|
||||
*/
|
||||
iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
|
||||
|
||||
/*
|
||||
* Wait for clock stabilization; once stabilized, access to
|
||||
* device-internal resources is supported, e.g. iwl_write_prph()
|
||||
* and accesses to uCode SRAM.
|
||||
*/
|
||||
ret = iwl_poll_bit(priv, CSR_GP_CNTRL,
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
|
||||
if (ret < 0) {
|
||||
IWL_DEBUG_INFO(priv, "Failed to init the card\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable DMA and BSM (if used) clocks, wait for them to stabilize.
|
||||
* BSM (Boostrap State Machine) is only in 3945 and 4965;
|
||||
* later devices (i.e. 5000 and later) have non-volatile SRAM,
|
||||
* and don't need BSM to restore data after power-saving sleep.
|
||||
*
|
||||
* Write to "CLK_EN_REG"; "1" bits enable clocks, while "0" bits
|
||||
* do not disable clocks. This preserves any hardware bits already
|
||||
* set by default in "CLK_CTRL_REG" after reset.
|
||||
*/
|
||||
if (priv->cfg->use_bsm)
|
||||
iwl_write_prph(priv, APMG_CLK_EN_REG,
|
||||
APMG_CLK_VAL_DMA_CLK_RQT | APMG_CLK_VAL_BSM_CLK_RQT);
|
||||
else
|
||||
iwl_write_prph(priv, APMG_CLK_EN_REG,
|
||||
APMG_CLK_VAL_DMA_CLK_RQT);
|
||||
udelay(20);
|
||||
|
||||
/* Disable L1-Active */
|
||||
iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG,
|
||||
APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_apm_init);
|
||||
|
||||
|
||||
|
||||
void iwl_configure_filter(struct ieee80211_hw *hw,
|
||||
unsigned int changed_flags,
|
||||
unsigned int *total_flags,
|
||||
|
@ -1412,73 +1548,14 @@ void iwl_configure_filter(struct ieee80211_hw *hw,
|
|||
}
|
||||
EXPORT_SYMBOL(iwl_configure_filter);
|
||||
|
||||
int iwl_setup_mac(struct iwl_priv *priv)
|
||||
{
|
||||
int ret;
|
||||
struct ieee80211_hw *hw = priv->hw;
|
||||
hw->rate_control_algorithm = "iwl-agn-rs";
|
||||
|
||||
/* Tell mac80211 our characteristics */
|
||||
hw->flags = IEEE80211_HW_SIGNAL_DBM |
|
||||
IEEE80211_HW_NOISE_DBM |
|
||||
IEEE80211_HW_AMPDU_AGGREGATION |
|
||||
IEEE80211_HW_SPECTRUM_MGMT;
|
||||
|
||||
if (!priv->cfg->broken_powersave)
|
||||
hw->flags |= IEEE80211_HW_SUPPORTS_PS |
|
||||
IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
|
||||
|
||||
hw->wiphy->interface_modes =
|
||||
BIT(NL80211_IFTYPE_STATION) |
|
||||
BIT(NL80211_IFTYPE_ADHOC);
|
||||
|
||||
hw->wiphy->custom_regulatory = true;
|
||||
|
||||
/* Firmware does not support this */
|
||||
hw->wiphy->disable_beacon_hints = true;
|
||||
|
||||
/*
|
||||
* For now, disable PS by default because it affects
|
||||
* RX performance significantly.
|
||||
*/
|
||||
hw->wiphy->ps_default = false;
|
||||
|
||||
hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX;
|
||||
/* we create the 802.11 header and a zero-length SSID element */
|
||||
hw->wiphy->max_scan_ie_len = IWL_MAX_PROBE_REQUEST - 24 - 2;
|
||||
|
||||
/* Default value; 4 EDCA QOS priorities */
|
||||
hw->queues = 4;
|
||||
|
||||
hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL;
|
||||
|
||||
if (priv->bands[IEEE80211_BAND_2GHZ].n_channels)
|
||||
priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
|
||||
&priv->bands[IEEE80211_BAND_2GHZ];
|
||||
if (priv->bands[IEEE80211_BAND_5GHZ].n_channels)
|
||||
priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
|
||||
&priv->bands[IEEE80211_BAND_5GHZ];
|
||||
|
||||
ret = ieee80211_register_hw(priv->hw);
|
||||
if (ret) {
|
||||
IWL_ERR(priv, "Failed to register hw (error %d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
priv->mac80211_registered = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_setup_mac);
|
||||
|
||||
int iwl_set_hw_params(struct iwl_priv *priv)
|
||||
{
|
||||
priv->hw_params.max_rxq_size = RX_QUEUE_SIZE;
|
||||
priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG;
|
||||
if (priv->cfg->mod_params->amsdu_size_8K)
|
||||
priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_8K;
|
||||
priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_8K);
|
||||
else
|
||||
priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_4K;
|
||||
priv->hw_params.max_pkt_size = priv->hw_params.rx_buf_size - 256;
|
||||
priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_4K);
|
||||
|
||||
priv->hw_params.max_beacon_itrvl = IWL_MAX_UCODE_BEACON_INTERVAL;
|
||||
|
||||
|
@ -1507,7 +1584,6 @@ int iwl_init_drv(struct iwl_priv *priv)
|
|||
/* Clear the driver's (not device's) station table */
|
||||
iwl_clear_stations_table(priv);
|
||||
|
||||
priv->data_retry_limit = -1;
|
||||
priv->ieee_channels = NULL;
|
||||
priv->ieee_rates = NULL;
|
||||
priv->band = IEEE80211_BAND_2GHZ;
|
||||
|
@ -1932,9 +2008,9 @@ EXPORT_SYMBOL(iwl_isr_legacy);
|
|||
int iwl_send_bt_config(struct iwl_priv *priv)
|
||||
{
|
||||
struct iwl_bt_cmd bt_cmd = {
|
||||
.flags = 3,
|
||||
.lead_time = 0xAA,
|
||||
.max_kill = 1,
|
||||
.flags = BT_COEX_MODE_4W,
|
||||
.lead_time = BT_LEAD_TIME_DEF,
|
||||
.max_kill = BT_MAX_KILL_DEF,
|
||||
.kill_ack_mask = 0,
|
||||
.kill_cts_mask = 0,
|
||||
};
|
||||
|
@ -2094,10 +2170,7 @@ void iwl_rf_kill_ct_config(struct iwl_priv *priv)
|
|||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
priv->thermal_throttle.ct_kill_toggle = false;
|
||||
|
||||
switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) {
|
||||
case CSR_HW_REV_TYPE_1000:
|
||||
case CSR_HW_REV_TYPE_6x00:
|
||||
case CSR_HW_REV_TYPE_6x50:
|
||||
if (priv->cfg->support_ct_kill_exit) {
|
||||
adv_cmd.critical_temperature_enter =
|
||||
cpu_to_le32(priv->hw_params.ct_kill_threshold);
|
||||
adv_cmd.critical_temperature_exit =
|
||||
|
@ -2114,8 +2187,7 @@ void iwl_rf_kill_ct_config(struct iwl_priv *priv)
|
|||
"exit is %d\n",
|
||||
priv->hw_params.ct_kill_threshold,
|
||||
priv->hw_params.ct_kill_exit_threshold);
|
||||
break;
|
||||
default:
|
||||
} else {
|
||||
cmd.critical_temperature_R =
|
||||
cpu_to_le32(priv->hw_params.ct_kill_threshold);
|
||||
|
||||
|
@ -2128,7 +2200,6 @@ void iwl_rf_kill_ct_config(struct iwl_priv *priv)
|
|||
"succeeded, "
|
||||
"critical temperature is %d\n",
|
||||
priv->hw_params.ct_kill_threshold);
|
||||
break;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_rf_kill_ct_config);
|
||||
|
@ -2160,7 +2231,7 @@ void iwl_rx_pm_sleep_notif(struct iwl_priv *priv,
|
|||
struct iwl_rx_mem_buffer *rxb)
|
||||
{
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_sleep_notification *sleep = &(pkt->u.sleep_notif);
|
||||
IWL_DEBUG_RX(priv, "sleep mode: %d, src: %d\n",
|
||||
sleep->pm_sleep_mode, sleep->pm_wakeup_src);
|
||||
|
@ -2171,7 +2242,7 @@ EXPORT_SYMBOL(iwl_rx_pm_sleep_notif);
|
|||
void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
u32 len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
|
||||
IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled "
|
||||
"notification for %s:\n", len,
|
||||
|
@ -2183,7 +2254,7 @@ EXPORT_SYMBOL(iwl_rx_pm_debug_statistics_notif);
|
|||
void iwl_rx_reply_error(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
|
||||
IWL_ERR(priv, "Error Reply type 0x%08X cmd %s (0x%02X) "
|
||||
"seq 0x%04X ser 0x%08X\n",
|
||||
|
@ -2648,6 +2719,14 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
|
|||
goto set_ch_out;
|
||||
}
|
||||
|
||||
if (iwl_is_associated(priv) &&
|
||||
(le16_to_cpu(priv->active_rxon.channel) != ch) &&
|
||||
priv->cfg->ops->lib->set_channel_switch) {
|
||||
ret = priv->cfg->ops->lib->set_channel_switch(priv,
|
||||
ch);
|
||||
goto out;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
|
||||
/* Configure HT40 channels */
|
||||
|
@ -2826,6 +2905,27 @@ void iwl_mac_reset_tsf(struct ieee80211_hw *hw)
|
|||
}
|
||||
EXPORT_SYMBOL(iwl_mac_reset_tsf);
|
||||
|
||||
int iwl_alloc_txq_mem(struct iwl_priv *priv)
|
||||
{
|
||||
if (!priv->txq)
|
||||
priv->txq = kzalloc(
|
||||
sizeof(struct iwl_tx_queue) * priv->cfg->num_of_queues,
|
||||
GFP_KERNEL);
|
||||
if (!priv->txq) {
|
||||
IWL_ERR(priv, "Not enough memory for txq \n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_alloc_txq_mem);
|
||||
|
||||
void iwl_free_txq_mem(struct iwl_priv *priv)
|
||||
{
|
||||
kfree(priv->txq);
|
||||
priv->txq = NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_free_txq_mem);
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
|
||||
#define IWL_TRAFFIC_DUMP_SIZE (IWL_TRAFFIC_ENTRY_SIZE * IWL_TRAFFIC_ENTRIES)
|
||||
|
|
|
@ -109,7 +109,6 @@ struct iwl_hcmd_utils_ops {
|
|||
|
||||
struct iwl_apm_ops {
|
||||
int (*init)(struct iwl_priv *priv);
|
||||
int (*reset)(struct iwl_priv *priv);
|
||||
void (*stop)(struct iwl_priv *priv);
|
||||
void (*config)(struct iwl_priv *priv);
|
||||
int (*set_pwr_src)(struct iwl_priv *priv, enum iwl_pwr_src src);
|
||||
|
@ -170,6 +169,7 @@ struct iwl_lib_ops {
|
|||
int (*load_ucode)(struct iwl_priv *priv);
|
||||
void (*dump_nic_event_log)(struct iwl_priv *priv);
|
||||
void (*dump_nic_error_log)(struct iwl_priv *priv);
|
||||
int (*set_channel_switch)(struct iwl_priv *priv, u16 channel);
|
||||
/* power management */
|
||||
struct iwl_apm_ops apm_ops;
|
||||
|
||||
|
@ -205,7 +205,6 @@ struct iwl_mod_params {
|
|||
int sw_crypto; /* def: 0 = using hardware encryption */
|
||||
int disable_hw_scan; /* def: 0 = use h/w scan */
|
||||
int num_of_queues; /* def: HW dependent */
|
||||
int num_of_ampdu_queues;/* def: HW dependent */
|
||||
int disable_11n; /* def: 0 = 11n capabilities enabled */
|
||||
int amsdu_size_8K; /* def: 1 = enable 8K amsdu size */
|
||||
int antenna; /* def: 0 = both antennas (use diversity) */
|
||||
|
@ -227,6 +226,8 @@ struct iwl_mod_params {
|
|||
* The detail algorithm is described in iwl-led.c
|
||||
* @use_rts_for_ht: use rts/cts protection for HT traffic
|
||||
* @chain_noise_num_beacons: number of beacons used to compute chain noise
|
||||
* @adv_thermal_throttle: support advance thermal throttle
|
||||
* @support_ct_kill_exit: support ct kill exit condition
|
||||
*
|
||||
* We enable the driver to be backward compatible wrt API version. The
|
||||
* driver specifies which APIs it supports (with @ucode_api_max being the
|
||||
|
@ -258,11 +259,18 @@ struct iwl_cfg {
|
|||
int eeprom_size;
|
||||
u16 eeprom_ver;
|
||||
u16 eeprom_calib_ver;
|
||||
int num_of_queues; /* def: HW dependent */
|
||||
int num_of_ampdu_queues;/* def: HW dependent */
|
||||
const struct iwl_ops *ops;
|
||||
const struct iwl_mod_params *mod_params;
|
||||
u8 valid_tx_ant;
|
||||
u8 valid_rx_ant;
|
||||
bool need_pll_cfg;
|
||||
|
||||
/* for iwl_apm_init() */
|
||||
u32 pll_cfg_val;
|
||||
bool set_l0s;
|
||||
bool use_bsm;
|
||||
|
||||
bool use_isr_legacy;
|
||||
enum iwl_pa_type pa_type;
|
||||
const u16 max_ll_items;
|
||||
|
@ -273,6 +281,8 @@ struct iwl_cfg {
|
|||
bool use_rts_for_ht;
|
||||
int chain_noise_num_beacons;
|
||||
const bool supports_idle;
|
||||
bool adv_thermal_throttle;
|
||||
bool support_ct_kill_exit;
|
||||
};
|
||||
|
||||
/***************************
|
||||
|
@ -305,7 +315,6 @@ void iwl_configure_filter(struct ieee80211_hw *hw,
|
|||
unsigned int changed_flags,
|
||||
unsigned int *total_flags, u64 multicast);
|
||||
int iwl_hw_nic_init(struct iwl_priv *priv);
|
||||
int iwl_setup_mac(struct iwl_priv *priv);
|
||||
int iwl_set_hw_params(struct iwl_priv *priv);
|
||||
int iwl_init_drv(struct iwl_priv *priv);
|
||||
void iwl_uninit_drv(struct iwl_priv *priv);
|
||||
|
@ -327,6 +336,10 @@ void iwl_config_ap(struct iwl_priv *priv);
|
|||
int iwl_mac_get_tx_stats(struct ieee80211_hw *hw,
|
||||
struct ieee80211_tx_queue_stats *stats);
|
||||
void iwl_mac_reset_tsf(struct ieee80211_hw *hw);
|
||||
int iwl_alloc_txq_mem(struct iwl_priv *priv);
|
||||
void iwl_free_txq_mem(struct iwl_priv *priv);
|
||||
void iwlcore_rts_tx_cmd_flag(struct ieee80211_tx_info *info,
|
||||
__le32 *tx_flags);
|
||||
#ifdef CONFIG_IWLWIFI_DEBUGFS
|
||||
int iwl_alloc_traffic_mem(struct iwl_priv *priv);
|
||||
void iwl_free_traffic_mem(struct iwl_priv *priv);
|
||||
|
@ -527,7 +540,7 @@ int iwl_send_cmd_pdu_async(struct iwl_priv *priv, u8 id, u16 len,
|
|||
const void *data,
|
||||
void (*callback)(struct iwl_priv *priv,
|
||||
struct iwl_device_cmd *cmd,
|
||||
struct sk_buff *skb));
|
||||
struct iwl_rx_packet *pkt));
|
||||
|
||||
int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
|
||||
|
||||
|
@ -660,6 +673,7 @@ void iwl_rx_reply_compressed_ba(struct iwl_priv *priv,
|
|||
struct iwl_rx_mem_buffer *rxb);
|
||||
void iwl_apm_stop(struct iwl_priv *priv);
|
||||
int iwl_apm_stop_master(struct iwl_priv *priv);
|
||||
int iwl_apm_init(struct iwl_priv *priv);
|
||||
|
||||
void iwl_setup_rxon_timing(struct iwl_priv *priv);
|
||||
static inline int iwl_send_rxon_assoc(struct iwl_priv *priv)
|
||||
|
|
|
@ -109,8 +109,9 @@
|
|||
* Bit fields:
|
||||
* 3-2: 0 = A, 1 = B, 2 = C, 3 = D step
|
||||
*/
|
||||
#define CSR_HW_REV_WA_REG (CSR_BASE+0x22C)
|
||||
#define CSR_DBG_HPET_MEM_REG (CSR_BASE+0x240)
|
||||
#define CSR_HW_REV_WA_REG (CSR_BASE+0x22C)
|
||||
#define CSR_DBG_HPET_MEM_REG (CSR_BASE+0x240)
|
||||
#define CSR_DBG_LINK_PWR_MGMT_REG (CSR_BASE+0x250)
|
||||
|
||||
/* Bits for CSR_HW_IF_CONFIG_REG */
|
||||
#define CSR49_HW_IF_CONFIG_REG_BIT_4965_R (0x00000010)
|
||||
|
@ -195,6 +196,7 @@
|
|||
#define CSR_RESET_REG_FLAG_SW_RESET (0x00000080)
|
||||
#define CSR_RESET_REG_FLAG_MASTER_DISABLED (0x00000100)
|
||||
#define CSR_RESET_REG_FLAG_STOP_MASTER (0x00000200)
|
||||
#define CSR_RESET_LINK_PWR_MGMT_DISABLED (0x80000000)
|
||||
|
||||
/* GP (general purpose) CONTROL */
|
||||
#define CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY (0x00000001)
|
||||
|
@ -235,6 +237,11 @@
|
|||
#define CSR_OTP_GP_REG_OTP_ACCESS_MODE (0x00020000) /* 0 - absolute, 1 - relative */
|
||||
#define CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK (0x00100000) /* bit 20 */
|
||||
#define CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK (0x00200000) /* bit 21 */
|
||||
#define CSR_GP_REG_POWER_SAVE_STATUS_MSK (0x03000000) /* bit 24/25 */
|
||||
#define CSR_GP_REG_NO_POWER_SAVE (0x00000000)
|
||||
#define CSR_GP_REG_MAC_POWER_SAVE (0x01000000)
|
||||
#define CSR_GP_REG_PHY_POWER_SAVE (0x02000000)
|
||||
#define CSR_GP_REG_POWER_SAVE_ERROR (0x03000000)
|
||||
|
||||
/* EEPROM signature */
|
||||
#define CSR_EEPROM_GP_BAD_SIGNATURE_BOTH_EEP_AND_OTP (0x00000000)
|
||||
|
|
|
@ -106,6 +106,7 @@ struct iwl_debugfs {
|
|||
struct dentry *file_sensitivity;
|
||||
struct dentry *file_chain_noise;
|
||||
struct dentry *file_tx_power;
|
||||
struct dentry *file_power_save_status;
|
||||
} dbgfs_debug_files;
|
||||
u32 sram_offset;
|
||||
u32 sram_len;
|
||||
|
|
|
@ -801,15 +801,20 @@ static ssize_t iwl_dbgfs_sleep_level_override_write(struct file *file,
|
|||
* valid here. However, let's not confuse them and present
|
||||
* IWL_POWER_INDEX_1 as "1", not "0".
|
||||
*/
|
||||
if (value > 0)
|
||||
if (value == 0)
|
||||
return -EINVAL;
|
||||
else if (value > 0)
|
||||
value -= 1;
|
||||
|
||||
if (value != -1 && (value < 0 || value >= IWL_POWER_NUM))
|
||||
return -EINVAL;
|
||||
|
||||
if (!iwl_is_ready_rf(priv))
|
||||
return -EAGAIN;
|
||||
|
||||
priv->power_data.debug_sleep_level_override = value;
|
||||
|
||||
iwl_power_update_mode(priv, false);
|
||||
iwl_power_update_mode(priv, true);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
@ -882,10 +887,14 @@ static ssize_t iwl_dbgfs_traffic_log_read(struct file *file,
|
|||
struct iwl_rx_queue *rxq = &priv->rxq;
|
||||
char *buf;
|
||||
int bufsz = ((IWL_TRAFFIC_ENTRIES * IWL_TRAFFIC_ENTRY_SIZE * 64) * 2) +
|
||||
(IWL_MAX_NUM_QUEUES * 32 * 8) + 400;
|
||||
(priv->cfg->num_of_queues * 32 * 8) + 400;
|
||||
const u8 *ptr;
|
||||
ssize_t ret;
|
||||
|
||||
if (!priv->txq) {
|
||||
IWL_ERR(priv, "txq not ready\n");
|
||||
return -EAGAIN;
|
||||
}
|
||||
buf = kzalloc(bufsz, GFP_KERNEL);
|
||||
if (!buf) {
|
||||
IWL_ERR(priv, "Can not allocate buffer\n");
|
||||
|
@ -977,8 +986,12 @@ static ssize_t iwl_dbgfs_tx_queue_read(struct file *file,
|
|||
int pos = 0;
|
||||
int cnt;
|
||||
int ret;
|
||||
const size_t bufsz = sizeof(char) * 60 * IWL_MAX_NUM_QUEUES;
|
||||
const size_t bufsz = sizeof(char) * 60 * priv->cfg->num_of_queues;
|
||||
|
||||
if (!priv->txq) {
|
||||
IWL_ERR(priv, "txq not ready\n");
|
||||
return -EAGAIN;
|
||||
}
|
||||
buf = kzalloc(bufsz, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
@ -1069,10 +1082,10 @@ static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file,
|
|||
sizeof(struct statistics_rx_non_phy) * 20 +
|
||||
sizeof(struct statistics_rx_ht_phy) * 20 + 400;
|
||||
ssize_t ret;
|
||||
struct statistics_rx_phy *ofdm;
|
||||
struct statistics_rx_phy *cck;
|
||||
struct statistics_rx_non_phy *general;
|
||||
struct statistics_rx_ht_phy *ht;
|
||||
struct statistics_rx_phy *ofdm, *accum_ofdm;
|
||||
struct statistics_rx_phy *cck, *accum_cck;
|
||||
struct statistics_rx_non_phy *general, *accum_general;
|
||||
struct statistics_rx_ht_phy *ht, *accum_ht;
|
||||
|
||||
if (!iwl_is_alive(priv))
|
||||
return -EAGAIN;
|
||||
|
@ -1101,155 +1114,268 @@ static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file,
|
|||
cck = &priv->statistics.rx.cck;
|
||||
general = &priv->statistics.rx.general;
|
||||
ht = &priv->statistics.rx.ofdm_ht;
|
||||
accum_ofdm = &priv->accum_statistics.rx.ofdm;
|
||||
accum_cck = &priv->accum_statistics.rx.cck;
|
||||
accum_general = &priv->accum_statistics.rx.general;
|
||||
accum_ht = &priv->accum_statistics.rx.ofdm_ht;
|
||||
pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - OFDM:\n");
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "ina_cnt: %u\n",
|
||||
le32_to_cpu(ofdm->ina_cnt));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "fina_cnt: %u\n",
|
||||
le32_to_cpu(ofdm->fina_cnt));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "plcp_err: %u\n",
|
||||
le32_to_cpu(ofdm->plcp_err));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "crc32_err: %u\n",
|
||||
le32_to_cpu(ofdm->crc32_err));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "overrun_err: %u\n",
|
||||
le32_to_cpu(ofdm->overrun_err));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "early_overrun_err: %u\n",
|
||||
le32_to_cpu(ofdm->early_overrun_err));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "crc32_good: %u\n",
|
||||
le32_to_cpu(ofdm->crc32_good));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "false_alarm_cnt: %u\n",
|
||||
le32_to_cpu(ofdm->false_alarm_cnt));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "fina_sync_err_cnt: %u\n",
|
||||
le32_to_cpu(ofdm->fina_sync_err_cnt));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "sfd_timeout: %u\n",
|
||||
le32_to_cpu(ofdm->sfd_timeout));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "fina_timeout: %u\n",
|
||||
le32_to_cpu(ofdm->fina_timeout));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "unresponded_rts: %u\n",
|
||||
le32_to_cpu(ofdm->unresponded_rts));
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"rxe_frame_limit_overrun: %u\n",
|
||||
le32_to_cpu(ofdm->rxe_frame_limit_overrun));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "sent_ack_cnt: %u\n",
|
||||
le32_to_cpu(ofdm->sent_ack_cnt));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "sent_cts_cnt: %u\n",
|
||||
le32_to_cpu(ofdm->sent_cts_cnt));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "sent_ba_rsp_cnt: %u\n",
|
||||
le32_to_cpu(ofdm->sent_ba_rsp_cnt));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "dsp_self_kill: %u\n",
|
||||
le32_to_cpu(ofdm->dsp_self_kill));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "mh_format_err: %u\n",
|
||||
le32_to_cpu(ofdm->mh_format_err));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "re_acq_main_rssi_sum: %u\n",
|
||||
le32_to_cpu(ofdm->re_acq_main_rssi_sum));
|
||||
"\t\t\tcurrent\t\t\taccumulative\n");
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "ina_cnt:\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(ofdm->ina_cnt), accum_ofdm->ina_cnt);
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "fina_cnt:\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(ofdm->fina_cnt), accum_ofdm->fina_cnt);
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "plcp_err:\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(ofdm->plcp_err), accum_ofdm->plcp_err);
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "crc32_err:\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(ofdm->crc32_err), accum_ofdm->crc32_err);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"overrun_err:\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(ofdm->overrun_err),
|
||||
accum_ofdm->overrun_err);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"early_overrun_err:\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(ofdm->early_overrun_err),
|
||||
accum_ofdm->early_overrun_err);
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "crc32_good:\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(ofdm->crc32_good),
|
||||
accum_ofdm->crc32_good);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"false_alarm_cnt:\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(ofdm->false_alarm_cnt),
|
||||
accum_ofdm->false_alarm_cnt);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"fina_sync_err_cnt:\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(ofdm->fina_sync_err_cnt),
|
||||
accum_ofdm->fina_sync_err_cnt);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"sfd_timeout:\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(ofdm->sfd_timeout),
|
||||
accum_ofdm->sfd_timeout);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"fina_timeout:\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(ofdm->fina_timeout),
|
||||
accum_ofdm->fina_timeout);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"unresponded_rts:\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(ofdm->unresponded_rts),
|
||||
accum_ofdm->unresponded_rts);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"rxe_frame_lmt_ovrun:\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(ofdm->rxe_frame_limit_overrun),
|
||||
accum_ofdm->rxe_frame_limit_overrun);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"sent_ack_cnt:\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(ofdm->sent_ack_cnt),
|
||||
accum_ofdm->sent_ack_cnt);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"sent_cts_cnt:\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(ofdm->sent_cts_cnt),
|
||||
accum_ofdm->sent_cts_cnt);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"sent_ba_rsp_cnt:\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(ofdm->sent_ba_rsp_cnt),
|
||||
accum_ofdm->sent_ba_rsp_cnt);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"dsp_self_kill:\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(ofdm->dsp_self_kill),
|
||||
accum_ofdm->dsp_self_kill);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"mh_format_err:\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(ofdm->mh_format_err),
|
||||
accum_ofdm->mh_format_err);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"re_acq_main_rssi_sum:\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(ofdm->re_acq_main_rssi_sum),
|
||||
accum_ofdm->re_acq_main_rssi_sum);
|
||||
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - CCK:\n");
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "ina_cnt: %u\n",
|
||||
le32_to_cpu(cck->ina_cnt));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "fina_cnt: %u\n",
|
||||
le32_to_cpu(cck->fina_cnt));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "plcp_err: %u\n",
|
||||
le32_to_cpu(cck->plcp_err));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "crc32_err: %u\n",
|
||||
le32_to_cpu(cck->crc32_err));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "overrun_err: %u\n",
|
||||
le32_to_cpu(cck->overrun_err));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "early_overrun_err: %u\n",
|
||||
le32_to_cpu(cck->early_overrun_err));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "crc32_good: %u\n",
|
||||
le32_to_cpu(cck->crc32_good));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "false_alarm_cnt: %u\n",
|
||||
le32_to_cpu(cck->false_alarm_cnt));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "fina_sync_err_cnt: %u\n",
|
||||
le32_to_cpu(cck->fina_sync_err_cnt));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "sfd_timeout: %u\n",
|
||||
le32_to_cpu(cck->sfd_timeout));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "fina_timeout: %u\n",
|
||||
le32_to_cpu(cck->fina_timeout));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "unresponded_rts: %u\n",
|
||||
le32_to_cpu(cck->unresponded_rts));
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"rxe_frame_limit_overrun: %u\n",
|
||||
le32_to_cpu(cck->rxe_frame_limit_overrun));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "sent_ack_cnt: %u\n",
|
||||
le32_to_cpu(cck->sent_ack_cnt));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "sent_cts_cnt: %u\n",
|
||||
le32_to_cpu(cck->sent_cts_cnt));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "sent_ba_rsp_cnt: %u\n",
|
||||
le32_to_cpu(cck->sent_ba_rsp_cnt));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "dsp_self_kill: %u\n",
|
||||
le32_to_cpu(cck->dsp_self_kill));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "mh_format_err: %u\n",
|
||||
le32_to_cpu(cck->mh_format_err));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "re_acq_main_rssi_sum: %u\n",
|
||||
le32_to_cpu(cck->re_acq_main_rssi_sum));
|
||||
"\t\t\tcurrent\t\t\taccumulative\n");
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "ina_cnt:\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(cck->ina_cnt), accum_cck->ina_cnt);
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "fina_cnt:\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(cck->fina_cnt), accum_cck->fina_cnt);
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "plcp_err:\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(cck->plcp_err), accum_cck->plcp_err);
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "crc32_err:\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(cck->crc32_err), accum_cck->crc32_err);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"overrun_err:\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(cck->overrun_err),
|
||||
accum_cck->overrun_err);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"early_overrun_err:\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(cck->early_overrun_err),
|
||||
accum_cck->early_overrun_err);
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "crc32_good:\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(cck->crc32_good), accum_cck->crc32_good);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"false_alarm_cnt:\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(cck->false_alarm_cnt),
|
||||
accum_cck->false_alarm_cnt);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"fina_sync_err_cnt:\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(cck->fina_sync_err_cnt),
|
||||
accum_cck->fina_sync_err_cnt);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"sfd_timeout:\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(cck->sfd_timeout),
|
||||
accum_cck->sfd_timeout);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"fina_timeout:\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(cck->fina_timeout),
|
||||
accum_cck->fina_timeout);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"unresponded_rts:\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(cck->unresponded_rts),
|
||||
accum_cck->unresponded_rts);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"rxe_frame_lmt_ovrun:\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(cck->rxe_frame_limit_overrun),
|
||||
accum_cck->rxe_frame_limit_overrun);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"sent_ack_cnt:\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(cck->sent_ack_cnt),
|
||||
accum_cck->sent_ack_cnt);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"sent_cts_cnt:\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(cck->sent_cts_cnt),
|
||||
accum_cck->sent_cts_cnt);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"sent_ba_rsp_cnt:\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(cck->sent_ba_rsp_cnt),
|
||||
accum_cck->sent_ba_rsp_cnt);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"dsp_self_kill:\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(cck->dsp_self_kill),
|
||||
accum_cck->dsp_self_kill);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"mh_format_err:\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(cck->mh_format_err),
|
||||
accum_cck->mh_format_err);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"re_acq_main_rssi_sum:\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(cck->re_acq_main_rssi_sum),
|
||||
accum_cck->re_acq_main_rssi_sum);
|
||||
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - GENERAL:\n");
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "bogus_cts: %u\n",
|
||||
le32_to_cpu(general->bogus_cts));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "bogus_ack: %u\n",
|
||||
le32_to_cpu(general->bogus_ack));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "non_bssid_frames: %u\n",
|
||||
le32_to_cpu(general->non_bssid_frames));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "filtered_frames: %u\n",
|
||||
le32_to_cpu(general->filtered_frames));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "non_channel_beacons: %u\n",
|
||||
le32_to_cpu(general->non_channel_beacons));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "channel_beacons: %u\n",
|
||||
le32_to_cpu(general->channel_beacons));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "num_missed_bcon: %u\n",
|
||||
le32_to_cpu(general->num_missed_bcon));
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"adc_rx_saturation_time: %u\n",
|
||||
le32_to_cpu(general->adc_rx_saturation_time));
|
||||
"\t\t\tcurrent\t\t\taccumulative\n");
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "bogus_cts:\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(general->bogus_cts),
|
||||
accum_general->bogus_cts);
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "bogus_ack:\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(general->bogus_ack),
|
||||
accum_general->bogus_ack);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"ina_detection_search_time: %u\n",
|
||||
le32_to_cpu(general->ina_detection_search_time));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "beacon_silence_rssi_a: %u\n",
|
||||
le32_to_cpu(general->beacon_silence_rssi_a));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "beacon_silence_rssi_b: %u\n",
|
||||
le32_to_cpu(general->beacon_silence_rssi_b));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "beacon_silence_rssi_c: %u\n",
|
||||
le32_to_cpu(general->beacon_silence_rssi_c));
|
||||
"non_bssid_frames:\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(general->non_bssid_frames),
|
||||
accum_general->non_bssid_frames);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"interference_data_flag: %u\n",
|
||||
le32_to_cpu(general->interference_data_flag));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "channel_load: %u\n",
|
||||
le32_to_cpu(general->channel_load));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "dsp_false_alarms: %u\n",
|
||||
le32_to_cpu(general->dsp_false_alarms));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "beacon_rssi_a: %u\n",
|
||||
le32_to_cpu(general->beacon_rssi_a));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "beacon_rssi_b: %u\n",
|
||||
le32_to_cpu(general->beacon_rssi_b));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "beacon_rssi_c: %u\n",
|
||||
le32_to_cpu(general->beacon_rssi_c));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "beacon_energy_a: %u\n",
|
||||
le32_to_cpu(general->beacon_energy_a));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "beacon_energy_b: %u\n",
|
||||
le32_to_cpu(general->beacon_energy_b));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "beacon_energy_c: %u\n",
|
||||
le32_to_cpu(general->beacon_energy_c));
|
||||
"filtered_frames:\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(general->filtered_frames),
|
||||
accum_general->filtered_frames);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"non_channel_beacons:\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(general->non_channel_beacons),
|
||||
accum_general->non_channel_beacons);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"channel_beacons:\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(general->channel_beacons),
|
||||
accum_general->channel_beacons);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"num_missed_bcon:\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(general->num_missed_bcon),
|
||||
accum_general->num_missed_bcon);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"adc_rx_saturation_time:\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(general->adc_rx_saturation_time),
|
||||
accum_general->adc_rx_saturation_time);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"ina_detect_search_tm:\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(general->ina_detection_search_time),
|
||||
accum_general->ina_detection_search_time);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"beacon_silence_rssi_a:\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(general->beacon_silence_rssi_a),
|
||||
accum_general->beacon_silence_rssi_a);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"beacon_silence_rssi_b:\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(general->beacon_silence_rssi_b),
|
||||
accum_general->beacon_silence_rssi_b);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"beacon_silence_rssi_c:\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(general->beacon_silence_rssi_c),
|
||||
accum_general->beacon_silence_rssi_c);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"interference_data_flag:\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(general->interference_data_flag),
|
||||
accum_general->interference_data_flag);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"channel_load:\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(general->channel_load),
|
||||
accum_general->channel_load);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"dsp_false_alarms:\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(general->dsp_false_alarms),
|
||||
accum_general->dsp_false_alarms);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"beacon_rssi_a:\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(general->beacon_rssi_a),
|
||||
accum_general->beacon_rssi_a);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"beacon_rssi_b:\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(general->beacon_rssi_b),
|
||||
accum_general->beacon_rssi_b);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"beacon_rssi_c:\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(general->beacon_rssi_c),
|
||||
accum_general->beacon_rssi_c);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"beacon_energy_a:\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(general->beacon_energy_a),
|
||||
accum_general->beacon_energy_a);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"beacon_energy_b:\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(general->beacon_energy_b),
|
||||
accum_general->beacon_energy_b);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"beacon_energy_c:\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(general->beacon_energy_c),
|
||||
accum_general->beacon_energy_c);
|
||||
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - OFDM_HT:\n");
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "plcp_err: %u\n",
|
||||
le32_to_cpu(ht->plcp_err));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "overrun_err: %u\n",
|
||||
le32_to_cpu(ht->overrun_err));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "early_overrun_err: %u\n",
|
||||
le32_to_cpu(ht->early_overrun_err));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "crc32_good: %u\n",
|
||||
le32_to_cpu(ht->crc32_good));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "crc32_err: %u\n",
|
||||
le32_to_cpu(ht->crc32_err));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "mh_format_err: %u\n",
|
||||
le32_to_cpu(ht->mh_format_err));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "agg_crc32_good: %u\n",
|
||||
le32_to_cpu(ht->agg_crc32_good));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "agg_mpdu_cnt: %u\n",
|
||||
le32_to_cpu(ht->agg_mpdu_cnt));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "agg_cnt: %u\n",
|
||||
le32_to_cpu(ht->agg_cnt));
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"\t\t\tcurrent\t\t\taccumulative\n");
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "plcp_err:\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(ht->plcp_err), accum_ht->plcp_err);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"overrun_err:\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(ht->overrun_err), accum_ht->overrun_err);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"early_overrun_err:\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(ht->early_overrun_err),
|
||||
accum_ht->early_overrun_err);
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "crc32_good:\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(ht->crc32_good), accum_ht->crc32_good);
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "crc32_err:\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(ht->crc32_err), accum_ht->crc32_err);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"mh_format_err:\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(ht->mh_format_err),
|
||||
accum_ht->mh_format_err);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"agg_crc32_good:\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(ht->agg_crc32_good),
|
||||
accum_ht->agg_crc32_good);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"agg_mpdu_cnt:\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(ht->agg_mpdu_cnt),
|
||||
accum_ht->agg_mpdu_cnt);
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "agg_cnt:\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(ht->agg_cnt), accum_ht->agg_cnt);
|
||||
|
||||
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
kfree(buf);
|
||||
|
@ -1265,7 +1391,7 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file,
|
|||
char *buf;
|
||||
int bufsz = (sizeof(struct statistics_tx) * 24) + 250;
|
||||
ssize_t ret;
|
||||
struct statistics_tx *tx;
|
||||
struct statistics_tx *tx, *accum_tx;
|
||||
|
||||
if (!iwl_is_alive(priv))
|
||||
return -EAGAIN;
|
||||
|
@ -1291,62 +1417,107 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file,
|
|||
* might not reflect the current uCode activity
|
||||
*/
|
||||
tx = &priv->statistics.tx;
|
||||
accum_tx = &priv->accum_statistics.tx;
|
||||
pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Tx:\n");
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "preamble: %u\n",
|
||||
le32_to_cpu(tx->preamble_cnt));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "rx_detected_cnt: %u\n",
|
||||
le32_to_cpu(tx->rx_detected_cnt));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "bt_prio_defer_cnt: %u\n",
|
||||
le32_to_cpu(tx->bt_prio_defer_cnt));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "bt_prio_kill_cnt: %u\n",
|
||||
le32_to_cpu(tx->bt_prio_kill_cnt));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "few_bytes_cnt: %u\n",
|
||||
le32_to_cpu(tx->few_bytes_cnt));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "cts_timeout: %u\n",
|
||||
le32_to_cpu(tx->cts_timeout));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "ack_timeout: %u\n",
|
||||
le32_to_cpu(tx->ack_timeout));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "expected_ack_cnt: %u\n",
|
||||
le32_to_cpu(tx->expected_ack_cnt));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "actual_ack_cnt: %u\n",
|
||||
le32_to_cpu(tx->actual_ack_cnt));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "dump_msdu_cnt: %u\n",
|
||||
le32_to_cpu(tx->dump_msdu_cnt));
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"burst_abort_next_frame_mismatch_cnt: %u\n",
|
||||
le32_to_cpu(tx->burst_abort_next_frame_mismatch_cnt));
|
||||
"\t\t\tcurrent\t\t\taccumulative\n");
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "preamble:\t\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(tx->preamble_cnt),
|
||||
accum_tx->preamble_cnt);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"burst_abort_missing_next_frame_cnt: %u\n",
|
||||
le32_to_cpu(tx->burst_abort_missing_next_frame_cnt));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "cts_timeout_collision: %u\n",
|
||||
le32_to_cpu(tx->cts_timeout_collision));
|
||||
"rx_detected_cnt:\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(tx->rx_detected_cnt),
|
||||
accum_tx->rx_detected_cnt);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"ack_or_ba_timeout_collision: %u\n",
|
||||
le32_to_cpu(tx->ack_or_ba_timeout_collision));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "agg ba_timeout: %u\n",
|
||||
le32_to_cpu(tx->agg.ba_timeout));
|
||||
"bt_prio_defer_cnt:\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(tx->bt_prio_defer_cnt),
|
||||
accum_tx->bt_prio_defer_cnt);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"agg ba_reschedule_frames: %u\n",
|
||||
le32_to_cpu(tx->agg.ba_reschedule_frames));
|
||||
"bt_prio_kill_cnt:\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(tx->bt_prio_kill_cnt),
|
||||
accum_tx->bt_prio_kill_cnt);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"agg scd_query_agg_frame_cnt: %u\n",
|
||||
le32_to_cpu(tx->agg.scd_query_agg_frame_cnt));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "agg scd_query_no_agg: %u\n",
|
||||
le32_to_cpu(tx->agg.scd_query_no_agg));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "agg scd_query_agg: %u\n",
|
||||
le32_to_cpu(tx->agg.scd_query_agg));
|
||||
"few_bytes_cnt:\t\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(tx->few_bytes_cnt),
|
||||
accum_tx->few_bytes_cnt);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"agg scd_query_mismatch: %u\n",
|
||||
le32_to_cpu(tx->agg.scd_query_mismatch));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "agg frame_not_ready: %u\n",
|
||||
le32_to_cpu(tx->agg.frame_not_ready));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "agg underrun: %u\n",
|
||||
le32_to_cpu(tx->agg.underrun));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "agg bt_prio_kill: %u\n",
|
||||
le32_to_cpu(tx->agg.bt_prio_kill));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "agg rx_ba_rsp_cnt: %u\n",
|
||||
le32_to_cpu(tx->agg.rx_ba_rsp_cnt));
|
||||
"cts_timeout:\t\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(tx->cts_timeout), accum_tx->cts_timeout);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"ack_timeout:\t\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(tx->ack_timeout),
|
||||
accum_tx->ack_timeout);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"expected_ack_cnt:\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(tx->expected_ack_cnt),
|
||||
accum_tx->expected_ack_cnt);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"actual_ack_cnt:\t\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(tx->actual_ack_cnt),
|
||||
accum_tx->actual_ack_cnt);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"dump_msdu_cnt:\t\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(tx->dump_msdu_cnt),
|
||||
accum_tx->dump_msdu_cnt);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"abort_nxt_frame_mismatch:"
|
||||
"\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(tx->burst_abort_next_frame_mismatch_cnt),
|
||||
accum_tx->burst_abort_next_frame_mismatch_cnt);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"abort_missing_nxt_frame:"
|
||||
"\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(tx->burst_abort_missing_next_frame_cnt),
|
||||
accum_tx->burst_abort_missing_next_frame_cnt);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"cts_timeout_collision:\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(tx->cts_timeout_collision),
|
||||
accum_tx->cts_timeout_collision);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"ack_ba_timeout_collision:\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(tx->ack_or_ba_timeout_collision),
|
||||
accum_tx->ack_or_ba_timeout_collision);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"agg ba_timeout:\t\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(tx->agg.ba_timeout),
|
||||
accum_tx->agg.ba_timeout);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"agg ba_resched_frames:\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(tx->agg.ba_reschedule_frames),
|
||||
accum_tx->agg.ba_reschedule_frames);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"agg scd_query_agg_frame:\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(tx->agg.scd_query_agg_frame_cnt),
|
||||
accum_tx->agg.scd_query_agg_frame_cnt);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"agg scd_query_no_agg:\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(tx->agg.scd_query_no_agg),
|
||||
accum_tx->agg.scd_query_no_agg);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"agg scd_query_agg:\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(tx->agg.scd_query_agg),
|
||||
accum_tx->agg.scd_query_agg);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"agg scd_query_mismatch:\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(tx->agg.scd_query_mismatch),
|
||||
accum_tx->agg.scd_query_mismatch);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"agg frame_not_ready:\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(tx->agg.frame_not_ready),
|
||||
accum_tx->agg.frame_not_ready);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"agg underrun:\t\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(tx->agg.underrun),
|
||||
accum_tx->agg.underrun);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"agg bt_prio_kill:\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(tx->agg.bt_prio_kill),
|
||||
accum_tx->agg.bt_prio_kill);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"agg rx_ba_rsp_cnt:\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(tx->agg.rx_ba_rsp_cnt),
|
||||
accum_tx->agg.rx_ba_rsp_cnt);
|
||||
|
||||
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
kfree(buf);
|
||||
|
@ -1362,9 +1533,9 @@ static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file,
|
|||
char *buf;
|
||||
int bufsz = sizeof(struct statistics_general) * 4 + 250;
|
||||
ssize_t ret;
|
||||
struct statistics_general *general;
|
||||
struct statistics_dbg *dbg;
|
||||
struct statistics_div *div;
|
||||
struct statistics_general *general, *accum_general;
|
||||
struct statistics_dbg *dbg, *accum_dbg;
|
||||
struct statistics_div *div, *accum_div;
|
||||
|
||||
if (!iwl_is_alive(priv))
|
||||
return -EAGAIN;
|
||||
|
@ -1392,34 +1563,53 @@ static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file,
|
|||
general = &priv->statistics.general;
|
||||
dbg = &priv->statistics.general.dbg;
|
||||
div = &priv->statistics.general.div;
|
||||
accum_general = &priv->accum_statistics.general;
|
||||
accum_dbg = &priv->accum_statistics.general.dbg;
|
||||
accum_div = &priv->accum_statistics.general.div;
|
||||
pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "Statistics_General:\n");
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "temperature: %u\n",
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"\t\t\tcurrent\t\t\taccumulative\n");
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "temperature:\t\t\t%u\n",
|
||||
le32_to_cpu(general->temperature));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "temperature_m: %u\n",
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "temperature_m:\t\t\t%u\n",
|
||||
le32_to_cpu(general->temperature_m));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "burst_check: %u\n",
|
||||
le32_to_cpu(dbg->burst_check));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "burst_count: %u\n",
|
||||
le32_to_cpu(dbg->burst_count));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "sleep_time: %u\n",
|
||||
le32_to_cpu(general->sleep_time));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "slots_out: %u\n",
|
||||
le32_to_cpu(general->slots_out));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "slots_idle: %u\n",
|
||||
le32_to_cpu(general->slots_idle));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "ttl_timestamp: %u\n",
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"burst_check:\t\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(dbg->burst_check),
|
||||
accum_dbg->burst_check);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"burst_count:\t\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(dbg->burst_count),
|
||||
accum_dbg->burst_count);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"sleep_time:\t\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(general->sleep_time),
|
||||
accum_general->sleep_time);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"slots_out:\t\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(general->slots_out),
|
||||
accum_general->slots_out);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"slots_idle:\t\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(general->slots_idle),
|
||||
accum_general->slots_idle);
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "ttl_timestamp:\t\t\t%u\n",
|
||||
le32_to_cpu(general->ttl_timestamp));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "tx_on_a: %u\n",
|
||||
le32_to_cpu(div->tx_on_a));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "tx_on_b: %u\n",
|
||||
le32_to_cpu(div->tx_on_b));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "exec_time: %u\n",
|
||||
le32_to_cpu(div->exec_time));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "probe_time: %u\n",
|
||||
le32_to_cpu(div->probe_time));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "rx_enable_counter: %u\n",
|
||||
le32_to_cpu(general->rx_enable_counter));
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "tx_on_a:\t\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(div->tx_on_a), accum_div->tx_on_a);
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "tx_on_b:\t\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(div->tx_on_b), accum_div->tx_on_b);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"exec_time:\t\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(div->exec_time), accum_div->exec_time);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"probe_time:\t\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(div->probe_time), accum_div->probe_time);
|
||||
pos += scnprintf(buf + pos, bufsz - pos,
|
||||
"rx_enable_counter:\t\t%u\t\t\t%u\n",
|
||||
le32_to_cpu(general->rx_enable_counter),
|
||||
accum_general->rx_enable_counter);
|
||||
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
kfree(buf);
|
||||
return ret;
|
||||
|
@ -1615,6 +1805,29 @@ static ssize_t iwl_dbgfs_tx_power_read(struct file *file,
|
|||
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
}
|
||||
|
||||
static ssize_t iwl_dbgfs_power_save_status_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
|
||||
char buf[60];
|
||||
int pos = 0;
|
||||
const size_t bufsz = sizeof(buf);
|
||||
u32 pwrsave_status;
|
||||
|
||||
pwrsave_status = iwl_read32(priv, CSR_GP_CNTRL) &
|
||||
CSR_GP_REG_POWER_SAVE_STATUS_MSK;
|
||||
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "Power Save Status: ");
|
||||
pos += scnprintf(buf + pos, bufsz - pos, "%s\n",
|
||||
(pwrsave_status == CSR_GP_REG_NO_POWER_SAVE) ? "none" :
|
||||
(pwrsave_status == CSR_GP_REG_MAC_POWER_SAVE) ? "MAC" :
|
||||
(pwrsave_status == CSR_GP_REG_PHY_POWER_SAVE) ? "PHY" :
|
||||
"error");
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
||||
}
|
||||
|
||||
DEBUGFS_READ_WRITE_FILE_OPS(rx_statistics);
|
||||
DEBUGFS_READ_WRITE_FILE_OPS(tx_statistics);
|
||||
DEBUGFS_READ_WRITE_FILE_OPS(traffic_log);
|
||||
|
@ -1626,6 +1839,7 @@ DEBUGFS_READ_FILE_OPS(ucode_general_stats);
|
|||
DEBUGFS_READ_FILE_OPS(sensitivity);
|
||||
DEBUGFS_READ_FILE_OPS(chain_noise);
|
||||
DEBUGFS_READ_FILE_OPS(tx_power);
|
||||
DEBUGFS_READ_FILE_OPS(power_save_status);
|
||||
|
||||
/*
|
||||
* Create the debugfs files and directories
|
||||
|
@ -1673,6 +1887,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
|
|||
DEBUGFS_ADD_FILE(rx_queue, debug);
|
||||
DEBUGFS_ADD_FILE(tx_queue, debug);
|
||||
DEBUGFS_ADD_FILE(tx_power, debug);
|
||||
DEBUGFS_ADD_FILE(power_save_status, debug);
|
||||
if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) {
|
||||
DEBUGFS_ADD_FILE(ucode_rx_stats, debug);
|
||||
DEBUGFS_ADD_FILE(ucode_tx_stats, debug);
|
||||
|
@ -1725,6 +1940,7 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv)
|
|||
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_rx_queue);
|
||||
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_queue);
|
||||
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_power);
|
||||
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_power_save_status);
|
||||
if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) {
|
||||
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
|
||||
file_ucode_rx_stats);
|
||||
|
|
|
@ -85,8 +85,6 @@ extern void iwl5000_rts_tx_cmd_flag(struct ieee80211_tx_info *info,
|
|||
__le32 *tx_flags);
|
||||
extern int iwl5000_calc_rssi(struct iwl_priv *priv,
|
||||
struct iwl_rx_phy_res *rx_resp);
|
||||
extern int iwl5000_apm_init(struct iwl_priv *priv);
|
||||
extern int iwl5000_apm_reset(struct iwl_priv *priv);
|
||||
extern void iwl5000_nic_config(struct iwl_priv *priv);
|
||||
extern u16 iwl5000_eeprom_calib_version(struct iwl_priv *priv);
|
||||
extern const u8 *iwl5000_eeprom_query_addr(const struct iwl_priv *priv,
|
||||
|
@ -147,12 +145,13 @@ extern void iwl5000_temperature(struct iwl_priv *priv);
|
|||
#define DEFAULT_LONG_RETRY_LIMIT 4U
|
||||
|
||||
struct iwl_rx_mem_buffer {
|
||||
dma_addr_t real_dma_addr;
|
||||
dma_addr_t aligned_dma_addr;
|
||||
struct sk_buff *skb;
|
||||
dma_addr_t page_dma;
|
||||
struct page *page;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
#define rxb_addr(r) page_address(r->page)
|
||||
|
||||
/* defined below */
|
||||
struct iwl_device_cmd;
|
||||
|
||||
|
@ -168,7 +167,7 @@ struct iwl_cmd_meta {
|
|||
*/
|
||||
void (*callback)(struct iwl_priv *priv,
|
||||
struct iwl_device_cmd *cmd,
|
||||
struct sk_buff *skb);
|
||||
struct iwl_rx_packet *pkt);
|
||||
|
||||
/* The CMD_SIZE_HUGE flag bit indicates that the command
|
||||
* structure is stored at the end of the shared queue memory. */
|
||||
|
@ -324,6 +323,12 @@ struct iwl_channel_info {
|
|||
* queue, 2 (unused) HCCA queues, and 4 HT queues (one for each AC) */
|
||||
#define IWL_MIN_NUM_QUEUES 10
|
||||
|
||||
/*
|
||||
* uCode queue management definitions ...
|
||||
* Queue #4 is the command queue for 3945/4965/5x00/1000/6x00.
|
||||
*/
|
||||
#define IWL_CMD_QUEUE_NUM 4
|
||||
|
||||
/* Power management (not Tx power) structures */
|
||||
|
||||
enum iwl_pwr_src {
|
||||
|
@ -359,7 +364,14 @@ enum {
|
|||
CMD_WANT_SKB = (1 << 2),
|
||||
};
|
||||
|
||||
#define IWL_CMD_MAX_PAYLOAD 320
|
||||
#define DEF_CMD_PAYLOAD_SIZE 320
|
||||
|
||||
/*
|
||||
* IWL_LINK_HDR_MAX should include ieee80211_hdr, radiotap header,
|
||||
* SNAP header and alignment. It should also be big enough for 802.11
|
||||
* control frames.
|
||||
*/
|
||||
#define IWL_LINK_HDR_MAX 64
|
||||
|
||||
/**
|
||||
* struct iwl_device_cmd
|
||||
|
@ -376,7 +388,8 @@ struct iwl_device_cmd {
|
|||
u16 val16;
|
||||
u32 val32;
|
||||
struct iwl_tx_cmd tx;
|
||||
u8 payload[IWL_CMD_MAX_PAYLOAD];
|
||||
struct iwl6000_channel_switch_cmd chswitch;
|
||||
u8 payload[DEF_CMD_PAYLOAD_SIZE];
|
||||
} __attribute__ ((packed)) cmd;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
@ -385,21 +398,15 @@ struct iwl_device_cmd {
|
|||
|
||||
struct iwl_host_cmd {
|
||||
const void *data;
|
||||
struct sk_buff *reply_skb;
|
||||
unsigned long reply_page;
|
||||
void (*callback)(struct iwl_priv *priv,
|
||||
struct iwl_device_cmd *cmd,
|
||||
struct sk_buff *skb);
|
||||
struct iwl_rx_packet *pkt);
|
||||
u32 flags;
|
||||
u16 len;
|
||||
u8 id;
|
||||
};
|
||||
|
||||
/*
|
||||
* RX related structures and functions
|
||||
*/
|
||||
#define RX_FREE_BUFFERS 64
|
||||
#define RX_LOW_WATERMARK 8
|
||||
|
||||
#define SUP_RATE_11A_MAX_NUM_CHANNELS 8
|
||||
#define SUP_RATE_11B_MAX_NUM_CHANNELS 4
|
||||
#define SUP_RATE_11G_MAX_NUM_CHANNELS 12
|
||||
|
@ -563,6 +570,19 @@ struct iwl_station_entry {
|
|||
struct iwl_hw_key keyinfo;
|
||||
};
|
||||
|
||||
/*
|
||||
* iwl_station_priv: Driver's private station information
|
||||
*
|
||||
* When mac80211 creates a station it reserves some space (hw->sta_data_size)
|
||||
* in the structure for use by driver. This structure is places in that
|
||||
* space.
|
||||
*
|
||||
* At the moment use it for the station's rate scaling information.
|
||||
*/
|
||||
struct iwl_station_priv {
|
||||
struct iwl_lq_sta lq_sta;
|
||||
};
|
||||
|
||||
/* one for each uCode image (inst/data, boot/init/runtime) */
|
||||
struct fw_desc {
|
||||
void *v_addr; /* access by driver */
|
||||
|
@ -624,6 +644,10 @@ struct iwl_sensitivity_ranges {
|
|||
u16 auto_corr_max_cck_mrc;
|
||||
u16 auto_corr_min_cck;
|
||||
u16 auto_corr_min_cck_mrc;
|
||||
|
||||
u16 barker_corr_th_min;
|
||||
u16 barker_corr_th_min_mrc;
|
||||
u16 nrg_th_cca;
|
||||
};
|
||||
|
||||
|
||||
|
@ -641,7 +665,7 @@ struct iwl_sensitivity_ranges {
|
|||
* @valid_tx/rx_ant: usable antennas
|
||||
* @max_rxq_size: Max # Rx frames in Rx queue (must be power-of-2)
|
||||
* @max_rxq_log: Log-base-2 of max_rxq_size
|
||||
* @rx_buf_size: Rx buffer size
|
||||
* @rx_page_order: Rx buffer page order
|
||||
* @rx_wrt_ptr_reg: FH{39}_RSCSR_CHNL0_WPTR
|
||||
* @max_stations:
|
||||
* @bcast_sta_id:
|
||||
|
@ -664,9 +688,8 @@ struct iwl_hw_params {
|
|||
u8 valid_rx_ant;
|
||||
u16 max_rxq_size;
|
||||
u16 max_rxq_log;
|
||||
u32 rx_buf_size;
|
||||
u32 rx_page_order;
|
||||
u32 rx_wrt_ptr_reg;
|
||||
u32 max_pkt_size;
|
||||
u8 max_stations;
|
||||
u8 bcast_sta_id;
|
||||
u8 ht40_channel;
|
||||
|
@ -713,7 +736,11 @@ static inline int iwl_queue_used(const struct iwl_queue *q, int i)
|
|||
|
||||
static inline u8 get_cmd_index(struct iwl_queue *q, u32 index, int is_huge)
|
||||
{
|
||||
/* This is for scan command, the big buffer at end of command array */
|
||||
/*
|
||||
* This is for init calibration result and scan command which
|
||||
* required buffer > TFD_MAX_PAYLOAD_SIZE,
|
||||
* the big buffer at end of command array
|
||||
*/
|
||||
if (is_huge)
|
||||
return q->n_window; /* must be power of 2 */
|
||||
|
||||
|
@ -845,6 +872,10 @@ struct iwl_sensitivity_data {
|
|||
s32 nrg_auto_corr_silence_diff;
|
||||
u32 num_in_cck_no_fa;
|
||||
u32 nrg_th_ofdm;
|
||||
|
||||
u16 barker_corr_th_min;
|
||||
u16 barker_corr_th_min_mrc;
|
||||
u16 nrg_th_cca;
|
||||
};
|
||||
|
||||
/* Chain noise (differential Rx gain) calib data */
|
||||
|
@ -961,8 +992,6 @@ struct traffic_stats {
|
|||
};
|
||||
#endif
|
||||
|
||||
#define IWL_MAX_NUM_QUEUES 20 /* FIXME: do dynamic allocation */
|
||||
|
||||
struct iwl_priv {
|
||||
|
||||
/* ieee device used by generic ieee processing code */
|
||||
|
@ -976,7 +1005,7 @@ struct iwl_priv {
|
|||
int frames_count;
|
||||
|
||||
enum ieee80211_band band;
|
||||
int alloc_rxb_skb;
|
||||
int alloc_rxb_page;
|
||||
|
||||
void (*rx_handlers[REPLY_MAX])(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb);
|
||||
|
@ -1081,7 +1110,6 @@ struct iwl_priv {
|
|||
u8 last_phy_res[100];
|
||||
|
||||
/* Rate scaling data */
|
||||
s8 data_retry_limit;
|
||||
u8 retry_rate;
|
||||
|
||||
wait_queue_head_t wait_command_queue;
|
||||
|
@ -1090,7 +1118,7 @@ struct iwl_priv {
|
|||
|
||||
/* Rx and Tx DMA processing queues */
|
||||
struct iwl_rx_queue rxq;
|
||||
struct iwl_tx_queue txq[IWL_MAX_NUM_QUEUES];
|
||||
struct iwl_tx_queue *txq;
|
||||
unsigned long txq_ctx_active_msk;
|
||||
struct iwl_dma_ptr kw; /* keep warm address */
|
||||
struct iwl_dma_ptr scd_bc_tbls;
|
||||
|
@ -1113,7 +1141,9 @@ struct iwl_priv {
|
|||
struct iwl_tt_mgmt thermal_throttle;
|
||||
|
||||
struct iwl_notif_statistics statistics;
|
||||
unsigned long last_statistics_time;
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
struct iwl_notif_statistics accum_statistics;
|
||||
#endif
|
||||
|
||||
/* context information */
|
||||
u16 rates_mask;
|
||||
|
|
|
@ -358,6 +358,14 @@ static int iwl_init_otp_access(struct iwl_priv *priv)
|
|||
udelay(5);
|
||||
iwl_clear_bits_prph(priv, APMG_PS_CTRL_REG,
|
||||
APMG_PS_CTRL_VAL_RESET_REQ);
|
||||
|
||||
/*
|
||||
* CSR auto clock gate disable bit -
|
||||
* this is only applicable for HW with OTP shadow RAM
|
||||
*/
|
||||
if (priv->cfg->shadow_ram_support)
|
||||
iwl_set_bit(priv, CSR_DBG_LINK_PWR_MGMT_REG,
|
||||
CSR_RESET_LINK_PWR_MGMT_DISABLED);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -261,9 +261,12 @@ struct iwl_eeprom_enhanced_txpwr {
|
|||
/* 1000 Specific */
|
||||
#define EEPROM_1000_EEPROM_VERSION (0x15C)
|
||||
|
||||
/* 60x0 Specific */
|
||||
/* 6x00 Specific */
|
||||
#define EEPROM_6000_EEPROM_VERSION (0x434)
|
||||
|
||||
/* 6x50 Specific */
|
||||
#define EEPROM_6050_EEPROM_VERSION (0x532)
|
||||
|
||||
/* OTP */
|
||||
/* lower blocks contain EEPROM image and calibration data */
|
||||
#define OTP_LOW_IMAGE_SIZE (2 * 512 * sizeof(u16)) /* 2 KB */
|
||||
|
|
|
@ -92,6 +92,8 @@ const char *get_cmd_string(u8 cmd)
|
|||
IWL_CMD(CALIBRATION_RES_NOTIFICATION);
|
||||
IWL_CMD(CALIBRATION_COMPLETE_NOTIFICATION);
|
||||
IWL_CMD(REPLY_TX_POWER_DBM_CMD);
|
||||
IWL_CMD(TEMPERATURE_NOTIFICATION);
|
||||
IWL_CMD(TX_ANT_CONFIGURATION_CMD);
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
|
||||
|
@ -103,17 +105,8 @@ EXPORT_SYMBOL(get_cmd_string);
|
|||
|
||||
static void iwl_generic_cmd_callback(struct iwl_priv *priv,
|
||||
struct iwl_device_cmd *cmd,
|
||||
struct sk_buff *skb)
|
||||
struct iwl_rx_packet *pkt)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = NULL;
|
||||
|
||||
if (!skb) {
|
||||
IWL_ERR(priv, "Error: Response NULL in %s.\n",
|
||||
get_cmd_string(cmd->hdr.cmd));
|
||||
return;
|
||||
}
|
||||
|
||||
pkt = (struct iwl_rx_packet *)skb->data;
|
||||
if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
|
||||
IWL_ERR(priv, "Bad return from %s (0x%08X)\n",
|
||||
get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
|
||||
|
@ -215,7 +208,7 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
|
|||
ret = -EIO;
|
||||
goto fail;
|
||||
}
|
||||
if ((cmd->flags & CMD_WANT_SKB) && !cmd->reply_skb) {
|
||||
if ((cmd->flags & CMD_WANT_SKB) && !cmd->reply_page) {
|
||||
IWL_ERR(priv, "Error: Response NULL in '%s'\n",
|
||||
get_cmd_string(cmd->id));
|
||||
ret = -EIO;
|
||||
|
@ -237,9 +230,9 @@ cancel:
|
|||
~CMD_WANT_SKB;
|
||||
}
|
||||
fail:
|
||||
if (cmd->reply_skb) {
|
||||
dev_kfree_skb_any(cmd->reply_skb);
|
||||
cmd->reply_skb = NULL;
|
||||
if (cmd->reply_page) {
|
||||
free_pages(cmd->reply_page, priv->hw_params.rx_page_order);
|
||||
cmd->reply_page = 0;
|
||||
}
|
||||
out:
|
||||
clear_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status);
|
||||
|
@ -272,7 +265,7 @@ int iwl_send_cmd_pdu_async(struct iwl_priv *priv,
|
|||
u8 id, u16 len, const void *data,
|
||||
void (*callback)(struct iwl_priv *priv,
|
||||
struct iwl_device_cmd *cmd,
|
||||
struct sk_buff *skb))
|
||||
struct iwl_rx_packet *pkt))
|
||||
{
|
||||
struct iwl_host_cmd cmd = {
|
||||
.id = id,
|
||||
|
|
|
@ -66,7 +66,7 @@ MODULE_PARM_DESC(no_sleep_autoadjust,
|
|||
|
||||
struct iwl_power_vec_entry {
|
||||
struct iwl_powertable_cmd cmd;
|
||||
u8 no_dtim;
|
||||
u8 no_dtim; /* number of skip dtim */
|
||||
};
|
||||
|
||||
#define IWL_DTIM_RANGE_0_MAX 2
|
||||
|
@ -83,8 +83,9 @@ struct iwl_power_vec_entry {
|
|||
cpu_to_le32(X4)}
|
||||
/* default power management (not Tx power) table values */
|
||||
/* for DTIM period 0 through IWL_DTIM_RANGE_0_MAX */
|
||||
/* DTIM 0 - 2 */
|
||||
static const struct iwl_power_vec_entry range_0[IWL_POWER_NUM] = {
|
||||
{{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0},
|
||||
{{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 1, 2, 2, 0xFF)}, 0},
|
||||
{{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0},
|
||||
{{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 2, 2, 2, 0xFF)}, 0},
|
||||
{{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 2, 4, 4, 0xFF)}, 1},
|
||||
|
@ -93,15 +94,17 @@ static const struct iwl_power_vec_entry range_0[IWL_POWER_NUM] = {
|
|||
|
||||
|
||||
/* for DTIM period IWL_DTIM_RANGE_0_MAX + 1 through IWL_DTIM_RANGE_1_MAX */
|
||||
/* DTIM 3 - 10 */
|
||||
static const struct iwl_power_vec_entry range_1[IWL_POWER_NUM] = {
|
||||
{{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 4)}, 0},
|
||||
{{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 3, 4, 7)}, 0},
|
||||
{{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 4, 6, 7, 9)}, 0},
|
||||
{{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 4, 6, 9, 10)}, 1},
|
||||
{{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(2, 4, 7, 10, 10)}, 2}
|
||||
{{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(2, 4, 6, 10, 10)}, 2}
|
||||
};
|
||||
|
||||
/* for DTIM period > IWL_DTIM_RANGE_1_MAX */
|
||||
/* DTIM 11 - */
|
||||
static const struct iwl_power_vec_entry range_2[IWL_POWER_NUM] = {
|
||||
{{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 0xFF)}, 0},
|
||||
{{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(2, 4, 6, 7, 0xFF)}, 0},
|
||||
|
@ -115,13 +118,15 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv,
|
|||
enum iwl_power_level lvl, int period)
|
||||
{
|
||||
const struct iwl_power_vec_entry *table;
|
||||
int max_sleep, i;
|
||||
bool skip;
|
||||
int max_sleep[IWL_POWER_VEC_SIZE] = { 0 };
|
||||
int i;
|
||||
u8 skip;
|
||||
u32 slp_itrvl;
|
||||
|
||||
table = range_2;
|
||||
if (period < IWL_DTIM_RANGE_1_MAX)
|
||||
if (period <= IWL_DTIM_RANGE_1_MAX)
|
||||
table = range_1;
|
||||
if (period < IWL_DTIM_RANGE_0_MAX)
|
||||
if (period <= IWL_DTIM_RANGE_0_MAX)
|
||||
table = range_0;
|
||||
|
||||
BUG_ON(lvl < 0 || lvl >= IWL_POWER_NUM);
|
||||
|
@ -129,34 +134,60 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv,
|
|||
*cmd = table[lvl].cmd;
|
||||
|
||||
if (period == 0) {
|
||||
skip = false;
|
||||
skip = 0;
|
||||
period = 1;
|
||||
for (i = 0; i < IWL_POWER_VEC_SIZE; i++)
|
||||
max_sleep[i] = 1;
|
||||
|
||||
} else {
|
||||
skip = !!table[lvl].no_dtim;
|
||||
skip = table[lvl].no_dtim;
|
||||
for (i = 0; i < IWL_POWER_VEC_SIZE; i++)
|
||||
max_sleep[i] = le32_to_cpu(cmd->sleep_interval[i]);
|
||||
max_sleep[IWL_POWER_VEC_SIZE - 1] = skip + 1;
|
||||
}
|
||||
|
||||
if (skip) {
|
||||
__le32 slp_itrvl = cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1];
|
||||
max_sleep = le32_to_cpu(slp_itrvl);
|
||||
if (max_sleep == 0xFF)
|
||||
max_sleep = period * (skip + 1);
|
||||
else if (max_sleep > period)
|
||||
max_sleep = (le32_to_cpu(slp_itrvl) / period) * period;
|
||||
slp_itrvl = le32_to_cpu(cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1]);
|
||||
/* figure out the listen interval based on dtim period and skip */
|
||||
if (slp_itrvl == 0xFF)
|
||||
cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1] =
|
||||
cpu_to_le32(period * (skip + 1));
|
||||
|
||||
slp_itrvl = le32_to_cpu(cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1]);
|
||||
if (slp_itrvl > period)
|
||||
cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1] =
|
||||
cpu_to_le32((slp_itrvl / period) * period);
|
||||
|
||||
if (skip)
|
||||
cmd->flags |= IWL_POWER_SLEEP_OVER_DTIM_MSK;
|
||||
} else {
|
||||
max_sleep = period;
|
||||
else
|
||||
cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK;
|
||||
}
|
||||
|
||||
for (i = 0; i < IWL_POWER_VEC_SIZE; i++)
|
||||
if (le32_to_cpu(cmd->sleep_interval[i]) > max_sleep)
|
||||
cmd->sleep_interval[i] = cpu_to_le32(max_sleep);
|
||||
slp_itrvl = le32_to_cpu(cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1]);
|
||||
if (slp_itrvl > IWL_CONN_MAX_LISTEN_INTERVAL)
|
||||
cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1] =
|
||||
cpu_to_le32(IWL_CONN_MAX_LISTEN_INTERVAL);
|
||||
|
||||
/* enforce max sleep interval */
|
||||
for (i = IWL_POWER_VEC_SIZE - 1; i >= 0 ; i--) {
|
||||
if (le32_to_cpu(cmd->sleep_interval[i]) >
|
||||
(max_sleep[i] * period))
|
||||
cmd->sleep_interval[i] =
|
||||
cpu_to_le32(max_sleep[i] * period);
|
||||
if (i != (IWL_POWER_VEC_SIZE - 1)) {
|
||||
if (le32_to_cpu(cmd->sleep_interval[i]) >
|
||||
le32_to_cpu(cmd->sleep_interval[i+1]))
|
||||
cmd->sleep_interval[i] =
|
||||
cmd->sleep_interval[i+1];
|
||||
}
|
||||
}
|
||||
|
||||
if (priv->power_data.pci_pm)
|
||||
cmd->flags |= IWL_POWER_PCI_PM_MSK;
|
||||
else
|
||||
cmd->flags &= ~IWL_POWER_PCI_PM_MSK;
|
||||
|
||||
IWL_DEBUG_POWER(priv, "numSkipDtim = %u, dtimPeriod = %d\n",
|
||||
skip, period);
|
||||
IWL_DEBUG_POWER(priv, "Sleep command for index %d\n", lvl + 1);
|
||||
}
|
||||
|
||||
|
@ -862,9 +893,7 @@ void iwl_tt_initialize(struct iwl_priv *priv)
|
|||
INIT_WORK(&priv->ct_enter, iwl_bg_ct_enter);
|
||||
INIT_WORK(&priv->ct_exit, iwl_bg_ct_exit);
|
||||
|
||||
switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) {
|
||||
case CSR_HW_REV_TYPE_6x00:
|
||||
case CSR_HW_REV_TYPE_6x50:
|
||||
if (priv->cfg->adv_thermal_throttle) {
|
||||
IWL_DEBUG_POWER(priv, "Advanced Thermal Throttling\n");
|
||||
tt->restriction = kzalloc(sizeof(struct iwl_tt_restriction) *
|
||||
IWL_TI_STATE_MAX, GFP_KERNEL);
|
||||
|
@ -897,11 +926,9 @@ void iwl_tt_initialize(struct iwl_priv *priv)
|
|||
&restriction_range[0], size);
|
||||
priv->thermal_throttle.advanced_tt = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
} else {
|
||||
IWL_DEBUG_POWER(priv, "Legacy Thermal Throttling\n");
|
||||
priv->thermal_throttle.advanced_tt = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_tt_initialize);
|
||||
|
|
|
@ -200,7 +200,7 @@ int iwl_rx_queue_restock(struct iwl_priv *priv)
|
|||
list_del(element);
|
||||
|
||||
/* Point to Rx buffer via next RBD in circular buffer */
|
||||
rxq->bd[rxq->write] = iwl_dma_addr2rbd_ptr(priv, rxb->aligned_dma_addr);
|
||||
rxq->bd[rxq->write] = iwl_dma_addr2rbd_ptr(priv, rxb->page_dma);
|
||||
rxq->queue[rxq->write] = rxb;
|
||||
rxq->write = (rxq->write + 1) & RX_QUEUE_MASK;
|
||||
rxq->free_count--;
|
||||
|
@ -239,8 +239,9 @@ void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority)
|
|||
struct iwl_rx_queue *rxq = &priv->rxq;
|
||||
struct list_head *element;
|
||||
struct iwl_rx_mem_buffer *rxb;
|
||||
struct sk_buff *skb;
|
||||
struct page *page;
|
||||
unsigned long flags;
|
||||
gfp_t gfp_mask = priority;
|
||||
|
||||
while (1) {
|
||||
spin_lock_irqsave(&rxq->lock, flags);
|
||||
|
@ -251,30 +252,35 @@ void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority)
|
|||
spin_unlock_irqrestore(&rxq->lock, flags);
|
||||
|
||||
if (rxq->free_count > RX_LOW_WATERMARK)
|
||||
priority |= __GFP_NOWARN;
|
||||
/* Alloc a new receive buffer */
|
||||
skb = alloc_skb(priv->hw_params.rx_buf_size + 256,
|
||||
priority);
|
||||
gfp_mask |= __GFP_NOWARN;
|
||||
|
||||
if (!skb) {
|
||||
if (priv->hw_params.rx_page_order > 0)
|
||||
gfp_mask |= __GFP_COMP;
|
||||
|
||||
/* Alloc a new receive buffer */
|
||||
page = alloc_pages(gfp_mask, priv->hw_params.rx_page_order);
|
||||
if (!page) {
|
||||
if (net_ratelimit())
|
||||
IWL_DEBUG_INFO(priv, "Failed to allocate SKB buffer.\n");
|
||||
IWL_DEBUG_INFO(priv, "alloc_pages failed, "
|
||||
"order: %d\n",
|
||||
priv->hw_params.rx_page_order);
|
||||
|
||||
if ((rxq->free_count <= RX_LOW_WATERMARK) &&
|
||||
net_ratelimit())
|
||||
IWL_CRIT(priv, "Failed to allocate SKB buffer with %s. Only %u free buffers remaining.\n",
|
||||
IWL_CRIT(priv, "Failed to alloc_pages with %s. Only %u free buffers remaining.\n",
|
||||
priority == GFP_ATOMIC ? "GFP_ATOMIC" : "GFP_KERNEL",
|
||||
rxq->free_count);
|
||||
/* We don't reschedule replenish work here -- we will
|
||||
* call the restock method and if it still needs
|
||||
* more buffers it will schedule replenish */
|
||||
break;
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&rxq->lock, flags);
|
||||
|
||||
if (list_empty(&rxq->rx_used)) {
|
||||
spin_unlock_irqrestore(&rxq->lock, flags);
|
||||
dev_kfree_skb_any(skb);
|
||||
__free_pages(page, priv->hw_params.rx_page_order);
|
||||
return;
|
||||
}
|
||||
element = rxq->rx_used.next;
|
||||
|
@ -283,24 +289,21 @@ void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority)
|
|||
|
||||
spin_unlock_irqrestore(&rxq->lock, flags);
|
||||
|
||||
rxb->skb = skb;
|
||||
/* Get physical address of RB/SKB */
|
||||
rxb->real_dma_addr = pci_map_single(
|
||||
priv->pci_dev,
|
||||
rxb->skb->data,
|
||||
priv->hw_params.rx_buf_size + 256,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
rxb->page = page;
|
||||
/* Get physical address of the RB */
|
||||
rxb->page_dma = pci_map_page(priv->pci_dev, page, 0,
|
||||
PAGE_SIZE << priv->hw_params.rx_page_order,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
/* dma address must be no more than 36 bits */
|
||||
BUG_ON(rxb->real_dma_addr & ~DMA_BIT_MASK(36));
|
||||
BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36));
|
||||
/* and also 256 byte aligned! */
|
||||
rxb->aligned_dma_addr = ALIGN(rxb->real_dma_addr, 256);
|
||||
skb_reserve(rxb->skb, rxb->aligned_dma_addr - rxb->real_dma_addr);
|
||||
BUG_ON(rxb->page_dma & DMA_BIT_MASK(8));
|
||||
|
||||
spin_lock_irqsave(&rxq->lock, flags);
|
||||
|
||||
list_add_tail(&rxb->list, &rxq->rx_free);
|
||||
rxq->free_count++;
|
||||
priv->alloc_rxb_skb++;
|
||||
priv->alloc_rxb_page++;
|
||||
|
||||
spin_unlock_irqrestore(&rxq->lock, flags);
|
||||
}
|
||||
|
@ -336,12 +339,14 @@ void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
|
|||
{
|
||||
int i;
|
||||
for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) {
|
||||
if (rxq->pool[i].skb != NULL) {
|
||||
pci_unmap_single(priv->pci_dev,
|
||||
rxq->pool[i].real_dma_addr,
|
||||
priv->hw_params.rx_buf_size + 256,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
dev_kfree_skb(rxq->pool[i].skb);
|
||||
if (rxq->pool[i].page != NULL) {
|
||||
pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma,
|
||||
PAGE_SIZE << priv->hw_params.rx_page_order,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
__free_pages(rxq->pool[i].page,
|
||||
priv->hw_params.rx_page_order);
|
||||
rxq->pool[i].page = NULL;
|
||||
priv->alloc_rxb_page--;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -405,14 +410,14 @@ void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
|
|||
for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) {
|
||||
/* In the reset function, these buffers may have been allocated
|
||||
* to an SKB, so we need to unmap and free potential storage */
|
||||
if (rxq->pool[i].skb != NULL) {
|
||||
pci_unmap_single(priv->pci_dev,
|
||||
rxq->pool[i].real_dma_addr,
|
||||
priv->hw_params.rx_buf_size + 256,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
priv->alloc_rxb_skb--;
|
||||
dev_kfree_skb(rxq->pool[i].skb);
|
||||
rxq->pool[i].skb = NULL;
|
||||
if (rxq->pool[i].page != NULL) {
|
||||
pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma,
|
||||
PAGE_SIZE << priv->hw_params.rx_page_order,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
priv->alloc_rxb_page--;
|
||||
__free_pages(rxq->pool[i].page,
|
||||
priv->hw_params.rx_page_order);
|
||||
rxq->pool[i].page = NULL;
|
||||
}
|
||||
list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
|
||||
}
|
||||
|
@ -491,7 +496,7 @@ void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
|
|||
struct iwl_rx_mem_buffer *rxb)
|
||||
|
||||
{
|
||||
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_missed_beacon_notif *missed_beacon;
|
||||
|
||||
missed_beacon = &pkt->u.missed_beacon;
|
||||
|
@ -548,13 +553,51 @@ static void iwl_rx_calc_noise(struct iwl_priv *priv)
|
|||
priv->last_rx_noise);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
/*
|
||||
* based on the assumption of all statistics counter are in DWORD
|
||||
* FIXME: This function is for debugging, do not deal with
|
||||
* the case of counters roll-over.
|
||||
*/
|
||||
static void iwl_accumulative_statistics(struct iwl_priv *priv,
|
||||
__le32 *stats)
|
||||
{
|
||||
int i;
|
||||
__le32 *prev_stats;
|
||||
u32 *accum_stats;
|
||||
|
||||
prev_stats = (__le32 *)&priv->statistics;
|
||||
accum_stats = (u32 *)&priv->accum_statistics;
|
||||
|
||||
for (i = sizeof(__le32); i < sizeof(struct iwl_notif_statistics);
|
||||
i += sizeof(__le32), stats++, prev_stats++, accum_stats++)
|
||||
if (le32_to_cpu(*stats) > le32_to_cpu(*prev_stats))
|
||||
*accum_stats += (le32_to_cpu(*stats) -
|
||||
le32_to_cpu(*prev_stats));
|
||||
|
||||
/* reset accumulative statistics for "no-counter" type statistics */
|
||||
priv->accum_statistics.general.temperature =
|
||||
priv->statistics.general.temperature;
|
||||
priv->accum_statistics.general.temperature_m =
|
||||
priv->statistics.general.temperature_m;
|
||||
priv->accum_statistics.general.ttl_timestamp =
|
||||
priv->statistics.general.ttl_timestamp;
|
||||
priv->accum_statistics.tx.tx_power.ant_a =
|
||||
priv->statistics.tx.tx_power.ant_a;
|
||||
priv->accum_statistics.tx.tx_power.ant_b =
|
||||
priv->statistics.tx.tx_power.ant_b;
|
||||
priv->accum_statistics.tx.tx_power.ant_c =
|
||||
priv->statistics.tx.tx_power.ant_c;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define REG_RECALIB_PERIOD (60)
|
||||
|
||||
void iwl_rx_statistics(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb)
|
||||
{
|
||||
int change;
|
||||
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
|
||||
IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n",
|
||||
(int)sizeof(priv->statistics),
|
||||
|
@ -566,6 +609,9 @@ void iwl_rx_statistics(struct iwl_priv *priv,
|
|||
STATISTICS_REPLY_FLG_HT40_MODE_MSK) !=
|
||||
(pkt->u.stats.flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK)));
|
||||
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats);
|
||||
#endif
|
||||
memcpy(&priv->statistics, &pkt->u.stats, sizeof(priv->statistics));
|
||||
|
||||
set_bit(STATUS_STATISTICS, &priv->status);
|
||||
|
@ -582,9 +628,6 @@ void iwl_rx_statistics(struct iwl_priv *priv,
|
|||
iwl_rx_calc_noise(priv);
|
||||
queue_work(priv->workqueue, &priv->run_time_calib_work);
|
||||
}
|
||||
|
||||
iwl_leds_background(priv);
|
||||
|
||||
if (priv->cfg->ops->lib->temp_ops.temperature && change)
|
||||
priv->cfg->ops->lib->temp_ops.temperature(priv);
|
||||
}
|
||||
|
@ -878,6 +921,10 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,
|
|||
struct iwl_rx_mem_buffer *rxb,
|
||||
struct ieee80211_rx_status *stats)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
int ret = 0;
|
||||
__le16 fc = hdr->frame_control;
|
||||
|
||||
/* We only process data packets if the interface is open */
|
||||
if (unlikely(!priv->is_open)) {
|
||||
IWL_DEBUG_DROP_LIMIT(priv,
|
||||
|
@ -890,15 +937,43 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,
|
|||
iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats))
|
||||
return;
|
||||
|
||||
/* Resize SKB from mac header to end of packet */
|
||||
skb_reserve(rxb->skb, (void *)hdr - (void *)rxb->skb->data);
|
||||
skb_put(rxb->skb, len);
|
||||
skb = alloc_skb(IWL_LINK_HDR_MAX, GFP_ATOMIC);
|
||||
if (!skb) {
|
||||
IWL_ERR(priv, "alloc_skb failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
iwl_update_stats(priv, false, hdr->frame_control, len);
|
||||
memcpy(IEEE80211_SKB_RXCB(rxb->skb), stats, sizeof(*stats));
|
||||
ieee80211_rx_irqsafe(priv->hw, rxb->skb);
|
||||
priv->alloc_rxb_skb--;
|
||||
rxb->skb = NULL;
|
||||
skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len);
|
||||
|
||||
/* mac80211 currently doesn't support paged SKB. Convert it to
|
||||
* linear SKB for management frame and data frame requires
|
||||
* software decryption or software defragementation. */
|
||||
if (ieee80211_is_mgmt(fc) ||
|
||||
ieee80211_has_protected(fc) ||
|
||||
ieee80211_has_morefrags(fc) ||
|
||||
le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG)
|
||||
ret = skb_linearize(skb);
|
||||
else
|
||||
ret = __pskb_pull_tail(skb, min_t(u16, IWL_LINK_HDR_MAX, len)) ?
|
||||
0 : -ENOMEM;
|
||||
|
||||
if (ret) {
|
||||
kfree_skb(skb);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX: We cannot touch the page and its virtual memory (hdr) after
|
||||
* here. It might have already been freed by the above skb change.
|
||||
*/
|
||||
|
||||
iwl_update_stats(priv, false, fc, len);
|
||||
memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
|
||||
|
||||
ieee80211_rx(priv->hw, skb);
|
||||
out:
|
||||
priv->alloc_rxb_page--;
|
||||
rxb->page = NULL;
|
||||
}
|
||||
|
||||
/* This is necessary only for a number of statistics, see the caller. */
|
||||
|
@ -926,7 +1001,7 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
|
|||
{
|
||||
struct ieee80211_hdr *header;
|
||||
struct ieee80211_rx_status rx_status;
|
||||
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_rx_phy_res *phy_res;
|
||||
__le32 rx_pkt_status;
|
||||
struct iwl4965_rx_mpdu_res_start *amsdu;
|
||||
|
@ -1087,7 +1162,7 @@ EXPORT_SYMBOL(iwl_rx_reply_rx);
|
|||
void iwl_rx_reply_rx_phy(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
priv->last_phy_res[0] = 1;
|
||||
memcpy(&priv->last_phy_res[1], &(pkt->u.raw[0]),
|
||||
sizeof(struct iwl_rx_phy_res));
|
||||
|
|
|
@ -111,7 +111,7 @@ EXPORT_SYMBOL(iwl_scan_cancel_timeout);
|
|||
static int iwl_send_scan_abort(struct iwl_priv *priv)
|
||||
{
|
||||
int ret = 0;
|
||||
struct iwl_rx_packet *res;
|
||||
struct iwl_rx_packet *pkt;
|
||||
struct iwl_host_cmd cmd = {
|
||||
.id = REPLY_SCAN_ABORT_CMD,
|
||||
.flags = CMD_WANT_SKB,
|
||||
|
@ -131,21 +131,21 @@ static int iwl_send_scan_abort(struct iwl_priv *priv)
|
|||
return ret;
|
||||
}
|
||||
|
||||
res = (struct iwl_rx_packet *)cmd.reply_skb->data;
|
||||
if (res->u.status != CAN_ABORT_STATUS) {
|
||||
pkt = (struct iwl_rx_packet *)cmd.reply_page;
|
||||
if (pkt->u.status != CAN_ABORT_STATUS) {
|
||||
/* The scan abort will return 1 for success or
|
||||
* 2 for "failure". A failure condition can be
|
||||
* due to simply not being in an active scan which
|
||||
* can occur if we send the scan abort before we
|
||||
* the microcode has notified us that a scan is
|
||||
* completed. */
|
||||
IWL_DEBUG_INFO(priv, "SCAN_ABORT returned %d.\n", res->u.status);
|
||||
IWL_DEBUG_INFO(priv, "SCAN_ABORT returned %d.\n", pkt->u.status);
|
||||
clear_bit(STATUS_SCAN_ABORTING, &priv->status);
|
||||
clear_bit(STATUS_SCAN_HW, &priv->status);
|
||||
}
|
||||
|
||||
priv->alloc_rxb_skb--;
|
||||
dev_kfree_skb_any(cmd.reply_skb);
|
||||
priv->alloc_rxb_page--;
|
||||
free_pages(cmd.reply_page, priv->hw_params.rx_page_order);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -155,7 +155,7 @@ static void iwl_rx_reply_scan(struct iwl_priv *priv,
|
|||
struct iwl_rx_mem_buffer *rxb)
|
||||
{
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_scanreq_notification *notif =
|
||||
(struct iwl_scanreq_notification *)pkt->u.raw;
|
||||
|
||||
|
@ -167,7 +167,7 @@ static void iwl_rx_reply_scan(struct iwl_priv *priv,
|
|||
static void iwl_rx_scan_start_notif(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_scanstart_notification *notif =
|
||||
(struct iwl_scanstart_notification *)pkt->u.raw;
|
||||
priv->scan_start_tsf = le32_to_cpu(notif->tsf_low);
|
||||
|
@ -186,7 +186,7 @@ static void iwl_rx_scan_results_notif(struct iwl_priv *priv,
|
|||
struct iwl_rx_mem_buffer *rxb)
|
||||
{
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_scanresults_notification *notif =
|
||||
(struct iwl_scanresults_notification *)pkt->u.raw;
|
||||
|
||||
|
@ -213,7 +213,7 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv,
|
|||
struct iwl_rx_mem_buffer *rxb)
|
||||
{
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_scancomplete_notification *scan_notif = (void *)pkt->u.raw;
|
||||
|
||||
IWL_DEBUG_SCAN(priv, "Scan complete: %d channels (TSF 0x%08X:%08X) - %d\n",
|
||||
|
|
|
@ -177,7 +177,7 @@ static int iwl_get_measurement(struct iwl_priv *priv,
|
|||
static void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_spectrum_notification *report = &(pkt->u.spectrum_notif);
|
||||
|
||||
if (!report->state) {
|
||||
|
|
|
@ -99,32 +99,25 @@ static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id)
|
|||
|
||||
static void iwl_add_sta_callback(struct iwl_priv *priv,
|
||||
struct iwl_device_cmd *cmd,
|
||||
struct sk_buff *skb)
|
||||
struct iwl_rx_packet *pkt)
|
||||
{
|
||||
struct iwl_rx_packet *res = NULL;
|
||||
struct iwl_addsta_cmd *addsta =
|
||||
(struct iwl_addsta_cmd *)cmd->cmd.payload;
|
||||
u8 sta_id = addsta->sta.sta_id;
|
||||
|
||||
if (!skb) {
|
||||
IWL_ERR(priv, "Error: Response NULL in REPLY_ADD_STA.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
res = (struct iwl_rx_packet *)skb->data;
|
||||
if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
|
||||
if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
|
||||
IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n",
|
||||
res->hdr.flags);
|
||||
pkt->hdr.flags);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (res->u.add_sta.status) {
|
||||
switch (pkt->u.add_sta.status) {
|
||||
case ADD_STA_SUCCESS_MSK:
|
||||
iwl_sta_ucode_activate(priv, sta_id);
|
||||
/* fall through */
|
||||
default:
|
||||
IWL_DEBUG_HC(priv, "Received REPLY_ADD_STA:(0x%08X)\n",
|
||||
res->u.add_sta.status);
|
||||
pkt->u.add_sta.status);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -132,7 +125,7 @@ static void iwl_add_sta_callback(struct iwl_priv *priv,
|
|||
int iwl_send_add_sta(struct iwl_priv *priv,
|
||||
struct iwl_addsta_cmd *sta, u8 flags)
|
||||
{
|
||||
struct iwl_rx_packet *res = NULL;
|
||||
struct iwl_rx_packet *pkt = NULL;
|
||||
int ret = 0;
|
||||
u8 data[sizeof(*sta)];
|
||||
struct iwl_host_cmd cmd = {
|
||||
|
@ -152,15 +145,15 @@ int iwl_send_add_sta(struct iwl_priv *priv,
|
|||
if (ret || (flags & CMD_ASYNC))
|
||||
return ret;
|
||||
|
||||
res = (struct iwl_rx_packet *)cmd.reply_skb->data;
|
||||
if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
|
||||
pkt = (struct iwl_rx_packet *)cmd.reply_page;
|
||||
if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
|
||||
IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n",
|
||||
res->hdr.flags);
|
||||
pkt->hdr.flags);
|
||||
ret = -EIO;
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
switch (res->u.add_sta.status) {
|
||||
switch (pkt->u.add_sta.status) {
|
||||
case ADD_STA_SUCCESS_MSK:
|
||||
iwl_sta_ucode_activate(priv, sta->sta.sta_id);
|
||||
IWL_DEBUG_INFO(priv, "REPLY_ADD_STA PASSED\n");
|
||||
|
@ -172,8 +165,8 @@ int iwl_send_add_sta(struct iwl_priv *priv,
|
|||
}
|
||||
}
|
||||
|
||||
priv->alloc_rxb_skb--;
|
||||
dev_kfree_skb_any(cmd.reply_skb);
|
||||
priv->alloc_rxb_page--;
|
||||
free_pages(cmd.reply_page, priv->hw_params.rx_page_order);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -324,26 +317,19 @@ static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, const char *addr)
|
|||
|
||||
static void iwl_remove_sta_callback(struct iwl_priv *priv,
|
||||
struct iwl_device_cmd *cmd,
|
||||
struct sk_buff *skb)
|
||||
struct iwl_rx_packet *pkt)
|
||||
{
|
||||
struct iwl_rx_packet *res = NULL;
|
||||
struct iwl_rem_sta_cmd *rm_sta =
|
||||
(struct iwl_rem_sta_cmd *)cmd->cmd.payload;
|
||||
(struct iwl_rem_sta_cmd *)cmd->cmd.payload;
|
||||
const char *addr = rm_sta->addr;
|
||||
|
||||
if (!skb) {
|
||||
IWL_ERR(priv, "Error: Response NULL in REPLY_REMOVE_STA.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
res = (struct iwl_rx_packet *)skb->data;
|
||||
if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
|
||||
if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
|
||||
IWL_ERR(priv, "Bad return from REPLY_REMOVE_STA (0x%08X)\n",
|
||||
res->hdr.flags);
|
||||
pkt->hdr.flags);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (res->u.rem_sta.status) {
|
||||
switch (pkt->u.rem_sta.status) {
|
||||
case REM_STA_SUCCESS_MSK:
|
||||
iwl_sta_ucode_deactivate(priv, addr);
|
||||
break;
|
||||
|
@ -356,7 +342,7 @@ static void iwl_remove_sta_callback(struct iwl_priv *priv,
|
|||
static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr,
|
||||
u8 flags)
|
||||
{
|
||||
struct iwl_rx_packet *res = NULL;
|
||||
struct iwl_rx_packet *pkt;
|
||||
int ret;
|
||||
|
||||
struct iwl_rem_sta_cmd rm_sta_cmd;
|
||||
|
@ -381,15 +367,15 @@ static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr,
|
|||
if (ret || (flags & CMD_ASYNC))
|
||||
return ret;
|
||||
|
||||
res = (struct iwl_rx_packet *)cmd.reply_skb->data;
|
||||
if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
|
||||
pkt = (struct iwl_rx_packet *)cmd.reply_page;
|
||||
if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
|
||||
IWL_ERR(priv, "Bad return from REPLY_REMOVE_STA (0x%08X)\n",
|
||||
res->hdr.flags);
|
||||
pkt->hdr.flags);
|
||||
ret = -EIO;
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
switch (res->u.rem_sta.status) {
|
||||
switch (pkt->u.rem_sta.status) {
|
||||
case REM_STA_SUCCESS_MSK:
|
||||
iwl_sta_ucode_deactivate(priv, addr);
|
||||
IWL_DEBUG_ASSOC(priv, "REPLY_REMOVE_STA PASSED\n");
|
||||
|
@ -401,8 +387,8 @@ static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr,
|
|||
}
|
||||
}
|
||||
|
||||
priv->alloc_rxb_skb--;
|
||||
dev_kfree_skb_any(cmd.reply_skb);
|
||||
priv->alloc_rxb_page--;
|
||||
free_pages(cmd.reply_page, priv->hw_params.rx_page_order);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -131,7 +131,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;
|
||||
int i, len;
|
||||
int i;
|
||||
|
||||
if (q->n_bd == 0)
|
||||
return;
|
||||
|
@ -141,8 +141,6 @@ void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id)
|
|||
q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd))
|
||||
priv->cfg->ops->lib->txq_free_tfd(priv, txq);
|
||||
|
||||
len = sizeof(struct iwl_device_cmd) * q->n_window;
|
||||
|
||||
/* De-alloc array of command/tx buffers */
|
||||
for (i = 0; i < TFD_TX_CMD_SLOTS; i++)
|
||||
kfree(txq->cmd[i]);
|
||||
|
@ -180,14 +178,11 @@ 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;
|
||||
int i, len;
|
||||
int i;
|
||||
|
||||
if (q->n_bd == 0)
|
||||
return;
|
||||
|
||||
len = sizeof(struct iwl_device_cmd) * q->n_window;
|
||||
len += IWL_MAX_SCAN_SIZE;
|
||||
|
||||
/* De-alloc array of command/tx buffers */
|
||||
for (i = 0; i <= TFD_CMD_SLOTS; i++)
|
||||
kfree(txq->cmd[i]);
|
||||
|
@ -405,15 +400,19 @@ void iwl_hw_txq_ctx_free(struct iwl_priv *priv)
|
|||
int txq_id;
|
||||
|
||||
/* Tx queues */
|
||||
for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
|
||||
if (txq_id == IWL_CMD_QUEUE_NUM)
|
||||
iwl_cmd_queue_free(priv);
|
||||
else
|
||||
iwl_tx_queue_free(priv, txq_id);
|
||||
|
||||
if (priv->txq)
|
||||
for (txq_id = 0; txq_id < priv->hw_params.max_txq_num;
|
||||
txq_id++)
|
||||
if (txq_id == IWL_CMD_QUEUE_NUM)
|
||||
iwl_cmd_queue_free(priv);
|
||||
else
|
||||
iwl_tx_queue_free(priv, txq_id);
|
||||
iwl_free_dma_ptr(priv, &priv->kw);
|
||||
|
||||
iwl_free_dma_ptr(priv, &priv->scd_bc_tbls);
|
||||
|
||||
/* free tx queue structure */
|
||||
iwl_free_txq_mem(priv);
|
||||
}
|
||||
EXPORT_SYMBOL(iwl_hw_txq_ctx_free);
|
||||
|
||||
|
@ -445,6 +444,12 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv)
|
|||
IWL_ERR(priv, "Keep Warm allocation failed\n");
|
||||
goto error_kw;
|
||||
}
|
||||
|
||||
/* allocate tx queue structure */
|
||||
ret = iwl_alloc_txq_mem(priv);
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
|
||||
/* Turn off all Tx DMA fifos */
|
||||
|
@ -581,9 +586,7 @@ static void iwl_tx_cmd_build_rate(struct iwl_priv *priv,
|
|||
u8 rate_plcp;
|
||||
|
||||
/* Set retry limit on DATA packets and Probe Responses*/
|
||||
if (priv->data_retry_limit != -1)
|
||||
data_retry_limit = priv->data_retry_limit;
|
||||
else if (ieee80211_is_probe_resp(fc))
|
||||
if (ieee80211_is_probe_resp(fc))
|
||||
data_retry_limit = 3;
|
||||
else
|
||||
data_retry_limit = IWL_DEFAULT_TX_RETRY;
|
||||
|
@ -1145,7 +1148,7 @@ static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id,
|
|||
*/
|
||||
void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
u16 sequence = le16_to_cpu(pkt->hdr.sequence);
|
||||
int txq_id = SEQ_TO_QUEUE(sequence);
|
||||
int index = SEQ_TO_INDEX(sequence);
|
||||
|
@ -1172,10 +1175,10 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
|
|||
|
||||
/* Input error checking is done when commands are added to queue. */
|
||||
if (meta->flags & CMD_WANT_SKB) {
|
||||
meta->source->reply_skb = rxb->skb;
|
||||
rxb->skb = NULL;
|
||||
meta->source->reply_page = (unsigned long)rxb_addr(rxb);
|
||||
rxb->page = NULL;
|
||||
} else if (meta->callback)
|
||||
meta->callback(priv, cmd, rxb->skb);
|
||||
meta->callback(priv, cmd, pkt);
|
||||
|
||||
iwl_hcmd_queue_reclaim(priv, txq_id, index, cmd_index);
|
||||
|
||||
|
@ -1434,7 +1437,7 @@ static int iwl_tx_status_reply_compressed_ba(struct iwl_priv *priv,
|
|||
void iwl_rx_reply_compressed_ba(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_compressed_ba_resp *ba_resp = &pkt->u.compressed_ba;
|
||||
struct iwl_tx_queue *txq = NULL;
|
||||
struct iwl_ht_agg *agg;
|
||||
|
|
|
@ -88,7 +88,6 @@ MODULE_LICENSE("GPL");
|
|||
|
||||
/* module parameters */
|
||||
struct iwl_mod_params iwl3945_mod_params = {
|
||||
.num_of_queues = IWL39_NUM_QUEUES, /* Not used */
|
||||
.sw_crypto = 1,
|
||||
.restart_fw = 1,
|
||||
/* the rest are 0 by default */
|
||||
|
@ -366,13 +365,13 @@ static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
|
|||
struct sk_buff *skb_frag,
|
||||
int sta_id)
|
||||
{
|
||||
struct iwl3945_tx_cmd *tx = (struct iwl3945_tx_cmd *)cmd->cmd.payload;
|
||||
struct iwl3945_tx_cmd *tx_cmd = (struct iwl3945_tx_cmd *)cmd->cmd.payload;
|
||||
struct iwl_hw_key *keyinfo = &priv->stations[sta_id].keyinfo;
|
||||
|
||||
switch (keyinfo->alg) {
|
||||
case ALG_CCMP:
|
||||
tx->sec_ctl = TX_CMD_SEC_CCM;
|
||||
memcpy(tx->key, keyinfo->key, keyinfo->keylen);
|
||||
tx_cmd->sec_ctl = TX_CMD_SEC_CCM;
|
||||
memcpy(tx_cmd->key, keyinfo->key, keyinfo->keylen);
|
||||
IWL_DEBUG_TX(priv, "tx_cmd with AES hwcrypto\n");
|
||||
break;
|
||||
|
||||
|
@ -380,13 +379,13 @@ static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
|
|||
break;
|
||||
|
||||
case ALG_WEP:
|
||||
tx->sec_ctl = TX_CMD_SEC_WEP |
|
||||
tx_cmd->sec_ctl = TX_CMD_SEC_WEP |
|
||||
(info->control.hw_key->hw_key_idx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT;
|
||||
|
||||
if (keyinfo->keylen == 13)
|
||||
tx->sec_ctl |= TX_CMD_SEC_KEY128;
|
||||
tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128;
|
||||
|
||||
memcpy(&tx->key[3], keyinfo->key, keyinfo->keylen);
|
||||
memcpy(&tx_cmd->key[3], keyinfo->key, keyinfo->keylen);
|
||||
|
||||
IWL_DEBUG_TX(priv, "Configuring packet for WEP encryption "
|
||||
"with key %d\n", info->control.hw_key->hw_key_idx);
|
||||
|
@ -406,12 +405,11 @@ static void iwl3945_build_tx_cmd_basic(struct iwl_priv *priv,
|
|||
struct ieee80211_tx_info *info,
|
||||
struct ieee80211_hdr *hdr, u8 std_id)
|
||||
{
|
||||
struct iwl3945_tx_cmd *tx = (struct iwl3945_tx_cmd *)cmd->cmd.payload;
|
||||
__le32 tx_flags = tx->tx_flags;
|
||||
struct iwl3945_tx_cmd *tx_cmd = (struct iwl3945_tx_cmd *)cmd->cmd.payload;
|
||||
__le32 tx_flags = tx_cmd->tx_flags;
|
||||
__le16 fc = hdr->frame_control;
|
||||
u8 rc_flags = info->control.rates[0].flags;
|
||||
|
||||
tx->stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
|
||||
tx_cmd->stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
|
||||
if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
|
||||
tx_flags |= TX_CMD_FLG_ACK_MSK;
|
||||
if (ieee80211_is_mgmt(fc))
|
||||
|
@ -424,25 +422,19 @@ static void iwl3945_build_tx_cmd_basic(struct iwl_priv *priv,
|
|||
tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
|
||||
}
|
||||
|
||||
tx->sta_id = std_id;
|
||||
tx_cmd->sta_id = std_id;
|
||||
if (ieee80211_has_morefrags(fc))
|
||||
tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK;
|
||||
|
||||
if (ieee80211_is_data_qos(fc)) {
|
||||
u8 *qc = ieee80211_get_qos_ctl(hdr);
|
||||
tx->tid_tspec = qc[0] & 0xf;
|
||||
tx_cmd->tid_tspec = qc[0] & 0xf;
|
||||
tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK;
|
||||
} else {
|
||||
tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
|
||||
}
|
||||
|
||||
if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) {
|
||||
tx_flags |= TX_CMD_FLG_RTS_MSK;
|
||||
tx_flags &= ~TX_CMD_FLG_CTS_MSK;
|
||||
} else if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
|
||||
tx_flags &= ~TX_CMD_FLG_RTS_MSK;
|
||||
tx_flags |= TX_CMD_FLG_CTS_MSK;
|
||||
}
|
||||
priv->cfg->ops->utils->rts_tx_cmd_flag(info, &tx_flags);
|
||||
|
||||
if ((tx_flags & TX_CMD_FLG_RTS_MSK) || (tx_flags & TX_CMD_FLG_CTS_MSK))
|
||||
tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK;
|
||||
|
@ -450,16 +442,16 @@ static void iwl3945_build_tx_cmd_basic(struct iwl_priv *priv,
|
|||
tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK);
|
||||
if (ieee80211_is_mgmt(fc)) {
|
||||
if (ieee80211_is_assoc_req(fc) || ieee80211_is_reassoc_req(fc))
|
||||
tx->timeout.pm_frame_timeout = cpu_to_le16(3);
|
||||
tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(3);
|
||||
else
|
||||
tx->timeout.pm_frame_timeout = cpu_to_le16(2);
|
||||
tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(2);
|
||||
} else {
|
||||
tx->timeout.pm_frame_timeout = 0;
|
||||
tx_cmd->timeout.pm_frame_timeout = 0;
|
||||
}
|
||||
|
||||
tx->driver_txop = 0;
|
||||
tx->tx_flags = tx_flags;
|
||||
tx->next_frame_len = 0;
|
||||
tx_cmd->driver_txop = 0;
|
||||
tx_cmd->tx_flags = tx_flags;
|
||||
tx_cmd->next_frame_len = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -469,7 +461,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
|||
{
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct iwl3945_tx_cmd *tx;
|
||||
struct iwl3945_tx_cmd *tx_cmd;
|
||||
struct iwl_tx_queue *txq = NULL;
|
||||
struct iwl_queue *q = NULL;
|
||||
struct iwl_device_cmd *out_cmd;
|
||||
|
@ -568,9 +560,9 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
|||
/* Init first empty entry in queue's array of Tx/cmd buffers */
|
||||
out_cmd = txq->cmd[idx];
|
||||
out_meta = &txq->meta[idx];
|
||||
tx = (struct iwl3945_tx_cmd *)out_cmd->cmd.payload;
|
||||
tx_cmd = (struct iwl3945_tx_cmd *)out_cmd->cmd.payload;
|
||||
memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr));
|
||||
memset(tx, 0, sizeof(*tx));
|
||||
memset(tx_cmd, 0, sizeof(*tx_cmd));
|
||||
|
||||
/*
|
||||
* Set up the Tx-command (not MAC!) header.
|
||||
|
@ -583,7 +575,7 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
|||
INDEX_TO_SEQ(q->write_ptr)));
|
||||
|
||||
/* Copy MAC header from skb into command buffer */
|
||||
memcpy(tx->hdr, hdr, hdr_len);
|
||||
memcpy(tx_cmd->hdr, hdr, hdr_len);
|
||||
|
||||
|
||||
if (info->control.hw_key)
|
||||
|
@ -597,12 +589,12 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
|||
|
||||
/* Total # bytes to be transmitted */
|
||||
len = (u16)skb->len;
|
||||
tx->len = cpu_to_le16(len);
|
||||
tx_cmd->len = cpu_to_le16(len);
|
||||
|
||||
iwl_dbg_log_tx_data_frame(priv, len, hdr);
|
||||
iwl_update_stats(priv, true, fc, len);
|
||||
tx->tx_flags &= ~TX_CMD_FLG_ANT_A_MSK;
|
||||
tx->tx_flags &= ~TX_CMD_FLG_ANT_B_MSK;
|
||||
tx_cmd->tx_flags &= ~TX_CMD_FLG_ANT_A_MSK;
|
||||
tx_cmd->tx_flags &= ~TX_CMD_FLG_ANT_B_MSK;
|
||||
|
||||
if (!ieee80211_has_morefrags(hdr->frame_control)) {
|
||||
txq->need_update = 1;
|
||||
|
@ -615,9 +607,9 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
|
|||
|
||||
IWL_DEBUG_TX(priv, "sequence nr = 0X%x \n",
|
||||
le16_to_cpu(out_cmd->hdr.sequence));
|
||||
IWL_DEBUG_TX(priv, "tx_flags = 0X%x \n", le32_to_cpu(tx->tx_flags));
|
||||
iwl_print_hex_dump(priv, IWL_DL_TX, tx, sizeof(*tx));
|
||||
iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx->hdr,
|
||||
IWL_DEBUG_TX(priv, "tx_flags = 0X%x \n", le32_to_cpu(tx_cmd->tx_flags));
|
||||
iwl_print_hex_dump(priv, IWL_DL_TX, tx_cmd, sizeof(*tx_cmd));
|
||||
iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd->hdr,
|
||||
ieee80211_hdrlen(fc));
|
||||
|
||||
/*
|
||||
|
@ -753,7 +745,7 @@ static int iwl3945_get_measurement(struct iwl_priv *priv,
|
|||
u8 type)
|
||||
{
|
||||
struct iwl_spectrum_cmd spectrum;
|
||||
struct iwl_rx_packet *res;
|
||||
struct iwl_rx_packet *pkt;
|
||||
struct iwl_host_cmd cmd = {
|
||||
.id = REPLY_SPECTRUM_MEASUREMENT_CMD,
|
||||
.data = (void *)&spectrum,
|
||||
|
@ -798,18 +790,18 @@ static int iwl3945_get_measurement(struct iwl_priv *priv,
|
|||
if (rc)
|
||||
return rc;
|
||||
|
||||
res = (struct iwl_rx_packet *)cmd.reply_skb->data;
|
||||
if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
|
||||
pkt = (struct iwl_rx_packet *)cmd.reply_page;
|
||||
if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
|
||||
IWL_ERR(priv, "Bad return from REPLY_RX_ON_ASSOC command\n");
|
||||
rc = -EIO;
|
||||
}
|
||||
|
||||
spectrum_resp_status = le16_to_cpu(res->u.spectrum.status);
|
||||
spectrum_resp_status = le16_to_cpu(pkt->u.spectrum.status);
|
||||
switch (spectrum_resp_status) {
|
||||
case 0: /* Command will be handled */
|
||||
if (res->u.spectrum.id != 0xff) {
|
||||
if (pkt->u.spectrum.id != 0xff) {
|
||||
IWL_DEBUG_INFO(priv, "Replaced existing measurement: %d\n",
|
||||
res->u.spectrum.id);
|
||||
pkt->u.spectrum.id);
|
||||
priv->measurement_status &= ~MEASUREMENT_READY;
|
||||
}
|
||||
priv->measurement_status |= MEASUREMENT_ACTIVE;
|
||||
|
@ -821,7 +813,7 @@ static int iwl3945_get_measurement(struct iwl_priv *priv,
|
|||
break;
|
||||
}
|
||||
|
||||
dev_kfree_skb_any(cmd.reply_skb);
|
||||
free_pages(cmd.reply_page, priv->hw_params.rx_page_order);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
@ -830,7 +822,7 @@ static int iwl3945_get_measurement(struct iwl_priv *priv,
|
|||
static void iwl3945_rx_reply_alive(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl_alive_resp *palive;
|
||||
struct delayed_work *pwork;
|
||||
|
||||
|
@ -867,7 +859,7 @@ static void iwl3945_rx_reply_add_sta(struct iwl_priv *priv,
|
|||
struct iwl_rx_mem_buffer *rxb)
|
||||
{
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
#endif
|
||||
|
||||
IWL_DEBUG_RX(priv, "Received REPLY_ADD_STA: 0x%02X\n", pkt->u.status);
|
||||
|
@ -903,7 +895,7 @@ static void iwl3945_rx_beacon_notif(struct iwl_priv *priv,
|
|||
struct iwl_rx_mem_buffer *rxb)
|
||||
{
|
||||
#ifdef CONFIG_IWLWIFI_DEBUG
|
||||
struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
struct iwl3945_beacon_notif *beacon = &(pkt->u.beacon_status);
|
||||
u8 rate = beacon->beacon_notify_hdr.rate;
|
||||
|
||||
|
@ -926,7 +918,7 @@ static void iwl3945_rx_beacon_notif(struct iwl_priv *priv,
|
|||
static void iwl3945_rx_card_state_notif(struct iwl_priv *priv,
|
||||
struct iwl_rx_mem_buffer *rxb)
|
||||
{
|
||||
struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
|
||||
struct iwl_rx_packet *pkt = rxb_addr(rxb);
|
||||
u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
|
||||
unsigned long status = priv->status;
|
||||
|
||||
|
@ -1090,7 +1082,7 @@ static int iwl3945_rx_queue_restock(struct iwl_priv *priv)
|
|||
list_del(element);
|
||||
|
||||
/* Point to Rx buffer via next RBD in circular buffer */
|
||||
rxq->bd[rxq->write] = iwl3945_dma_addr2rbd_ptr(priv, rxb->real_dma_addr);
|
||||
rxq->bd[rxq->write] = iwl3945_dma_addr2rbd_ptr(priv, rxb->page_dma);
|
||||
rxq->queue[rxq->write] = rxb;
|
||||
rxq->write = (rxq->write + 1) & RX_QUEUE_MASK;
|
||||
rxq->free_count--;
|
||||
|
@ -1130,8 +1122,9 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority)
|
|||
struct iwl_rx_queue *rxq = &priv->rxq;
|
||||
struct list_head *element;
|
||||
struct iwl_rx_mem_buffer *rxb;
|
||||
struct sk_buff *skb;
|
||||
struct page *page;
|
||||
unsigned long flags;
|
||||
gfp_t gfp_mask = priority;
|
||||
|
||||
while (1) {
|
||||
spin_lock_irqsave(&rxq->lock, flags);
|
||||
|
@ -1143,10 +1136,14 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority)
|
|||
spin_unlock_irqrestore(&rxq->lock, flags);
|
||||
|
||||
if (rxq->free_count > RX_LOW_WATERMARK)
|
||||
priority |= __GFP_NOWARN;
|
||||
gfp_mask |= __GFP_NOWARN;
|
||||
|
||||
if (priv->hw_params.rx_page_order > 0)
|
||||
gfp_mask |= __GFP_COMP;
|
||||
|
||||
/* Alloc a new receive buffer */
|
||||
skb = alloc_skb(priv->hw_params.rx_buf_size, priority);
|
||||
if (!skb) {
|
||||
page = alloc_pages(gfp_mask, priv->hw_params.rx_page_order);
|
||||
if (!page) {
|
||||
if (net_ratelimit())
|
||||
IWL_DEBUG_INFO(priv, "Failed to allocate SKB buffer.\n");
|
||||
if ((rxq->free_count <= RX_LOW_WATERMARK) &&
|
||||
|
@ -1163,7 +1160,7 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority)
|
|||
spin_lock_irqsave(&rxq->lock, flags);
|
||||
if (list_empty(&rxq->rx_used)) {
|
||||
spin_unlock_irqrestore(&rxq->lock, flags);
|
||||
dev_kfree_skb_any(skb);
|
||||
__free_pages(page, priv->hw_params.rx_page_order);
|
||||
return;
|
||||
}
|
||||
element = rxq->rx_used.next;
|
||||
|
@ -1171,26 +1168,18 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority)
|
|||
list_del(element);
|
||||
spin_unlock_irqrestore(&rxq->lock, flags);
|
||||
|
||||
rxb->skb = skb;
|
||||
|
||||
/* If radiotap head is required, reserve some headroom here.
|
||||
* The physical head count is a variable rx_stats->phy_count.
|
||||
* We reserve 4 bytes here. Plus these extra bytes, the
|
||||
* headroom of the physical head should be enough for the
|
||||
* radiotap head that iwl3945 supported. See iwl3945_rt.
|
||||
*/
|
||||
skb_reserve(rxb->skb, 4);
|
||||
|
||||
rxb->page = page;
|
||||
/* Get physical address of RB/SKB */
|
||||
rxb->real_dma_addr = pci_map_single(priv->pci_dev,
|
||||
rxb->skb->data,
|
||||
priv->hw_params.rx_buf_size,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
rxb->page_dma = pci_map_page(priv->pci_dev, page, 0,
|
||||
PAGE_SIZE << priv->hw_params.rx_page_order,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
|
||||
spin_lock_irqsave(&rxq->lock, flags);
|
||||
|
||||
list_add_tail(&rxb->list, &rxq->rx_free);
|
||||
priv->alloc_rxb_skb++;
|
||||
rxq->free_count++;
|
||||
priv->alloc_rxb_page++;
|
||||
|
||||
spin_unlock_irqrestore(&rxq->lock, flags);
|
||||
}
|
||||
}
|
||||
|
@ -1206,14 +1195,14 @@ void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
|
|||
for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) {
|
||||
/* In the reset function, these buffers may have been allocated
|
||||
* to an SKB, so we need to unmap and free potential storage */
|
||||
if (rxq->pool[i].skb != NULL) {
|
||||
pci_unmap_single(priv->pci_dev,
|
||||
rxq->pool[i].real_dma_addr,
|
||||
priv->hw_params.rx_buf_size,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
priv->alloc_rxb_skb--;
|
||||
dev_kfree_skb(rxq->pool[i].skb);
|
||||
rxq->pool[i].skb = NULL;
|
||||
if (rxq->pool[i].page != NULL) {
|
||||
pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma,
|
||||
PAGE_SIZE << priv->hw_params.rx_page_order,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
priv->alloc_rxb_page--;
|
||||
__free_pages(rxq->pool[i].page,
|
||||
priv->hw_params.rx_page_order);
|
||||
rxq->pool[i].page = NULL;
|
||||
}
|
||||
list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
|
||||
}
|
||||
|
@ -1221,8 +1210,8 @@ void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
|
|||
/* Set us so that we have processed and used all buffers, but have
|
||||
* not restocked the Rx queue with fresh buffers */
|
||||
rxq->read = rxq->write = 0;
|
||||
rxq->free_count = 0;
|
||||
rxq->write_actual = 0;
|
||||
rxq->free_count = 0;
|
||||
spin_unlock_irqrestore(&rxq->lock, flags);
|
||||
}
|
||||
|
||||
|
@ -1255,12 +1244,14 @@ static void iwl3945_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rx
|
|||
{
|
||||
int i;
|
||||
for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) {
|
||||
if (rxq->pool[i].skb != NULL) {
|
||||
pci_unmap_single(priv->pci_dev,
|
||||
rxq->pool[i].real_dma_addr,
|
||||
priv->hw_params.rx_buf_size,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
dev_kfree_skb(rxq->pool[i].skb);
|
||||
if (rxq->pool[i].page != NULL) {
|
||||
pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma,
|
||||
PAGE_SIZE << priv->hw_params.rx_page_order,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
__free_pages(rxq->pool[i].page,
|
||||
priv->hw_params.rx_page_order);
|
||||
rxq->pool[i].page = NULL;
|
||||
priv->alloc_rxb_page--;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1376,7 +1367,7 @@ static void iwl3945_rx_handle(struct iwl_priv *priv)
|
|||
i = rxq->read;
|
||||
|
||||
/* calculate total frames need to be restock after handling RX */
|
||||
total_empty = r - priv->rxq.write_actual;
|
||||
total_empty = r - rxq->write_actual;
|
||||
if (total_empty < 0)
|
||||
total_empty += RX_QUEUE_SIZE;
|
||||
|
||||
|
@ -1396,10 +1387,10 @@ static void iwl3945_rx_handle(struct iwl_priv *priv)
|
|||
|
||||
rxq->queue[i] = NULL;
|
||||
|
||||
pci_unmap_single(priv->pci_dev, rxb->real_dma_addr,
|
||||
priv->hw_params.rx_buf_size,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
pkt = (struct iwl_rx_packet *)rxb->skb->data;
|
||||
pci_unmap_page(priv->pci_dev, rxb->page_dma,
|
||||
PAGE_SIZE << priv->hw_params.rx_page_order,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
pkt = rxb_addr(rxb);
|
||||
|
||||
trace_iwlwifi_dev_rx(priv, pkt,
|
||||
le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK);
|
||||
|
@ -1420,44 +1411,55 @@ static void iwl3945_rx_handle(struct iwl_priv *priv)
|
|||
if (priv->rx_handlers[pkt->hdr.cmd]) {
|
||||
IWL_DEBUG_RX(priv, "r = %d, i = %d, %s, 0x%02x\n", r, i,
|
||||
get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
|
||||
priv->rx_handlers[pkt->hdr.cmd] (priv, rxb);
|
||||
priv->isr_stats.rx_handlers[pkt->hdr.cmd]++;
|
||||
priv->rx_handlers[pkt->hdr.cmd] (priv, rxb);
|
||||
} else {
|
||||
/* No handling needed */
|
||||
IWL_DEBUG_RX(priv, "r %d i %d No handler needed for %s, 0x%02x\n",
|
||||
IWL_DEBUG_RX(priv,
|
||||
"r %d i %d No handler needed for %s, 0x%02x\n",
|
||||
r, i, get_cmd_string(pkt->hdr.cmd),
|
||||
pkt->hdr.cmd);
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX: After here, we should always check rxb->page
|
||||
* against NULL before touching it or its virtual
|
||||
* memory (pkt). Because some rx_handler might have
|
||||
* already taken or freed the pages.
|
||||
*/
|
||||
|
||||
if (reclaim) {
|
||||
/* Invoke any callbacks, transfer the skb to caller, and
|
||||
* fire off the (possibly) blocking iwl_send_cmd()
|
||||
/* Invoke any callbacks, transfer the buffer to caller,
|
||||
* and fire off the (possibly) blocking iwl_send_cmd()
|
||||
* as we reclaim the driver command queue */
|
||||
if (rxb && rxb->skb)
|
||||
if (rxb->page)
|
||||
iwl_tx_cmd_complete(priv, rxb);
|
||||
else
|
||||
IWL_WARN(priv, "Claim null rxb?\n");
|
||||
}
|
||||
|
||||
/* For now we just don't re-use anything. We can tweak this
|
||||
* later to try and re-use notification packets and SKBs that
|
||||
* fail to Rx correctly */
|
||||
if (rxb->skb != NULL) {
|
||||
priv->alloc_rxb_skb--;
|
||||
dev_kfree_skb_any(rxb->skb);
|
||||
rxb->skb = NULL;
|
||||
}
|
||||
|
||||
/* Reuse the page if possible. For notification packets and
|
||||
* SKBs that fail to Rx correctly, add them back into the
|
||||
* rx_free list for reuse later. */
|
||||
spin_lock_irqsave(&rxq->lock, flags);
|
||||
list_add_tail(&rxb->list, &priv->rxq.rx_used);
|
||||
if (rxb->page != NULL) {
|
||||
rxb->page_dma = pci_map_page(priv->pci_dev, rxb->page,
|
||||
0, PAGE_SIZE << priv->hw_params.rx_page_order,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
list_add_tail(&rxb->list, &rxq->rx_free);
|
||||
rxq->free_count++;
|
||||
} else
|
||||
list_add_tail(&rxb->list, &rxq->rx_used);
|
||||
|
||||
spin_unlock_irqrestore(&rxq->lock, flags);
|
||||
|
||||
i = (i + 1) & RX_QUEUE_MASK;
|
||||
/* If there are a lot of unused frames,
|
||||
* restock the Rx queue so ucode won't assert. */
|
||||
if (fill_rx) {
|
||||
count++;
|
||||
if (count >= 8) {
|
||||
priv->rxq.read = i;
|
||||
rxq->read = i;
|
||||
iwl3945_rx_replenish_now(priv);
|
||||
count = 0;
|
||||
}
|
||||
|
@ -1465,7 +1467,7 @@ static void iwl3945_rx_handle(struct iwl_priv *priv)
|
|||
}
|
||||
|
||||
/* Backtrack one entry */
|
||||
priv->rxq.read = i;
|
||||
rxq->read = i;
|
||||
if (fill_rx)
|
||||
iwl3945_rx_replenish_now(priv);
|
||||
else
|
||||
|
@ -1686,6 +1688,8 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
|
|||
}
|
||||
#endif
|
||||
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
/* Since CSR_INT and CSR_FH_INT_STATUS reads and clears are not
|
||||
* atomic, make sure that inta covers all the interrupts that
|
||||
* we've discovered, even if FH interrupt came in just after
|
||||
|
@ -1707,8 +1711,6 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
|
|||
|
||||
handled |= CSR_INT_BIT_HW_ERR;
|
||||
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1800,7 +1802,6 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
|
|||
"flags 0x%08lx\n", inta, inta_mask, inta_fh, flags);
|
||||
}
|
||||
#endif
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
}
|
||||
|
||||
static int iwl3945_get_channels_for_scan(struct iwl_priv *priv,
|
||||
|
@ -2563,11 +2564,6 @@ static void __iwl3945_down(struct iwl_priv *priv)
|
|||
test_bit(STATUS_EXIT_PENDING, &priv->status) <<
|
||||
STATUS_EXIT_PENDING;
|
||||
|
||||
priv->cfg->ops->lib->apm_ops.reset(priv);
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
|
||||
iwl3945_hw_txq_ctx_stop(priv);
|
||||
iwl3945_hw_rxq_stop(priv);
|
||||
|
||||
|
@ -2576,10 +2572,8 @@ static void __iwl3945_down(struct iwl_priv *priv)
|
|||
|
||||
udelay(5);
|
||||
|
||||
if (exit_pending)
|
||||
priv->cfg->ops->lib->apm_ops.stop(priv);
|
||||
else
|
||||
priv->cfg->ops->lib->apm_ops.reset(priv);
|
||||
/* Stop the device, and put it in low power state */
|
||||
priv->cfg->ops->lib->apm_ops.stop(priv);
|
||||
|
||||
exit:
|
||||
memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp));
|
||||
|
@ -2724,19 +2718,34 @@ static void iwl3945_bg_alive_start(struct work_struct *data)
|
|||
mutex_unlock(&priv->mutex);
|
||||
}
|
||||
|
||||
/*
|
||||
* 3945 cannot interrupt driver when hardware rf kill switch toggles;
|
||||
* driver must poll CSR_GP_CNTRL_REG register for change. This register
|
||||
* *is* readable even when device has been SW_RESET into low power mode
|
||||
* (e.g. during RF KILL).
|
||||
*/
|
||||
static void iwl3945_rfkill_poll(struct work_struct *data)
|
||||
{
|
||||
struct iwl_priv *priv =
|
||||
container_of(data, struct iwl_priv, rfkill_poll.work);
|
||||
bool old_rfkill = test_bit(STATUS_RF_KILL_HW, &priv->status);
|
||||
bool new_rfkill = !(iwl_read32(priv, CSR_GP_CNTRL)
|
||||
& CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW);
|
||||
|
||||
if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
|
||||
clear_bit(STATUS_RF_KILL_HW, &priv->status);
|
||||
else
|
||||
set_bit(STATUS_RF_KILL_HW, &priv->status);
|
||||
if (new_rfkill != old_rfkill) {
|
||||
if (new_rfkill)
|
||||
set_bit(STATUS_RF_KILL_HW, &priv->status);
|
||||
else
|
||||
clear_bit(STATUS_RF_KILL_HW, &priv->status);
|
||||
|
||||
wiphy_rfkill_set_hw_state(priv->hw->wiphy,
|
||||
test_bit(STATUS_RF_KILL_HW, &priv->status));
|
||||
wiphy_rfkill_set_hw_state(priv->hw->wiphy, new_rfkill);
|
||||
|
||||
IWL_DEBUG_RF_KILL(priv, "RF_KILL bit toggled to %s.\n",
|
||||
new_rfkill ? "disable radio" : "enable radio");
|
||||
}
|
||||
|
||||
/* Keep this running, even if radio now enabled. This will be
|
||||
* cancelled in mac_start() if system decides to start again */
|
||||
queue_delayed_work(priv->workqueue, &priv->rfkill_poll,
|
||||
round_jiffies_relative(2 * HZ));
|
||||
|
||||
|
@ -3797,7 +3806,6 @@ static int iwl3945_init_drv(struct iwl_priv *priv)
|
|||
/* Clear the driver's (not device's) station table */
|
||||
iwl_clear_stations_table(priv);
|
||||
|
||||
priv->data_retry_limit = -1;
|
||||
priv->ieee_channels = NULL;
|
||||
priv->ieee_rates = NULL;
|
||||
priv->band = IEEE80211_BAND_2GHZ;
|
||||
|
@ -4056,6 +4064,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
|
|||
&priv->bands[IEEE80211_BAND_2GHZ].channels[5]);
|
||||
iwl3945_setup_deferred_work(priv);
|
||||
iwl3945_setup_rx_handlers(priv);
|
||||
iwl_power_initialize(priv);
|
||||
|
||||
/*********************************
|
||||
* 8. Setup and Register mac80211
|
||||
|
@ -4126,6 +4135,15 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
|
|||
iwl3945_down(priv);
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure device is reset to low power before unloading driver.
|
||||
* This may be redundant with iwl_down(), but there are paths to
|
||||
* run iwl_down() without calling apm_ops.stop(), and there are
|
||||
* paths to avoid running iwl_down() at all before leaving driver.
|
||||
* This (inexpensive) call *makes sure* device is reset.
|
||||
*/
|
||||
priv->cfg->ops->lib->apm_ops.stop(priv);
|
||||
|
||||
/* make sure we flush any pending irq or
|
||||
* tasklet for the driver
|
||||
*/
|
||||
|
|
|
@ -404,39 +404,21 @@ static int iwm_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
|
|||
{
|
||||
struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
|
||||
struct ieee80211_channel *chan = params->channel;
|
||||
struct cfg80211_bss *bss;
|
||||
|
||||
if (!test_bit(IWM_STATUS_READY, &iwm->status))
|
||||
return -EIO;
|
||||
|
||||
/* UMAC doesn't support creating IBSS network with specified bssid.
|
||||
* This should be removed after we have join only mode supported. */
|
||||
/* UMAC doesn't support creating or joining an IBSS network
|
||||
* with specified bssid. */
|
||||
if (params->bssid)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
bss = cfg80211_get_ibss(iwm_to_wiphy(iwm), NULL,
|
||||
params->ssid, params->ssid_len);
|
||||
if (!bss) {
|
||||
iwm_scan_one_ssid(iwm, params->ssid, params->ssid_len);
|
||||
schedule_timeout_interruptible(2 * HZ);
|
||||
bss = cfg80211_get_ibss(iwm_to_wiphy(iwm), NULL,
|
||||
params->ssid, params->ssid_len);
|
||||
}
|
||||
/* IBSS join only mode is not supported by UMAC ATM */
|
||||
if (bss) {
|
||||
cfg80211_put_bss(bss);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
iwm->channel = ieee80211_frequency_to_channel(chan->center_freq);
|
||||
iwm->umac_profile->ibss.band = chan->band;
|
||||
iwm->umac_profile->ibss.channel = iwm->channel;
|
||||
iwm->umac_profile->ssid.ssid_len = params->ssid_len;
|
||||
memcpy(iwm->umac_profile->ssid.ssid, params->ssid, params->ssid_len);
|
||||
|
||||
if (params->bssid)
|
||||
memcpy(&iwm->umac_profile->bssid[0], params->bssid, ETH_ALEN);
|
||||
|
||||
return iwm_send_mlme_profile(iwm);
|
||||
}
|
||||
|
||||
|
@ -489,12 +471,12 @@ static int iwm_set_wpa_version(struct iwm_priv *iwm, u32 wpa_version)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (wpa_version & NL80211_WPA_VERSION_1)
|
||||
iwm->umac_profile->sec.flags = UMAC_SEC_FLG_WPA_ON_MSK;
|
||||
|
||||
if (wpa_version & NL80211_WPA_VERSION_2)
|
||||
iwm->umac_profile->sec.flags = UMAC_SEC_FLG_RSNA_ON_MSK;
|
||||
|
||||
if (wpa_version & NL80211_WPA_VERSION_1)
|
||||
iwm->umac_profile->sec.flags |= UMAC_SEC_FLG_WPA_ON_MSK;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -645,6 +627,13 @@ static int iwm_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
|
|||
iwm->default_key = sme->key_idx;
|
||||
}
|
||||
|
||||
/* WPA and open AUTH type from wpa_s means WPS (a.k.a. WSC) */
|
||||
if ((iwm->umac_profile->sec.flags &
|
||||
(UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) &&
|
||||
iwm->umac_profile->sec.auth_type == UMAC_AUTH_TYPE_OPEN) {
|
||||
iwm->umac_profile->sec.flags = UMAC_SEC_FLG_WSC_ON_MSK;
|
||||
}
|
||||
|
||||
ret = iwm_send_mlme_profile(iwm);
|
||||
|
||||
if (iwm->umac_profile->sec.auth_type != UMAC_AUTH_TYPE_LEGACY_PSK ||
|
||||
|
@ -681,9 +670,19 @@ static int iwm_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
|
|||
static int iwm_cfg80211_set_txpower(struct wiphy *wiphy,
|
||||
enum tx_power_setting type, int dbm)
|
||||
{
|
||||
struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
|
||||
int ret;
|
||||
|
||||
switch (type) {
|
||||
case TX_POWER_AUTOMATIC:
|
||||
return 0;
|
||||
case TX_POWER_FIXED:
|
||||
ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
|
||||
CFG_TX_PWR_LIMIT_USR, dbm * 2);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return iwm_tx_power_trigger(iwm);
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
@ -695,7 +694,7 @@ static int iwm_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
|
|||
{
|
||||
struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
|
||||
|
||||
*dbm = iwm->txpower;
|
||||
*dbm = iwm->txpower >> 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -76,6 +76,11 @@ int iwm_send_wifi_if_cmd(struct iwm_priv *iwm, void *payload, u16 payload_size,
|
|||
int ret;
|
||||
u8 oid = hdr->oid;
|
||||
|
||||
if (!test_bit(IWM_STATUS_READY, &iwm->status)) {
|
||||
IWM_ERR(iwm, "Interface is not ready yet");
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
umac_cmd.id = UMAC_CMD_OPCODE_WIFI_IF_WRAPPER;
|
||||
umac_cmd.resp = resp;
|
||||
|
||||
|
@ -274,6 +279,17 @@ int iwm_send_calib_results(struct iwm_priv *iwm)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int iwm_send_ct_kill_cfg(struct iwm_priv *iwm, u8 entry, u8 exit)
|
||||
{
|
||||
struct iwm_ct_kill_cfg_cmd cmd;
|
||||
|
||||
cmd.entry_threshold = entry;
|
||||
cmd.exit_threshold = exit;
|
||||
|
||||
return iwm_send_lmac_ptrough_cmd(iwm, REPLY_CT_KILL_CONFIG_CMD, &cmd,
|
||||
sizeof(struct iwm_ct_kill_cfg_cmd), 0);
|
||||
}
|
||||
|
||||
int iwm_send_umac_reset(struct iwm_priv *iwm, __le32 reset_flags, bool resp)
|
||||
{
|
||||
struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT;
|
||||
|
@ -777,11 +793,24 @@ int iwm_invalidate_mlme_profile(struct iwm_priv *iwm)
|
|||
return ret;
|
||||
|
||||
ret = wait_event_interruptible_timeout(iwm->mlme_queue,
|
||||
(iwm->umac_profile_active == 0), 2 * HZ);
|
||||
(iwm->umac_profile_active == 0), 5 * HZ);
|
||||
|
||||
return ret ? 0 : -EBUSY;
|
||||
}
|
||||
|
||||
int iwm_tx_power_trigger(struct iwm_priv *iwm)
|
||||
{
|
||||
struct iwm_umac_pwr_trigger pwr_trigger;
|
||||
|
||||
pwr_trigger.hdr.oid = UMAC_WIFI_IF_CMD_TX_PWR_TRIGGER;
|
||||
pwr_trigger.hdr.buf_size =
|
||||
cpu_to_le16(sizeof(struct iwm_umac_pwr_trigger) -
|
||||
sizeof(struct iwm_umac_wifi_if));
|
||||
|
||||
|
||||
return iwm_send_wifi_if_cmd(iwm, &pwr_trigger, sizeof(pwr_trigger), 1);
|
||||
}
|
||||
|
||||
int iwm_send_umac_stats_req(struct iwm_priv *iwm, u32 flags)
|
||||
{
|
||||
struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT;
|
||||
|
|
|
@ -102,7 +102,6 @@ enum {
|
|||
CFG_SCAN_NUM_PASSIVE_CHAN_PER_PARTIAL_SCAN,
|
||||
CFG_TLC_SUPPORTED_TX_HT_RATES,
|
||||
CFG_TLC_SUPPORTED_TX_RATES,
|
||||
CFG_TLC_VALID_ANTENNA,
|
||||
CFG_TLC_SPATIAL_STREAM_SUPPORTED,
|
||||
CFG_TLC_RETRY_PER_RATE,
|
||||
CFG_TLC_RETRY_PER_HT_RATE,
|
||||
|
@ -136,6 +135,10 @@ enum {
|
|||
CFG_TLC_RENEW_ADDBA_DELAY,
|
||||
CFG_TLC_NUM_OF_MULTISEC_TO_COUN_LOAD,
|
||||
CFG_TLC_IS_STABLE_IN_HT,
|
||||
CFG_TLC_SR_SIC_1ST_FAIL,
|
||||
CFG_TLC_SR_SIC_1ST_PASS,
|
||||
CFG_TLC_SR_SIC_TOTAL_FAIL,
|
||||
CFG_TLC_SR_SIC_TOTAL_PASS,
|
||||
CFG_RLC_CHAIN_CTRL,
|
||||
CFG_TRK_TABLE_OP_MODE,
|
||||
CFG_TRK_TABLE_RSSI_THRESHOLD,
|
||||
|
@ -147,6 +150,58 @@ enum {
|
|||
CFG_MLME_DBG_NOTIF_BLOCK,
|
||||
CFG_BT_OFF_BECONS_INTERVALS,
|
||||
CFG_BT_FRAG_DURATION,
|
||||
CFG_ACTIVE_CHAINS,
|
||||
CFG_CALIB_CTRL,
|
||||
CFG_CAPABILITY_SUPPORTED_HT_RATES,
|
||||
CFG_HT_MAC_PARAM_INFO,
|
||||
CFG_MIMO_PS_MODE,
|
||||
CFG_HT_DEFAULT_CAPABILIES_INFO,
|
||||
CFG_LED_SC_RESOLUTION_FACTOR,
|
||||
CFG_PTAM_ENERGY_CCK_DET_DEFAULT,
|
||||
CFG_PTAM_CORR40_4_TH_ADD_MIN_MRC_DEFAULT,
|
||||
CFG_PTAM_CORR40_4_TH_ADD_MIN_DEFAULT,
|
||||
CFG_PTAM_CORR32_4_TH_ADD_MIN_MRC_DEFAULT,
|
||||
CFG_PTAM_CORR32_4_TH_ADD_MIN_DEFAULT,
|
||||
CFG_PTAM_CORR32_1_TH_ADD_MIN_MRC_DEFAULT,
|
||||
CFG_PTAM_CORR32_1_TH_ADD_MIN_DEFAULT,
|
||||
CFG_PTAM_ENERGY_CCK_DET_MIN_VAL,
|
||||
CFG_PTAM_CORR40_4_TH_ADD_MIN_MRC_MIN_VAL,
|
||||
CFG_PTAM_CORR40_4_TH_ADD_MIN_MIN_VAL,
|
||||
CFG_PTAM_CORR32_4_TH_ADD_MIN_MRC_MIN_VAL,
|
||||
CFG_PTAM_CORR32_4_TH_ADD_MIN_MIN_VAL,
|
||||
CFG_PTAM_CORR32_1_TH_ADD_MIN_MRC_MIN_VAL,
|
||||
CFG_PTAM_CORR32_1_TH_ADD_MIN_MIN_VAL,
|
||||
CFG_PTAM_ENERGY_CCK_DET_MAX_VAL,
|
||||
CFG_PTAM_CORR40_4_TH_ADD_MIN_MRC_MAX_VAL,
|
||||
CFG_PTAM_CORR40_4_TH_ADD_MIN_MAX_VAL,
|
||||
CFG_PTAM_CORR32_4_TH_ADD_MIN_MRC_MAX_VAL,
|
||||
CFG_PTAM_CORR32_4_TH_ADD_MIN_MAX_VAL,
|
||||
CFG_PTAM_CORR32_1_TH_ADD_MIN_MRC_MAX_VAL,
|
||||
CFG_PTAM_CORR32_1_TH_ADD_MIN_MAX_VAL,
|
||||
CFG_PTAM_ENERGY_CCK_DET_STEP_VAL,
|
||||
CFG_PTAM_CORR40_4_TH_ADD_MIN_MRC_STEP_VAL,
|
||||
CFG_PTAM_CORR40_4_TH_ADD_MIN_STEP_VAL,
|
||||
CFG_PTAM_CORR32_4_TH_ADD_MIN_MRC_STEP_VAL,
|
||||
CFG_PTAM_CORR32_4_TH_ADD_MIN_STEP_VAL,
|
||||
CFG_PTAM_CORR32_1_TH_ADD_MIN_MRC_STEP_VAL,
|
||||
CFG_PTAM_CORR32_1_TH_ADD_MIN_STEP_VAL,
|
||||
CFG_PTAM_LINK_SENS_FA_OFDM_MAX,
|
||||
CFG_PTAM_LINK_SENS_FA_OFDM_MIN,
|
||||
CFG_PTAM_LINK_SENS_FA_CCK_MAX,
|
||||
CFG_PTAM_LINK_SENS_FA_CCK_MIN,
|
||||
CFG_PTAM_LINK_SENS_NRG_DIFF,
|
||||
CFG_PTAM_LINK_SENS_NRG_MARGIN,
|
||||
CFG_PTAM_LINK_SENS_MAX_NUMBER_OF_TIMES_IN_CCK_NO_FA,
|
||||
CFG_PTAM_LINK_SENS_AUTO_CORR_MAX_TH_CCK,
|
||||
CFG_AGG_MGG_TID_LOAD_ADDBA_THRESHOLD,
|
||||
CFG_AGG_MGG_TID_LOAD_DELBA_THRESHOLD,
|
||||
CFG_AGG_MGG_ADDBA_BUF_SIZE,
|
||||
CFG_AGG_MGG_ADDBA_INACTIVE_TIMEOUT,
|
||||
CFG_AGG_MGG_ADDBA_DEBUG_FLAGS,
|
||||
CFG_SCAN_PERIODIC_RSSI_HIGH_THRESHOLD,
|
||||
CFG_SCAN_PERIODIC_COEF_RSSI_HIGH,
|
||||
CFG_11D_ENABLED,
|
||||
CFG_11H_FEATURE_FLAGS,
|
||||
|
||||
/* <-- LAST --> */
|
||||
CFG_TBL_FIX_LAST
|
||||
|
@ -155,7 +210,8 @@ enum {
|
|||
/* variable size table */
|
||||
enum {
|
||||
CFG_NET_ADDR = 0,
|
||||
CFG_PROFILE,
|
||||
CFG_LED_PATTERN_TABLE,
|
||||
|
||||
/* <-- LAST --> */
|
||||
CFG_TBL_VAR_LAST
|
||||
};
|
||||
|
@ -288,6 +344,9 @@ struct iwm_umac_cmd_scan_request {
|
|||
/* iwm_umac_security.flag is WSC mode on -- bits [2:2] */
|
||||
#define UMAC_SEC_FLG_WSC_ON_POS 2
|
||||
#define UMAC_SEC_FLG_WSC_ON_SEED 1
|
||||
#define UMAC_SEC_FLG_WSC_ON_MSK (UMAC_SEC_FLG_WSC_ON_SEED << \
|
||||
UMAC_SEC_FLG_WSC_ON_POS)
|
||||
|
||||
|
||||
/* Legacy profile can use only WEP40 and WEP104 for encryption and
|
||||
* OPEN or PSK for authentication */
|
||||
|
@ -382,6 +441,11 @@ struct iwm_umac_tx_key_id {
|
|||
u8 reserved[3];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct iwm_umac_pwr_trigger {
|
||||
struct iwm_umac_wifi_if hdr;
|
||||
__le32 reseved;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct iwm_umac_cmd_stats_req {
|
||||
__le32 flags;
|
||||
} __attribute__ ((packed));
|
||||
|
@ -393,6 +457,7 @@ int iwm_send_init_calib_cfg(struct iwm_priv *iwm, u8 calib_requested);
|
|||
int iwm_send_periodic_calib_cfg(struct iwm_priv *iwm, u8 calib_requested);
|
||||
int iwm_send_calib_results(struct iwm_priv *iwm);
|
||||
int iwm_store_rxiq_calib_result(struct iwm_priv *iwm);
|
||||
int iwm_send_ct_kill_cfg(struct iwm_priv *iwm, u8 entry, u8 exit);
|
||||
|
||||
/* UMAC commands */
|
||||
int iwm_send_wifi_if_cmd(struct iwm_priv *iwm, void *payload, u16 payload_size,
|
||||
|
@ -407,6 +472,7 @@ int iwm_invalidate_mlme_profile(struct iwm_priv *iwm);
|
|||
int iwm_send_packet(struct iwm_priv *iwm, struct sk_buff *skb, int pool_id);
|
||||
int iwm_set_tx_key(struct iwm_priv *iwm, u8 key_idx);
|
||||
int iwm_set_key(struct iwm_priv *iwm, bool remove, struct iwm_key *key);
|
||||
int iwm_tx_power_trigger(struct iwm_priv *iwm);
|
||||
int iwm_send_umac_stats_req(struct iwm_priv *iwm, u32 flags);
|
||||
int iwm_send_umac_channel_list(struct iwm_priv *iwm);
|
||||
int iwm_scan_ssids(struct iwm_priv *iwm, struct cfg80211_ssid *ssids,
|
||||
|
|
|
@ -217,6 +217,13 @@ static int iwm_load_img(struct iwm_priv *iwm, const char *img_name)
|
|||
IWM_BUILD_YEAR(build_date), IWM_BUILD_MONTH(build_date),
|
||||
IWM_BUILD_DAY(build_date));
|
||||
|
||||
if (!strcmp(img_name, iwm->bus_ops->umac_name))
|
||||
sprintf(iwm->umac_version, "%02X.%02X",
|
||||
ver->major, ver->minor);
|
||||
|
||||
if (!strcmp(img_name, iwm->bus_ops->lmac_name))
|
||||
sprintf(iwm->lmac_version, "%02X.%02X",
|
||||
ver->major, ver->minor);
|
||||
|
||||
err_release_fw:
|
||||
release_firmware(fw);
|
||||
|
@ -398,6 +405,8 @@ int iwm_load_fw(struct iwm_priv *iwm)
|
|||
iwm_send_prio_table(iwm);
|
||||
iwm_send_calib_results(iwm);
|
||||
iwm_send_periodic_calib_cfg(iwm, periodic_calib_map);
|
||||
iwm_send_ct_kill_cfg(iwm, iwm->conf.ct_kill_entry,
|
||||
iwm->conf.ct_kill_exit);
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -65,6 +65,8 @@ struct iwm_conf {
|
|||
u32 sdio_ior_timeout;
|
||||
unsigned long calib_map;
|
||||
unsigned long expected_calib_map;
|
||||
u8 ct_kill_entry;
|
||||
u8 ct_kill_exit;
|
||||
bool reset_on_fatal_err;
|
||||
bool auto_connect;
|
||||
bool wimax_not_present;
|
||||
|
@ -276,12 +278,14 @@ struct iwm_priv {
|
|||
struct iw_statistics wstats;
|
||||
struct delayed_work stats_request;
|
||||
struct delayed_work disconnect;
|
||||
struct delayed_work ct_kill_delay;
|
||||
|
||||
struct iwm_debugfs dbg;
|
||||
|
||||
u8 *eeprom;
|
||||
struct timer_list watchdog;
|
||||
struct work_struct reset_worker;
|
||||
struct work_struct auth_retry_worker;
|
||||
struct mutex mutex;
|
||||
|
||||
u8 *req_ie;
|
||||
|
@ -290,6 +294,8 @@ struct iwm_priv {
|
|||
int resp_ie_len;
|
||||
|
||||
struct iwm_fw_error_hdr *last_fw_err;
|
||||
char umac_version[8];
|
||||
char lmac_version[8];
|
||||
|
||||
char private[0] __attribute__((__aligned__(NETDEV_ALIGN)));
|
||||
};
|
||||
|
|
|
@ -187,6 +187,14 @@ struct iwm_coex_prio_table_cmd {
|
|||
COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK | \
|
||||
COEX_EVT_FLAG_DELAY_MEDIUM_FREE_NTFY_MSK)
|
||||
|
||||
/* CT kill config command */
|
||||
struct iwm_ct_kill_cfg_cmd {
|
||||
u32 exit_threshold;
|
||||
u32 reserved;
|
||||
u32 entry_threshold;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
/* LMAC OP CODES */
|
||||
#define REPLY_PAD 0x0
|
||||
#define REPLY_ALIVE 0x1
|
||||
|
|
|
@ -63,6 +63,8 @@ static struct iwm_conf def_iwm_conf = {
|
|||
BIT(PHY_CALIBRATE_TX_IQ_CMD) |
|
||||
BIT(PHY_CALIBRATE_RX_IQ_CMD) |
|
||||
BIT(SHILOH_PHY_CALIBRATE_BASE_BAND_CMD),
|
||||
.ct_kill_entry = 110,
|
||||
.ct_kill_exit = 110,
|
||||
.reset_on_fatal_err = 1,
|
||||
.auto_connect = 1,
|
||||
.wimax_not_present = 0,
|
||||
|
@ -133,6 +135,17 @@ static void iwm_disconnect_work(struct work_struct *work)
|
|||
cfg80211_disconnected(iwm_to_ndev(iwm), 0, NULL, 0, GFP_KERNEL);
|
||||
}
|
||||
|
||||
static void iwm_ct_kill_work(struct work_struct *work)
|
||||
{
|
||||
struct iwm_priv *iwm =
|
||||
container_of(work, struct iwm_priv, ct_kill_delay.work);
|
||||
struct wiphy *wiphy = iwm_to_wiphy(iwm);
|
||||
|
||||
IWM_INFO(iwm, "CT kill delay timeout\n");
|
||||
|
||||
wiphy_rfkill_set_hw_state(wiphy, false);
|
||||
}
|
||||
|
||||
static int __iwm_up(struct iwm_priv *iwm);
|
||||
static int __iwm_down(struct iwm_priv *iwm);
|
||||
|
||||
|
@ -194,6 +207,33 @@ static void iwm_reset_worker(struct work_struct *work)
|
|||
mutex_unlock(&iwm->mutex);
|
||||
}
|
||||
|
||||
static void iwm_auth_retry_worker(struct work_struct *work)
|
||||
{
|
||||
struct iwm_priv *iwm;
|
||||
int i, ret;
|
||||
|
||||
iwm = container_of(work, struct iwm_priv, auth_retry_worker);
|
||||
if (iwm->umac_profile_active) {
|
||||
ret = iwm_invalidate_mlme_profile(iwm);
|
||||
if (ret < 0)
|
||||
return;
|
||||
}
|
||||
|
||||
iwm->umac_profile->sec.auth_type = UMAC_AUTH_TYPE_LEGACY_PSK;
|
||||
|
||||
ret = iwm_send_mlme_profile(iwm);
|
||||
if (ret < 0)
|
||||
return;
|
||||
|
||||
for (i = 0; i < IWM_NUM_KEYS; i++)
|
||||
if (iwm->keys[i].key_len)
|
||||
iwm_set_key(iwm, 0, &iwm->keys[i]);
|
||||
|
||||
iwm_set_tx_key(iwm, iwm->default_key);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void iwm_watchdog(unsigned long data)
|
||||
{
|
||||
struct iwm_priv *iwm = (struct iwm_priv *)data;
|
||||
|
@ -225,7 +265,9 @@ int iwm_priv_init(struct iwm_priv *iwm)
|
|||
iwm->scan_id = 1;
|
||||
INIT_DELAYED_WORK(&iwm->stats_request, iwm_statistics_request);
|
||||
INIT_DELAYED_WORK(&iwm->disconnect, iwm_disconnect_work);
|
||||
INIT_DELAYED_WORK(&iwm->ct_kill_delay, iwm_ct_kill_work);
|
||||
INIT_WORK(&iwm->reset_worker, iwm_reset_worker);
|
||||
INIT_WORK(&iwm->auth_retry_worker, iwm_auth_retry_worker);
|
||||
INIT_LIST_HEAD(&iwm->bss_list);
|
||||
|
||||
skb_queue_head_init(&iwm->rx_list);
|
||||
|
@ -586,6 +628,7 @@ static int __iwm_up(struct iwm_priv *iwm)
|
|||
{
|
||||
int ret;
|
||||
struct iwm_notif *notif_reboot, *notif_ack = NULL;
|
||||
struct wiphy *wiphy = iwm_to_wiphy(iwm);
|
||||
|
||||
ret = iwm_bus_enable(iwm);
|
||||
if (ret) {
|
||||
|
@ -647,6 +690,9 @@ static int __iwm_up(struct iwm_priv *iwm)
|
|||
goto err_disable;
|
||||
}
|
||||
|
||||
snprintf(wiphy->fw_version, sizeof(wiphy->fw_version), "L%s_U%s",
|
||||
iwm->lmac_version, iwm->umac_version);
|
||||
|
||||
/* We configure the UMAC and enable the wifi module */
|
||||
ret = iwm_send_umac_config(iwm,
|
||||
cpu_to_le32(UMAC_RST_CTRL_FLG_WIFI_CORE_EN) |
|
||||
|
|
|
@ -152,6 +152,7 @@ void iwm_if_free(struct iwm_priv *iwm)
|
|||
if (!iwm_to_ndev(iwm))
|
||||
return;
|
||||
|
||||
cancel_delayed_work_sync(&iwm->ct_kill_delay);
|
||||
free_netdev(iwm_to_ndev(iwm));
|
||||
iwm_priv_deinit(iwm);
|
||||
kfree(iwm->umac_profile);
|
||||
|
|
|
@ -422,7 +422,9 @@ static int iwm_ntf_rx_ticket(struct iwm_priv *iwm, u8 *buf,
|
|||
if (IS_ERR(ticket_node))
|
||||
return PTR_ERR(ticket_node);
|
||||
|
||||
IWM_DBG_RX(iwm, DBG, "TICKET RELEASE(%d)\n",
|
||||
IWM_DBG_RX(iwm, DBG, "TICKET %s(%d)\n",
|
||||
ticket->action == IWM_RX_TICKET_RELEASE ?
|
||||
"RELEASE" : "DROP",
|
||||
ticket->id);
|
||||
list_add_tail(&ticket_node->node, &iwm->rx_tickets);
|
||||
|
||||
|
@ -499,6 +501,18 @@ static int iwm_mlme_assoc_start(struct iwm_priv *iwm, u8 *buf,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static u8 iwm_is_open_wep_profile(struct iwm_priv *iwm)
|
||||
{
|
||||
if ((iwm->umac_profile->sec.ucast_cipher == UMAC_CIPHER_TYPE_WEP_40 ||
|
||||
iwm->umac_profile->sec.ucast_cipher == UMAC_CIPHER_TYPE_WEP_104) &&
|
||||
(iwm->umac_profile->sec.ucast_cipher ==
|
||||
iwm->umac_profile->sec.mcast_cipher) &&
|
||||
(iwm->umac_profile->sec.auth_type == UMAC_AUTH_TYPE_OPEN))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf,
|
||||
unsigned long buf_size,
|
||||
struct iwm_wifi_cmd *cmd)
|
||||
|
@ -564,11 +578,17 @@ static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf,
|
|||
goto ibss;
|
||||
|
||||
if (!test_bit(IWM_STATUS_RESETTING, &iwm->status))
|
||||
cfg80211_connect_result(iwm_to_ndev(iwm),
|
||||
complete->bssid,
|
||||
NULL, 0, NULL, 0,
|
||||
WLAN_STATUS_UNSPECIFIED_FAILURE,
|
||||
GFP_KERNEL);
|
||||
if (!iwm_is_open_wep_profile(iwm)) {
|
||||
cfg80211_connect_result(iwm_to_ndev(iwm),
|
||||
complete->bssid,
|
||||
NULL, 0, NULL, 0,
|
||||
WLAN_STATUS_UNSPECIFIED_FAILURE,
|
||||
GFP_KERNEL);
|
||||
} else {
|
||||
/* Let's try shared WEP auth */
|
||||
IWM_ERR(iwm, "Trying WEP shared auth\n");
|
||||
schedule_work(&iwm->auth_retry_worker);
|
||||
}
|
||||
else
|
||||
cfg80211_disconnected(iwm_to_ndev(iwm), 0, NULL, 0,
|
||||
GFP_KERNEL);
|
||||
|
@ -712,6 +732,19 @@ static int iwm_mlme_update_sta_table(struct iwm_priv *iwm, u8 *buf,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int iwm_mlme_medium_lost(struct iwm_priv *iwm, u8 *buf,
|
||||
unsigned long buf_size,
|
||||
struct iwm_wifi_cmd *cmd)
|
||||
{
|
||||
struct wiphy *wiphy = iwm_to_wiphy(iwm);
|
||||
|
||||
IWM_DBG_NTF(iwm, DBG, "WiFi/WiMax coexistence radio is OFF\n");
|
||||
|
||||
wiphy_rfkill_set_hw_state(wiphy, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwm_mlme_update_bss_table(struct iwm_priv *iwm, u8 *buf,
|
||||
unsigned long buf_size,
|
||||
struct iwm_wifi_cmd *cmd)
|
||||
|
@ -898,6 +931,8 @@ static int iwm_ntf_mlme(struct iwm_priv *iwm, u8 *buf,
|
|||
case WIFI_IF_NTFY_EXTENDED_IE_REQUIRED:
|
||||
IWM_DBG_MLME(iwm, DBG, "Extended IE required\n");
|
||||
break;
|
||||
case WIFI_IF_NTFY_RADIO_PREEMPTION:
|
||||
return iwm_mlme_medium_lost(iwm, buf, buf_size, cmd);
|
||||
case WIFI_IF_NTFY_BSS_TRK_TABLE_CHANGED:
|
||||
return iwm_mlme_update_bss_table(iwm, buf, buf_size, cmd);
|
||||
case WIFI_IF_NTFY_BSS_TRK_ENTRIES_REMOVED:
|
||||
|
@ -1055,8 +1090,14 @@ static int iwm_ntf_wifi_if_wrapper(struct iwm_priv *iwm, u8 *buf,
|
|||
unsigned long buf_size,
|
||||
struct iwm_wifi_cmd *cmd)
|
||||
{
|
||||
struct iwm_umac_wifi_if *hdr =
|
||||
(struct iwm_umac_wifi_if *)cmd->buf.payload;
|
||||
struct iwm_umac_wifi_if *hdr;
|
||||
|
||||
if (cmd == NULL) {
|
||||
IWM_ERR(iwm, "Couldn't find expected wifi command\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
hdr = (struct iwm_umac_wifi_if *)cmd->buf.payload;
|
||||
|
||||
IWM_DBG_NTF(iwm, DBG, "WIFI_IF_WRAPPER cmd is delivered to UMAC: "
|
||||
"oid is 0x%x\n", hdr->oid);
|
||||
|
@ -1078,6 +1119,7 @@ static int iwm_ntf_wifi_if_wrapper(struct iwm_priv *iwm, u8 *buf,
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define CT_KILL_DELAY (30 * HZ)
|
||||
static int iwm_ntf_card_state(struct iwm_priv *iwm, u8 *buf,
|
||||
unsigned long buf_size, struct iwm_wifi_cmd *cmd)
|
||||
{
|
||||
|
@ -1090,7 +1132,20 @@ static int iwm_ntf_card_state(struct iwm_priv *iwm, u8 *buf,
|
|||
flags & IWM_CARD_STATE_HW_DISABLED ? "ON" : "OFF",
|
||||
flags & IWM_CARD_STATE_CTKILL_DISABLED ? "ON" : "OFF");
|
||||
|
||||
wiphy_rfkill_set_hw_state(wiphy, flags & IWM_CARD_STATE_HW_DISABLED);
|
||||
if (flags & IWM_CARD_STATE_CTKILL_DISABLED) {
|
||||
/*
|
||||
* We got a CTKILL event: We bring the interface down in
|
||||
* oder to cool the device down, and try to bring it up
|
||||
* 30 seconds later. If it's still too hot, we'll go through
|
||||
* this code path again.
|
||||
*/
|
||||
cancel_delayed_work_sync(&iwm->ct_kill_delay);
|
||||
schedule_delayed_work(&iwm->ct_kill_delay, CT_KILL_DELAY);
|
||||
}
|
||||
|
||||
wiphy_rfkill_set_hw_state(wiphy, flags &
|
||||
(IWM_CARD_STATE_HW_DISABLED |
|
||||
IWM_CARD_STATE_CTKILL_DISABLED));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1281,6 +1336,14 @@ int iwm_rx_handle(struct iwm_priv *iwm, u8 *buf, unsigned long buf_size)
|
|||
|
||||
switch (le32_to_cpu(hdr->cmd)) {
|
||||
case UMAC_REBOOT_BARKER:
|
||||
if (test_bit(IWM_STATUS_READY, &iwm->status)) {
|
||||
IWM_ERR(iwm, "Unexpected BARKER\n");
|
||||
|
||||
schedule_work(&iwm->reset_worker);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return iwm_notif_send(iwm, NULL, IWM_BARKER_REBOOT_NOTIFICATION,
|
||||
IWM_SRC_UDMA, buf, buf_size);
|
||||
case UMAC_ACK_BARKER:
|
||||
|
@ -1443,7 +1506,8 @@ static void iwm_rx_process_packet(struct iwm_priv *iwm,
|
|||
}
|
||||
break;
|
||||
case IWM_RX_TICKET_DROP:
|
||||
IWM_DBG_RX(iwm, DBG, "DROP packet\n");
|
||||
IWM_DBG_RX(iwm, DBG, "DROP packet: 0x%x\n",
|
||||
le16_to_cpu(ticket_node->ticket->flags));
|
||||
kfree_skb(packet->skb);
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -224,8 +224,6 @@ static int if_sdio_disable(struct iwm_priv *iwm)
|
|||
struct iwm_sdio_priv *hw = iwm_to_if_sdio(iwm);
|
||||
int ret;
|
||||
|
||||
iwm_reset(iwm);
|
||||
|
||||
sdio_claim_host(hw->func);
|
||||
sdio_writeb(hw->func, 0, IWM_SDIO_INTR_ENABLE_ADDR, &ret);
|
||||
if (ret < 0)
|
||||
|
@ -237,6 +235,8 @@ static int if_sdio_disable(struct iwm_priv *iwm)
|
|||
|
||||
iwm_sdio_rx_free(hw);
|
||||
|
||||
iwm_reset(iwm);
|
||||
|
||||
IWM_DBG_SDIO(iwm, INFO, "IWM SDIO disable\n");
|
||||
|
||||
return 0;
|
||||
|
@ -493,8 +493,10 @@ static void iwm_sdio_remove(struct sdio_func *func)
|
|||
}
|
||||
|
||||
static const struct sdio_device_id iwm_sdio_ids[] = {
|
||||
{ SDIO_DEVICE(SDIO_VENDOR_ID_INTEL,
|
||||
SDIO_DEVICE_ID_INTEL_IWMC3200WIFI) },
|
||||
/* Global/AGN SKU */
|
||||
{ SDIO_DEVICE(SDIO_VENDOR_ID_INTEL, 0x1403) },
|
||||
/* BGN SKU */
|
||||
{ SDIO_DEVICE(SDIO_VENDOR_ID_INTEL, 0x1408) },
|
||||
{ /* end: all zeroes */ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(sdio, iwm_sdio_ids);
|
||||
|
|
|
@ -687,6 +687,9 @@ struct iwm_umac_notif_rx_ticket {
|
|||
/* Tx/Rx rates window (number of max of last update window per second) */
|
||||
#define UMAC_NTF_RATE_SAMPLE_NR 4
|
||||
|
||||
/* Max numbers of bits required to go through all antennae in bitmasks */
|
||||
#define UMAC_PHY_NUM_CHAINS 3
|
||||
|
||||
#define IWM_UMAC_MGMT_TID 8
|
||||
#define IWM_UMAC_TID_NR 8
|
||||
|
||||
|
@ -697,9 +700,11 @@ struct iwm_umac_notif_stats {
|
|||
__le16 tid_load[IWM_UMAC_TID_NR + 2]; /* 1 non-QoS + 1 dword align */
|
||||
__le16 tx_rate[UMAC_NTF_RATE_SAMPLE_NR];
|
||||
__le16 rx_rate[UMAC_NTF_RATE_SAMPLE_NR];
|
||||
__le32 chain_energy[UMAC_PHY_NUM_CHAINS];
|
||||
s32 rssi_dbm;
|
||||
s32 noise_dbm;
|
||||
__le32 supp_rates;
|
||||
__le32 supp_ht_rates;
|
||||
__le32 missed_beacons;
|
||||
__le32 rx_beacons;
|
||||
__le32 rx_dir_pkts;
|
||||
|
|
|
@ -1,696 +0,0 @@
|
|||
/**
|
||||
* This file contains functions for 802.11D.
|
||||
*/
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/wireless.h>
|
||||
|
||||
#include "host.h"
|
||||
#include "decl.h"
|
||||
#include "11d.h"
|
||||
#include "dev.h"
|
||||
#include "wext.h"
|
||||
|
||||
#define TX_PWR_DEFAULT 10
|
||||
|
||||
static struct region_code_mapping region_code_mapping[] = {
|
||||
{"US ", 0x10}, /* US FCC */
|
||||
{"CA ", 0x10}, /* IC Canada */
|
||||
{"SG ", 0x10}, /* Singapore */
|
||||
{"EU ", 0x30}, /* ETSI */
|
||||
{"AU ", 0x30}, /* Australia */
|
||||
{"KR ", 0x30}, /* Republic Of Korea */
|
||||
{"ES ", 0x31}, /* Spain */
|
||||
{"FR ", 0x32}, /* France */
|
||||
{"JP ", 0x40}, /* Japan */
|
||||
};
|
||||
|
||||
/* Following 2 structure defines the supported channels */
|
||||
static struct chan_freq_power channel_freq_power_UN_BG[] = {
|
||||
{1, 2412, TX_PWR_DEFAULT},
|
||||
{2, 2417, TX_PWR_DEFAULT},
|
||||
{3, 2422, TX_PWR_DEFAULT},
|
||||
{4, 2427, TX_PWR_DEFAULT},
|
||||
{5, 2432, TX_PWR_DEFAULT},
|
||||
{6, 2437, TX_PWR_DEFAULT},
|
||||
{7, 2442, TX_PWR_DEFAULT},
|
||||
{8, 2447, TX_PWR_DEFAULT},
|
||||
{9, 2452, TX_PWR_DEFAULT},
|
||||
{10, 2457, TX_PWR_DEFAULT},
|
||||
{11, 2462, TX_PWR_DEFAULT},
|
||||
{12, 2467, TX_PWR_DEFAULT},
|
||||
{13, 2472, TX_PWR_DEFAULT},
|
||||
{14, 2484, TX_PWR_DEFAULT}
|
||||
};
|
||||
|
||||
static u8 lbs_region_2_code(u8 *region)
|
||||
{
|
||||
u8 i;
|
||||
|
||||
for (i = 0; i < COUNTRY_CODE_LEN && region[i]; i++)
|
||||
region[i] = toupper(region[i]);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(region_code_mapping); i++) {
|
||||
if (!memcmp(region, region_code_mapping[i].region,
|
||||
COUNTRY_CODE_LEN))
|
||||
return (region_code_mapping[i].code);
|
||||
}
|
||||
|
||||
/* default is US */
|
||||
return (region_code_mapping[0].code);
|
||||
}
|
||||
|
||||
static u8 *lbs_code_2_region(u8 code)
|
||||
{
|
||||
u8 i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(region_code_mapping); i++) {
|
||||
if (region_code_mapping[i].code == code)
|
||||
return (region_code_mapping[i].region);
|
||||
}
|
||||
/* default is US */
|
||||
return (region_code_mapping[0].region);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function finds the nrchan-th chan after the firstchan
|
||||
* @param band band
|
||||
* @param firstchan first channel number
|
||||
* @param nrchan number of channels
|
||||
* @return the nrchan-th chan number
|
||||
*/
|
||||
static u8 lbs_get_chan_11d(u8 firstchan, u8 nrchan, u8 *chan)
|
||||
/*find the nrchan-th chan after the firstchan*/
|
||||
{
|
||||
u8 i;
|
||||
struct chan_freq_power *cfp;
|
||||
u8 cfp_no;
|
||||
|
||||
cfp = channel_freq_power_UN_BG;
|
||||
cfp_no = ARRAY_SIZE(channel_freq_power_UN_BG);
|
||||
|
||||
for (i = 0; i < cfp_no; i++) {
|
||||
if ((cfp + i)->channel == firstchan) {
|
||||
lbs_deb_11d("firstchan found\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i < cfp_no) {
|
||||
/*if beyond the boundary */
|
||||
if (i + nrchan < cfp_no) {
|
||||
*chan = (cfp + i + nrchan)->channel;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function Checks if chan txpwr is learned from AP/IBSS
|
||||
* @param chan chan number
|
||||
* @param parsed_region_chan pointer to parsed_region_chan_11d
|
||||
* @return TRUE; FALSE
|
||||
*/
|
||||
static u8 lbs_channel_known_11d(u8 chan,
|
||||
struct parsed_region_chan_11d * parsed_region_chan)
|
||||
{
|
||||
struct chan_power_11d *chanpwr = parsed_region_chan->chanpwr;
|
||||
u8 nr_chan = parsed_region_chan->nr_chan;
|
||||
u8 i = 0;
|
||||
|
||||
lbs_deb_hex(LBS_DEB_11D, "parsed_region_chan", (char *)chanpwr,
|
||||
sizeof(struct chan_power_11d) * nr_chan);
|
||||
|
||||
for (i = 0; i < nr_chan; i++) {
|
||||
if (chan == chanpwr[i].chan) {
|
||||
lbs_deb_11d("found chan %d\n", chan);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
lbs_deb_11d("chan %d not found\n", chan);
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 lbs_chan_2_freq(u8 chan)
|
||||
{
|
||||
struct chan_freq_power *cf;
|
||||
u16 i;
|
||||
u32 freq = 0;
|
||||
|
||||
cf = channel_freq_power_UN_BG;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(channel_freq_power_UN_BG); i++) {
|
||||
if (chan == cf[i].channel)
|
||||
freq = cf[i].freq;
|
||||
}
|
||||
|
||||
return freq;
|
||||
}
|
||||
|
||||
static int generate_domain_info_11d(struct parsed_region_chan_11d
|
||||
*parsed_region_chan,
|
||||
struct lbs_802_11d_domain_reg *domaininfo)
|
||||
{
|
||||
u8 nr_subband = 0;
|
||||
|
||||
u8 nr_chan = parsed_region_chan->nr_chan;
|
||||
u8 nr_parsedchan = 0;
|
||||
|
||||
u8 firstchan = 0, nextchan = 0, maxpwr = 0;
|
||||
|
||||
u8 i, flag = 0;
|
||||
|
||||
memcpy(domaininfo->countrycode, parsed_region_chan->countrycode,
|
||||
COUNTRY_CODE_LEN);
|
||||
|
||||
lbs_deb_11d("nrchan %d\n", nr_chan);
|
||||
lbs_deb_hex(LBS_DEB_11D, "parsed_region_chan", (char *)parsed_region_chan,
|
||||
sizeof(struct parsed_region_chan_11d));
|
||||
|
||||
for (i = 0; i < nr_chan; i++) {
|
||||
if (!flag) {
|
||||
flag = 1;
|
||||
nextchan = firstchan =
|
||||
parsed_region_chan->chanpwr[i].chan;
|
||||
maxpwr = parsed_region_chan->chanpwr[i].pwr;
|
||||
nr_parsedchan = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (parsed_region_chan->chanpwr[i].chan == nextchan + 1 &&
|
||||
parsed_region_chan->chanpwr[i].pwr == maxpwr) {
|
||||
nextchan++;
|
||||
nr_parsedchan++;
|
||||
} else {
|
||||
domaininfo->subband[nr_subband].firstchan = firstchan;
|
||||
domaininfo->subband[nr_subband].nrchan =
|
||||
nr_parsedchan;
|
||||
domaininfo->subband[nr_subband].maxtxpwr = maxpwr;
|
||||
nr_subband++;
|
||||
nextchan = firstchan =
|
||||
parsed_region_chan->chanpwr[i].chan;
|
||||
maxpwr = parsed_region_chan->chanpwr[i].pwr;
|
||||
}
|
||||
}
|
||||
|
||||
if (flag) {
|
||||
domaininfo->subband[nr_subband].firstchan = firstchan;
|
||||
domaininfo->subband[nr_subband].nrchan = nr_parsedchan;
|
||||
domaininfo->subband[nr_subband].maxtxpwr = maxpwr;
|
||||
nr_subband++;
|
||||
}
|
||||
domaininfo->nr_subband = nr_subband;
|
||||
|
||||
lbs_deb_11d("nr_subband=%x\n", domaininfo->nr_subband);
|
||||
lbs_deb_hex(LBS_DEB_11D, "domaininfo", (char *)domaininfo,
|
||||
COUNTRY_CODE_LEN + 1 +
|
||||
sizeof(struct ieee_subbandset) * nr_subband);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function generates parsed_region_chan from Domain Info learned from AP/IBSS
|
||||
* @param region_chan pointer to struct region_channel
|
||||
* @param *parsed_region_chan pointer to parsed_region_chan_11d
|
||||
* @return N/A
|
||||
*/
|
||||
static void lbs_generate_parsed_region_chan_11d(struct region_channel *region_chan,
|
||||
struct parsed_region_chan_11d *
|
||||
parsed_region_chan)
|
||||
{
|
||||
u8 i;
|
||||
struct chan_freq_power *cfp;
|
||||
|
||||
if (region_chan == NULL) {
|
||||
lbs_deb_11d("region_chan is NULL\n");
|
||||
return;
|
||||
}
|
||||
|
||||
cfp = region_chan->CFP;
|
||||
if (cfp == NULL) {
|
||||
lbs_deb_11d("cfp is NULL \n");
|
||||
return;
|
||||
}
|
||||
|
||||
parsed_region_chan->band = region_chan->band;
|
||||
parsed_region_chan->region = region_chan->region;
|
||||
memcpy(parsed_region_chan->countrycode,
|
||||
lbs_code_2_region(region_chan->region), COUNTRY_CODE_LEN);
|
||||
|
||||
lbs_deb_11d("region 0x%x, band %d\n", parsed_region_chan->region,
|
||||
parsed_region_chan->band);
|
||||
|
||||
for (i = 0; i < region_chan->nrcfp; i++, cfp++) {
|
||||
parsed_region_chan->chanpwr[i].chan = cfp->channel;
|
||||
parsed_region_chan->chanpwr[i].pwr = cfp->maxtxpower;
|
||||
lbs_deb_11d("chan %d, pwr %d\n",
|
||||
parsed_region_chan->chanpwr[i].chan,
|
||||
parsed_region_chan->chanpwr[i].pwr);
|
||||
}
|
||||
parsed_region_chan->nr_chan = region_chan->nrcfp;
|
||||
|
||||
lbs_deb_11d("nrchan %d\n", parsed_region_chan->nr_chan);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief generate parsed_region_chan from Domain Info learned from AP/IBSS
|
||||
* @param region region ID
|
||||
* @param band band
|
||||
* @param chan chan
|
||||
* @return TRUE;FALSE
|
||||
*/
|
||||
static u8 lbs_region_chan_supported_11d(u8 region, u8 chan)
|
||||
{
|
||||
struct chan_freq_power *cfp;
|
||||
int cfp_no;
|
||||
u8 idx;
|
||||
int ret = 0;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_11D);
|
||||
|
||||
cfp = lbs_get_region_cfp_table(region, &cfp_no);
|
||||
if (cfp == NULL)
|
||||
return 0;
|
||||
|
||||
for (idx = 0; idx < cfp_no; idx++) {
|
||||
if (chan == (cfp + idx)->channel) {
|
||||
/* If Mrvl Chip Supported? */
|
||||
if ((cfp + idx)->unsupported) {
|
||||
ret = 0;
|
||||
} else {
|
||||
ret = 1;
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
/*chan is not in the region table */
|
||||
|
||||
done:
|
||||
lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function checks if chan txpwr is learned from AP/IBSS
|
||||
* @param chan chan number
|
||||
* @param parsed_region_chan pointer to parsed_region_chan_11d
|
||||
* @return 0
|
||||
*/
|
||||
static int parse_domain_info_11d(struct ieee_ie_country_info_full_set *countryinfo,
|
||||
u8 band,
|
||||
struct parsed_region_chan_11d *parsed_region_chan)
|
||||
{
|
||||
u8 nr_subband, nrchan;
|
||||
u8 lastchan, firstchan;
|
||||
u8 region;
|
||||
u8 curchan = 0;
|
||||
|
||||
u8 idx = 0; /*chan index in parsed_region_chan */
|
||||
|
||||
u8 j, i;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_11D);
|
||||
|
||||
/*validation Rules:
|
||||
1. valid region Code
|
||||
2. First Chan increment
|
||||
3. channel range no overlap
|
||||
4. channel is valid?
|
||||
5. channel is supported by region?
|
||||
6. Others
|
||||
*/
|
||||
|
||||
lbs_deb_hex(LBS_DEB_11D, "countryinfo", (u8 *) countryinfo, 30);
|
||||
|
||||
if ((*(countryinfo->countrycode)) == 0
|
||||
|| (countryinfo->header.len <= COUNTRY_CODE_LEN)) {
|
||||
/* No region Info or Wrong region info: treat as No 11D info */
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*Step1: check region_code */
|
||||
parsed_region_chan->region = region =
|
||||
lbs_region_2_code(countryinfo->countrycode);
|
||||
|
||||
lbs_deb_11d("regioncode=%x\n", (u8) parsed_region_chan->region);
|
||||
lbs_deb_hex(LBS_DEB_11D, "countrycode", (char *)countryinfo->countrycode,
|
||||
COUNTRY_CODE_LEN);
|
||||
|
||||
parsed_region_chan->band = band;
|
||||
|
||||
memcpy(parsed_region_chan->countrycode, countryinfo->countrycode,
|
||||
COUNTRY_CODE_LEN);
|
||||
|
||||
nr_subband = (countryinfo->header.len - COUNTRY_CODE_LEN) /
|
||||
sizeof(struct ieee_subbandset);
|
||||
|
||||
for (j = 0, lastchan = 0; j < nr_subband; j++) {
|
||||
|
||||
if (countryinfo->subband[j].firstchan <= lastchan) {
|
||||
/*Step2&3. Check First Chan Num increment and no overlap */
|
||||
lbs_deb_11d("chan %d>%d, overlap\n",
|
||||
countryinfo->subband[j].firstchan, lastchan);
|
||||
continue;
|
||||
}
|
||||
|
||||
firstchan = countryinfo->subband[j].firstchan;
|
||||
nrchan = countryinfo->subband[j].nrchan;
|
||||
|
||||
for (i = 0; idx < MAX_NO_OF_CHAN && i < nrchan; i++) {
|
||||
/*step4: channel is supported? */
|
||||
|
||||
if (!lbs_get_chan_11d(firstchan, i, &curchan)) {
|
||||
/* Chan is not found in UN table */
|
||||
lbs_deb_11d("chan is not supported: %d \n", i);
|
||||
break;
|
||||
}
|
||||
|
||||
lastchan = curchan;
|
||||
|
||||
if (lbs_region_chan_supported_11d(region, curchan)) {
|
||||
/*step5: Check if curchan is supported by mrvl in region */
|
||||
parsed_region_chan->chanpwr[idx].chan = curchan;
|
||||
parsed_region_chan->chanpwr[idx].pwr =
|
||||
countryinfo->subband[j].maxtxpwr;
|
||||
idx++;
|
||||
} else {
|
||||
/*not supported and ignore the chan */
|
||||
lbs_deb_11d(
|
||||
"i %d, chan %d unsupported in region %x, band %d\n",
|
||||
i, curchan, region, band);
|
||||
}
|
||||
}
|
||||
|
||||
/*Step6: Add other checking if any */
|
||||
|
||||
}
|
||||
|
||||
parsed_region_chan->nr_chan = idx;
|
||||
|
||||
lbs_deb_11d("nrchan=%x\n", parsed_region_chan->nr_chan);
|
||||
lbs_deb_hex(LBS_DEB_11D, "parsed_region_chan", (u8 *) parsed_region_chan,
|
||||
2 + COUNTRY_CODE_LEN + sizeof(struct parsed_region_chan_11d) * idx);
|
||||
|
||||
done:
|
||||
lbs_deb_enter(LBS_DEB_11D);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function calculates the scan type for channels
|
||||
* @param chan chan number
|
||||
* @param parsed_region_chan pointer to parsed_region_chan_11d
|
||||
* @return PASSIVE if chan is unknown; ACTIVE if chan is known
|
||||
*/
|
||||
u8 lbs_get_scan_type_11d(u8 chan,
|
||||
struct parsed_region_chan_11d * parsed_region_chan)
|
||||
{
|
||||
u8 scan_type = CMD_SCAN_TYPE_PASSIVE;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_11D);
|
||||
|
||||
if (lbs_channel_known_11d(chan, parsed_region_chan)) {
|
||||
lbs_deb_11d("found, do active scan\n");
|
||||
scan_type = CMD_SCAN_TYPE_ACTIVE;
|
||||
} else {
|
||||
lbs_deb_11d("not found, do passive scan\n");
|
||||
}
|
||||
|
||||
lbs_deb_leave_args(LBS_DEB_11D, "ret scan_type %d", scan_type);
|
||||
return scan_type;
|
||||
|
||||
}
|
||||
|
||||
void lbs_init_11d(struct lbs_private *priv)
|
||||
{
|
||||
priv->enable11d = 0;
|
||||
memset(&(priv->parsed_region_chan), 0,
|
||||
sizeof(struct parsed_region_chan_11d));
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function sets DOMAIN INFO to FW
|
||||
* @param priv pointer to struct lbs_private
|
||||
* @return 0; -1
|
||||
*/
|
||||
static int set_domain_info_11d(struct lbs_private *priv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!priv->enable11d) {
|
||||
lbs_deb_11d("dnld domain Info with 11d disabled\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = lbs_prepare_and_send_command(priv, CMD_802_11D_DOMAIN_INFO,
|
||||
CMD_ACT_SET,
|
||||
CMD_OPTION_WAITFORRSP, 0, NULL);
|
||||
if (ret)
|
||||
lbs_deb_11d("fail to dnld domain info\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function setups scan channels
|
||||
* @param priv pointer to struct lbs_private
|
||||
* @param band band
|
||||
* @return 0
|
||||
*/
|
||||
int lbs_set_universaltable(struct lbs_private *priv, u8 band)
|
||||
{
|
||||
u16 size = sizeof(struct chan_freq_power);
|
||||
u16 i = 0;
|
||||
|
||||
memset(priv->universal_channel, 0,
|
||||
sizeof(priv->universal_channel));
|
||||
|
||||
priv->universal_channel[i].nrcfp =
|
||||
sizeof(channel_freq_power_UN_BG) / size;
|
||||
lbs_deb_11d("BG-band nrcfp %d\n",
|
||||
priv->universal_channel[i].nrcfp);
|
||||
|
||||
priv->universal_channel[i].CFP = channel_freq_power_UN_BG;
|
||||
priv->universal_channel[i].valid = 1;
|
||||
priv->universal_channel[i].region = UNIVERSAL_REGION_CODE;
|
||||
priv->universal_channel[i].band = band;
|
||||
i++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function implements command CMD_802_11D_DOMAIN_INFO
|
||||
* @param priv pointer to struct lbs_private
|
||||
* @param cmd pointer to cmd buffer
|
||||
* @param cmdno cmd ID
|
||||
* @param cmdOption cmd action
|
||||
* @return 0
|
||||
*/
|
||||
int lbs_cmd_802_11d_domain_info(struct lbs_private *priv,
|
||||
struct cmd_ds_command *cmd, u16 cmdno,
|
||||
u16 cmdoption)
|
||||
{
|
||||
struct cmd_ds_802_11d_domain_info *pdomaininfo =
|
||||
&cmd->params.domaininfo;
|
||||
struct mrvl_ie_domain_param_set *domain = &pdomaininfo->domain;
|
||||
u8 nr_subband = priv->domainreg.nr_subband;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_11D);
|
||||
|
||||
lbs_deb_11d("nr_subband=%x\n", nr_subband);
|
||||
|
||||
cmd->command = cpu_to_le16(cmdno);
|
||||
pdomaininfo->action = cpu_to_le16(cmdoption);
|
||||
if (cmdoption == CMD_ACT_GET) {
|
||||
cmd->size =
|
||||
cpu_to_le16(sizeof(pdomaininfo->action) + S_DS_GEN);
|
||||
lbs_deb_hex(LBS_DEB_11D, "802_11D_DOMAIN_INFO", (u8 *) cmd,
|
||||
le16_to_cpu(cmd->size));
|
||||
goto done;
|
||||
}
|
||||
|
||||
domain->header.type = cpu_to_le16(TLV_TYPE_DOMAIN);
|
||||
memcpy(domain->countrycode, priv->domainreg.countrycode,
|
||||
sizeof(domain->countrycode));
|
||||
|
||||
domain->header.len =
|
||||
cpu_to_le16(nr_subband * sizeof(struct ieee_subbandset) +
|
||||
sizeof(domain->countrycode));
|
||||
|
||||
if (nr_subband) {
|
||||
memcpy(domain->subband, priv->domainreg.subband,
|
||||
nr_subband * sizeof(struct ieee_subbandset));
|
||||
|
||||
cmd->size = cpu_to_le16(sizeof(pdomaininfo->action) +
|
||||
le16_to_cpu(domain->header.len) +
|
||||
sizeof(struct mrvl_ie_header) +
|
||||
S_DS_GEN);
|
||||
} else {
|
||||
cmd->size =
|
||||
cpu_to_le16(sizeof(pdomaininfo->action) + S_DS_GEN);
|
||||
}
|
||||
|
||||
lbs_deb_hex(LBS_DEB_11D, "802_11D_DOMAIN_INFO", (u8 *) cmd, le16_to_cpu(cmd->size));
|
||||
|
||||
done:
|
||||
lbs_deb_enter(LBS_DEB_11D);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function parses countryinfo from AP and download country info to FW
|
||||
* @param priv pointer to struct lbs_private
|
||||
* @param resp pointer to command response buffer
|
||||
* @return 0; -1
|
||||
*/
|
||||
int lbs_ret_802_11d_domain_info(struct cmd_ds_command *resp)
|
||||
{
|
||||
struct cmd_ds_802_11d_domain_info *domaininfo = &resp->params.domaininforesp;
|
||||
struct mrvl_ie_domain_param_set *domain = &domaininfo->domain;
|
||||
u16 action = le16_to_cpu(domaininfo->action);
|
||||
s16 ret = 0;
|
||||
u8 nr_subband = 0;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_11D);
|
||||
|
||||
lbs_deb_hex(LBS_DEB_11D, "domain info resp", (u8 *) resp,
|
||||
(int)le16_to_cpu(resp->size));
|
||||
|
||||
nr_subband = (le16_to_cpu(domain->header.len) - COUNTRY_CODE_LEN) /
|
||||
sizeof(struct ieee_subbandset);
|
||||
|
||||
lbs_deb_11d("domain info resp: nr_subband %d\n", nr_subband);
|
||||
|
||||
if (nr_subband > MRVDRV_MAX_SUBBAND_802_11D) {
|
||||
lbs_deb_11d("Invalid Numrer of Subband returned!!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (action) {
|
||||
case CMD_ACT_SET: /*Proc Set action */
|
||||
break;
|
||||
|
||||
case CMD_ACT_GET:
|
||||
break;
|
||||
default:
|
||||
lbs_deb_11d("Invalid action:%d\n", domaininfo->action);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function parses countryinfo from AP and download country info to FW
|
||||
* @param priv pointer to struct lbs_private
|
||||
* @return 0; -1
|
||||
*/
|
||||
int lbs_parse_dnld_countryinfo_11d(struct lbs_private *priv,
|
||||
struct bss_descriptor * bss)
|
||||
{
|
||||
int ret;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_11D);
|
||||
if (priv->enable11d) {
|
||||
memset(&priv->parsed_region_chan, 0,
|
||||
sizeof(struct parsed_region_chan_11d));
|
||||
ret = parse_domain_info_11d(&bss->countryinfo, 0,
|
||||
&priv->parsed_region_chan);
|
||||
|
||||
if (ret == -1) {
|
||||
lbs_deb_11d("error parsing domain_info from AP\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
memset(&priv->domainreg, 0,
|
||||
sizeof(struct lbs_802_11d_domain_reg));
|
||||
generate_domain_info_11d(&priv->parsed_region_chan,
|
||||
&priv->domainreg);
|
||||
|
||||
ret = set_domain_info_11d(priv);
|
||||
|
||||
if (ret) {
|
||||
lbs_deb_11d("error setting domain info\n");
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
ret = 0;
|
||||
|
||||
done:
|
||||
lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function generates 11D info from user specified regioncode and download to FW
|
||||
* @param priv pointer to struct lbs_private
|
||||
* @return 0; -1
|
||||
*/
|
||||
int lbs_create_dnld_countryinfo_11d(struct lbs_private *priv)
|
||||
{
|
||||
int ret;
|
||||
struct region_channel *region_chan;
|
||||
u8 j;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_11D);
|
||||
lbs_deb_11d("curbssparams.band %d\n", priv->curbssparams.band);
|
||||
|
||||
if (priv->enable11d) {
|
||||
/* update parsed_region_chan_11; dnld domaininf to FW */
|
||||
|
||||
for (j = 0; j < ARRAY_SIZE(priv->region_channel); j++) {
|
||||
region_chan = &priv->region_channel[j];
|
||||
|
||||
lbs_deb_11d("%d region_chan->band %d\n", j,
|
||||
region_chan->band);
|
||||
|
||||
if (!region_chan || !region_chan->valid
|
||||
|| !region_chan->CFP)
|
||||
continue;
|
||||
if (region_chan->band != priv->curbssparams.band)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
||||
if (j >= ARRAY_SIZE(priv->region_channel)) {
|
||||
lbs_deb_11d("region_chan not found, band %d\n",
|
||||
priv->curbssparams.band);
|
||||
ret = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
memset(&priv->parsed_region_chan, 0,
|
||||
sizeof(struct parsed_region_chan_11d));
|
||||
lbs_generate_parsed_region_chan_11d(region_chan,
|
||||
&priv->
|
||||
parsed_region_chan);
|
||||
|
||||
memset(&priv->domainreg, 0,
|
||||
sizeof(struct lbs_802_11d_domain_reg));
|
||||
generate_domain_info_11d(&priv->parsed_region_chan,
|
||||
&priv->domainreg);
|
||||
|
||||
ret = set_domain_info_11d(priv);
|
||||
|
||||
if (ret) {
|
||||
lbs_deb_11d("error setting domain info\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
}
|
||||
ret = 0;
|
||||
|
||||
done:
|
||||
lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
|
@ -1,105 +0,0 @@
|
|||
/**
|
||||
* This header file contains data structures and
|
||||
* function declarations of 802.11d
|
||||
*/
|
||||
#ifndef _LBS_11D_
|
||||
#define _LBS_11D_
|
||||
|
||||
#include "types.h"
|
||||
#include "defs.h"
|
||||
|
||||
#define UNIVERSAL_REGION_CODE 0xff
|
||||
|
||||
/** (Beaconsize(256)-5(IEId,len,contrystr(3))/3(FirstChan,NoOfChan,MaxPwr)
|
||||
*/
|
||||
#define MRVDRV_MAX_SUBBAND_802_11D 83
|
||||
|
||||
#define COUNTRY_CODE_LEN 3
|
||||
#define MAX_NO_OF_CHAN 40
|
||||
|
||||
struct cmd_ds_command;
|
||||
|
||||
/** Data structure for Country IE*/
|
||||
struct ieee_subbandset {
|
||||
u8 firstchan;
|
||||
u8 nrchan;
|
||||
u8 maxtxpwr;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct ieee_ie_country_info_set {
|
||||
struct ieee_ie_header header;
|
||||
|
||||
u8 countrycode[COUNTRY_CODE_LEN];
|
||||
struct ieee_subbandset subband[1];
|
||||
};
|
||||
|
||||
struct ieee_ie_country_info_full_set {
|
||||
struct ieee_ie_header header;
|
||||
|
||||
u8 countrycode[COUNTRY_CODE_LEN];
|
||||
struct ieee_subbandset subband[MRVDRV_MAX_SUBBAND_802_11D];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct mrvl_ie_domain_param_set {
|
||||
struct mrvl_ie_header header;
|
||||
|
||||
u8 countrycode[COUNTRY_CODE_LEN];
|
||||
struct ieee_subbandset subband[1];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_802_11d_domain_info {
|
||||
__le16 action;
|
||||
struct mrvl_ie_domain_param_set domain;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/** domain regulatory information */
|
||||
struct lbs_802_11d_domain_reg {
|
||||
/** country Code*/
|
||||
u8 countrycode[COUNTRY_CODE_LEN];
|
||||
/** No. of subband*/
|
||||
u8 nr_subband;
|
||||
struct ieee_subbandset subband[MRVDRV_MAX_SUBBAND_802_11D];
|
||||
};
|
||||
|
||||
struct chan_power_11d {
|
||||
u8 chan;
|
||||
u8 pwr;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct parsed_region_chan_11d {
|
||||
u8 band;
|
||||
u8 region;
|
||||
s8 countrycode[COUNTRY_CODE_LEN];
|
||||
struct chan_power_11d chanpwr[MAX_NO_OF_CHAN];
|
||||
u8 nr_chan;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct region_code_mapping {
|
||||
u8 region[COUNTRY_CODE_LEN];
|
||||
u8 code;
|
||||
};
|
||||
|
||||
struct lbs_private;
|
||||
|
||||
u8 lbs_get_scan_type_11d(u8 chan,
|
||||
struct parsed_region_chan_11d *parsed_region_chan);
|
||||
|
||||
u32 lbs_chan_2_freq(u8 chan);
|
||||
|
||||
void lbs_init_11d(struct lbs_private *priv);
|
||||
|
||||
int lbs_set_universaltable(struct lbs_private *priv, u8 band);
|
||||
|
||||
int lbs_cmd_802_11d_domain_info(struct lbs_private *priv,
|
||||
struct cmd_ds_command *cmd, u16 cmdno,
|
||||
u16 cmdOption);
|
||||
|
||||
int lbs_ret_802_11d_domain_info(struct cmd_ds_command *resp);
|
||||
|
||||
struct bss_descriptor;
|
||||
int lbs_parse_dnld_countryinfo_11d(struct lbs_private *priv,
|
||||
struct bss_descriptor * bss);
|
||||
|
||||
int lbs_create_dnld_countryinfo_11d(struct lbs_private *priv);
|
||||
|
||||
#endif
|
|
@ -1,4 +1,3 @@
|
|||
libertas-y += 11d.o
|
||||
libertas-y += assoc.o
|
||||
libertas-y += cfg.o
|
||||
libertas-y += cmd.o
|
||||
|
|
|
@ -23,6 +23,13 @@ static const u8 bssid_off[ETH_ALEN] __attribute__ ((aligned (2))) =
|
|||
*/
|
||||
#define CAPINFO_MASK (~(0xda00))
|
||||
|
||||
/**
|
||||
* 802.11b/g supported bitrates (in 500Kb/s units)
|
||||
*/
|
||||
u8 lbs_bg_rates[MAX_RATES] =
|
||||
{ 0x02, 0x04, 0x0b, 0x16, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c,
|
||||
0x00, 0x00 };
|
||||
|
||||
|
||||
/**
|
||||
* @brief This function finds common rates between rates and card rates.
|
||||
|
@ -147,6 +154,397 @@ static int lbs_set_authentication(struct lbs_private *priv, u8 bssid[6], u8 auth
|
|||
}
|
||||
|
||||
|
||||
int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action,
|
||||
struct assoc_request *assoc)
|
||||
{
|
||||
struct cmd_ds_802_11_set_wep cmd;
|
||||
int ret = 0;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_CMD);
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
cmd.hdr.command = cpu_to_le16(CMD_802_11_SET_WEP);
|
||||
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
|
||||
|
||||
cmd.action = cpu_to_le16(cmd_action);
|
||||
|
||||
if (cmd_action == CMD_ACT_ADD) {
|
||||
int i;
|
||||
|
||||
/* default tx key index */
|
||||
cmd.keyindex = cpu_to_le16(assoc->wep_tx_keyidx &
|
||||
CMD_WEP_KEY_INDEX_MASK);
|
||||
|
||||
/* Copy key types and material to host command structure */
|
||||
for (i = 0; i < 4; i++) {
|
||||
struct enc_key *pkey = &assoc->wep_keys[i];
|
||||
|
||||
switch (pkey->len) {
|
||||
case KEY_LEN_WEP_40:
|
||||
cmd.keytype[i] = CMD_TYPE_WEP_40_BIT;
|
||||
memmove(cmd.keymaterial[i], pkey->key, pkey->len);
|
||||
lbs_deb_cmd("SET_WEP: add key %d (40 bit)\n", i);
|
||||
break;
|
||||
case KEY_LEN_WEP_104:
|
||||
cmd.keytype[i] = CMD_TYPE_WEP_104_BIT;
|
||||
memmove(cmd.keymaterial[i], pkey->key, pkey->len);
|
||||
lbs_deb_cmd("SET_WEP: add key %d (104 bit)\n", i);
|
||||
break;
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
lbs_deb_cmd("SET_WEP: invalid key %d, length %d\n",
|
||||
i, pkey->len);
|
||||
ret = -1;
|
||||
goto done;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (cmd_action == CMD_ACT_REMOVE) {
|
||||
/* ACT_REMOVE clears _all_ WEP keys */
|
||||
|
||||
/* default tx key index */
|
||||
cmd.keyindex = cpu_to_le16(priv->wep_tx_keyidx &
|
||||
CMD_WEP_KEY_INDEX_MASK);
|
||||
lbs_deb_cmd("SET_WEP: remove key %d\n", priv->wep_tx_keyidx);
|
||||
}
|
||||
|
||||
ret = lbs_cmd_with_response(priv, CMD_802_11_SET_WEP, &cmd);
|
||||
done:
|
||||
lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action,
|
||||
uint16_t *enable)
|
||||
{
|
||||
struct cmd_ds_802_11_enable_rsn cmd;
|
||||
int ret;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_CMD);
|
||||
|
||||
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
|
||||
cmd.action = cpu_to_le16(cmd_action);
|
||||
|
||||
if (cmd_action == CMD_ACT_GET)
|
||||
cmd.enable = 0;
|
||||
else {
|
||||
if (*enable)
|
||||
cmd.enable = cpu_to_le16(CMD_ENABLE_RSN);
|
||||
else
|
||||
cmd.enable = cpu_to_le16(CMD_DISABLE_RSN);
|
||||
lbs_deb_cmd("ENABLE_RSN: %d\n", *enable);
|
||||
}
|
||||
|
||||
ret = lbs_cmd_with_response(priv, CMD_802_11_ENABLE_RSN, &cmd);
|
||||
if (!ret && cmd_action == CMD_ACT_GET)
|
||||
*enable = le16_to_cpu(cmd.enable);
|
||||
|
||||
lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void set_one_wpa_key(struct MrvlIEtype_keyParamSet *keyparam,
|
||||
struct enc_key *key)
|
||||
{
|
||||
lbs_deb_enter(LBS_DEB_CMD);
|
||||
|
||||
if (key->flags & KEY_INFO_WPA_ENABLED)
|
||||
keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_ENABLED);
|
||||
if (key->flags & KEY_INFO_WPA_UNICAST)
|
||||
keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_UNICAST);
|
||||
if (key->flags & KEY_INFO_WPA_MCAST)
|
||||
keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_MCAST);
|
||||
|
||||
keyparam->type = cpu_to_le16(TLV_TYPE_KEY_MATERIAL);
|
||||
keyparam->keytypeid = cpu_to_le16(key->type);
|
||||
keyparam->keylen = cpu_to_le16(key->len);
|
||||
memcpy(keyparam->key, key->key, key->len);
|
||||
|
||||
/* Length field doesn't include the {type,length} header */
|
||||
keyparam->length = cpu_to_le16(sizeof(*keyparam) - 4);
|
||||
lbs_deb_leave(LBS_DEB_CMD);
|
||||
}
|
||||
|
||||
int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action,
|
||||
struct assoc_request *assoc)
|
||||
{
|
||||
struct cmd_ds_802_11_key_material cmd;
|
||||
int ret = 0;
|
||||
int index = 0;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_CMD);
|
||||
|
||||
cmd.action = cpu_to_le16(cmd_action);
|
||||
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
|
||||
|
||||
if (cmd_action == CMD_ACT_GET) {
|
||||
cmd.hdr.size = cpu_to_le16(sizeof(struct cmd_header) + 2);
|
||||
} else {
|
||||
memset(cmd.keyParamSet, 0, sizeof(cmd.keyParamSet));
|
||||
|
||||
if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc->flags)) {
|
||||
set_one_wpa_key(&cmd.keyParamSet[index],
|
||||
&assoc->wpa_unicast_key);
|
||||
index++;
|
||||
}
|
||||
|
||||
if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc->flags)) {
|
||||
set_one_wpa_key(&cmd.keyParamSet[index],
|
||||
&assoc->wpa_mcast_key);
|
||||
index++;
|
||||
}
|
||||
|
||||
/* The common header and as many keys as we included */
|
||||
cmd.hdr.size = cpu_to_le16(offsetof(typeof(cmd),
|
||||
keyParamSet[index]));
|
||||
}
|
||||
ret = lbs_cmd_with_response(priv, CMD_802_11_KEY_MATERIAL, &cmd);
|
||||
/* Copy the returned key to driver private data */
|
||||
if (!ret && cmd_action == CMD_ACT_GET) {
|
||||
void *buf_ptr = cmd.keyParamSet;
|
||||
void *resp_end = &(&cmd)[1];
|
||||
|
||||
while (buf_ptr < resp_end) {
|
||||
struct MrvlIEtype_keyParamSet *keyparam = buf_ptr;
|
||||
struct enc_key *key;
|
||||
uint16_t param_set_len = le16_to_cpu(keyparam->length);
|
||||
uint16_t key_len = le16_to_cpu(keyparam->keylen);
|
||||
uint16_t key_flags = le16_to_cpu(keyparam->keyinfo);
|
||||
uint16_t key_type = le16_to_cpu(keyparam->keytypeid);
|
||||
void *end;
|
||||
|
||||
end = (void *)keyparam + sizeof(keyparam->type)
|
||||
+ sizeof(keyparam->length) + param_set_len;
|
||||
|
||||
/* Make sure we don't access past the end of the IEs */
|
||||
if (end > resp_end)
|
||||
break;
|
||||
|
||||
if (key_flags & KEY_INFO_WPA_UNICAST)
|
||||
key = &priv->wpa_unicast_key;
|
||||
else if (key_flags & KEY_INFO_WPA_MCAST)
|
||||
key = &priv->wpa_mcast_key;
|
||||
else
|
||||
break;
|
||||
|
||||
/* Copy returned key into driver */
|
||||
memset(key, 0, sizeof(struct enc_key));
|
||||
if (key_len > sizeof(key->key))
|
||||
break;
|
||||
key->type = key_type;
|
||||
key->flags = key_flags;
|
||||
key->len = key_len;
|
||||
memcpy(key->key, keyparam->key, key->len);
|
||||
|
||||
buf_ptr = end + 1;
|
||||
}
|
||||
}
|
||||
|
||||
lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __le16 lbs_rate_to_fw_bitmap(int rate, int lower_rates_ok)
|
||||
{
|
||||
/* Bit Rate
|
||||
* 15:13 Reserved
|
||||
* 12 54 Mbps
|
||||
* 11 48 Mbps
|
||||
* 10 36 Mbps
|
||||
* 9 24 Mbps
|
||||
* 8 18 Mbps
|
||||
* 7 12 Mbps
|
||||
* 6 9 Mbps
|
||||
* 5 6 Mbps
|
||||
* 4 Reserved
|
||||
* 3 11 Mbps
|
||||
* 2 5.5 Mbps
|
||||
* 1 2 Mbps
|
||||
* 0 1 Mbps
|
||||
**/
|
||||
|
||||
uint16_t ratemask;
|
||||
int i = lbs_data_rate_to_fw_index(rate);
|
||||
if (lower_rates_ok)
|
||||
ratemask = (0x1fef >> (12 - i));
|
||||
else
|
||||
ratemask = (1 << i);
|
||||
return cpu_to_le16(ratemask);
|
||||
}
|
||||
|
||||
int lbs_cmd_802_11_rate_adapt_rateset(struct lbs_private *priv,
|
||||
uint16_t cmd_action)
|
||||
{
|
||||
struct cmd_ds_802_11_rate_adapt_rateset cmd;
|
||||
int ret;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_CMD);
|
||||
|
||||
if (!priv->cur_rate && !priv->enablehwauto)
|
||||
return -EINVAL;
|
||||
|
||||
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
|
||||
|
||||
cmd.action = cpu_to_le16(cmd_action);
|
||||
cmd.enablehwauto = cpu_to_le16(priv->enablehwauto);
|
||||
cmd.bitmap = lbs_rate_to_fw_bitmap(priv->cur_rate, priv->enablehwauto);
|
||||
ret = lbs_cmd_with_response(priv, CMD_802_11_RATE_ADAPT_RATESET, &cmd);
|
||||
if (!ret && cmd_action == CMD_ACT_GET) {
|
||||
priv->ratebitmap = le16_to_cpu(cmd.bitmap);
|
||||
priv->enablehwauto = le16_to_cpu(cmd.enablehwauto);
|
||||
}
|
||||
|
||||
lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the data rate
|
||||
*
|
||||
* @param priv A pointer to struct lbs_private structure
|
||||
* @param rate The desired data rate, or 0 to clear a locked rate
|
||||
*
|
||||
* @return 0 on success, error on failure
|
||||
*/
|
||||
int lbs_set_data_rate(struct lbs_private *priv, u8 rate)
|
||||
{
|
||||
struct cmd_ds_802_11_data_rate cmd;
|
||||
int ret = 0;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_CMD);
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
|
||||
|
||||
if (rate > 0) {
|
||||
cmd.action = cpu_to_le16(CMD_ACT_SET_TX_FIX_RATE);
|
||||
cmd.rates[0] = lbs_data_rate_to_fw_index(rate);
|
||||
if (cmd.rates[0] == 0) {
|
||||
lbs_deb_cmd("DATA_RATE: invalid requested rate of"
|
||||
" 0x%02X\n", rate);
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
lbs_deb_cmd("DATA_RATE: set fixed 0x%02X\n", cmd.rates[0]);
|
||||
} else {
|
||||
cmd.action = cpu_to_le16(CMD_ACT_SET_TX_AUTO);
|
||||
lbs_deb_cmd("DATA_RATE: setting auto\n");
|
||||
}
|
||||
|
||||
ret = lbs_cmd_with_response(priv, CMD_802_11_DATA_RATE, &cmd);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
lbs_deb_hex(LBS_DEB_CMD, "DATA_RATE_RESP", (u8 *) &cmd, sizeof(cmd));
|
||||
|
||||
/* FIXME: get actual rates FW can do if this command actually returns
|
||||
* all data rates supported.
|
||||
*/
|
||||
priv->cur_rate = lbs_fw_index_to_data_rate(cmd.rates[0]);
|
||||
lbs_deb_cmd("DATA_RATE: current rate is 0x%02x\n", priv->cur_rate);
|
||||
|
||||
out:
|
||||
lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int lbs_cmd_802_11_rssi(struct lbs_private *priv,
|
||||
struct cmd_ds_command *cmd)
|
||||
{
|
||||
|
||||
lbs_deb_enter(LBS_DEB_CMD);
|
||||
cmd->command = cpu_to_le16(CMD_802_11_RSSI);
|
||||
cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_rssi) +
|
||||
sizeof(struct cmd_header));
|
||||
cmd->params.rssi.N = cpu_to_le16(DEFAULT_BCN_AVG_FACTOR);
|
||||
|
||||
/* reset Beacon SNR/NF/RSSI values */
|
||||
priv->SNR[TYPE_BEACON][TYPE_NOAVG] = 0;
|
||||
priv->SNR[TYPE_BEACON][TYPE_AVG] = 0;
|
||||
priv->NF[TYPE_BEACON][TYPE_NOAVG] = 0;
|
||||
priv->NF[TYPE_BEACON][TYPE_AVG] = 0;
|
||||
priv->RSSI[TYPE_BEACON][TYPE_NOAVG] = 0;
|
||||
priv->RSSI[TYPE_BEACON][TYPE_AVG] = 0;
|
||||
|
||||
lbs_deb_leave(LBS_DEB_CMD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lbs_ret_802_11_rssi(struct lbs_private *priv,
|
||||
struct cmd_ds_command *resp)
|
||||
{
|
||||
struct cmd_ds_802_11_rssi_rsp *rssirsp = &resp->params.rssirsp;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_CMD);
|
||||
|
||||
/* store the non average value */
|
||||
priv->SNR[TYPE_BEACON][TYPE_NOAVG] = get_unaligned_le16(&rssirsp->SNR);
|
||||
priv->NF[TYPE_BEACON][TYPE_NOAVG] =
|
||||
get_unaligned_le16(&rssirsp->noisefloor);
|
||||
|
||||
priv->SNR[TYPE_BEACON][TYPE_AVG] = get_unaligned_le16(&rssirsp->avgSNR);
|
||||
priv->NF[TYPE_BEACON][TYPE_AVG] =
|
||||
get_unaligned_le16(&rssirsp->avgnoisefloor);
|
||||
|
||||
priv->RSSI[TYPE_BEACON][TYPE_NOAVG] =
|
||||
CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_NOAVG],
|
||||
priv->NF[TYPE_BEACON][TYPE_NOAVG]);
|
||||
|
||||
priv->RSSI[TYPE_BEACON][TYPE_AVG] =
|
||||
CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_AVG] / AVG_SCALE,
|
||||
priv->NF[TYPE_BEACON][TYPE_AVG] / AVG_SCALE);
|
||||
|
||||
lbs_deb_cmd("RSSI: beacon %d, avg %d\n",
|
||||
priv->RSSI[TYPE_BEACON][TYPE_NOAVG],
|
||||
priv->RSSI[TYPE_BEACON][TYPE_AVG]);
|
||||
|
||||
lbs_deb_leave(LBS_DEB_CMD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int lbs_cmd_bcn_ctrl(struct lbs_private *priv,
|
||||
struct cmd_ds_command *cmd,
|
||||
u16 cmd_action)
|
||||
{
|
||||
struct cmd_ds_802_11_beacon_control
|
||||
*bcn_ctrl = &cmd->params.bcn_ctrl;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_CMD);
|
||||
cmd->size =
|
||||
cpu_to_le16(sizeof(struct cmd_ds_802_11_beacon_control)
|
||||
+ sizeof(struct cmd_header));
|
||||
cmd->command = cpu_to_le16(CMD_802_11_BEACON_CTRL);
|
||||
|
||||
bcn_ctrl->action = cpu_to_le16(cmd_action);
|
||||
bcn_ctrl->beacon_enable = cpu_to_le16(priv->beacon_enable);
|
||||
bcn_ctrl->beacon_period = cpu_to_le16(priv->beacon_period);
|
||||
|
||||
lbs_deb_leave(LBS_DEB_CMD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lbs_ret_802_11_bcn_ctrl(struct lbs_private *priv,
|
||||
struct cmd_ds_command *resp)
|
||||
{
|
||||
struct cmd_ds_802_11_beacon_control *bcn_ctrl =
|
||||
&resp->params.bcn_ctrl;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_CMD);
|
||||
|
||||
if (bcn_ctrl->action == CMD_ACT_GET) {
|
||||
priv->beacon_enable = (u8) le16_to_cpu(bcn_ctrl->beacon_enable);
|
||||
priv->beacon_period = le16_to_cpu(bcn_ctrl->beacon_period);
|
||||
}
|
||||
|
||||
lbs_deb_enter(LBS_DEB_CMD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int lbs_assoc_post(struct lbs_private *priv,
|
||||
struct cmd_ds_802_11_associate_response *resp)
|
||||
{
|
||||
|
@ -226,7 +624,7 @@ static int lbs_assoc_post(struct lbs_private *priv,
|
|||
priv->connect_status = LBS_CONNECTED;
|
||||
|
||||
/* Update current SSID and BSSID */
|
||||
memcpy(&priv->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE);
|
||||
memcpy(&priv->curbssparams.ssid, &bss->ssid, IEEE80211_MAX_SSID_LEN);
|
||||
priv->curbssparams.ssid_len = bss->ssid_len;
|
||||
memcpy(priv->curbssparams.bssid, bss->bssid, ETH_ALEN);
|
||||
|
||||
|
@ -369,12 +767,7 @@ static int lbs_associate(struct lbs_private *priv,
|
|||
(u16)(pos - (u8 *) &cmd.iebuf));
|
||||
|
||||
/* update curbssparams */
|
||||
priv->curbssparams.channel = bss->phy.ds.channel;
|
||||
|
||||
if (lbs_parse_dnld_countryinfo_11d(priv, bss)) {
|
||||
ret = -1;
|
||||
goto done;
|
||||
}
|
||||
priv->channel = bss->phy.ds.channel;
|
||||
|
||||
ret = lbs_cmd_with_response(priv, command, &cmd);
|
||||
if (ret == 0) {
|
||||
|
@ -472,7 +865,7 @@ static int lbs_adhoc_post(struct lbs_private *priv,
|
|||
memcpy(&priv->curbssparams.bssid, bss->bssid, ETH_ALEN);
|
||||
|
||||
/* Set the new SSID to current SSID */
|
||||
memcpy(&priv->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE);
|
||||
memcpy(&priv->curbssparams.ssid, &bss->ssid, IEEE80211_MAX_SSID_LEN);
|
||||
priv->curbssparams.ssid_len = bss->ssid_len;
|
||||
|
||||
netif_carrier_on(priv->dev);
|
||||
|
@ -487,7 +880,7 @@ static int lbs_adhoc_post(struct lbs_private *priv,
|
|||
lbs_deb_join("ADHOC_RESP: Joined/started '%s', BSSID %pM, channel %d\n",
|
||||
print_ssid(ssid, bss->ssid, bss->ssid_len),
|
||||
priv->curbssparams.bssid,
|
||||
priv->curbssparams.channel);
|
||||
priv->channel);
|
||||
|
||||
done:
|
||||
lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
|
||||
|
@ -560,7 +953,7 @@ static int lbs_adhoc_join(struct lbs_private *priv,
|
|||
lbs_deb_join("AdhocJoin: band = %c\n", assoc_req->band);
|
||||
|
||||
priv->adhoccreate = 0;
|
||||
priv->curbssparams.channel = bss->channel;
|
||||
priv->channel = bss->channel;
|
||||
|
||||
/* Build the join command */
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
|
@ -633,11 +1026,6 @@ static int lbs_adhoc_join(struct lbs_private *priv,
|
|||
}
|
||||
}
|
||||
|
||||
if (lbs_parse_dnld_countryinfo_11d(priv, bss)) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_JOIN, &cmd);
|
||||
if (ret == 0) {
|
||||
ret = lbs_adhoc_post(priv,
|
||||
|
@ -737,12 +1125,6 @@ static int lbs_adhoc_start(struct lbs_private *priv,
|
|||
lbs_deb_join("ADHOC_START: rates=%02x %02x %02x %02x\n",
|
||||
cmd.rates[0], cmd.rates[1], cmd.rates[2], cmd.rates[3]);
|
||||
|
||||
if (lbs_create_dnld_countryinfo_11d(priv)) {
|
||||
lbs_deb_join("ADHOC_START: dnld_countryinfo_11d failed\n");
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
lbs_deb_join("ADHOC_START: Starting Ad-Hoc BSS on channel %d, band %d\n",
|
||||
assoc_req->channel, assoc_req->band);
|
||||
|
||||
|
@ -1099,7 +1481,7 @@ static int assoc_helper_essid(struct lbs_private *priv,
|
|||
/* else send START command */
|
||||
lbs_deb_assoc("SSID not found, creating adhoc network\n");
|
||||
memcpy(&assoc_req->bss.ssid, &assoc_req->ssid,
|
||||
IW_ESSID_MAX_SIZE);
|
||||
IEEE80211_MAX_SSID_LEN);
|
||||
assoc_req->bss.ssid_len = assoc_req->ssid_len;
|
||||
lbs_adhoc_start(priv, assoc_req);
|
||||
}
|
||||
|
@ -1185,7 +1567,8 @@ static int assoc_helper_mode(struct lbs_private *priv,
|
|||
}
|
||||
|
||||
priv->mode = assoc_req->mode;
|
||||
ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, assoc_req->mode);
|
||||
ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE,
|
||||
assoc_req->mode == IW_MODE_ADHOC ? 2 : 1);
|
||||
|
||||
done:
|
||||
lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
|
||||
|
@ -1205,7 +1588,7 @@ static int assoc_helper_channel(struct lbs_private *priv,
|
|||
goto done;
|
||||
}
|
||||
|
||||
if (assoc_req->channel == priv->curbssparams.channel)
|
||||
if (assoc_req->channel == priv->channel)
|
||||
goto done;
|
||||
|
||||
if (priv->mesh_dev) {
|
||||
|
@ -1217,7 +1600,7 @@ static int assoc_helper_channel(struct lbs_private *priv,
|
|||
}
|
||||
|
||||
lbs_deb_assoc("ASSOC: channel: %d -> %d\n",
|
||||
priv->curbssparams.channel, assoc_req->channel);
|
||||
priv->channel, assoc_req->channel);
|
||||
|
||||
ret = lbs_set_channel(priv, assoc_req->channel);
|
||||
if (ret < 0)
|
||||
|
@ -1232,7 +1615,7 @@ static int assoc_helper_channel(struct lbs_private *priv,
|
|||
goto done;
|
||||
}
|
||||
|
||||
if (assoc_req->channel != priv->curbssparams.channel) {
|
||||
if (assoc_req->channel != priv->channel) {
|
||||
lbs_deb_assoc("ASSOC: channel: failed to update channel to %d\n",
|
||||
assoc_req->channel);
|
||||
goto restore_mesh;
|
||||
|
@ -1253,7 +1636,7 @@ static int assoc_helper_channel(struct lbs_private *priv,
|
|||
restore_mesh:
|
||||
if (priv->mesh_dev)
|
||||
lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
|
||||
priv->curbssparams.channel);
|
||||
priv->channel);
|
||||
|
||||
done:
|
||||
lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
|
||||
|
@ -1475,7 +1858,7 @@ static int should_stop_adhoc(struct lbs_private *priv,
|
|||
}
|
||||
|
||||
if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) {
|
||||
if (assoc_req->channel != priv->curbssparams.channel)
|
||||
if (assoc_req->channel != priv->channel)
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1557,7 +1940,7 @@ static int lbs_find_best_network_ssid(struct lbs_private *priv,
|
|||
|
||||
found = lbs_find_best_ssid_in_list(priv, preferred_mode);
|
||||
if (found && (found->ssid_len > 0)) {
|
||||
memcpy(out_ssid, &found->ssid, IW_ESSID_MAX_SIZE);
|
||||
memcpy(out_ssid, &found->ssid, IEEE80211_MAX_SSID_LEN);
|
||||
*out_ssid_len = found->ssid_len;
|
||||
*out_mode = found->mode;
|
||||
ret = 0;
|
||||
|
@ -1775,12 +2158,12 @@ struct assoc_request *lbs_get_association_request(struct lbs_private *priv)
|
|||
assoc_req = priv->pending_assoc_req;
|
||||
if (!test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
|
||||
memcpy(&assoc_req->ssid, &priv->curbssparams.ssid,
|
||||
IW_ESSID_MAX_SIZE);
|
||||
IEEE80211_MAX_SSID_LEN);
|
||||
assoc_req->ssid_len = priv->curbssparams.ssid_len;
|
||||
}
|
||||
|
||||
if (!test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags))
|
||||
assoc_req->channel = priv->curbssparams.channel;
|
||||
assoc_req->channel = priv->channel;
|
||||
|
||||
if (!test_bit(ASSOC_FLAG_BAND, &assoc_req->flags))
|
||||
assoc_req->band = priv->curbssparams.band;
|
||||
|
|
|
@ -3,7 +3,126 @@
|
|||
#ifndef _LBS_ASSOC_H_
|
||||
#define _LBS_ASSOC_H_
|
||||
|
||||
#include "dev.h"
|
||||
|
||||
#include "defs.h"
|
||||
#include "host.h"
|
||||
|
||||
|
||||
struct lbs_private;
|
||||
|
||||
/*
|
||||
* In theory, the IE is limited to the IE length, 255,
|
||||
* but in practice 64 bytes are enough.
|
||||
*/
|
||||
#define MAX_WPA_IE_LEN 64
|
||||
|
||||
|
||||
|
||||
struct lbs_802_11_security {
|
||||
u8 WPAenabled;
|
||||
u8 WPA2enabled;
|
||||
u8 wep_enabled;
|
||||
u8 auth_mode;
|
||||
u32 key_mgmt;
|
||||
};
|
||||
|
||||
/** Current Basic Service Set State Structure */
|
||||
struct current_bss_params {
|
||||
/** bssid */
|
||||
u8 bssid[ETH_ALEN];
|
||||
/** ssid */
|
||||
u8 ssid[IEEE80211_MAX_SSID_LEN + 1];
|
||||
u8 ssid_len;
|
||||
|
||||
/** band */
|
||||
u8 band;
|
||||
/** channel is directly in priv->channel */
|
||||
/** zero-terminated array of supported data rates */
|
||||
u8 rates[MAX_RATES + 1];
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Structure used to store information for each beacon/probe response
|
||||
*/
|
||||
struct bss_descriptor {
|
||||
u8 bssid[ETH_ALEN];
|
||||
|
||||
u8 ssid[IEEE80211_MAX_SSID_LEN + 1];
|
||||
u8 ssid_len;
|
||||
|
||||
u16 capability;
|
||||
u32 rssi;
|
||||
u32 channel;
|
||||
u16 beaconperiod;
|
||||
__le16 atimwindow;
|
||||
|
||||
/* IW_MODE_AUTO, IW_MODE_ADHOC, IW_MODE_INFRA */
|
||||
u8 mode;
|
||||
|
||||
/* zero-terminated array of supported data rates */
|
||||
u8 rates[MAX_RATES + 1];
|
||||
|
||||
unsigned long last_scanned;
|
||||
|
||||
union ieee_phy_param_set phy;
|
||||
union ieee_ss_param_set ss;
|
||||
|
||||
u8 wpa_ie[MAX_WPA_IE_LEN];
|
||||
size_t wpa_ie_len;
|
||||
u8 rsn_ie[MAX_WPA_IE_LEN];
|
||||
size_t rsn_ie_len;
|
||||
|
||||
u8 mesh;
|
||||
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
/** Association request
|
||||
*
|
||||
* Encapsulates all the options that describe a specific assocation request
|
||||
* or configuration of the wireless card's radio, mode, and security settings.
|
||||
*/
|
||||
struct assoc_request {
|
||||
#define ASSOC_FLAG_SSID 1
|
||||
#define ASSOC_FLAG_CHANNEL 2
|
||||
#define ASSOC_FLAG_BAND 3
|
||||
#define ASSOC_FLAG_MODE 4
|
||||
#define ASSOC_FLAG_BSSID 5
|
||||
#define ASSOC_FLAG_WEP_KEYS 6
|
||||
#define ASSOC_FLAG_WEP_TX_KEYIDX 7
|
||||
#define ASSOC_FLAG_WPA_MCAST_KEY 8
|
||||
#define ASSOC_FLAG_WPA_UCAST_KEY 9
|
||||
#define ASSOC_FLAG_SECINFO 10
|
||||
#define ASSOC_FLAG_WPA_IE 11
|
||||
unsigned long flags;
|
||||
|
||||
u8 ssid[IEEE80211_MAX_SSID_LEN + 1];
|
||||
u8 ssid_len;
|
||||
u8 channel;
|
||||
u8 band;
|
||||
u8 mode;
|
||||
u8 bssid[ETH_ALEN] __attribute__ ((aligned (2)));
|
||||
|
||||
/** WEP keys */
|
||||
struct enc_key wep_keys[4];
|
||||
u16 wep_tx_keyidx;
|
||||
|
||||
/** WPA keys */
|
||||
struct enc_key wpa_mcast_key;
|
||||
struct enc_key wpa_unicast_key;
|
||||
|
||||
struct lbs_802_11_security secinfo;
|
||||
|
||||
/** WPA Information Elements*/
|
||||
u8 wpa_ie[MAX_WPA_IE_LEN];
|
||||
u8 wpa_ie_len;
|
||||
|
||||
/* BSS to associate with for infrastructure of Ad-Hoc join */
|
||||
struct bss_descriptor bss;
|
||||
};
|
||||
|
||||
|
||||
extern u8 lbs_bg_rates[MAX_RATES];
|
||||
|
||||
void lbs_association_worker(struct work_struct *work);
|
||||
struct assoc_request *lbs_get_association_request(struct lbs_private *priv);
|
||||
|
@ -13,4 +132,24 @@ int lbs_adhoc_stop(struct lbs_private *priv);
|
|||
int lbs_cmd_80211_deauthenticate(struct lbs_private *priv,
|
||||
u8 bssid[ETH_ALEN], u16 reason);
|
||||
|
||||
int lbs_cmd_802_11_rssi(struct lbs_private *priv,
|
||||
struct cmd_ds_command *cmd);
|
||||
int lbs_ret_802_11_rssi(struct lbs_private *priv,
|
||||
struct cmd_ds_command *resp);
|
||||
|
||||
int lbs_cmd_bcn_ctrl(struct lbs_private *priv,
|
||||
struct cmd_ds_command *cmd,
|
||||
u16 cmd_action);
|
||||
int lbs_ret_802_11_bcn_ctrl(struct lbs_private *priv,
|
||||
struct cmd_ds_command *resp);
|
||||
|
||||
int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action,
|
||||
struct assoc_request *assoc);
|
||||
|
||||
int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action,
|
||||
uint16_t *enable);
|
||||
|
||||
int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action,
|
||||
struct assoc_request *assoc);
|
||||
|
||||
#endif /* _LBS_ASSOC_H */
|
||||
|
|
|
@ -3,18 +3,20 @@
|
|||
* It prepares command and sends it to firmware when it is ready.
|
||||
*/
|
||||
|
||||
#include <net/iw_handler.h>
|
||||
#include <net/lib80211.h>
|
||||
#include <linux/kfifo.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
#include "host.h"
|
||||
#include "hostcmd.h"
|
||||
#include "decl.h"
|
||||
#include "defs.h"
|
||||
#include "dev.h"
|
||||
#include "assoc.h"
|
||||
#include "wext.h"
|
||||
#include "scan.h"
|
||||
#include "cmd.h"
|
||||
|
||||
|
||||
static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv);
|
||||
|
||||
/**
|
||||
|
@ -191,11 +193,6 @@ int lbs_update_hw_spec(struct lbs_private *priv)
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (lbs_set_universaltable(priv, 0)) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
lbs_deb_leave(LBS_DEB_CMD);
|
||||
return ret;
|
||||
|
@ -244,7 +241,7 @@ static int lbs_cmd_802_11_ps_mode(struct cmd_ds_command *cmd,
|
|||
|
||||
cmd->command = cpu_to_le16(CMD_802_11_PS_MODE);
|
||||
cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ps_mode) +
|
||||
S_DS_GEN);
|
||||
sizeof(struct cmd_header));
|
||||
psm->action = cpu_to_le16(cmd_action);
|
||||
psm->multipledtim = 0;
|
||||
switch (cmd_action) {
|
||||
|
@ -273,33 +270,6 @@ static int lbs_cmd_802_11_ps_mode(struct cmd_ds_command *cmd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int lbs_cmd_802_11_inactivity_timeout(struct lbs_private *priv,
|
||||
uint16_t cmd_action, uint16_t *timeout)
|
||||
{
|
||||
struct cmd_ds_802_11_inactivity_timeout cmd;
|
||||
int ret;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_CMD);
|
||||
|
||||
cmd.hdr.command = cpu_to_le16(CMD_802_11_INACTIVITY_TIMEOUT);
|
||||
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
|
||||
|
||||
cmd.action = cpu_to_le16(cmd_action);
|
||||
|
||||
if (cmd_action == CMD_ACT_SET)
|
||||
cmd.timeout = cpu_to_le16(*timeout);
|
||||
else
|
||||
cmd.timeout = 0;
|
||||
|
||||
ret = lbs_cmd_with_response(priv, CMD_802_11_INACTIVITY_TIMEOUT, &cmd);
|
||||
|
||||
if (!ret)
|
||||
*timeout = le16_to_cpu(cmd.timeout);
|
||||
|
||||
lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action,
|
||||
struct sleep_params *sp)
|
||||
{
|
||||
|
@ -396,197 +366,6 @@ int lbs_set_deep_sleep(struct lbs_private *priv, int deep_sleep)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action,
|
||||
struct assoc_request *assoc)
|
||||
{
|
||||
struct cmd_ds_802_11_set_wep cmd;
|
||||
int ret = 0;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_CMD);
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
cmd.hdr.command = cpu_to_le16(CMD_802_11_SET_WEP);
|
||||
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
|
||||
|
||||
cmd.action = cpu_to_le16(cmd_action);
|
||||
|
||||
if (cmd_action == CMD_ACT_ADD) {
|
||||
int i;
|
||||
|
||||
/* default tx key index */
|
||||
cmd.keyindex = cpu_to_le16(assoc->wep_tx_keyidx &
|
||||
CMD_WEP_KEY_INDEX_MASK);
|
||||
|
||||
/* Copy key types and material to host command structure */
|
||||
for (i = 0; i < 4; i++) {
|
||||
struct enc_key *pkey = &assoc->wep_keys[i];
|
||||
|
||||
switch (pkey->len) {
|
||||
case KEY_LEN_WEP_40:
|
||||
cmd.keytype[i] = CMD_TYPE_WEP_40_BIT;
|
||||
memmove(cmd.keymaterial[i], pkey->key, pkey->len);
|
||||
lbs_deb_cmd("SET_WEP: add key %d (40 bit)\n", i);
|
||||
break;
|
||||
case KEY_LEN_WEP_104:
|
||||
cmd.keytype[i] = CMD_TYPE_WEP_104_BIT;
|
||||
memmove(cmd.keymaterial[i], pkey->key, pkey->len);
|
||||
lbs_deb_cmd("SET_WEP: add key %d (104 bit)\n", i);
|
||||
break;
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
lbs_deb_cmd("SET_WEP: invalid key %d, length %d\n",
|
||||
i, pkey->len);
|
||||
ret = -1;
|
||||
goto done;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (cmd_action == CMD_ACT_REMOVE) {
|
||||
/* ACT_REMOVE clears _all_ WEP keys */
|
||||
|
||||
/* default tx key index */
|
||||
cmd.keyindex = cpu_to_le16(priv->wep_tx_keyidx &
|
||||
CMD_WEP_KEY_INDEX_MASK);
|
||||
lbs_deb_cmd("SET_WEP: remove key %d\n", priv->wep_tx_keyidx);
|
||||
}
|
||||
|
||||
ret = lbs_cmd_with_response(priv, CMD_802_11_SET_WEP, &cmd);
|
||||
done:
|
||||
lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action,
|
||||
uint16_t *enable)
|
||||
{
|
||||
struct cmd_ds_802_11_enable_rsn cmd;
|
||||
int ret;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_CMD);
|
||||
|
||||
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
|
||||
cmd.action = cpu_to_le16(cmd_action);
|
||||
|
||||
if (cmd_action == CMD_ACT_GET)
|
||||
cmd.enable = 0;
|
||||
else {
|
||||
if (*enable)
|
||||
cmd.enable = cpu_to_le16(CMD_ENABLE_RSN);
|
||||
else
|
||||
cmd.enable = cpu_to_le16(CMD_DISABLE_RSN);
|
||||
lbs_deb_cmd("ENABLE_RSN: %d\n", *enable);
|
||||
}
|
||||
|
||||
ret = lbs_cmd_with_response(priv, CMD_802_11_ENABLE_RSN, &cmd);
|
||||
if (!ret && cmd_action == CMD_ACT_GET)
|
||||
*enable = le16_to_cpu(cmd.enable);
|
||||
|
||||
lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void set_one_wpa_key(struct MrvlIEtype_keyParamSet *keyparam,
|
||||
struct enc_key *key)
|
||||
{
|
||||
lbs_deb_enter(LBS_DEB_CMD);
|
||||
|
||||
if (key->flags & KEY_INFO_WPA_ENABLED)
|
||||
keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_ENABLED);
|
||||
if (key->flags & KEY_INFO_WPA_UNICAST)
|
||||
keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_UNICAST);
|
||||
if (key->flags & KEY_INFO_WPA_MCAST)
|
||||
keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_MCAST);
|
||||
|
||||
keyparam->type = cpu_to_le16(TLV_TYPE_KEY_MATERIAL);
|
||||
keyparam->keytypeid = cpu_to_le16(key->type);
|
||||
keyparam->keylen = cpu_to_le16(key->len);
|
||||
memcpy(keyparam->key, key->key, key->len);
|
||||
|
||||
/* Length field doesn't include the {type,length} header */
|
||||
keyparam->length = cpu_to_le16(sizeof(*keyparam) - 4);
|
||||
lbs_deb_leave(LBS_DEB_CMD);
|
||||
}
|
||||
|
||||
int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action,
|
||||
struct assoc_request *assoc)
|
||||
{
|
||||
struct cmd_ds_802_11_key_material cmd;
|
||||
int ret = 0;
|
||||
int index = 0;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_CMD);
|
||||
|
||||
cmd.action = cpu_to_le16(cmd_action);
|
||||
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
|
||||
|
||||
if (cmd_action == CMD_ACT_GET) {
|
||||
cmd.hdr.size = cpu_to_le16(S_DS_GEN + 2);
|
||||
} else {
|
||||
memset(cmd.keyParamSet, 0, sizeof(cmd.keyParamSet));
|
||||
|
||||
if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc->flags)) {
|
||||
set_one_wpa_key(&cmd.keyParamSet[index],
|
||||
&assoc->wpa_unicast_key);
|
||||
index++;
|
||||
}
|
||||
|
||||
if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc->flags)) {
|
||||
set_one_wpa_key(&cmd.keyParamSet[index],
|
||||
&assoc->wpa_mcast_key);
|
||||
index++;
|
||||
}
|
||||
|
||||
/* The common header and as many keys as we included */
|
||||
cmd.hdr.size = cpu_to_le16(offsetof(typeof(cmd),
|
||||
keyParamSet[index]));
|
||||
}
|
||||
ret = lbs_cmd_with_response(priv, CMD_802_11_KEY_MATERIAL, &cmd);
|
||||
/* Copy the returned key to driver private data */
|
||||
if (!ret && cmd_action == CMD_ACT_GET) {
|
||||
void *buf_ptr = cmd.keyParamSet;
|
||||
void *resp_end = &(&cmd)[1];
|
||||
|
||||
while (buf_ptr < resp_end) {
|
||||
struct MrvlIEtype_keyParamSet *keyparam = buf_ptr;
|
||||
struct enc_key *key;
|
||||
uint16_t param_set_len = le16_to_cpu(keyparam->length);
|
||||
uint16_t key_len = le16_to_cpu(keyparam->keylen);
|
||||
uint16_t key_flags = le16_to_cpu(keyparam->keyinfo);
|
||||
uint16_t key_type = le16_to_cpu(keyparam->keytypeid);
|
||||
void *end;
|
||||
|
||||
end = (void *)keyparam + sizeof(keyparam->type)
|
||||
+ sizeof(keyparam->length) + param_set_len;
|
||||
|
||||
/* Make sure we don't access past the end of the IEs */
|
||||
if (end > resp_end)
|
||||
break;
|
||||
|
||||
if (key_flags & KEY_INFO_WPA_UNICAST)
|
||||
key = &priv->wpa_unicast_key;
|
||||
else if (key_flags & KEY_INFO_WPA_MCAST)
|
||||
key = &priv->wpa_mcast_key;
|
||||
else
|
||||
break;
|
||||
|
||||
/* Copy returned key into driver */
|
||||
memset(key, 0, sizeof(struct enc_key));
|
||||
if (key_len > sizeof(key->key))
|
||||
break;
|
||||
key->type = key_type;
|
||||
key->flags = key_flags;
|
||||
key->len = key_len;
|
||||
memcpy(key->key, keyparam->key, key->len);
|
||||
|
||||
buf_ptr = end + 1;
|
||||
}
|
||||
}
|
||||
|
||||
lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set an SNMP MIB value
|
||||
*
|
||||
|
@ -611,7 +390,7 @@ int lbs_set_snmp_mib(struct lbs_private *priv, u32 oid, u16 val)
|
|||
switch (oid) {
|
||||
case SNMP_MIB_OID_BSS_TYPE:
|
||||
cmd.bufsize = cpu_to_le16(sizeof(u8));
|
||||
cmd.value[0] = (val == IW_MODE_ADHOC) ? 2 : 1;
|
||||
cmd.value[0] = val;
|
||||
break;
|
||||
case SNMP_MIB_OID_11D_ENABLE:
|
||||
case SNMP_MIB_OID_FRAG_THRESHOLD:
|
||||
|
@ -664,13 +443,7 @@ int lbs_get_snmp_mib(struct lbs_private *priv, u32 oid, u16 *out_val)
|
|||
|
||||
switch (le16_to_cpu(cmd.bufsize)) {
|
||||
case sizeof(u8):
|
||||
if (oid == SNMP_MIB_OID_BSS_TYPE) {
|
||||
if (cmd.value[0] == 2)
|
||||
*out_val = IW_MODE_ADHOC;
|
||||
else
|
||||
*out_val = IW_MODE_INFRA;
|
||||
} else
|
||||
*out_val = cmd.value[0];
|
||||
*out_val = cmd.value[0];
|
||||
break;
|
||||
case sizeof(u16):
|
||||
*out_val = le16_to_cpu(*((__le16 *)(&cmd.value)));
|
||||
|
@ -757,7 +530,7 @@ static int lbs_cmd_802_11_monitor_mode(struct cmd_ds_command *cmd,
|
|||
cmd->command = cpu_to_le16(CMD_802_11_MONITOR_MODE);
|
||||
cmd->size =
|
||||
cpu_to_le16(sizeof(struct cmd_ds_802_11_monitor_mode) +
|
||||
S_DS_GEN);
|
||||
sizeof(struct cmd_header));
|
||||
|
||||
monitor->action = cpu_to_le16(cmd_action);
|
||||
if (cmd_action == CMD_ACT_SET) {
|
||||
|
@ -768,111 +541,6 @@ static int lbs_cmd_802_11_monitor_mode(struct cmd_ds_command *cmd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static __le16 lbs_rate_to_fw_bitmap(int rate, int lower_rates_ok)
|
||||
{
|
||||
/* Bit Rate
|
||||
* 15:13 Reserved
|
||||
* 12 54 Mbps
|
||||
* 11 48 Mbps
|
||||
* 10 36 Mbps
|
||||
* 9 24 Mbps
|
||||
* 8 18 Mbps
|
||||
* 7 12 Mbps
|
||||
* 6 9 Mbps
|
||||
* 5 6 Mbps
|
||||
* 4 Reserved
|
||||
* 3 11 Mbps
|
||||
* 2 5.5 Mbps
|
||||
* 1 2 Mbps
|
||||
* 0 1 Mbps
|
||||
**/
|
||||
|
||||
uint16_t ratemask;
|
||||
int i = lbs_data_rate_to_fw_index(rate);
|
||||
if (lower_rates_ok)
|
||||
ratemask = (0x1fef >> (12 - i));
|
||||
else
|
||||
ratemask = (1 << i);
|
||||
return cpu_to_le16(ratemask);
|
||||
}
|
||||
|
||||
int lbs_cmd_802_11_rate_adapt_rateset(struct lbs_private *priv,
|
||||
uint16_t cmd_action)
|
||||
{
|
||||
struct cmd_ds_802_11_rate_adapt_rateset cmd;
|
||||
int ret;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_CMD);
|
||||
|
||||
if (!priv->cur_rate && !priv->enablehwauto)
|
||||
return -EINVAL;
|
||||
|
||||
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
|
||||
|
||||
cmd.action = cpu_to_le16(cmd_action);
|
||||
cmd.enablehwauto = cpu_to_le16(priv->enablehwauto);
|
||||
cmd.bitmap = lbs_rate_to_fw_bitmap(priv->cur_rate, priv->enablehwauto);
|
||||
ret = lbs_cmd_with_response(priv, CMD_802_11_RATE_ADAPT_RATESET, &cmd);
|
||||
if (!ret && cmd_action == CMD_ACT_GET) {
|
||||
priv->ratebitmap = le16_to_cpu(cmd.bitmap);
|
||||
priv->enablehwauto = le16_to_cpu(cmd.enablehwauto);
|
||||
}
|
||||
|
||||
lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(lbs_cmd_802_11_rate_adapt_rateset);
|
||||
|
||||
/**
|
||||
* @brief Set the data rate
|
||||
*
|
||||
* @param priv A pointer to struct lbs_private structure
|
||||
* @param rate The desired data rate, or 0 to clear a locked rate
|
||||
*
|
||||
* @return 0 on success, error on failure
|
||||
*/
|
||||
int lbs_set_data_rate(struct lbs_private *priv, u8 rate)
|
||||
{
|
||||
struct cmd_ds_802_11_data_rate cmd;
|
||||
int ret = 0;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_CMD);
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
|
||||
|
||||
if (rate > 0) {
|
||||
cmd.action = cpu_to_le16(CMD_ACT_SET_TX_FIX_RATE);
|
||||
cmd.rates[0] = lbs_data_rate_to_fw_index(rate);
|
||||
if (cmd.rates[0] == 0) {
|
||||
lbs_deb_cmd("DATA_RATE: invalid requested rate of"
|
||||
" 0x%02X\n", rate);
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
lbs_deb_cmd("DATA_RATE: set fixed 0x%02X\n", cmd.rates[0]);
|
||||
} else {
|
||||
cmd.action = cpu_to_le16(CMD_ACT_SET_TX_AUTO);
|
||||
lbs_deb_cmd("DATA_RATE: setting auto\n");
|
||||
}
|
||||
|
||||
ret = lbs_cmd_with_response(priv, CMD_802_11_DATA_RATE, &cmd);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
lbs_deb_hex(LBS_DEB_CMD, "DATA_RATE_RESP", (u8 *) &cmd, sizeof (cmd));
|
||||
|
||||
/* FIXME: get actual rates FW can do if this command actually returns
|
||||
* all data rates supported.
|
||||
*/
|
||||
priv->cur_rate = lbs_fw_index_to_data_rate(cmd.rates[0]);
|
||||
lbs_deb_cmd("DATA_RATE: current rate is 0x%02x\n", priv->cur_rate);
|
||||
|
||||
out:
|
||||
lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the radio channel
|
||||
*
|
||||
|
@ -880,7 +548,7 @@ out:
|
|||
*
|
||||
* @return The channel on success, error on failure
|
||||
*/
|
||||
int lbs_get_channel(struct lbs_private *priv)
|
||||
static int lbs_get_channel(struct lbs_private *priv)
|
||||
{
|
||||
struct cmd_ds_802_11_rf_channel cmd;
|
||||
int ret = 0;
|
||||
|
@ -912,7 +580,7 @@ int lbs_update_channel(struct lbs_private *priv)
|
|||
|
||||
ret = lbs_get_channel(priv);
|
||||
if (ret > 0) {
|
||||
priv->curbssparams.channel = ret;
|
||||
priv->channel = ret;
|
||||
ret = 0;
|
||||
}
|
||||
lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
|
||||
|
@ -931,7 +599,7 @@ int lbs_set_channel(struct lbs_private *priv, u8 channel)
|
|||
{
|
||||
struct cmd_ds_802_11_rf_channel cmd;
|
||||
#ifdef DEBUG
|
||||
u8 old_channel = priv->curbssparams.channel;
|
||||
u8 old_channel = priv->channel;
|
||||
#endif
|
||||
int ret = 0;
|
||||
|
||||
|
@ -946,36 +614,15 @@ int lbs_set_channel(struct lbs_private *priv, u8 channel)
|
|||
if (ret)
|
||||
goto out;
|
||||
|
||||
priv->curbssparams.channel = (uint8_t) le16_to_cpu(cmd.channel);
|
||||
priv->channel = (uint8_t) le16_to_cpu(cmd.channel);
|
||||
lbs_deb_cmd("channel switch from %d to %d\n", old_channel,
|
||||
priv->curbssparams.channel);
|
||||
priv->channel);
|
||||
|
||||
out:
|
||||
lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int lbs_cmd_802_11_rssi(struct lbs_private *priv,
|
||||
struct cmd_ds_command *cmd)
|
||||
{
|
||||
|
||||
lbs_deb_enter(LBS_DEB_CMD);
|
||||
cmd->command = cpu_to_le16(CMD_802_11_RSSI);
|
||||
cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_rssi) + S_DS_GEN);
|
||||
cmd->params.rssi.N = cpu_to_le16(DEFAULT_BCN_AVG_FACTOR);
|
||||
|
||||
/* reset Beacon SNR/NF/RSSI values */
|
||||
priv->SNR[TYPE_BEACON][TYPE_NOAVG] = 0;
|
||||
priv->SNR[TYPE_BEACON][TYPE_AVG] = 0;
|
||||
priv->NF[TYPE_BEACON][TYPE_NOAVG] = 0;
|
||||
priv->NF[TYPE_BEACON][TYPE_AVG] = 0;
|
||||
priv->RSSI[TYPE_BEACON][TYPE_NOAVG] = 0;
|
||||
priv->RSSI[TYPE_BEACON][TYPE_AVG] = 0;
|
||||
|
||||
lbs_deb_leave(LBS_DEB_CMD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lbs_cmd_reg_access(struct cmd_ds_command *cmdptr,
|
||||
u8 cmd_action, void *pdata_buf)
|
||||
{
|
||||
|
@ -992,7 +639,7 @@ static int lbs_cmd_reg_access(struct cmd_ds_command *cmdptr,
|
|||
|
||||
cmdptr->size =
|
||||
cpu_to_le16(sizeof (struct cmd_ds_mac_reg_access)
|
||||
+ S_DS_GEN);
|
||||
+ sizeof(struct cmd_header));
|
||||
macreg =
|
||||
(struct cmd_ds_mac_reg_access *)&cmdptr->params.
|
||||
macreg;
|
||||
|
@ -1011,7 +658,7 @@ static int lbs_cmd_reg_access(struct cmd_ds_command *cmdptr,
|
|||
cmdptr->size =
|
||||
cpu_to_le16(sizeof
|
||||
(struct cmd_ds_bbp_reg_access)
|
||||
+ S_DS_GEN);
|
||||
+ sizeof(struct cmd_header));
|
||||
bbpreg =
|
||||
(struct cmd_ds_bbp_reg_access *)&cmdptr->params.
|
||||
bbpreg;
|
||||
|
@ -1030,7 +677,7 @@ static int lbs_cmd_reg_access(struct cmd_ds_command *cmdptr,
|
|||
cmdptr->size =
|
||||
cpu_to_le16(sizeof
|
||||
(struct cmd_ds_rf_reg_access) +
|
||||
S_DS_GEN);
|
||||
sizeof(struct cmd_header));
|
||||
rfreg =
|
||||
(struct cmd_ds_rf_reg_access *)&cmdptr->params.
|
||||
rfreg;
|
||||
|
@ -1057,7 +704,8 @@ static int lbs_cmd_bt_access(struct cmd_ds_command *cmd,
|
|||
lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
|
||||
|
||||
cmd->command = cpu_to_le16(CMD_BT_ACCESS);
|
||||
cmd->size = cpu_to_le16(sizeof(struct cmd_ds_bt_access) + S_DS_GEN);
|
||||
cmd->size = cpu_to_le16(sizeof(struct cmd_ds_bt_access) +
|
||||
sizeof(struct cmd_header));
|
||||
cmd->result = 0;
|
||||
bt_access->action = cpu_to_le16(cmd_action);
|
||||
|
||||
|
@ -1094,7 +742,8 @@ static int lbs_cmd_fwt_access(struct cmd_ds_command *cmd,
|
|||
lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
|
||||
|
||||
cmd->command = cpu_to_le16(CMD_FWT_ACCESS);
|
||||
cmd->size = cpu_to_le16(sizeof(struct cmd_ds_fwt_access) + S_DS_GEN);
|
||||
cmd->size = cpu_to_le16(sizeof(struct cmd_ds_fwt_access) +
|
||||
sizeof(struct cmd_header));
|
||||
cmd->result = 0;
|
||||
|
||||
if (pdata_buf)
|
||||
|
@ -1200,7 +849,7 @@ int lbs_mesh_config(struct lbs_private *priv, uint16_t action, uint16_t chan)
|
|||
ie->val.mesh_id_len = priv->mesh_ssid_len;
|
||||
memcpy(ie->val.mesh_id, priv->mesh_ssid, priv->mesh_ssid_len);
|
||||
ie->len = sizeof(struct mrvl_meshie_val) -
|
||||
IW_ESSID_MAX_SIZE + priv->mesh_ssid_len;
|
||||
IEEE80211_MAX_SSID_LEN + priv->mesh_ssid_len;
|
||||
cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie_val));
|
||||
break;
|
||||
case CMD_ACT_MESH_CONFIG_STOP:
|
||||
|
@ -1215,27 +864,6 @@ int lbs_mesh_config(struct lbs_private *priv, uint16_t action, uint16_t chan)
|
|||
return __lbs_mesh_config_send(priv, &cmd, action, priv->mesh_tlv);
|
||||
}
|
||||
|
||||
static int lbs_cmd_bcn_ctrl(struct lbs_private * priv,
|
||||
struct cmd_ds_command *cmd,
|
||||
u16 cmd_action)
|
||||
{
|
||||
struct cmd_ds_802_11_beacon_control
|
||||
*bcn_ctrl = &cmd->params.bcn_ctrl;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_CMD);
|
||||
cmd->size =
|
||||
cpu_to_le16(sizeof(struct cmd_ds_802_11_beacon_control)
|
||||
+ S_DS_GEN);
|
||||
cmd->command = cpu_to_le16(CMD_802_11_BEACON_CTRL);
|
||||
|
||||
bcn_ctrl->action = cpu_to_le16(cmd_action);
|
||||
bcn_ctrl->beacon_enable = cpu_to_le16(priv->beacon_enable);
|
||||
bcn_ctrl->beacon_period = cpu_to_le16(priv->beacon_period);
|
||||
|
||||
lbs_deb_leave(LBS_DEB_CMD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void lbs_queue_cmd(struct lbs_private *priv,
|
||||
struct cmd_ctrl_node *cmdnode)
|
||||
{
|
||||
|
@ -1531,7 +1159,7 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
|
|||
|
||||
cmdptr->command = cpu_to_le16(cmd_no);
|
||||
cmdptr->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_afc) +
|
||||
S_DS_GEN);
|
||||
sizeof(struct cmd_header));
|
||||
|
||||
memmove(&cmdptr->params.afc,
|
||||
pdata_buf, sizeof(struct cmd_ds_802_11_afc));
|
||||
|
@ -1539,45 +1167,17 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
|
|||
ret = 0;
|
||||
goto done;
|
||||
|
||||
case CMD_802_11D_DOMAIN_INFO:
|
||||
ret = lbs_cmd_802_11d_domain_info(priv, cmdptr,
|
||||
cmd_no, cmd_action);
|
||||
break;
|
||||
|
||||
case CMD_802_11_TPC_CFG:
|
||||
cmdptr->command = cpu_to_le16(CMD_802_11_TPC_CFG);
|
||||
cmdptr->size =
|
||||
cpu_to_le16(sizeof(struct cmd_ds_802_11_tpc_cfg) +
|
||||
S_DS_GEN);
|
||||
sizeof(struct cmd_header));
|
||||
|
||||
memmove(&cmdptr->params.tpccfg,
|
||||
pdata_buf, sizeof(struct cmd_ds_802_11_tpc_cfg));
|
||||
|
||||
ret = 0;
|
||||
break;
|
||||
case CMD_802_11_LED_GPIO_CTRL:
|
||||
{
|
||||
struct mrvl_ie_ledgpio *gpio =
|
||||
(struct mrvl_ie_ledgpio*)
|
||||
cmdptr->params.ledgpio.data;
|
||||
|
||||
memmove(&cmdptr->params.ledgpio,
|
||||
pdata_buf,
|
||||
sizeof(struct cmd_ds_802_11_led_ctrl));
|
||||
|
||||
cmdptr->command =
|
||||
cpu_to_le16(CMD_802_11_LED_GPIO_CTRL);
|
||||
|
||||
#define ACTION_NUMLED_TLVTYPE_LEN_FIELDS_LEN 8
|
||||
cmdptr->size =
|
||||
cpu_to_le16(le16_to_cpu(gpio->header.len)
|
||||
+ S_DS_GEN
|
||||
+ ACTION_NUMLED_TLVTYPE_LEN_FIELDS_LEN);
|
||||
gpio->header.len = gpio->header.len;
|
||||
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case CMD_BT_ACCESS:
|
||||
ret = lbs_cmd_bt_access(cmdptr, cmd_action, pdata_buf);
|
||||
|
@ -1587,18 +1187,12 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
|
|||
ret = lbs_cmd_fwt_access(cmdptr, cmd_action, pdata_buf);
|
||||
break;
|
||||
|
||||
case CMD_GET_TSF:
|
||||
cmdptr->command = cpu_to_le16(CMD_GET_TSF);
|
||||
cmdptr->size = cpu_to_le16(sizeof(struct cmd_ds_get_tsf) +
|
||||
S_DS_GEN);
|
||||
ret = 0;
|
||||
break;
|
||||
case CMD_802_11_BEACON_CTRL:
|
||||
ret = lbs_cmd_bcn_ctrl(priv, cmdptr, cmd_action);
|
||||
break;
|
||||
case CMD_802_11_DEEP_SLEEP:
|
||||
cmdptr->command = cpu_to_le16(CMD_802_11_DEEP_SLEEP);
|
||||
cmdptr->size = cpu_to_le16(S_DS_GEN);
|
||||
cmdptr->size = cpu_to_le16(sizeof(struct cmd_header));
|
||||
break;
|
||||
default:
|
||||
lbs_pr_err("PREP_CMD: unknown command 0x%04x\n", cmd_no);
|
||||
|
@ -1917,30 +1511,6 @@ done:
|
|||
return ret;
|
||||
}
|
||||
|
||||
void lbs_send_iwevcustom_event(struct lbs_private *priv, s8 *str)
|
||||
{
|
||||
union iwreq_data iwrq;
|
||||
u8 buf[50];
|
||||
|
||||
lbs_deb_enter(LBS_DEB_WEXT);
|
||||
|
||||
memset(&iwrq, 0, sizeof(union iwreq_data));
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
snprintf(buf, sizeof(buf) - 1, "%s", str);
|
||||
|
||||
iwrq.data.length = strlen(buf) + 1 + IW_EV_LCP_LEN;
|
||||
|
||||
/* Send Event to upper layer */
|
||||
lbs_deb_wext("event indication string %s\n", (char *)buf);
|
||||
lbs_deb_wext("event indication length %d\n", iwrq.data.length);
|
||||
lbs_deb_wext("sending wireless event IWEVCUSTOM for %s\n", str);
|
||||
|
||||
wireless_send_event(priv->dev, IWEVCUSTOM, &iwrq, buf);
|
||||
|
||||
lbs_deb_leave(LBS_DEB_WEXT);
|
||||
}
|
||||
|
||||
static void lbs_send_confirmsleep(struct lbs_private *priv)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
@ -2118,7 +1688,7 @@ int lbs_set_power_adapt_cfg(struct lbs_private *priv, int enable, int8_t p0,
|
|||
}
|
||||
|
||||
|
||||
static struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv,
|
||||
struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv,
|
||||
uint16_t command, struct cmd_header *in_cmd, int in_cmd_size,
|
||||
int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),
|
||||
unsigned long callback_arg)
|
||||
|
@ -2216,5 +1786,3 @@ done:
|
|||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(__lbs_cmd);
|
||||
|
||||
|
||||
|
|
|
@ -3,11 +3,30 @@
|
|||
#ifndef _LBS_CMD_H_
|
||||
#define _LBS_CMD_H_
|
||||
|
||||
#include "hostcmd.h"
|
||||
#include "host.h"
|
||||
#include "dev.h"
|
||||
|
||||
|
||||
/* Command & response transfer between host and card */
|
||||
|
||||
struct cmd_ctrl_node {
|
||||
struct list_head list;
|
||||
int result;
|
||||
/* command response */
|
||||
int (*callback)(struct lbs_private *,
|
||||
unsigned long,
|
||||
struct cmd_header *);
|
||||
unsigned long callback_arg;
|
||||
/* command data */
|
||||
struct cmd_header *cmdbuf;
|
||||
/* wait queue */
|
||||
u16 cmdwaitqwoken;
|
||||
wait_queue_head_t cmdwait_q;
|
||||
};
|
||||
|
||||
|
||||
/* lbs_cmd() infers the size of the buffer to copy data back into, from
|
||||
the size of the target of the pointer. Since the command to be sent
|
||||
the size of the target of the pointer. Since the command to be sent
|
||||
may often be smaller, that size is set in cmd->size by the caller.*/
|
||||
#define lbs_cmd(priv, cmdnr, cmd, cb, cb_arg) ({ \
|
||||
uint16_t __sz = le16_to_cpu((cmd)->hdr.size); \
|
||||
|
@ -18,6 +37,11 @@
|
|||
#define lbs_cmd_with_response(priv, cmdnr, cmd) \
|
||||
lbs_cmd(priv, cmdnr, cmd, lbs_cmd_copyback, (unsigned long) (cmd))
|
||||
|
||||
int lbs_prepare_and_send_command(struct lbs_private *priv,
|
||||
u16 cmd_no,
|
||||
u16 cmd_action,
|
||||
u16 wait_option, u32 cmd_oid, void *pdata_buf);
|
||||
|
||||
void lbs_cmd_async(struct lbs_private *priv, uint16_t command,
|
||||
struct cmd_header *in_cmd, int in_cmd_size);
|
||||
|
||||
|
@ -26,62 +50,93 @@ int __lbs_cmd(struct lbs_private *priv, uint16_t command,
|
|||
int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),
|
||||
unsigned long callback_arg);
|
||||
|
||||
int lbs_set_power_adapt_cfg(struct lbs_private *priv, int enable, int8_t p0,
|
||||
int8_t p1, int8_t p2);
|
||||
|
||||
int lbs_set_tpc_cfg(struct lbs_private *priv, int enable, int8_t p0, int8_t p1,
|
||||
int8_t p2, int usesnr);
|
||||
|
||||
int lbs_set_power_adapt_cfg(struct lbs_private *priv, int enable, int8_t p0,
|
||||
int8_t p1, int8_t p2);
|
||||
|
||||
int lbs_set_tpc_cfg(struct lbs_private *priv, int enable, int8_t p0, int8_t p1,
|
||||
int8_t p2, int usesnr);
|
||||
struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv,
|
||||
uint16_t command, struct cmd_header *in_cmd, int in_cmd_size,
|
||||
int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),
|
||||
unsigned long callback_arg);
|
||||
|
||||
int lbs_cmd_copyback(struct lbs_private *priv, unsigned long extra,
|
||||
struct cmd_header *resp);
|
||||
|
||||
int lbs_allocate_cmd_buffer(struct lbs_private *priv);
|
||||
int lbs_free_cmd_buffer(struct lbs_private *priv);
|
||||
|
||||
int lbs_execute_next_command(struct lbs_private *priv);
|
||||
void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
|
||||
int result);
|
||||
int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len);
|
||||
|
||||
|
||||
/* From cmdresp.c */
|
||||
|
||||
void lbs_mac_event_disconnected(struct lbs_private *priv);
|
||||
|
||||
|
||||
|
||||
/* Events */
|
||||
|
||||
int lbs_process_event(struct lbs_private *priv, u32 event);
|
||||
|
||||
|
||||
/* Actual commands */
|
||||
|
||||
int lbs_update_hw_spec(struct lbs_private *priv);
|
||||
|
||||
int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action,
|
||||
struct cmd_ds_mesh_access *cmd);
|
||||
|
||||
int lbs_set_data_rate(struct lbs_private *priv, u8 rate);
|
||||
|
||||
int lbs_get_channel(struct lbs_private *priv);
|
||||
int lbs_set_channel(struct lbs_private *priv, u8 channel);
|
||||
|
||||
int lbs_mesh_config_send(struct lbs_private *priv,
|
||||
struct cmd_ds_mesh_config *cmd,
|
||||
uint16_t action, uint16_t type);
|
||||
int lbs_mesh_config(struct lbs_private *priv, uint16_t enable, uint16_t chan);
|
||||
int lbs_update_channel(struct lbs_private *priv);
|
||||
|
||||
int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria,
|
||||
struct wol_config *p_wol_config);
|
||||
int lbs_suspend(struct lbs_private *priv);
|
||||
void lbs_resume(struct lbs_private *priv);
|
||||
|
||||
int lbs_cmd_802_11_rate_adapt_rateset(struct lbs_private *priv,
|
||||
uint16_t cmd_action);
|
||||
int lbs_cmd_802_11_inactivity_timeout(struct lbs_private *priv,
|
||||
uint16_t cmd_action, uint16_t *timeout);
|
||||
int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action,
|
||||
struct sleep_params *sp);
|
||||
int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action,
|
||||
struct assoc_request *assoc);
|
||||
int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action,
|
||||
uint16_t *enable);
|
||||
int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action,
|
||||
struct assoc_request *assoc);
|
||||
|
||||
void lbs_ps_sleep(struct lbs_private *priv, int wait_option);
|
||||
|
||||
void lbs_ps_wakeup(struct lbs_private *priv, int wait_option);
|
||||
|
||||
void lbs_ps_confirm_sleep(struct lbs_private *priv);
|
||||
|
||||
int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on);
|
||||
|
||||
void lbs_set_mac_control(struct lbs_private *priv);
|
||||
|
||||
int lbs_get_tx_power(struct lbs_private *priv, s16 *curlevel, s16 *minlevel,
|
||||
s16 *maxlevel);
|
||||
int lbs_set_tx_power(struct lbs_private *priv, s16 dbm);
|
||||
|
||||
int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on);
|
||||
|
||||
int lbs_set_snmp_mib(struct lbs_private *priv, u32 oid, u16 val);
|
||||
|
||||
int lbs_get_snmp_mib(struct lbs_private *priv, u32 oid, u16 *out_val);
|
||||
|
||||
|
||||
/* Mesh related */
|
||||
|
||||
int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action,
|
||||
struct cmd_ds_mesh_access *cmd);
|
||||
|
||||
int lbs_mesh_config_send(struct lbs_private *priv,
|
||||
struct cmd_ds_mesh_config *cmd,
|
||||
uint16_t action, uint16_t type);
|
||||
|
||||
int lbs_mesh_config(struct lbs_private *priv, uint16_t enable, uint16_t chan);
|
||||
|
||||
|
||||
/* Commands only used in wext.c, assoc. and scan.c */
|
||||
|
||||
int lbs_set_power_adapt_cfg(struct lbs_private *priv, int enable, int8_t p0,
|
||||
int8_t p1, int8_t p2);
|
||||
|
||||
int lbs_set_tpc_cfg(struct lbs_private *priv, int enable, int8_t p0, int8_t p1,
|
||||
int8_t p2, int usesnr);
|
||||
|
||||
int lbs_set_data_rate(struct lbs_private *priv, u8 rate);
|
||||
|
||||
int lbs_cmd_802_11_rate_adapt_rateset(struct lbs_private *priv,
|
||||
uint16_t cmd_action);
|
||||
|
||||
int lbs_set_tx_power(struct lbs_private *priv, s16 dbm);
|
||||
|
||||
int lbs_set_deep_sleep(struct lbs_private *priv, int deep_sleep);
|
||||
|
||||
#endif /* _LBS_CMD_H */
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include "host.h"
|
||||
#include "decl.h"
|
||||
#include "cmd.h"
|
||||
#include "defs.h"
|
||||
#include "dev.h"
|
||||
#include "assoc.h"
|
||||
|
@ -26,23 +27,17 @@
|
|||
*/
|
||||
void lbs_mac_event_disconnected(struct lbs_private *priv)
|
||||
{
|
||||
union iwreq_data wrqu;
|
||||
|
||||
if (priv->connect_status != LBS_CONNECTED)
|
||||
return;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_ASSOC);
|
||||
|
||||
memset(wrqu.ap_addr.sa_data, 0x00, ETH_ALEN);
|
||||
wrqu.ap_addr.sa_family = ARPHRD_ETHER;
|
||||
|
||||
/*
|
||||
* Cisco AP sends EAP failure and de-auth in less than 0.5 ms.
|
||||
* It causes problem in the Supplicant
|
||||
*/
|
||||
|
||||
msleep_interruptible(1000);
|
||||
wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
|
||||
lbs_send_disconnect_notification(priv);
|
||||
|
||||
/* report disconnect to upper layer */
|
||||
netif_stop_queue(priv->dev);
|
||||
|
@ -67,7 +62,7 @@ void lbs_mac_event_disconnected(struct lbs_private *priv)
|
|||
* no longer valid.
|
||||
*/
|
||||
memset(&priv->curbssparams.bssid, 0, ETH_ALEN);
|
||||
memset(&priv->curbssparams.ssid, 0, IW_ESSID_MAX_SIZE);
|
||||
memset(&priv->curbssparams.ssid, 0, IEEE80211_MAX_SSID_LEN);
|
||||
priv->curbssparams.ssid_len = 0;
|
||||
|
||||
if (priv->psstate != PS_STATE_FULL_POWER) {
|
||||
|
@ -78,32 +73,6 @@ void lbs_mac_event_disconnected(struct lbs_private *priv)
|
|||
lbs_deb_leave(LBS_DEB_ASSOC);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles MIC failure event.
|
||||
*
|
||||
* @param priv A pointer to struct lbs_private structure
|
||||
* @para event the event id
|
||||
* @return n/a
|
||||
*/
|
||||
static void handle_mic_failureevent(struct lbs_private *priv, u32 event)
|
||||
{
|
||||
char buf[50];
|
||||
|
||||
lbs_deb_enter(LBS_DEB_CMD);
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
sprintf(buf, "%s", "MLME-MICHAELMICFAILURE.indication ");
|
||||
|
||||
if (event == MACREG_INT_CODE_MIC_ERR_UNICAST) {
|
||||
strcat(buf, "unicast ");
|
||||
} else {
|
||||
strcat(buf, "multicast ");
|
||||
}
|
||||
|
||||
lbs_send_iwevcustom_event(priv, buf);
|
||||
lbs_deb_leave(LBS_DEB_CMD);
|
||||
}
|
||||
|
||||
static int lbs_ret_reg_access(struct lbs_private *priv,
|
||||
u16 type, struct cmd_ds_command *resp)
|
||||
{
|
||||
|
@ -147,53 +116,6 @@ static int lbs_ret_reg_access(struct lbs_private *priv,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int lbs_ret_802_11_rssi(struct lbs_private *priv,
|
||||
struct cmd_ds_command *resp)
|
||||
{
|
||||
struct cmd_ds_802_11_rssi_rsp *rssirsp = &resp->params.rssirsp;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_CMD);
|
||||
|
||||
/* store the non average value */
|
||||
priv->SNR[TYPE_BEACON][TYPE_NOAVG] = get_unaligned_le16(&rssirsp->SNR);
|
||||
priv->NF[TYPE_BEACON][TYPE_NOAVG] = get_unaligned_le16(&rssirsp->noisefloor);
|
||||
|
||||
priv->SNR[TYPE_BEACON][TYPE_AVG] = get_unaligned_le16(&rssirsp->avgSNR);
|
||||
priv->NF[TYPE_BEACON][TYPE_AVG] = get_unaligned_le16(&rssirsp->avgnoisefloor);
|
||||
|
||||
priv->RSSI[TYPE_BEACON][TYPE_NOAVG] =
|
||||
CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_NOAVG],
|
||||
priv->NF[TYPE_BEACON][TYPE_NOAVG]);
|
||||
|
||||
priv->RSSI[TYPE_BEACON][TYPE_AVG] =
|
||||
CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_AVG] / AVG_SCALE,
|
||||
priv->NF[TYPE_BEACON][TYPE_AVG] / AVG_SCALE);
|
||||
|
||||
lbs_deb_cmd("RSSI: beacon %d, avg %d\n",
|
||||
priv->RSSI[TYPE_BEACON][TYPE_NOAVG],
|
||||
priv->RSSI[TYPE_BEACON][TYPE_AVG]);
|
||||
|
||||
lbs_deb_leave(LBS_DEB_CMD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lbs_ret_802_11_bcn_ctrl(struct lbs_private * priv,
|
||||
struct cmd_ds_command *resp)
|
||||
{
|
||||
struct cmd_ds_802_11_beacon_control *bcn_ctrl =
|
||||
&resp->params.bcn_ctrl;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_CMD);
|
||||
|
||||
if (bcn_ctrl->action == CMD_ACT_GET) {
|
||||
priv->beacon_enable = (u8) le16_to_cpu(bcn_ctrl->beacon_enable);
|
||||
priv->beacon_period = le16_to_cpu(bcn_ctrl->beacon_period);
|
||||
}
|
||||
|
||||
lbs_deb_enter(LBS_DEB_CMD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int handle_cmd_response(struct lbs_private *priv,
|
||||
struct cmd_header *cmd_response)
|
||||
{
|
||||
|
@ -227,29 +149,13 @@ static inline int handle_cmd_response(struct lbs_private *priv,
|
|||
ret = lbs_ret_802_11_rssi(priv, resp);
|
||||
break;
|
||||
|
||||
case CMD_RET(CMD_802_11D_DOMAIN_INFO):
|
||||
ret = lbs_ret_802_11d_domain_info(resp);
|
||||
break;
|
||||
|
||||
case CMD_RET(CMD_802_11_TPC_CFG):
|
||||
spin_lock_irqsave(&priv->driver_lock, flags);
|
||||
memmove((void *)priv->cur_cmd->callback_arg, &resp->params.tpccfg,
|
||||
sizeof(struct cmd_ds_802_11_tpc_cfg));
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
break;
|
||||
case CMD_RET(CMD_802_11_LED_GPIO_CTRL):
|
||||
spin_lock_irqsave(&priv->driver_lock, flags);
|
||||
memmove((void *)priv->cur_cmd->callback_arg, &resp->params.ledgpio,
|
||||
sizeof(struct cmd_ds_802_11_led_ctrl));
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
break;
|
||||
|
||||
case CMD_RET(CMD_GET_TSF):
|
||||
spin_lock_irqsave(&priv->driver_lock, flags);
|
||||
memcpy((void *)priv->cur_cmd->callback_arg,
|
||||
&resp->params.gettsf.tsfvalue, sizeof(u64));
|
||||
spin_unlock_irqrestore(&priv->driver_lock, flags);
|
||||
break;
|
||||
case CMD_RET(CMD_BT_ACCESS):
|
||||
spin_lock_irqsave(&priv->driver_lock, flags);
|
||||
if (priv->cur_cmd->callback_arg)
|
||||
|
@ -545,12 +451,12 @@ int lbs_process_event(struct lbs_private *priv, u32 event)
|
|||
|
||||
case MACREG_INT_CODE_MIC_ERR_UNICAST:
|
||||
lbs_deb_cmd("EVENT: UNICAST MIC ERROR\n");
|
||||
handle_mic_failureevent(priv, MACREG_INT_CODE_MIC_ERR_UNICAST);
|
||||
lbs_send_mic_failureevent(priv, event);
|
||||
break;
|
||||
|
||||
case MACREG_INT_CODE_MIC_ERR_MULTICAST:
|
||||
lbs_deb_cmd("EVENT: MULTICAST MIC ERROR\n");
|
||||
handle_mic_failureevent(priv, MACREG_INT_CODE_MIC_ERR_MULTICAST);
|
||||
lbs_send_mic_failureevent(priv, event);
|
||||
break;
|
||||
|
||||
case MACREG_INT_CODE_MIB_CHANGED:
|
||||
|
|
|
@ -451,10 +451,12 @@ static ssize_t lbs_rdmac_read(struct file *file, char __user *userbuf,
|
|||
CMD_MAC_REG_ACCESS, 0,
|
||||
CMD_OPTION_WAITFORRSP, 0, &offval);
|
||||
mdelay(10);
|
||||
pos += snprintf(buf+pos, len-pos, "MAC[0x%x] = 0x%08x\n",
|
||||
if (!ret) {
|
||||
pos += snprintf(buf+pos, len-pos, "MAC[0x%x] = 0x%08x\n",
|
||||
priv->mac_offset, priv->offsetvalue.value);
|
||||
|
||||
ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
|
||||
ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
|
||||
}
|
||||
free_page(addr);
|
||||
return ret;
|
||||
}
|
||||
|
@ -514,7 +516,8 @@ static ssize_t lbs_wrmac_write(struct file *file,
|
|||
CMD_OPTION_WAITFORRSP, 0, &offval);
|
||||
mdelay(10);
|
||||
|
||||
res = count;
|
||||
if (!res)
|
||||
res = count;
|
||||
out_unlock:
|
||||
free_page(addr);
|
||||
return res;
|
||||
|
@ -539,10 +542,12 @@ static ssize_t lbs_rdbbp_read(struct file *file, char __user *userbuf,
|
|||
CMD_BBP_REG_ACCESS, 0,
|
||||
CMD_OPTION_WAITFORRSP, 0, &offval);
|
||||
mdelay(10);
|
||||
pos += snprintf(buf+pos, len-pos, "BBP[0x%x] = 0x%08x\n",
|
||||
if (!ret) {
|
||||
pos += snprintf(buf+pos, len-pos, "BBP[0x%x] = 0x%08x\n",
|
||||
priv->bbp_offset, priv->offsetvalue.value);
|
||||
|
||||
ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
|
||||
ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
|
||||
}
|
||||
free_page(addr);
|
||||
|
||||
return ret;
|
||||
|
@ -603,7 +608,8 @@ static ssize_t lbs_wrbbp_write(struct file *file,
|
|||
CMD_OPTION_WAITFORRSP, 0, &offval);
|
||||
mdelay(10);
|
||||
|
||||
res = count;
|
||||
if (!res)
|
||||
res = count;
|
||||
out_unlock:
|
||||
free_page(addr);
|
||||
return res;
|
||||
|
@ -628,10 +634,12 @@ static ssize_t lbs_rdrf_read(struct file *file, char __user *userbuf,
|
|||
CMD_RF_REG_ACCESS, 0,
|
||||
CMD_OPTION_WAITFORRSP, 0, &offval);
|
||||
mdelay(10);
|
||||
pos += snprintf(buf+pos, len-pos, "RF[0x%x] = 0x%08x\n",
|
||||
if (!ret) {
|
||||
pos += snprintf(buf+pos, len-pos, "RF[0x%x] = 0x%08x\n",
|
||||
priv->rf_offset, priv->offsetvalue.value);
|
||||
|
||||
ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
|
||||
ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
|
||||
}
|
||||
free_page(addr);
|
||||
|
||||
return ret;
|
||||
|
@ -692,7 +700,8 @@ static ssize_t lbs_wrrf_write(struct file *file,
|
|||
CMD_OPTION_WAITFORRSP, 0, &offval);
|
||||
mdelay(10);
|
||||
|
||||
res = count;
|
||||
if (!res)
|
||||
res = count;
|
||||
out_unlock:
|
||||
free_page(addr);
|
||||
return res;
|
||||
|
|
|
@ -8,74 +8,48 @@
|
|||
|
||||
#include <linux/netdevice.h>
|
||||
|
||||
#include "defs.h"
|
||||
|
||||
/** Function Prototype Declaration */
|
||||
struct lbs_private;
|
||||
struct sk_buff;
|
||||
struct net_device;
|
||||
struct cmd_ctrl_node;
|
||||
struct cmd_ds_command;
|
||||
|
||||
void lbs_set_mac_control(struct lbs_private *priv);
|
||||
|
||||
/* ethtool.c */
|
||||
extern const struct ethtool_ops lbs_ethtool_ops;
|
||||
|
||||
|
||||
/* tx.c */
|
||||
void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count);
|
||||
|
||||
int lbs_free_cmd_buffer(struct lbs_private *priv);
|
||||
|
||||
int lbs_prepare_and_send_command(struct lbs_private *priv,
|
||||
u16 cmd_no,
|
||||
u16 cmd_action,
|
||||
u16 wait_option, u32 cmd_oid, void *pdata_buf);
|
||||
|
||||
int lbs_allocate_cmd_buffer(struct lbs_private *priv);
|
||||
int lbs_execute_next_command(struct lbs_private *priv);
|
||||
int lbs_process_event(struct lbs_private *priv, u32 event);
|
||||
void lbs_queue_event(struct lbs_private *priv, u32 event);
|
||||
void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx);
|
||||
int lbs_set_deep_sleep(struct lbs_private *priv, int deep_sleep);
|
||||
int lbs_enter_auto_deep_sleep(struct lbs_private *priv);
|
||||
int lbs_exit_auto_deep_sleep(struct lbs_private *priv);
|
||||
|
||||
u32 lbs_fw_index_to_data_rate(u8 index);
|
||||
u8 lbs_data_rate_to_fw_index(u32 rate);
|
||||
|
||||
/** The proc fs interface */
|
||||
int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len);
|
||||
void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
|
||||
int result);
|
||||
netdev_tx_t lbs_hard_start_xmit(struct sk_buff *skb,
|
||||
struct net_device *dev);
|
||||
int lbs_set_regiontable(struct lbs_private *priv, u8 region, u8 band);
|
||||
|
||||
/* rx.c */
|
||||
int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *);
|
||||
|
||||
void lbs_ps_sleep(struct lbs_private *priv, int wait_option);
|
||||
void lbs_ps_confirm_sleep(struct lbs_private *priv);
|
||||
void lbs_ps_wakeup(struct lbs_private *priv, int wait_option);
|
||||
|
||||
struct chan_freq_power *lbs_find_cfp_by_band_and_channel(
|
||||
struct lbs_private *priv,
|
||||
u8 band,
|
||||
u16 channel);
|
||||
|
||||
void lbs_mac_event_disconnected(struct lbs_private *priv);
|
||||
|
||||
void lbs_send_iwevcustom_event(struct lbs_private *priv, s8 *str);
|
||||
|
||||
/* persistcfg.c */
|
||||
void lbs_persist_config_init(struct net_device *net);
|
||||
void lbs_persist_config_remove(struct net_device *net);
|
||||
|
||||
|
||||
/* main.c */
|
||||
struct chan_freq_power *lbs_get_region_cfp_table(u8 region,
|
||||
int *cfp_no);
|
||||
struct lbs_private *lbs_add_card(void *card, struct device *dmdev);
|
||||
void lbs_remove_card(struct lbs_private *priv);
|
||||
int lbs_start_card(struct lbs_private *priv);
|
||||
void lbs_stop_card(struct lbs_private *priv);
|
||||
void lbs_host_to_card_done(struct lbs_private *priv);
|
||||
|
||||
int lbs_update_channel(struct lbs_private *priv);
|
||||
int lbs_suspend(struct lbs_private *priv);
|
||||
void lbs_resume(struct lbs_private *priv);
|
||||
|
||||
void lbs_queue_event(struct lbs_private *priv, u32 event);
|
||||
void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx);
|
||||
|
||||
int lbs_enter_auto_deep_sleep(struct lbs_private *priv);
|
||||
int lbs_exit_auto_deep_sleep(struct lbs_private *priv);
|
||||
|
||||
u32 lbs_fw_index_to_data_rate(u8 index);
|
||||
u8 lbs_data_rate_to_fw_index(u32 rate);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -322,7 +322,6 @@ static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, in
|
|||
extern const char lbs_driver_version[];
|
||||
extern u16 lbs_region_code_to_index[MRVDRV_MAX_REGION_CODE];
|
||||
|
||||
extern u8 lbs_bg_rates[MAX_RATES];
|
||||
|
||||
/** ENUM definition*/
|
||||
/** SNRNF_TYPE */
|
||||
|
|
|
@ -6,75 +6,10 @@
|
|||
#ifndef _LBS_DEV_H_
|
||||
#define _LBS_DEV_H_
|
||||
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/wireless.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include "scan.h"
|
||||
#include "assoc.h"
|
||||
|
||||
#include "defs.h"
|
||||
#include "hostcmd.h"
|
||||
|
||||
extern const struct ethtool_ops lbs_ethtool_ops;
|
||||
|
||||
#define MAX_BSSID_PER_CHANNEL 16
|
||||
|
||||
#define NR_TX_QUEUE 3
|
||||
|
||||
/* For the extended Scan */
|
||||
#define MAX_EXTENDED_SCAN_BSSID_LIST MAX_BSSID_PER_CHANNEL * \
|
||||
MRVDRV_MAX_CHANNEL_SIZE + 1
|
||||
|
||||
#define MAX_REGION_CHANNEL_NUM 2
|
||||
|
||||
/** Chan-freq-TxPower mapping table*/
|
||||
struct chan_freq_power {
|
||||
/** channel Number */
|
||||
u16 channel;
|
||||
/** frequency of this channel */
|
||||
u32 freq;
|
||||
/** Max allowed Tx power level */
|
||||
u16 maxtxpower;
|
||||
/** TRUE:channel unsupported; FLASE:supported*/
|
||||
u8 unsupported;
|
||||
};
|
||||
|
||||
/** region-band mapping table*/
|
||||
struct region_channel {
|
||||
/** TRUE if this entry is valid */
|
||||
u8 valid;
|
||||
/** region code for US, Japan ... */
|
||||
u8 region;
|
||||
/** band B/G/A, used for BAND_CONFIG cmd */
|
||||
u8 band;
|
||||
/** Actual No. of elements in the array below */
|
||||
u8 nrcfp;
|
||||
/** chan-freq-txpower mapping table*/
|
||||
struct chan_freq_power *CFP;
|
||||
};
|
||||
|
||||
struct lbs_802_11_security {
|
||||
u8 WPAenabled;
|
||||
u8 WPA2enabled;
|
||||
u8 wep_enabled;
|
||||
u8 auth_mode;
|
||||
u32 key_mgmt;
|
||||
};
|
||||
|
||||
/** Current Basic Service Set State Structure */
|
||||
struct current_bss_params {
|
||||
/** bssid */
|
||||
u8 bssid[ETH_ALEN];
|
||||
/** ssid */
|
||||
u8 ssid[IW_ESSID_MAX_SIZE + 1];
|
||||
u8 ssid_len;
|
||||
|
||||
/** band */
|
||||
u8 band;
|
||||
/** channel */
|
||||
u8 channel;
|
||||
/** zero-terminated array of supported data rates */
|
||||
u8 rates[MAX_RATES + 1];
|
||||
};
|
||||
|
||||
/** sleep_params */
|
||||
struct sleep_params {
|
||||
|
@ -100,113 +35,96 @@ struct lbs_mesh_stats {
|
|||
|
||||
/** Private structure for the MV device */
|
||||
struct lbs_private {
|
||||
|
||||
/* Basic networking */
|
||||
struct net_device *dev;
|
||||
u32 connect_status;
|
||||
int infra_open;
|
||||
struct work_struct mcast_work;
|
||||
u32 nr_of_multicastmacaddr;
|
||||
u8 multicastlist[MRVDRV_MAX_MULTICAST_LIST_SIZE][ETH_ALEN];
|
||||
|
||||
/* CFG80211 */
|
||||
struct wireless_dev *wdev;
|
||||
|
||||
/* Mesh */
|
||||
struct net_device *mesh_dev; /* Virtual device */
|
||||
u32 mesh_connect_status;
|
||||
struct lbs_mesh_stats mstats;
|
||||
int mesh_open;
|
||||
int mesh_fw_ver;
|
||||
int infra_open;
|
||||
int mesh_autostart_enabled;
|
||||
uint16_t mesh_tlv;
|
||||
u8 mesh_ssid[IEEE80211_MAX_SSID_LEN + 1];
|
||||
u8 mesh_ssid_len;
|
||||
struct work_struct sync_channel;
|
||||
|
||||
char name[DEV_NAME_LEN];
|
||||
|
||||
void *card;
|
||||
struct net_device *dev;
|
||||
|
||||
struct net_device *mesh_dev; /* Virtual device */
|
||||
/* Monitor mode */
|
||||
struct net_device *rtap_net_dev;
|
||||
u32 monitormode;
|
||||
|
||||
struct iw_statistics wstats;
|
||||
struct lbs_mesh_stats mstats;
|
||||
/* Debugfs */
|
||||
struct dentry *debugfs_dir;
|
||||
struct dentry *debugfs_debug;
|
||||
struct dentry *debugfs_files[6];
|
||||
|
||||
struct dentry *events_dir;
|
||||
struct dentry *debugfs_events_files[6];
|
||||
|
||||
struct dentry *regs_dir;
|
||||
struct dentry *debugfs_regs_files[6];
|
||||
|
||||
/* Hardware debugging */
|
||||
u32 mac_offset;
|
||||
u32 bbp_offset;
|
||||
u32 rf_offset;
|
||||
struct lbs_offset_value offsetvalue;
|
||||
|
||||
/** Deep sleep flag */
|
||||
/* Power management */
|
||||
u16 psmode;
|
||||
u32 psstate;
|
||||
u8 needtowakeup;
|
||||
|
||||
/* Deep sleep */
|
||||
int is_deep_sleep;
|
||||
/** Auto deep sleep enabled flag */
|
||||
int is_auto_deep_sleep_enabled;
|
||||
/** Device wakeup required flag */
|
||||
int wakeup_dev_required;
|
||||
/** Auto deep sleep flag*/
|
||||
int is_activity_detected;
|
||||
/** Auto deep sleep timeout (in miliseconds) */
|
||||
int auto_deep_sleep_timeout;
|
||||
int auto_deep_sleep_timeout; /* in ms */
|
||||
wait_queue_head_t ds_awake_q;
|
||||
struct timer_list auto_deepsleep_timer;
|
||||
|
||||
/** Deep sleep wait queue */
|
||||
wait_queue_head_t ds_awake_q;
|
||||
|
||||
/* Download sent:
|
||||
bit0 1/0=data_sent/data_tx_done,
|
||||
bit1 1/0=cmd_sent/cmd_tx_done,
|
||||
all other bits reserved 0 */
|
||||
u8 dnld_sent;
|
||||
|
||||
/** thread to service interrupts */
|
||||
struct task_struct *main_thread;
|
||||
wait_queue_head_t waitq;
|
||||
struct workqueue_struct *work_thread;
|
||||
|
||||
struct work_struct mcast_work;
|
||||
|
||||
/** Scanning */
|
||||
struct delayed_work scan_work;
|
||||
struct delayed_work assoc_work;
|
||||
struct work_struct sync_channel;
|
||||
/* remember which channel was scanned last, != 0 if currently scanning */
|
||||
int scan_channel;
|
||||
u8 scan_ssid[IW_ESSID_MAX_SIZE + 1];
|
||||
u8 scan_ssid_len;
|
||||
|
||||
/** Hardware access */
|
||||
/* Hardware access */
|
||||
void *card;
|
||||
u8 fw_ready;
|
||||
u8 surpriseremoved;
|
||||
int (*hw_host_to_card) (struct lbs_private *priv, u8 type, u8 *payload, u16 nb);
|
||||
void (*reset_card) (struct lbs_private *priv);
|
||||
int (*enter_deep_sleep) (struct lbs_private *priv);
|
||||
int (*exit_deep_sleep) (struct lbs_private *priv);
|
||||
int (*reset_deep_sleep_wakeup) (struct lbs_private *priv);
|
||||
|
||||
/* Wake On LAN */
|
||||
uint32_t wol_criteria;
|
||||
uint8_t wol_gpio;
|
||||
uint8_t wol_gap;
|
||||
|
||||
/** Wlan adapter data structure*/
|
||||
/** STATUS variables */
|
||||
/* Adapter info (from EEPROM) */
|
||||
u32 fwrelease;
|
||||
u32 fwcapinfo;
|
||||
u16 regioncode;
|
||||
u8 current_addr[ETH_ALEN];
|
||||
|
||||
struct mutex lock;
|
||||
|
||||
/* TX packet ready to be sent... */
|
||||
int tx_pending_len; /* -1 while building packet */
|
||||
|
||||
u8 tx_pending_buf[LBS_UPLD_SIZE];
|
||||
/* protected by hard_start_xmit serialization */
|
||||
|
||||
/** command-related variables */
|
||||
/* Command download */
|
||||
u8 dnld_sent;
|
||||
/* bit0 1/0=data_sent/data_tx_done,
|
||||
bit1 1/0=cmd_sent/cmd_tx_done,
|
||||
all other bits reserved 0 */
|
||||
u16 seqnum;
|
||||
|
||||
struct cmd_ctrl_node *cmd_array;
|
||||
/** Current command */
|
||||
struct cmd_ctrl_node *cur_cmd;
|
||||
int cur_cmd_retcode;
|
||||
/** command Queues */
|
||||
/** Free command buffers */
|
||||
struct list_head cmdfreeq;
|
||||
/** Pending command buffers */
|
||||
struct list_head cmdpendingq;
|
||||
|
||||
struct list_head cmdfreeq; /* free command buffers */
|
||||
struct list_head cmdpendingq; /* pending command buffers */
|
||||
wait_queue_head_t cmd_pending;
|
||||
struct timer_list command_timer;
|
||||
int nr_retries;
|
||||
int cmd_timed_out;
|
||||
|
||||
/* Command responses sent from the hardware to the driver */
|
||||
int cur_cmd_retcode;
|
||||
u8 resp_idx;
|
||||
u8 resp_buf[2][LBS_UPLD_SIZE];
|
||||
u32 resp_len[2];
|
||||
|
@ -214,96 +132,76 @@ struct lbs_private {
|
|||
/* Events sent from hardware to driver */
|
||||
struct kfifo *event_fifo;
|
||||
|
||||
/* nickname */
|
||||
u8 nodename[16];
|
||||
/** thread to service interrupts */
|
||||
struct task_struct *main_thread;
|
||||
wait_queue_head_t waitq;
|
||||
struct workqueue_struct *work_thread;
|
||||
|
||||
/** spin locks */
|
||||
spinlock_t driver_lock;
|
||||
/** Encryption stuff */
|
||||
struct lbs_802_11_security secinfo;
|
||||
struct enc_key wpa_mcast_key;
|
||||
struct enc_key wpa_unicast_key;
|
||||
u8 wpa_ie[MAX_WPA_IE_LEN];
|
||||
u8 wpa_ie_len;
|
||||
u16 wep_tx_keyidx;
|
||||
struct enc_key wep_keys[4];
|
||||
|
||||
/** Timers */
|
||||
struct timer_list command_timer;
|
||||
struct timer_list auto_deepsleep_timer;
|
||||
int nr_retries;
|
||||
int cmd_timed_out;
|
||||
|
||||
/** current ssid/bssid related parameters*/
|
||||
struct current_bss_params curbssparams;
|
||||
|
||||
uint16_t mesh_tlv;
|
||||
u8 mesh_ssid[IW_ESSID_MAX_SIZE + 1];
|
||||
u8 mesh_ssid_len;
|
||||
|
||||
/* IW_MODE_* */
|
||||
u8 mode;
|
||||
|
||||
/* Scan results list */
|
||||
struct list_head network_list;
|
||||
struct list_head network_free_list;
|
||||
struct bss_descriptor *networks;
|
||||
|
||||
u16 beacon_period;
|
||||
u8 beacon_enable;
|
||||
u8 adhoccreate;
|
||||
|
||||
/** capability Info used in Association, start, join */
|
||||
u16 capability;
|
||||
|
||||
/** MAC address information */
|
||||
u8 current_addr[ETH_ALEN];
|
||||
u8 multicastlist[MRVDRV_MAX_MULTICAST_LIST_SIZE][ETH_ALEN];
|
||||
u32 nr_of_multicastmacaddr;
|
||||
|
||||
/** 802.11 statistics */
|
||||
// struct cmd_DS_802_11_GET_STAT wlan802_11Stat;
|
||||
|
||||
uint16_t enablehwauto;
|
||||
uint16_t ratebitmap;
|
||||
/* Wake On LAN */
|
||||
uint32_t wol_criteria;
|
||||
uint8_t wol_gpio;
|
||||
uint8_t wol_gap;
|
||||
|
||||
/* Transmitting */
|
||||
int tx_pending_len; /* -1 while building packet */
|
||||
u8 tx_pending_buf[LBS_UPLD_SIZE];
|
||||
/* protected by hard_start_xmit serialization */
|
||||
u8 txretrycount;
|
||||
|
||||
/** Tx-related variables (for single packet tx) */
|
||||
struct sk_buff *currenttxskb;
|
||||
|
||||
/** NIC Operation characteristics */
|
||||
/* Locks */
|
||||
struct mutex lock;
|
||||
spinlock_t driver_lock;
|
||||
|
||||
/* NIC/link operation characteristics */
|
||||
u16 mac_control;
|
||||
u32 connect_status;
|
||||
u32 mesh_connect_status;
|
||||
u16 regioncode;
|
||||
u8 radio_on;
|
||||
u8 channel;
|
||||
s16 txpower_cur;
|
||||
s16 txpower_min;
|
||||
s16 txpower_max;
|
||||
|
||||
/** POWER MANAGEMENT AND PnP SUPPORT */
|
||||
u8 surpriseremoved;
|
||||
|
||||
u16 psmode; /* Wlan802_11PowermodeCAM=disable
|
||||
Wlan802_11PowermodeMAX_PSP=enable */
|
||||
u32 psstate;
|
||||
u8 needtowakeup;
|
||||
/** Scanning */
|
||||
struct delayed_work scan_work;
|
||||
int scan_channel;
|
||||
/* remember which channel was scanned last, != 0 if currently scanning */
|
||||
u8 scan_ssid[IEEE80211_MAX_SSID_LEN + 1];
|
||||
u8 scan_ssid_len;
|
||||
|
||||
/* Associating */
|
||||
struct delayed_work assoc_work;
|
||||
struct current_bss_params curbssparams;
|
||||
u8 mode;
|
||||
struct list_head network_list;
|
||||
struct list_head network_free_list;
|
||||
struct bss_descriptor *networks;
|
||||
struct assoc_request * pending_assoc_req;
|
||||
struct assoc_request * in_progress_assoc_req;
|
||||
u16 capability;
|
||||
uint16_t enablehwauto;
|
||||
uint16_t ratebitmap;
|
||||
|
||||
/** Encryption parameter */
|
||||
struct lbs_802_11_security secinfo;
|
||||
/* ADHOC */
|
||||
u16 beacon_period;
|
||||
u8 beacon_enable;
|
||||
u8 adhoccreate;
|
||||
|
||||
/** WEP keys */
|
||||
struct enc_key wep_keys[4];
|
||||
u16 wep_tx_keyidx;
|
||||
|
||||
/** WPA keys */
|
||||
struct enc_key wpa_mcast_key;
|
||||
struct enc_key wpa_unicast_key;
|
||||
|
||||
/*
|
||||
* In theory, the IE is limited to the IE length, 255,
|
||||
* but in practice 64 bytes are enough.
|
||||
*/
|
||||
#define MAX_WPA_IE_LEN 64
|
||||
|
||||
/** WPA Information Elements*/
|
||||
u8 wpa_ie[MAX_WPA_IE_LEN];
|
||||
u8 wpa_ie_len;
|
||||
/* WEXT */
|
||||
char name[DEV_NAME_LEN];
|
||||
u8 nodename[16];
|
||||
struct iw_statistics wstats;
|
||||
u8 cur_rate;
|
||||
#define MAX_REGION_CHANNEL_NUM 2
|
||||
struct region_channel region_channel[MAX_REGION_CHANNEL_NUM];
|
||||
|
||||
/** Requested Signal Strength*/
|
||||
u16 SNR[MAX_TYPE_B][MAX_TYPE_AVG];
|
||||
|
@ -313,116 +211,8 @@ struct lbs_private {
|
|||
u8 rawNF[DEFAULT_DATA_AVG_FACTOR];
|
||||
u16 nextSNRNF;
|
||||
u16 numSNRNF;
|
||||
|
||||
u8 radio_on;
|
||||
|
||||
/** data rate stuff */
|
||||
u8 cur_rate;
|
||||
|
||||
/** RF calibration data */
|
||||
|
||||
#define MAX_REGION_CHANNEL_NUM 2
|
||||
/** region channel data */
|
||||
struct region_channel region_channel[MAX_REGION_CHANNEL_NUM];
|
||||
|
||||
struct region_channel universal_channel[MAX_REGION_CHANNEL_NUM];
|
||||
|
||||
/** 11D and Domain Regulatory Data */
|
||||
struct lbs_802_11d_domain_reg domainreg;
|
||||
struct parsed_region_chan_11d parsed_region_chan;
|
||||
|
||||
/** FSM variable for 11d support */
|
||||
u32 enable11d;
|
||||
|
||||
/** MISCELLANEOUS */
|
||||
struct lbs_offset_value offsetvalue;
|
||||
|
||||
u32 monitormode;
|
||||
u8 fw_ready;
|
||||
};
|
||||
|
||||
extern struct cmd_confirm_sleep confirm_sleep;
|
||||
|
||||
/**
|
||||
* @brief Structure used to store information for each beacon/probe response
|
||||
*/
|
||||
struct bss_descriptor {
|
||||
u8 bssid[ETH_ALEN];
|
||||
|
||||
u8 ssid[IW_ESSID_MAX_SIZE + 1];
|
||||
u8 ssid_len;
|
||||
|
||||
u16 capability;
|
||||
u32 rssi;
|
||||
u32 channel;
|
||||
u16 beaconperiod;
|
||||
__le16 atimwindow;
|
||||
|
||||
/* IW_MODE_AUTO, IW_MODE_ADHOC, IW_MODE_INFRA */
|
||||
u8 mode;
|
||||
|
||||
/* zero-terminated array of supported data rates */
|
||||
u8 rates[MAX_RATES + 1];
|
||||
|
||||
unsigned long last_scanned;
|
||||
|
||||
union ieee_phy_param_set phy;
|
||||
union ieee_ss_param_set ss;
|
||||
|
||||
struct ieee_ie_country_info_full_set countryinfo;
|
||||
|
||||
u8 wpa_ie[MAX_WPA_IE_LEN];
|
||||
size_t wpa_ie_len;
|
||||
u8 rsn_ie[MAX_WPA_IE_LEN];
|
||||
size_t rsn_ie_len;
|
||||
|
||||
u8 mesh;
|
||||
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
/** Association request
|
||||
*
|
||||
* Encapsulates all the options that describe a specific assocation request
|
||||
* or configuration of the wireless card's radio, mode, and security settings.
|
||||
*/
|
||||
struct assoc_request {
|
||||
#define ASSOC_FLAG_SSID 1
|
||||
#define ASSOC_FLAG_CHANNEL 2
|
||||
#define ASSOC_FLAG_BAND 3
|
||||
#define ASSOC_FLAG_MODE 4
|
||||
#define ASSOC_FLAG_BSSID 5
|
||||
#define ASSOC_FLAG_WEP_KEYS 6
|
||||
#define ASSOC_FLAG_WEP_TX_KEYIDX 7
|
||||
#define ASSOC_FLAG_WPA_MCAST_KEY 8
|
||||
#define ASSOC_FLAG_WPA_UCAST_KEY 9
|
||||
#define ASSOC_FLAG_SECINFO 10
|
||||
#define ASSOC_FLAG_WPA_IE 11
|
||||
unsigned long flags;
|
||||
|
||||
u8 ssid[IW_ESSID_MAX_SIZE + 1];
|
||||
u8 ssid_len;
|
||||
u8 channel;
|
||||
u8 band;
|
||||
u8 mode;
|
||||
u8 bssid[ETH_ALEN] __attribute__ ((aligned (2)));
|
||||
|
||||
/** WEP keys */
|
||||
struct enc_key wep_keys[4];
|
||||
u16 wep_tx_keyidx;
|
||||
|
||||
/** WPA keys */
|
||||
struct enc_key wpa_mcast_key;
|
||||
struct enc_key wpa_unicast_key;
|
||||
|
||||
struct lbs_802_11_security secinfo;
|
||||
|
||||
/** WPA Information Elements*/
|
||||
u8 wpa_ie[MAX_WPA_IE_LEN];
|
||||
u8 wpa_ie_len;
|
||||
|
||||
/* BSS to associate with for infrastructure of Ad-Hoc join */
|
||||
struct bss_descriptor bss;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,800 +0,0 @@
|
|||
/*
|
||||
* This file contains the function prototypes, data structure
|
||||
* and defines for all the host/station commands
|
||||
*/
|
||||
#ifndef _LBS_HOSTCMD_H
|
||||
#define _LBS_HOSTCMD_H
|
||||
|
||||
#include <linux/wireless.h>
|
||||
#include "11d.h"
|
||||
#include "types.h"
|
||||
|
||||
/* 802.11-related definitions */
|
||||
|
||||
/* TxPD descriptor */
|
||||
struct txpd {
|
||||
/* union to cope up with later FW revisions */
|
||||
union {
|
||||
/* Current Tx packet status */
|
||||
__le32 tx_status;
|
||||
struct {
|
||||
/* BSS type: client, AP, etc. */
|
||||
u8 bss_type;
|
||||
/* BSS number */
|
||||
u8 bss_num;
|
||||
/* Reserved */
|
||||
__le16 reserved;
|
||||
} bss;
|
||||
} u;
|
||||
/* Tx control */
|
||||
__le32 tx_control;
|
||||
__le32 tx_packet_location;
|
||||
/* Tx packet length */
|
||||
__le16 tx_packet_length;
|
||||
/* First 2 byte of destination MAC address */
|
||||
u8 tx_dest_addr_high[2];
|
||||
/* Last 4 byte of destination MAC address */
|
||||
u8 tx_dest_addr_low[4];
|
||||
/* Pkt Priority */
|
||||
u8 priority;
|
||||
/* Pkt Trasnit Power control */
|
||||
u8 powermgmt;
|
||||
/* Amount of time the packet has been queued in the driver (units = 2ms) */
|
||||
u8 pktdelay_2ms;
|
||||
/* reserved */
|
||||
u8 reserved1;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* RxPD Descriptor */
|
||||
struct rxpd {
|
||||
/* union to cope up with later FW revisions */
|
||||
union {
|
||||
/* Current Rx packet status */
|
||||
__le16 status;
|
||||
struct {
|
||||
/* BSS type: client, AP, etc. */
|
||||
u8 bss_type;
|
||||
/* BSS number */
|
||||
u8 bss_num;
|
||||
} __attribute__ ((packed)) bss;
|
||||
} __attribute__ ((packed)) u;
|
||||
|
||||
/* SNR */
|
||||
u8 snr;
|
||||
|
||||
/* Tx control */
|
||||
u8 rx_control;
|
||||
|
||||
/* Pkt length */
|
||||
__le16 pkt_len;
|
||||
|
||||
/* Noise Floor */
|
||||
u8 nf;
|
||||
|
||||
/* Rx Packet Rate */
|
||||
u8 rx_rate;
|
||||
|
||||
/* Pkt addr */
|
||||
__le32 pkt_ptr;
|
||||
|
||||
/* Next Rx RxPD addr */
|
||||
__le32 next_rxpd_ptr;
|
||||
|
||||
/* Pkt Priority */
|
||||
u8 priority;
|
||||
u8 reserved[3];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_header {
|
||||
__le16 command;
|
||||
__le16 size;
|
||||
__le16 seqnum;
|
||||
__le16 result;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ctrl_node {
|
||||
struct list_head list;
|
||||
int result;
|
||||
/* command response */
|
||||
int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *);
|
||||
unsigned long callback_arg;
|
||||
/* command data */
|
||||
struct cmd_header *cmdbuf;
|
||||
/* wait queue */
|
||||
u16 cmdwaitqwoken;
|
||||
wait_queue_head_t cmdwait_q;
|
||||
};
|
||||
|
||||
/* Generic structure to hold all key types. */
|
||||
struct enc_key {
|
||||
u16 len;
|
||||
u16 flags; /* KEY_INFO_* from defs.h */
|
||||
u16 type; /* KEY_TYPE_* from defs.h */
|
||||
u8 key[32];
|
||||
};
|
||||
|
||||
/* lbs_offset_value */
|
||||
struct lbs_offset_value {
|
||||
u32 offset;
|
||||
u32 value;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Define general data structure */
|
||||
/* cmd_DS_GEN */
|
||||
struct cmd_ds_gen {
|
||||
__le16 command;
|
||||
__le16 size;
|
||||
__le16 seqnum;
|
||||
__le16 result;
|
||||
void *cmdresp[0];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#define S_DS_GEN sizeof(struct cmd_ds_gen)
|
||||
|
||||
|
||||
/*
|
||||
* Define data structure for CMD_GET_HW_SPEC
|
||||
* This structure defines the response for the GET_HW_SPEC command
|
||||
*/
|
||||
struct cmd_ds_get_hw_spec {
|
||||
struct cmd_header hdr;
|
||||
|
||||
/* HW Interface version number */
|
||||
__le16 hwifversion;
|
||||
/* HW version number */
|
||||
__le16 version;
|
||||
/* Max number of TxPD FW can handle */
|
||||
__le16 nr_txpd;
|
||||
/* Max no of Multicast address */
|
||||
__le16 nr_mcast_adr;
|
||||
/* MAC address */
|
||||
u8 permanentaddr[6];
|
||||
|
||||
/* region Code */
|
||||
__le16 regioncode;
|
||||
|
||||
/* Number of antenna used */
|
||||
__le16 nr_antenna;
|
||||
|
||||
/* FW release number, example 0x01030304 = 2.3.4p1 */
|
||||
__le32 fwrelease;
|
||||
|
||||
/* Base Address of TxPD queue */
|
||||
__le32 wcb_base;
|
||||
/* Read Pointer of RxPd queue */
|
||||
__le32 rxpd_rdptr;
|
||||
|
||||
/* Write Pointer of RxPd queue */
|
||||
__le32 rxpd_wrptr;
|
||||
|
||||
/*FW/HW capability */
|
||||
__le32 fwcapinfo;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_802_11_subscribe_event {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 action;
|
||||
__le16 events;
|
||||
|
||||
/* A TLV to the CMD_802_11_SUBSCRIBE_EVENT command can contain a
|
||||
* number of TLVs. From the v5.1 manual, those TLVs would add up to
|
||||
* 40 bytes. However, future firmware might add additional TLVs, so I
|
||||
* bump this up a bit.
|
||||
*/
|
||||
uint8_t tlv[128];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/*
|
||||
* This scan handle Country Information IE(802.11d compliant)
|
||||
* Define data structure for CMD_802_11_SCAN
|
||||
*/
|
||||
struct cmd_ds_802_11_scan {
|
||||
struct cmd_header hdr;
|
||||
|
||||
uint8_t bsstype;
|
||||
uint8_t bssid[ETH_ALEN];
|
||||
uint8_t tlvbuffer[0];
|
||||
#if 0
|
||||
mrvlietypes_ssidparamset_t ssidParamSet;
|
||||
mrvlietypes_chanlistparamset_t ChanListParamSet;
|
||||
mrvlietypes_ratesparamset_t OpRateSet;
|
||||
#endif
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_802_11_scan_rsp {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 bssdescriptsize;
|
||||
uint8_t nr_sets;
|
||||
uint8_t bssdesc_and_tlvbuffer[0];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_802_11_get_log {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le32 mcasttxframe;
|
||||
__le32 failed;
|
||||
__le32 retry;
|
||||
__le32 multiretry;
|
||||
__le32 framedup;
|
||||
__le32 rtssuccess;
|
||||
__le32 rtsfailure;
|
||||
__le32 ackfailure;
|
||||
__le32 rxfrag;
|
||||
__le32 mcastrxframe;
|
||||
__le32 fcserror;
|
||||
__le32 txframe;
|
||||
__le32 wepundecryptable;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_mac_control {
|
||||
struct cmd_header hdr;
|
||||
__le16 action;
|
||||
u16 reserved;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_mac_multicast_adr {
|
||||
struct cmd_header hdr;
|
||||
__le16 action;
|
||||
__le16 nr_of_adrs;
|
||||
u8 maclist[ETH_ALEN * MRVDRV_MAX_MULTICAST_LIST_SIZE];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_gspi_bus_config {
|
||||
struct cmd_header hdr;
|
||||
__le16 action;
|
||||
__le16 bus_delay_mode;
|
||||
__le16 host_time_delay_to_read_port;
|
||||
__le16 host_time_delay_to_read_register;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_802_11_authenticate {
|
||||
struct cmd_header hdr;
|
||||
|
||||
u8 bssid[ETH_ALEN];
|
||||
u8 authtype;
|
||||
u8 reserved[10];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_802_11_deauthenticate {
|
||||
struct cmd_header hdr;
|
||||
|
||||
u8 macaddr[ETH_ALEN];
|
||||
__le16 reasoncode;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_802_11_associate {
|
||||
struct cmd_header hdr;
|
||||
|
||||
u8 bssid[6];
|
||||
__le16 capability;
|
||||
__le16 listeninterval;
|
||||
__le16 bcnperiod;
|
||||
u8 dtimperiod;
|
||||
u8 iebuf[512]; /* Enough for required and most optional IEs */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_802_11_associate_response {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 capability;
|
||||
__le16 statuscode;
|
||||
__le16 aid;
|
||||
u8 iebuf[512];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_802_11_set_wep {
|
||||
struct cmd_header hdr;
|
||||
|
||||
/* ACT_ADD, ACT_REMOVE or ACT_ENABLE */
|
||||
__le16 action;
|
||||
|
||||
/* key Index selected for Tx */
|
||||
__le16 keyindex;
|
||||
|
||||
/* 40, 128bit or TXWEP */
|
||||
uint8_t keytype[4];
|
||||
uint8_t keymaterial[4][16];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_802_3_get_stat {
|
||||
__le32 xmitok;
|
||||
__le32 rcvok;
|
||||
__le32 xmiterror;
|
||||
__le32 rcverror;
|
||||
__le32 rcvnobuffer;
|
||||
__le32 rcvcrcerror;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_802_11_get_stat {
|
||||
__le32 txfragmentcnt;
|
||||
__le32 mcasttxframecnt;
|
||||
__le32 failedcnt;
|
||||
__le32 retrycnt;
|
||||
__le32 Multipleretrycnt;
|
||||
__le32 rtssuccesscnt;
|
||||
__le32 rtsfailurecnt;
|
||||
__le32 ackfailurecnt;
|
||||
__le32 frameduplicatecnt;
|
||||
__le32 rxfragmentcnt;
|
||||
__le32 mcastrxframecnt;
|
||||
__le32 fcserrorcnt;
|
||||
__le32 bcasttxframecnt;
|
||||
__le32 bcastrxframecnt;
|
||||
__le32 txbeacon;
|
||||
__le32 rxbeacon;
|
||||
__le32 wepundecryptable;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_802_11_snmp_mib {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 action;
|
||||
__le16 oid;
|
||||
__le16 bufsize;
|
||||
u8 value[128];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_mac_reg_map {
|
||||
__le16 buffersize;
|
||||
u8 regmap[128];
|
||||
__le16 reserved;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_bbp_reg_map {
|
||||
__le16 buffersize;
|
||||
u8 regmap[128];
|
||||
__le16 reserved;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_rf_reg_map {
|
||||
__le16 buffersize;
|
||||
u8 regmap[64];
|
||||
__le16 reserved;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_mac_reg_access {
|
||||
__le16 action;
|
||||
__le16 offset;
|
||||
__le32 value;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_bbp_reg_access {
|
||||
__le16 action;
|
||||
__le16 offset;
|
||||
u8 value;
|
||||
u8 reserved[3];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_rf_reg_access {
|
||||
__le16 action;
|
||||
__le16 offset;
|
||||
u8 value;
|
||||
u8 reserved[3];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_802_11_radio_control {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 action;
|
||||
__le16 control;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_802_11_beacon_control {
|
||||
__le16 action;
|
||||
__le16 beacon_enable;
|
||||
__le16 beacon_period;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_802_11_sleep_params {
|
||||
struct cmd_header hdr;
|
||||
|
||||
/* ACT_GET/ACT_SET */
|
||||
__le16 action;
|
||||
|
||||
/* Sleep clock error in ppm */
|
||||
__le16 error;
|
||||
|
||||
/* Wakeup offset in usec */
|
||||
__le16 offset;
|
||||
|
||||
/* Clock stabilization time in usec */
|
||||
__le16 stabletime;
|
||||
|
||||
/* control periodic calibration */
|
||||
uint8_t calcontrol;
|
||||
|
||||
/* control the use of external sleep clock */
|
||||
uint8_t externalsleepclk;
|
||||
|
||||
/* reserved field, should be set to zero */
|
||||
__le16 reserved;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_802_11_inactivity_timeout {
|
||||
struct cmd_header hdr;
|
||||
|
||||
/* ACT_GET/ACT_SET */
|
||||
__le16 action;
|
||||
|
||||
/* Inactivity timeout in msec */
|
||||
__le16 timeout;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_802_11_rf_channel {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 action;
|
||||
__le16 channel;
|
||||
__le16 rftype; /* unused */
|
||||
__le16 reserved; /* unused */
|
||||
u8 channellist[32]; /* unused */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_802_11_rssi {
|
||||
/* weighting factor */
|
||||
__le16 N;
|
||||
|
||||
__le16 reserved_0;
|
||||
__le16 reserved_1;
|
||||
__le16 reserved_2;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_802_11_rssi_rsp {
|
||||
__le16 SNR;
|
||||
__le16 noisefloor;
|
||||
__le16 avgSNR;
|
||||
__le16 avgnoisefloor;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_802_11_mac_address {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 action;
|
||||
u8 macadd[ETH_ALEN];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_802_11_rf_tx_power {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 action;
|
||||
__le16 curlevel;
|
||||
s8 maxlevel;
|
||||
s8 minlevel;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_802_11_rf_antenna {
|
||||
__le16 action;
|
||||
|
||||
/* Number of antennas or 0xffff(diversity) */
|
||||
__le16 antennamode;
|
||||
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_802_11_monitor_mode {
|
||||
__le16 action;
|
||||
__le16 mode;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_set_boot2_ver {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 action;
|
||||
__le16 version;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_802_11_fw_wake_method {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 action;
|
||||
__le16 method;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_802_11_sleep_period {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 action;
|
||||
__le16 period;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_802_11_ps_mode {
|
||||
__le16 action;
|
||||
__le16 nullpktinterval;
|
||||
__le16 multipledtim;
|
||||
__le16 reserved;
|
||||
__le16 locallisteninterval;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_confirm_sleep {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 action;
|
||||
__le16 nullpktinterval;
|
||||
__le16 multipledtim;
|
||||
__le16 reserved;
|
||||
__le16 locallisteninterval;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_802_11_data_rate {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 action;
|
||||
__le16 reserved;
|
||||
u8 rates[MAX_RATES];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_802_11_rate_adapt_rateset {
|
||||
struct cmd_header hdr;
|
||||
__le16 action;
|
||||
__le16 enablehwauto;
|
||||
__le16 bitmap;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_802_11_ad_hoc_start {
|
||||
struct cmd_header hdr;
|
||||
|
||||
u8 ssid[IW_ESSID_MAX_SIZE];
|
||||
u8 bsstype;
|
||||
__le16 beaconperiod;
|
||||
u8 dtimperiod; /* Reserved on v9 and later */
|
||||
struct ieee_ie_ibss_param_set ibss;
|
||||
u8 reserved1[4];
|
||||
struct ieee_ie_ds_param_set ds;
|
||||
u8 reserved2[4];
|
||||
__le16 probedelay; /* Reserved on v9 and later */
|
||||
__le16 capability;
|
||||
u8 rates[MAX_RATES];
|
||||
u8 tlv_memory_size_pad[100];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_802_11_ad_hoc_result {
|
||||
struct cmd_header hdr;
|
||||
|
||||
u8 pad[3];
|
||||
u8 bssid[ETH_ALEN];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct adhoc_bssdesc {
|
||||
u8 bssid[ETH_ALEN];
|
||||
u8 ssid[IW_ESSID_MAX_SIZE];
|
||||
u8 type;
|
||||
__le16 beaconperiod;
|
||||
u8 dtimperiod;
|
||||
__le64 timestamp;
|
||||
__le64 localtime;
|
||||
struct ieee_ie_ds_param_set ds;
|
||||
u8 reserved1[4];
|
||||
struct ieee_ie_ibss_param_set ibss;
|
||||
u8 reserved2[4];
|
||||
__le16 capability;
|
||||
u8 rates[MAX_RATES];
|
||||
|
||||
/* DO NOT ADD ANY FIELDS TO THIS STRUCTURE. It is used below in the
|
||||
* Adhoc join command and will cause a binary layout mismatch with
|
||||
* the firmware
|
||||
*/
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_802_11_ad_hoc_join {
|
||||
struct cmd_header hdr;
|
||||
|
||||
struct adhoc_bssdesc bss;
|
||||
__le16 failtimeout; /* Reserved on v9 and later */
|
||||
__le16 probedelay; /* Reserved on v9 and later */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_802_11_ad_hoc_stop {
|
||||
struct cmd_header hdr;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_802_11_enable_rsn {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 action;
|
||||
__le16 enable;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct MrvlIEtype_keyParamSet {
|
||||
/* type ID */
|
||||
__le16 type;
|
||||
|
||||
/* length of Payload */
|
||||
__le16 length;
|
||||
|
||||
/* type of key: WEP=0, TKIP=1, AES=2 */
|
||||
__le16 keytypeid;
|
||||
|
||||
/* key control Info specific to a keytypeid */
|
||||
__le16 keyinfo;
|
||||
|
||||
/* length of key */
|
||||
__le16 keylen;
|
||||
|
||||
/* key material of size keylen */
|
||||
u8 key[32];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#define MAX_WOL_RULES 16
|
||||
|
||||
struct host_wol_rule {
|
||||
uint8_t rule_no;
|
||||
uint8_t rule_ops;
|
||||
__le16 sig_offset;
|
||||
__le16 sig_length;
|
||||
__le16 reserve;
|
||||
__be32 sig_mask;
|
||||
__be32 signature;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct wol_config {
|
||||
uint8_t action;
|
||||
uint8_t pattern;
|
||||
uint8_t no_rules_in_cmd;
|
||||
uint8_t result;
|
||||
struct host_wol_rule rule[MAX_WOL_RULES];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_host_sleep {
|
||||
struct cmd_header hdr;
|
||||
__le32 criteria;
|
||||
uint8_t gpio;
|
||||
uint16_t gap;
|
||||
struct wol_config wol_conf;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
|
||||
struct cmd_ds_802_11_key_material {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 action;
|
||||
struct MrvlIEtype_keyParamSet keyParamSet[2];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_802_11_eeprom_access {
|
||||
struct cmd_header hdr;
|
||||
__le16 action;
|
||||
__le16 offset;
|
||||
__le16 len;
|
||||
/* firmware says it returns a maximum of 20 bytes */
|
||||
#define LBS_EEPROM_READ_LEN 20
|
||||
u8 value[LBS_EEPROM_READ_LEN];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_802_11_tpc_cfg {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 action;
|
||||
uint8_t enable;
|
||||
int8_t P0;
|
||||
int8_t P1;
|
||||
int8_t P2;
|
||||
uint8_t usesnr;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
struct cmd_ds_802_11_pa_cfg {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 action;
|
||||
uint8_t enable;
|
||||
int8_t P0;
|
||||
int8_t P1;
|
||||
int8_t P2;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
struct cmd_ds_802_11_led_ctrl {
|
||||
__le16 action;
|
||||
__le16 numled;
|
||||
u8 data[256];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_802_11_afc {
|
||||
__le16 afc_auto;
|
||||
union {
|
||||
struct {
|
||||
__le16 threshold;
|
||||
__le16 period;
|
||||
};
|
||||
struct {
|
||||
__le16 timing_offset; /* signed */
|
||||
__le16 carrier_offset; /* signed */
|
||||
};
|
||||
};
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_tx_rate_query {
|
||||
__le16 txrate;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_get_tsf {
|
||||
__le64 tsfvalue;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_bt_access {
|
||||
__le16 action;
|
||||
__le32 id;
|
||||
u8 addr1[ETH_ALEN];
|
||||
u8 addr2[ETH_ALEN];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct cmd_ds_fwt_access {
|
||||
__le16 action;
|
||||
__le32 id;
|
||||
u8 valid;
|
||||
u8 da[ETH_ALEN];
|
||||
u8 dir;
|
||||
u8 ra[ETH_ALEN];
|
||||
__le32 ssn;
|
||||
__le32 dsn;
|
||||
__le32 metric;
|
||||
u8 rate;
|
||||
u8 hopcount;
|
||||
u8 ttl;
|
||||
__le32 expiration;
|
||||
u8 sleepmode;
|
||||
__le32 snr;
|
||||
__le32 references;
|
||||
u8 prec[ETH_ALEN];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
struct cmd_ds_mesh_config {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 action;
|
||||
__le16 channel;
|
||||
__le16 type;
|
||||
__le16 length;
|
||||
u8 data[128]; /* last position reserved */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
|
||||
struct cmd_ds_mesh_access {
|
||||
struct cmd_header hdr;
|
||||
|
||||
__le16 action;
|
||||
__le32 data[32]; /* last position reserved */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* Number of stats counters returned by the firmware */
|
||||
#define MESH_STATS_NUM 8
|
||||
|
||||
struct cmd_ds_command {
|
||||
/* command header */
|
||||
__le16 command;
|
||||
__le16 size;
|
||||
__le16 seqnum;
|
||||
__le16 result;
|
||||
|
||||
/* command Body */
|
||||
union {
|
||||
struct cmd_ds_802_11_ps_mode psmode;
|
||||
struct cmd_ds_802_11_get_stat gstat;
|
||||
struct cmd_ds_802_3_get_stat gstat_8023;
|
||||
struct cmd_ds_802_11_rf_antenna rant;
|
||||
struct cmd_ds_802_11_monitor_mode monitor;
|
||||
struct cmd_ds_802_11_rssi rssi;
|
||||
struct cmd_ds_802_11_rssi_rsp rssirsp;
|
||||
struct cmd_ds_mac_reg_access macreg;
|
||||
struct cmd_ds_bbp_reg_access bbpreg;
|
||||
struct cmd_ds_rf_reg_access rfreg;
|
||||
|
||||
struct cmd_ds_802_11d_domain_info domaininfo;
|
||||
struct cmd_ds_802_11d_domain_info domaininforesp;
|
||||
|
||||
struct cmd_ds_802_11_tpc_cfg tpccfg;
|
||||
struct cmd_ds_802_11_afc afc;
|
||||
struct cmd_ds_802_11_led_ctrl ledgpio;
|
||||
|
||||
struct cmd_tx_rate_query txrate;
|
||||
struct cmd_ds_bt_access bt;
|
||||
struct cmd_ds_fwt_access fwt;
|
||||
struct cmd_ds_get_tsf gettsf;
|
||||
struct cmd_ds_802_11_beacon_control bcn_ctrl;
|
||||
} params;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#endif
|
|
@ -45,132 +45,12 @@ module_param_named(libertas_debug, lbs_debug, int, 0644);
|
|||
struct cmd_confirm_sleep confirm_sleep;
|
||||
|
||||
|
||||
#define LBS_TX_PWR_DEFAULT 20 /*100mW */
|
||||
#define LBS_TX_PWR_US_DEFAULT 20 /*100mW */
|
||||
#define LBS_TX_PWR_JP_DEFAULT 16 /*50mW */
|
||||
#define LBS_TX_PWR_FR_DEFAULT 20 /*100mW */
|
||||
#define LBS_TX_PWR_EMEA_DEFAULT 20 /*100mW */
|
||||
|
||||
/* Format { channel, frequency (MHz), maxtxpower } */
|
||||
/* band: 'B/G', region: USA FCC/Canada IC */
|
||||
static struct chan_freq_power channel_freq_power_US_BG[] = {
|
||||
{1, 2412, LBS_TX_PWR_US_DEFAULT},
|
||||
{2, 2417, LBS_TX_PWR_US_DEFAULT},
|
||||
{3, 2422, LBS_TX_PWR_US_DEFAULT},
|
||||
{4, 2427, LBS_TX_PWR_US_DEFAULT},
|
||||
{5, 2432, LBS_TX_PWR_US_DEFAULT},
|
||||
{6, 2437, LBS_TX_PWR_US_DEFAULT},
|
||||
{7, 2442, LBS_TX_PWR_US_DEFAULT},
|
||||
{8, 2447, LBS_TX_PWR_US_DEFAULT},
|
||||
{9, 2452, LBS_TX_PWR_US_DEFAULT},
|
||||
{10, 2457, LBS_TX_PWR_US_DEFAULT},
|
||||
{11, 2462, LBS_TX_PWR_US_DEFAULT}
|
||||
};
|
||||
|
||||
/* band: 'B/G', region: Europe ETSI */
|
||||
static struct chan_freq_power channel_freq_power_EU_BG[] = {
|
||||
{1, 2412, LBS_TX_PWR_EMEA_DEFAULT},
|
||||
{2, 2417, LBS_TX_PWR_EMEA_DEFAULT},
|
||||
{3, 2422, LBS_TX_PWR_EMEA_DEFAULT},
|
||||
{4, 2427, LBS_TX_PWR_EMEA_DEFAULT},
|
||||
{5, 2432, LBS_TX_PWR_EMEA_DEFAULT},
|
||||
{6, 2437, LBS_TX_PWR_EMEA_DEFAULT},
|
||||
{7, 2442, LBS_TX_PWR_EMEA_DEFAULT},
|
||||
{8, 2447, LBS_TX_PWR_EMEA_DEFAULT},
|
||||
{9, 2452, LBS_TX_PWR_EMEA_DEFAULT},
|
||||
{10, 2457, LBS_TX_PWR_EMEA_DEFAULT},
|
||||
{11, 2462, LBS_TX_PWR_EMEA_DEFAULT},
|
||||
{12, 2467, LBS_TX_PWR_EMEA_DEFAULT},
|
||||
{13, 2472, LBS_TX_PWR_EMEA_DEFAULT}
|
||||
};
|
||||
|
||||
/* band: 'B/G', region: Spain */
|
||||
static struct chan_freq_power channel_freq_power_SPN_BG[] = {
|
||||
{10, 2457, LBS_TX_PWR_DEFAULT},
|
||||
{11, 2462, LBS_TX_PWR_DEFAULT}
|
||||
};
|
||||
|
||||
/* band: 'B/G', region: France */
|
||||
static struct chan_freq_power channel_freq_power_FR_BG[] = {
|
||||
{10, 2457, LBS_TX_PWR_FR_DEFAULT},
|
||||
{11, 2462, LBS_TX_PWR_FR_DEFAULT},
|
||||
{12, 2467, LBS_TX_PWR_FR_DEFAULT},
|
||||
{13, 2472, LBS_TX_PWR_FR_DEFAULT}
|
||||
};
|
||||
|
||||
/* band: 'B/G', region: Japan */
|
||||
static struct chan_freq_power channel_freq_power_JPN_BG[] = {
|
||||
{1, 2412, LBS_TX_PWR_JP_DEFAULT},
|
||||
{2, 2417, LBS_TX_PWR_JP_DEFAULT},
|
||||
{3, 2422, LBS_TX_PWR_JP_DEFAULT},
|
||||
{4, 2427, LBS_TX_PWR_JP_DEFAULT},
|
||||
{5, 2432, LBS_TX_PWR_JP_DEFAULT},
|
||||
{6, 2437, LBS_TX_PWR_JP_DEFAULT},
|
||||
{7, 2442, LBS_TX_PWR_JP_DEFAULT},
|
||||
{8, 2447, LBS_TX_PWR_JP_DEFAULT},
|
||||
{9, 2452, LBS_TX_PWR_JP_DEFAULT},
|
||||
{10, 2457, LBS_TX_PWR_JP_DEFAULT},
|
||||
{11, 2462, LBS_TX_PWR_JP_DEFAULT},
|
||||
{12, 2467, LBS_TX_PWR_JP_DEFAULT},
|
||||
{13, 2472, LBS_TX_PWR_JP_DEFAULT},
|
||||
{14, 2484, LBS_TX_PWR_JP_DEFAULT}
|
||||
};
|
||||
|
||||
/**
|
||||
* the structure for channel, frequency and power
|
||||
*/
|
||||
struct region_cfp_table {
|
||||
u8 region;
|
||||
struct chan_freq_power *cfp_BG;
|
||||
int cfp_no_BG;
|
||||
};
|
||||
|
||||
/**
|
||||
* the structure for the mapping between region and CFP
|
||||
*/
|
||||
static struct region_cfp_table region_cfp_table[] = {
|
||||
{0x10, /*US FCC */
|
||||
channel_freq_power_US_BG,
|
||||
ARRAY_SIZE(channel_freq_power_US_BG),
|
||||
}
|
||||
,
|
||||
{0x20, /*CANADA IC */
|
||||
channel_freq_power_US_BG,
|
||||
ARRAY_SIZE(channel_freq_power_US_BG),
|
||||
}
|
||||
,
|
||||
{0x30, /*EU*/ channel_freq_power_EU_BG,
|
||||
ARRAY_SIZE(channel_freq_power_EU_BG),
|
||||
}
|
||||
,
|
||||
{0x31, /*SPAIN*/ channel_freq_power_SPN_BG,
|
||||
ARRAY_SIZE(channel_freq_power_SPN_BG),
|
||||
}
|
||||
,
|
||||
{0x32, /*FRANCE*/ channel_freq_power_FR_BG,
|
||||
ARRAY_SIZE(channel_freq_power_FR_BG),
|
||||
}
|
||||
,
|
||||
{0x40, /*JAPAN*/ channel_freq_power_JPN_BG,
|
||||
ARRAY_SIZE(channel_freq_power_JPN_BG),
|
||||
}
|
||||
,
|
||||
/*Add new region here */
|
||||
};
|
||||
|
||||
/**
|
||||
* the table to keep region code
|
||||
*/
|
||||
u16 lbs_region_code_to_index[MRVDRV_MAX_REGION_CODE] =
|
||||
{ 0x10, 0x20, 0x30, 0x31, 0x32, 0x40 };
|
||||
|
||||
/**
|
||||
* 802.11b/g supported bitrates (in 500Kb/s units)
|
||||
*/
|
||||
u8 lbs_bg_rates[MAX_RATES] =
|
||||
{ 0x02, 0x04, 0x0b, 0x16, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c,
|
||||
0x00, 0x00 };
|
||||
|
||||
/**
|
||||
* FW rate table. FW refers to rates by their index in this table, not by the
|
||||
* rate value itself. Values of 0x00 are
|
||||
|
@ -405,7 +285,7 @@ static ssize_t lbs_mesh_set(struct device *dev,
|
|||
return count;
|
||||
if (enable)
|
||||
action = CMD_ACT_MESH_CONFIG_START;
|
||||
ret = lbs_mesh_config(priv, action, priv->curbssparams.channel);
|
||||
ret = lbs_mesh_config(priv, action, priv->channel);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -1089,6 +969,8 @@ static void auto_deepsleep_timer_fn(unsigned long data)
|
|||
ret = lbs_prepare_and_send_command(priv,
|
||||
CMD_802_11_DEEP_SLEEP, 0,
|
||||
0, 0, NULL);
|
||||
if (ret)
|
||||
lbs_pr_err("Enter Deep Sleep command failed\n");
|
||||
}
|
||||
}
|
||||
mod_timer(&priv->auto_deepsleep_timer , jiffies +
|
||||
|
@ -1164,7 +1046,7 @@ static int lbs_init_adapter(struct lbs_private *priv)
|
|||
priv->mesh_connect_status = LBS_DISCONNECTED;
|
||||
priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
|
||||
priv->mode = IW_MODE_INFRA;
|
||||
priv->curbssparams.channel = DEFAULT_AD_HOC_CHANNEL;
|
||||
priv->channel = DEFAULT_AD_HOC_CHANNEL;
|
||||
priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON;
|
||||
priv->radio_on = 1;
|
||||
priv->enablehwauto = 1;
|
||||
|
@ -1345,7 +1227,6 @@ EXPORT_SYMBOL_GPL(lbs_add_card);
|
|||
void lbs_remove_card(struct lbs_private *priv)
|
||||
{
|
||||
struct net_device *dev = priv->dev;
|
||||
union iwreq_data wrqu;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_MAIN);
|
||||
|
||||
|
@ -1370,9 +1251,7 @@ void lbs_remove_card(struct lbs_private *priv)
|
|||
lbs_ps_wakeup(priv, CMD_OPTION_WAITFORRSP);
|
||||
}
|
||||
|
||||
memset(wrqu.ap_addr.sa_data, 0xaa, ETH_ALEN);
|
||||
wrqu.ap_addr.sa_family = ARPHRD_ETHER;
|
||||
wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
|
||||
lbs_send_disconnect_notification(priv);
|
||||
|
||||
if (priv->is_deep_sleep) {
|
||||
priv->is_deep_sleep = 0;
|
||||
|
@ -1406,9 +1285,6 @@ int lbs_start_card(struct lbs_private *priv)
|
|||
if (ret)
|
||||
goto done;
|
||||
|
||||
/* init 802.11d */
|
||||
lbs_init_11d(priv);
|
||||
|
||||
if (lbs_cfg_register(priv)) {
|
||||
lbs_pr_err("cannot register device\n");
|
||||
goto done;
|
||||
|
@ -1435,10 +1311,10 @@ int lbs_start_card(struct lbs_private *priv)
|
|||
|
||||
priv->mesh_tlv = TLV_TYPE_OLD_MESH_ID;
|
||||
if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
|
||||
priv->curbssparams.channel)) {
|
||||
priv->channel)) {
|
||||
priv->mesh_tlv = TLV_TYPE_MESH_ID;
|
||||
if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
|
||||
priv->curbssparams.channel))
|
||||
priv->channel))
|
||||
priv->mesh_tlv = 0;
|
||||
}
|
||||
} else if (priv->mesh_fw_ver == MESH_FW_NEW) {
|
||||
|
@ -1447,7 +1323,7 @@ int lbs_start_card(struct lbs_private *priv)
|
|||
*/
|
||||
priv->mesh_tlv = TLV_TYPE_MESH_ID;
|
||||
if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
|
||||
priv->curbssparams.channel))
|
||||
priv->channel))
|
||||
priv->mesh_tlv = 0;
|
||||
}
|
||||
if (priv->mesh_tlv) {
|
||||
|
@ -1618,68 +1494,6 @@ static void lbs_remove_mesh(struct lbs_private *priv)
|
|||
lbs_deb_leave(LBS_DEB_MESH);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function finds the CFP in
|
||||
* region_cfp_table based on region and band parameter.
|
||||
*
|
||||
* @param region The region code
|
||||
* @param band The band
|
||||
* @param cfp_no A pointer to CFP number
|
||||
* @return A pointer to CFP
|
||||
*/
|
||||
struct chan_freq_power *lbs_get_region_cfp_table(u8 region, int *cfp_no)
|
||||
{
|
||||
int i, end;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_MAIN);
|
||||
|
||||
end = ARRAY_SIZE(region_cfp_table);
|
||||
|
||||
for (i = 0; i < end ; i++) {
|
||||
lbs_deb_main("region_cfp_table[i].region=%d\n",
|
||||
region_cfp_table[i].region);
|
||||
if (region_cfp_table[i].region == region) {
|
||||
*cfp_no = region_cfp_table[i].cfp_no_BG;
|
||||
lbs_deb_leave(LBS_DEB_MAIN);
|
||||
return region_cfp_table[i].cfp_BG;
|
||||
}
|
||||
}
|
||||
|
||||
lbs_deb_leave_args(LBS_DEB_MAIN, "ret NULL");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int lbs_set_regiontable(struct lbs_private *priv, u8 region, u8 band)
|
||||
{
|
||||
int ret = 0;
|
||||
int i = 0;
|
||||
|
||||
struct chan_freq_power *cfp;
|
||||
int cfp_no;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_MAIN);
|
||||
|
||||
memset(priv->region_channel, 0, sizeof(priv->region_channel));
|
||||
|
||||
cfp = lbs_get_region_cfp_table(region, &cfp_no);
|
||||
if (cfp != NULL) {
|
||||
priv->region_channel[i].nrcfp = cfp_no;
|
||||
priv->region_channel[i].CFP = cfp;
|
||||
} else {
|
||||
lbs_deb_main("wrong region code %#x in band B/G\n",
|
||||
region);
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
priv->region_channel[i].valid = 1;
|
||||
priv->region_channel[i].region = region;
|
||||
priv->region_channel[i].band = band;
|
||||
i++;
|
||||
out:
|
||||
lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void lbs_queue_event(struct lbs_private *priv, u32 event)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
|
|
@ -187,9 +187,9 @@ static ssize_t mesh_id_get(struct device *dev, struct device_attribute *attr,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (defs.meshie.val.mesh_id_len > IW_ESSID_MAX_SIZE) {
|
||||
if (defs.meshie.val.mesh_id_len > IEEE80211_MAX_SSID_LEN) {
|
||||
lbs_pr_err("inconsistent mesh ID length");
|
||||
defs.meshie.val.mesh_id_len = IW_ESSID_MAX_SIZE;
|
||||
defs.meshie.val.mesh_id_len = IEEE80211_MAX_SSID_LEN;
|
||||
}
|
||||
|
||||
/* SSID not null terminated: reserve room for \0 + \n */
|
||||
|
@ -214,7 +214,7 @@ static ssize_t mesh_id_set(struct device *dev, struct device_attribute *attr,
|
|||
int len;
|
||||
int ret;
|
||||
|
||||
if (count < 2 || count > IW_ESSID_MAX_SIZE + 1)
|
||||
if (count < 2 || count > IEEE80211_MAX_SSID_LEN + 1)
|
||||
return -EINVAL;
|
||||
|
||||
memset(&cmd, 0, sizeof(struct cmd_ds_mesh_config));
|
||||
|
@ -233,7 +233,7 @@ static ssize_t mesh_id_set(struct device *dev, struct device_attribute *attr,
|
|||
/* SSID len */
|
||||
ie->val.mesh_id_len = len;
|
||||
/* IE len */
|
||||
ie->len = sizeof(struct mrvl_meshie_val) - IW_ESSID_MAX_SIZE + len;
|
||||
ie->len = sizeof(struct mrvl_meshie_val) - IEEE80211_MAX_SSID_LEN + len;
|
||||
|
||||
ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
|
||||
CMD_TYPE_MESH_SET_MESH_IE);
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include <linux/etherdevice.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include "hostcmd.h"
|
||||
#include "host.h"
|
||||
#include "radiotap.h"
|
||||
#include "decl.h"
|
||||
#include "dev.h"
|
||||
|
|
|
@ -12,18 +12,19 @@
|
|||
#include <net/lib80211.h>
|
||||
|
||||
#include "host.h"
|
||||
#include "decl.h"
|
||||
#include "dev.h"
|
||||
#include "scan.h"
|
||||
#include "assoc.h"
|
||||
#include "wext.h"
|
||||
#include "cmd.h"
|
||||
|
||||
//! Approximate amount of data needed to pass a scan result back to iwlist
|
||||
#define MAX_SCAN_CELL_SIZE (IW_EV_ADDR_LEN \
|
||||
+ IW_ESSID_MAX_SIZE \
|
||||
+ IEEE80211_MAX_SSID_LEN \
|
||||
+ IW_EV_UINT_LEN \
|
||||
+ IW_EV_FREQ_LEN \
|
||||
+ IW_EV_QUAL_LEN \
|
||||
+ IW_ESSID_MAX_SIZE \
|
||||
+ IEEE80211_MAX_SSID_LEN \
|
||||
+ IW_EV_PARAM_LEN \
|
||||
+ 40) /* 40 for WPAIE */
|
||||
|
||||
|
@ -121,6 +122,189 @@ static inline int is_same_network(struct bss_descriptor *src,
|
|||
|
||||
|
||||
|
||||
/*********************************************************************/
|
||||
/* */
|
||||
/* Region channel support */
|
||||
/* */
|
||||
/*********************************************************************/
|
||||
|
||||
#define LBS_TX_PWR_DEFAULT 20 /*100mW */
|
||||
#define LBS_TX_PWR_US_DEFAULT 20 /*100mW */
|
||||
#define LBS_TX_PWR_JP_DEFAULT 16 /*50mW */
|
||||
#define LBS_TX_PWR_FR_DEFAULT 20 /*100mW */
|
||||
#define LBS_TX_PWR_EMEA_DEFAULT 20 /*100mW */
|
||||
|
||||
/* Format { channel, frequency (MHz), maxtxpower } */
|
||||
/* band: 'B/G', region: USA FCC/Canada IC */
|
||||
static struct chan_freq_power channel_freq_power_US_BG[] = {
|
||||
{1, 2412, LBS_TX_PWR_US_DEFAULT},
|
||||
{2, 2417, LBS_TX_PWR_US_DEFAULT},
|
||||
{3, 2422, LBS_TX_PWR_US_DEFAULT},
|
||||
{4, 2427, LBS_TX_PWR_US_DEFAULT},
|
||||
{5, 2432, LBS_TX_PWR_US_DEFAULT},
|
||||
{6, 2437, LBS_TX_PWR_US_DEFAULT},
|
||||
{7, 2442, LBS_TX_PWR_US_DEFAULT},
|
||||
{8, 2447, LBS_TX_PWR_US_DEFAULT},
|
||||
{9, 2452, LBS_TX_PWR_US_DEFAULT},
|
||||
{10, 2457, LBS_TX_PWR_US_DEFAULT},
|
||||
{11, 2462, LBS_TX_PWR_US_DEFAULT}
|
||||
};
|
||||
|
||||
/* band: 'B/G', region: Europe ETSI */
|
||||
static struct chan_freq_power channel_freq_power_EU_BG[] = {
|
||||
{1, 2412, LBS_TX_PWR_EMEA_DEFAULT},
|
||||
{2, 2417, LBS_TX_PWR_EMEA_DEFAULT},
|
||||
{3, 2422, LBS_TX_PWR_EMEA_DEFAULT},
|
||||
{4, 2427, LBS_TX_PWR_EMEA_DEFAULT},
|
||||
{5, 2432, LBS_TX_PWR_EMEA_DEFAULT},
|
||||
{6, 2437, LBS_TX_PWR_EMEA_DEFAULT},
|
||||
{7, 2442, LBS_TX_PWR_EMEA_DEFAULT},
|
||||
{8, 2447, LBS_TX_PWR_EMEA_DEFAULT},
|
||||
{9, 2452, LBS_TX_PWR_EMEA_DEFAULT},
|
||||
{10, 2457, LBS_TX_PWR_EMEA_DEFAULT},
|
||||
{11, 2462, LBS_TX_PWR_EMEA_DEFAULT},
|
||||
{12, 2467, LBS_TX_PWR_EMEA_DEFAULT},
|
||||
{13, 2472, LBS_TX_PWR_EMEA_DEFAULT}
|
||||
};
|
||||
|
||||
/* band: 'B/G', region: Spain */
|
||||
static struct chan_freq_power channel_freq_power_SPN_BG[] = {
|
||||
{10, 2457, LBS_TX_PWR_DEFAULT},
|
||||
{11, 2462, LBS_TX_PWR_DEFAULT}
|
||||
};
|
||||
|
||||
/* band: 'B/G', region: France */
|
||||
static struct chan_freq_power channel_freq_power_FR_BG[] = {
|
||||
{10, 2457, LBS_TX_PWR_FR_DEFAULT},
|
||||
{11, 2462, LBS_TX_PWR_FR_DEFAULT},
|
||||
{12, 2467, LBS_TX_PWR_FR_DEFAULT},
|
||||
{13, 2472, LBS_TX_PWR_FR_DEFAULT}
|
||||
};
|
||||
|
||||
/* band: 'B/G', region: Japan */
|
||||
static struct chan_freq_power channel_freq_power_JPN_BG[] = {
|
||||
{1, 2412, LBS_TX_PWR_JP_DEFAULT},
|
||||
{2, 2417, LBS_TX_PWR_JP_DEFAULT},
|
||||
{3, 2422, LBS_TX_PWR_JP_DEFAULT},
|
||||
{4, 2427, LBS_TX_PWR_JP_DEFAULT},
|
||||
{5, 2432, LBS_TX_PWR_JP_DEFAULT},
|
||||
{6, 2437, LBS_TX_PWR_JP_DEFAULT},
|
||||
{7, 2442, LBS_TX_PWR_JP_DEFAULT},
|
||||
{8, 2447, LBS_TX_PWR_JP_DEFAULT},
|
||||
{9, 2452, LBS_TX_PWR_JP_DEFAULT},
|
||||
{10, 2457, LBS_TX_PWR_JP_DEFAULT},
|
||||
{11, 2462, LBS_TX_PWR_JP_DEFAULT},
|
||||
{12, 2467, LBS_TX_PWR_JP_DEFAULT},
|
||||
{13, 2472, LBS_TX_PWR_JP_DEFAULT},
|
||||
{14, 2484, LBS_TX_PWR_JP_DEFAULT}
|
||||
};
|
||||
|
||||
/**
|
||||
* the structure for channel, frequency and power
|
||||
*/
|
||||
struct region_cfp_table {
|
||||
u8 region;
|
||||
struct chan_freq_power *cfp_BG;
|
||||
int cfp_no_BG;
|
||||
};
|
||||
|
||||
/**
|
||||
* the structure for the mapping between region and CFP
|
||||
*/
|
||||
static struct region_cfp_table region_cfp_table[] = {
|
||||
{0x10, /*US FCC */
|
||||
channel_freq_power_US_BG,
|
||||
ARRAY_SIZE(channel_freq_power_US_BG),
|
||||
}
|
||||
,
|
||||
{0x20, /*CANADA IC */
|
||||
channel_freq_power_US_BG,
|
||||
ARRAY_SIZE(channel_freq_power_US_BG),
|
||||
}
|
||||
,
|
||||
{0x30, /*EU*/ channel_freq_power_EU_BG,
|
||||
ARRAY_SIZE(channel_freq_power_EU_BG),
|
||||
}
|
||||
,
|
||||
{0x31, /*SPAIN*/ channel_freq_power_SPN_BG,
|
||||
ARRAY_SIZE(channel_freq_power_SPN_BG),
|
||||
}
|
||||
,
|
||||
{0x32, /*FRANCE*/ channel_freq_power_FR_BG,
|
||||
ARRAY_SIZE(channel_freq_power_FR_BG),
|
||||
}
|
||||
,
|
||||
{0x40, /*JAPAN*/ channel_freq_power_JPN_BG,
|
||||
ARRAY_SIZE(channel_freq_power_JPN_BG),
|
||||
}
|
||||
,
|
||||
/*Add new region here */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief This function finds the CFP in
|
||||
* region_cfp_table based on region and band parameter.
|
||||
*
|
||||
* @param region The region code
|
||||
* @param band The band
|
||||
* @param cfp_no A pointer to CFP number
|
||||
* @return A pointer to CFP
|
||||
*/
|
||||
static struct chan_freq_power *lbs_get_region_cfp_table(u8 region, int *cfp_no)
|
||||
{
|
||||
int i, end;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_MAIN);
|
||||
|
||||
end = ARRAY_SIZE(region_cfp_table);
|
||||
|
||||
for (i = 0; i < end ; i++) {
|
||||
lbs_deb_main("region_cfp_table[i].region=%d\n",
|
||||
region_cfp_table[i].region);
|
||||
if (region_cfp_table[i].region == region) {
|
||||
*cfp_no = region_cfp_table[i].cfp_no_BG;
|
||||
lbs_deb_leave(LBS_DEB_MAIN);
|
||||
return region_cfp_table[i].cfp_BG;
|
||||
}
|
||||
}
|
||||
|
||||
lbs_deb_leave_args(LBS_DEB_MAIN, "ret NULL");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int lbs_set_regiontable(struct lbs_private *priv, u8 region, u8 band)
|
||||
{
|
||||
int ret = 0;
|
||||
int i = 0;
|
||||
|
||||
struct chan_freq_power *cfp;
|
||||
int cfp_no;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_MAIN);
|
||||
|
||||
memset(priv->region_channel, 0, sizeof(priv->region_channel));
|
||||
|
||||
cfp = lbs_get_region_cfp_table(region, &cfp_no);
|
||||
if (cfp != NULL) {
|
||||
priv->region_channel[i].nrcfp = cfp_no;
|
||||
priv->region_channel[i].CFP = cfp;
|
||||
} else {
|
||||
lbs_deb_main("wrong region code %#x in band B/G\n",
|
||||
region);
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
priv->region_channel[i].valid = 1;
|
||||
priv->region_channel[i].region = region;
|
||||
priv->region_channel[i].band = band;
|
||||
i++;
|
||||
out:
|
||||
lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*********************************************************************/
|
||||
/* */
|
||||
|
@ -161,31 +345,15 @@ static int lbs_scan_create_channel_list(struct lbs_private *priv,
|
|||
scantype = CMD_SCAN_TYPE_ACTIVE;
|
||||
|
||||
for (rgnidx = 0; rgnidx < ARRAY_SIZE(priv->region_channel); rgnidx++) {
|
||||
if (priv->enable11d && (priv->connect_status != LBS_CONNECTED)
|
||||
&& (priv->mesh_connect_status != LBS_CONNECTED)) {
|
||||
/* Scan all the supported chan for the first scan */
|
||||
if (!priv->universal_channel[rgnidx].valid)
|
||||
continue;
|
||||
scanregion = &priv->universal_channel[rgnidx];
|
||||
|
||||
/* clear the parsed_region_chan for the first scan */
|
||||
memset(&priv->parsed_region_chan, 0x00,
|
||||
sizeof(priv->parsed_region_chan));
|
||||
} else {
|
||||
if (!priv->region_channel[rgnidx].valid)
|
||||
continue;
|
||||
scanregion = &priv->region_channel[rgnidx];
|
||||
}
|
||||
if (!priv->region_channel[rgnidx].valid)
|
||||
continue;
|
||||
scanregion = &priv->region_channel[rgnidx];
|
||||
|
||||
for (nextchan = 0; nextchan < scanregion->nrcfp; nextchan++, chanidx++) {
|
||||
struct chanscanparamset *chan = &scanchanlist[chanidx];
|
||||
|
||||
cfp = scanregion->CFP + nextchan;
|
||||
|
||||
if (priv->enable11d)
|
||||
scantype = lbs_get_scan_type_11d(cfp->channel,
|
||||
&priv->parsed_region_chan);
|
||||
|
||||
if (scanregion->band == BAND_B || scanregion->band == BAND_G)
|
||||
chan->radiotype = CMD_SCAN_RADIO_TYPE_BG;
|
||||
|
||||
|
@ -519,7 +687,6 @@ static int lbs_process_bss(struct bss_descriptor *bss,
|
|||
struct ieee_ie_cf_param_set *cf;
|
||||
struct ieee_ie_ibss_param_set *ibss;
|
||||
DECLARE_SSID_BUF(ssid);
|
||||
struct ieee_ie_country_info_set *pcountryinfo;
|
||||
uint8_t *pos, *end, *p;
|
||||
uint8_t n_ex_rates = 0, got_basic_rates = 0, n_basic_rates = 0;
|
||||
uint16_t beaconsize = 0;
|
||||
|
@ -642,26 +809,6 @@ static int lbs_process_bss(struct bss_descriptor *bss,
|
|||
lbs_deb_scan("got IBSS IE\n");
|
||||
break;
|
||||
|
||||
case WLAN_EID_COUNTRY:
|
||||
pcountryinfo = (struct ieee_ie_country_info_set *) pos;
|
||||
lbs_deb_scan("got COUNTRY IE\n");
|
||||
if (pcountryinfo->header.len < sizeof(pcountryinfo->countrycode)
|
||||
|| pcountryinfo->header.len > 254) {
|
||||
lbs_deb_scan("%s: 11D- Err CountryInfo len %d, min %zd, max 254\n",
|
||||
__func__,
|
||||
pcountryinfo->header.len,
|
||||
sizeof(pcountryinfo->countrycode));
|
||||
ret = -1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
memcpy(&bss->countryinfo, pcountryinfo,
|
||||
pcountryinfo->header.len + 2);
|
||||
lbs_deb_hex(LBS_DEB_SCAN, "process_bss: 11d countryinfo",
|
||||
(uint8_t *) pcountryinfo,
|
||||
(int) (pcountryinfo->header.len + 2));
|
||||
break;
|
||||
|
||||
case WLAN_EID_EXT_SUPP_RATES:
|
||||
/* only process extended supported rate if data rate is
|
||||
* already found. Data rate IE should come before
|
||||
|
@ -812,7 +959,7 @@ static inline char *lbs_translate_scan(struct lbs_private *priv,
|
|||
/* SSID */
|
||||
iwe.cmd = SIOCGIWESSID;
|
||||
iwe.u.data.flags = 1;
|
||||
iwe.u.data.length = min((uint32_t) bss->ssid_len, (uint32_t) IW_ESSID_MAX_SIZE);
|
||||
iwe.u.data.length = min((uint32_t) bss->ssid_len, (uint32_t) IEEE80211_MAX_SSID_LEN);
|
||||
start = iwe_stream_add_point(info, start, stop, &iwe, bss->ssid);
|
||||
|
||||
/* Mode */
|
||||
|
@ -1022,9 +1169,12 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info,
|
|||
return -EAGAIN;
|
||||
|
||||
/* Update RSSI if current BSS is a locally created ad-hoc BSS */
|
||||
if ((priv->mode == IW_MODE_ADHOC) && priv->adhoccreate)
|
||||
lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
|
||||
CMD_OPTION_WAITFORRSP, 0, NULL);
|
||||
if ((priv->mode == IW_MODE_ADHOC) && priv->adhoccreate) {
|
||||
err = lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
|
||||
CMD_OPTION_WAITFORRSP, 0, NULL);
|
||||
if (err)
|
||||
goto out;
|
||||
}
|
||||
|
||||
mutex_lock(&priv->lock);
|
||||
list_for_each_entry_safe (iter_bss, safe, &priv->network_list, list) {
|
||||
|
@ -1058,7 +1208,7 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info,
|
|||
|
||||
dwrq->length = (ev - extra);
|
||||
dwrq->flags = 0;
|
||||
|
||||
out:
|
||||
lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", err);
|
||||
return err;
|
||||
}
|
||||
|
@ -1141,11 +1291,11 @@ static int lbs_ret_80211_scan(struct lbs_private *priv, unsigned long dummy,
|
|||
/* The size of the TLV buffer is equal to the entire command response
|
||||
* size (scanrespsize) minus the fixed fields (sizeof()'s), the
|
||||
* BSS Descriptions (bssdescriptsize as bytesLef) and the command
|
||||
* response header (S_DS_GEN)
|
||||
* response header (sizeof(struct cmd_header))
|
||||
*/
|
||||
tlvbufsize = scanrespsize - (bytesleft + sizeof(scanresp->bssdescriptsize)
|
||||
+ sizeof(scanresp->nr_sets)
|
||||
+ S_DS_GEN);
|
||||
+ sizeof(struct cmd_header));
|
||||
|
||||
/*
|
||||
* Process each scan response returned (scanresp->nr_sets). Save
|
||||
|
|
|
@ -9,8 +9,36 @@
|
|||
|
||||
#include <net/iw_handler.h>
|
||||
|
||||
struct lbs_private;
|
||||
|
||||
#define MAX_NETWORK_COUNT 128
|
||||
|
||||
/** Chan-freq-TxPower mapping table*/
|
||||
struct chan_freq_power {
|
||||
/** channel Number */
|
||||
u16 channel;
|
||||
/** frequency of this channel */
|
||||
u32 freq;
|
||||
/** Max allowed Tx power level */
|
||||
u16 maxtxpower;
|
||||
/** TRUE:channel unsupported; FLASE:supported*/
|
||||
u8 unsupported;
|
||||
};
|
||||
|
||||
/** region-band mapping table*/
|
||||
struct region_channel {
|
||||
/** TRUE if this entry is valid */
|
||||
u8 valid;
|
||||
/** region code for US, Japan ... */
|
||||
u8 region;
|
||||
/** band B/G/A, used for BAND_CONFIG cmd */
|
||||
u8 band;
|
||||
/** Actual No. of elements in the array below */
|
||||
u8 nrcfp;
|
||||
/** chan-freq-txpower mapping table*/
|
||||
struct chan_freq_power *CFP;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Maximum number of channels that can be sent in a setuserscan ioctl
|
||||
*/
|
||||
|
@ -18,6 +46,8 @@
|
|||
|
||||
int lbs_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len);
|
||||
|
||||
int lbs_set_regiontable(struct lbs_private *priv, u8 region, u8 band);
|
||||
|
||||
int lbs_send_specific_ssid_scan(struct lbs_private *priv, u8 *ssid,
|
||||
u8 ssid_len);
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
|
||||
#include "hostcmd.h"
|
||||
#include "host.h"
|
||||
#include "radiotap.h"
|
||||
#include "decl.h"
|
||||
#include "defs.h"
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
#define _LBS_TYPES_H_
|
||||
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/ieee80211.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <linux/wireless.h>
|
||||
|
||||
struct ieee_ie_header {
|
||||
u8 id;
|
||||
|
@ -247,7 +247,7 @@ struct mrvl_meshie_val {
|
|||
uint8_t active_metric_id;
|
||||
uint8_t mesh_capability;
|
||||
uint8_t mesh_id_len;
|
||||
uint8_t mesh_id[IW_ESSID_MAX_SIZE];
|
||||
uint8_t mesh_id[IEEE80211_MAX_SSID_LEN];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct mrvl_meshie {
|
||||
|
|
|
@ -45,6 +45,64 @@ static inline void lbs_cancel_association_work(struct lbs_private *priv)
|
|||
priv->pending_assoc_req = NULL;
|
||||
}
|
||||
|
||||
void lbs_send_disconnect_notification(struct lbs_private *priv)
|
||||
{
|
||||
union iwreq_data wrqu;
|
||||
|
||||
memset(wrqu.ap_addr.sa_data, 0x00, ETH_ALEN);
|
||||
wrqu.ap_addr.sa_family = ARPHRD_ETHER;
|
||||
wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
|
||||
}
|
||||
|
||||
static void lbs_send_iwevcustom_event(struct lbs_private *priv, s8 *str)
|
||||
{
|
||||
union iwreq_data iwrq;
|
||||
u8 buf[50];
|
||||
|
||||
lbs_deb_enter(LBS_DEB_WEXT);
|
||||
|
||||
memset(&iwrq, 0, sizeof(union iwreq_data));
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
snprintf(buf, sizeof(buf) - 1, "%s", str);
|
||||
|
||||
iwrq.data.length = strlen(buf) + 1 + IW_EV_LCP_LEN;
|
||||
|
||||
/* Send Event to upper layer */
|
||||
lbs_deb_wext("event indication string %s\n", (char *)buf);
|
||||
lbs_deb_wext("event indication length %d\n", iwrq.data.length);
|
||||
lbs_deb_wext("sending wireless event IWEVCUSTOM for %s\n", str);
|
||||
|
||||
wireless_send_event(priv->dev, IWEVCUSTOM, &iwrq, buf);
|
||||
|
||||
lbs_deb_leave(LBS_DEB_WEXT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles MIC failure event.
|
||||
*
|
||||
* @param priv A pointer to struct lbs_private structure
|
||||
* @para event the event id
|
||||
* @return n/a
|
||||
*/
|
||||
void lbs_send_mic_failureevent(struct lbs_private *priv, u32 event)
|
||||
{
|
||||
char buf[50];
|
||||
|
||||
lbs_deb_enter(LBS_DEB_CMD);
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
sprintf(buf, "%s", "MLME-MICHAELMICFAILURE.indication ");
|
||||
|
||||
if (event == MACREG_INT_CODE_MIC_ERR_UNICAST)
|
||||
strcat(buf, "unicast ");
|
||||
else
|
||||
strcat(buf, "multicast ");
|
||||
|
||||
lbs_send_iwevcustom_event(priv, buf);
|
||||
lbs_deb_leave(LBS_DEB_CMD);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Find the channel frequency power info with specific channel
|
||||
*
|
||||
|
@ -65,8 +123,6 @@ struct chan_freq_power *lbs_find_cfp_by_band_and_channel(
|
|||
for (j = 0; !cfp && (j < ARRAY_SIZE(priv->region_channel)); j++) {
|
||||
rc = &priv->region_channel[j];
|
||||
|
||||
if (priv->enable11d)
|
||||
rc = &priv->universal_channel[j];
|
||||
if (!rc->valid || !rc->CFP)
|
||||
continue;
|
||||
if (rc->band != band)
|
||||
|
@ -106,8 +162,6 @@ static struct chan_freq_power *find_cfp_by_band_and_freq(
|
|||
for (j = 0; !cfp && (j < ARRAY_SIZE(priv->region_channel)); j++) {
|
||||
rc = &priv->region_channel[j];
|
||||
|
||||
if (priv->enable11d)
|
||||
rc = &priv->universal_channel[j];
|
||||
if (!rc->valid || !rc->CFP)
|
||||
continue;
|
||||
if (rc->band != band)
|
||||
|
@ -168,12 +222,12 @@ static int lbs_get_freq(struct net_device *dev, struct iw_request_info *info,
|
|||
lbs_deb_enter(LBS_DEB_WEXT);
|
||||
|
||||
cfp = lbs_find_cfp_by_band_and_channel(priv, 0,
|
||||
priv->curbssparams.channel);
|
||||
priv->channel);
|
||||
|
||||
if (!cfp) {
|
||||
if (priv->curbssparams.channel)
|
||||
if (priv->channel)
|
||||
lbs_deb_wext("invalid channel %d\n",
|
||||
priv->curbssparams.channel);
|
||||
priv->channel);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -546,8 +600,6 @@ static int lbs_get_range(struct net_device *dev, struct iw_request_info *info,
|
|||
struct chan_freq_power *cfp;
|
||||
u8 rates[MAX_RATES + 1];
|
||||
|
||||
u8 flag = 0;
|
||||
|
||||
lbs_deb_enter(LBS_DEB_WEXT);
|
||||
|
||||
dwrq->length = sizeof(struct iw_range);
|
||||
|
@ -569,52 +621,21 @@ static int lbs_get_range(struct net_device *dev, struct iw_request_info *info,
|
|||
|
||||
range->scan_capa = IW_SCAN_CAPA_ESSID;
|
||||
|
||||
if (priv->enable11d &&
|
||||
(priv->connect_status == LBS_CONNECTED ||
|
||||
priv->mesh_connect_status == LBS_CONNECTED)) {
|
||||
u8 chan_no;
|
||||
u8 band;
|
||||
|
||||
struct parsed_region_chan_11d *parsed_region_chan =
|
||||
&priv->parsed_region_chan;
|
||||
|
||||
if (parsed_region_chan == NULL) {
|
||||
lbs_deb_wext("11d: parsed_region_chan is NULL\n");
|
||||
goto out;
|
||||
}
|
||||
band = parsed_region_chan->band;
|
||||
lbs_deb_wext("band %d, nr_char %d\n", band,
|
||||
parsed_region_chan->nr_chan);
|
||||
|
||||
for (j = 0; (range->num_frequency < IW_MAX_FREQUENCIES)
|
||||
&& (j < ARRAY_SIZE(priv->region_channel)); j++) {
|
||||
cfp = priv->region_channel[j].CFP;
|
||||
for (i = 0; (range->num_frequency < IW_MAX_FREQUENCIES)
|
||||
&& (i < parsed_region_chan->nr_chan); i++) {
|
||||
chan_no = parsed_region_chan->chanpwr[i].chan;
|
||||
lbs_deb_wext("chan_no %d\n", chan_no);
|
||||
range->freq[range->num_frequency].i = (long)chan_no;
|
||||
&& priv->region_channel[j].valid
|
||||
&& cfp
|
||||
&& (i < priv->region_channel[j].nrcfp); i++) {
|
||||
range->freq[range->num_frequency].i =
|
||||
(long)cfp->channel;
|
||||
range->freq[range->num_frequency].m =
|
||||
(long)lbs_chan_2_freq(chan_no) * 100000;
|
||||
(long)cfp->freq * 100000;
|
||||
range->freq[range->num_frequency].e = 1;
|
||||
cfp++;
|
||||
range->num_frequency++;
|
||||
}
|
||||
flag = 1;
|
||||
}
|
||||
if (!flag) {
|
||||
for (j = 0; (range->num_frequency < IW_MAX_FREQUENCIES)
|
||||
&& (j < ARRAY_SIZE(priv->region_channel)); j++) {
|
||||
cfp = priv->region_channel[j].CFP;
|
||||
for (i = 0; (range->num_frequency < IW_MAX_FREQUENCIES)
|
||||
&& priv->region_channel[j].valid
|
||||
&& cfp
|
||||
&& (i < priv->region_channel[j].nrcfp); i++) {
|
||||
range->freq[range->num_frequency].i =
|
||||
(long)cfp->channel;
|
||||
range->freq[range->num_frequency].m =
|
||||
(long)cfp->freq * 100000;
|
||||
range->freq[range->num_frequency].e = 1;
|
||||
cfp++;
|
||||
range->num_frequency++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lbs_deb_wext("IW_MAX_FREQUENCIES %d, num_frequency %d\n",
|
||||
|
@ -699,7 +720,6 @@ static int lbs_get_range(struct net_device *dev, struct iw_request_info *info,
|
|||
| IW_ENC_CAPA_CIPHER_CCMP;
|
||||
}
|
||||
|
||||
out:
|
||||
lbs_deb_leave(LBS_DEB_WEXT);
|
||||
return 0;
|
||||
}
|
||||
|
@ -832,7 +852,7 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
|
|||
u32 rssi_qual;
|
||||
u32 tx_qual;
|
||||
u32 quality = 0;
|
||||
int stats_valid = 0;
|
||||
int ret, stats_valid = 0;
|
||||
u8 rssi;
|
||||
u32 tx_retries;
|
||||
struct cmd_ds_802_11_get_log log;
|
||||
|
@ -881,7 +901,9 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
|
|||
|
||||
memset(&log, 0, sizeof(log));
|
||||
log.hdr.size = cpu_to_le16(sizeof(log));
|
||||
lbs_cmd_with_response(priv, CMD_802_11_GET_LOG, &log);
|
||||
ret = lbs_cmd_with_response(priv, CMD_802_11_GET_LOG, &log);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
tx_retries = le32_to_cpu(log.retry);
|
||||
|
||||
|
@ -909,8 +931,10 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
|
|||
stats_valid = 1;
|
||||
|
||||
/* update stats asynchronously for future calls */
|
||||
lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
|
||||
ret = lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
|
||||
0, 0, NULL);
|
||||
if (ret)
|
||||
lbs_pr_err("RSSI command failed\n");
|
||||
out:
|
||||
if (!stats_valid) {
|
||||
priv->wstats.miss.beacon = 0;
|
||||
|
@ -1020,7 +1044,7 @@ static int lbs_mesh_set_freq(struct net_device *dev,
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (fwrq->m != priv->curbssparams.channel) {
|
||||
if (fwrq->m != priv->channel) {
|
||||
lbs_deb_wext("mesh channel change forces eth disconnect\n");
|
||||
if (priv->mode == IW_MODE_INFRA)
|
||||
lbs_cmd_80211_deauthenticate(priv,
|
||||
|
@ -2023,7 +2047,7 @@ static int lbs_set_essid(struct net_device *dev, struct iw_request_info *info,
|
|||
{
|
||||
struct lbs_private *priv = dev->ml_priv;
|
||||
int ret = 0;
|
||||
u8 ssid[IW_ESSID_MAX_SIZE];
|
||||
u8 ssid[IEEE80211_MAX_SSID_LEN];
|
||||
u8 ssid_len = 0;
|
||||
struct assoc_request * assoc_req;
|
||||
int in_ssid_len = dwrq->length;
|
||||
|
@ -2037,7 +2061,7 @@ static int lbs_set_essid(struct net_device *dev, struct iw_request_info *info,
|
|||
}
|
||||
|
||||
/* Check the size of the string */
|
||||
if (in_ssid_len > IW_ESSID_MAX_SIZE) {
|
||||
if (in_ssid_len > IEEE80211_MAX_SSID_LEN) {
|
||||
ret = -E2BIG;
|
||||
goto out;
|
||||
}
|
||||
|
@ -2068,7 +2092,7 @@ out:
|
|||
ret = -ENOMEM;
|
||||
} else {
|
||||
/* Copy the SSID to the association request */
|
||||
memcpy(&assoc_req->ssid, &ssid, IW_ESSID_MAX_SIZE);
|
||||
memcpy(&assoc_req->ssid, &ssid, IEEE80211_MAX_SSID_LEN);
|
||||
assoc_req->ssid_len = ssid_len;
|
||||
set_bit(ASSOC_FLAG_SSID, &assoc_req->flags);
|
||||
lbs_postpone_association_work(priv);
|
||||
|
@ -2119,7 +2143,7 @@ static int lbs_mesh_set_essid(struct net_device *dev,
|
|||
}
|
||||
|
||||
/* Check the size of the string */
|
||||
if (dwrq->length > IW_ESSID_MAX_SIZE) {
|
||||
if (dwrq->length > IEEE80211_MAX_SSID_LEN) {
|
||||
ret = -E2BIG;
|
||||
goto out;
|
||||
}
|
||||
|
@ -2134,7 +2158,7 @@ static int lbs_mesh_set_essid(struct net_device *dev,
|
|||
}
|
||||
|
||||
lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
|
||||
priv->curbssparams.channel);
|
||||
priv->channel);
|
||||
out:
|
||||
lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
|
||||
return ret;
|
||||
|
|
|
@ -4,7 +4,15 @@
|
|||
#ifndef _LBS_WEXT_H_
|
||||
#define _LBS_WEXT_H_
|
||||
|
||||
void lbs_send_disconnect_notification(struct lbs_private *priv);
|
||||
void lbs_send_mic_failureevent(struct lbs_private *priv, u32 event);
|
||||
|
||||
extern struct iw_handler_def lbs_handler_def;
|
||||
extern struct iw_handler_def mesh_handler_def;
|
||||
|
||||
struct chan_freq_power *lbs_find_cfp_by_band_and_channel(
|
||||
struct lbs_private *priv,
|
||||
u8 band,
|
||||
u16 channel);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -60,8 +60,15 @@ static inline fwtype_t determine_firmware_type(struct comp_id *nic_id)
|
|||
/* Set priv->firmware type, determine firmware properties
|
||||
* This function can be called before we have registerred with netdev,
|
||||
* so all errors go out with dev_* rather than printk
|
||||
*
|
||||
* If non-NULL stores a firmware description in fw_name.
|
||||
* If non-NULL stores a HW version in hw_ver
|
||||
*
|
||||
* These are output via generic cfg80211 ethtool support.
|
||||
*/
|
||||
int determine_fw_capabilities(struct orinoco_private *priv)
|
||||
int determine_fw_capabilities(struct orinoco_private *priv,
|
||||
char *fw_name, size_t fw_name_len,
|
||||
u32 *hw_ver)
|
||||
{
|
||||
struct device *dev = priv->dev;
|
||||
hermes_t *hw = &priv->hw;
|
||||
|
@ -85,6 +92,12 @@ int determine_fw_capabilities(struct orinoco_private *priv)
|
|||
dev_info(dev, "Hardware identity %04x:%04x:%04x:%04x\n",
|
||||
nic_id.id, nic_id.variant, nic_id.major, nic_id.minor);
|
||||
|
||||
if (hw_ver)
|
||||
*hw_ver = (((nic_id.id & 0xff) << 24) |
|
||||
((nic_id.variant & 0xff) << 16) |
|
||||
((nic_id.major & 0xff) << 8) |
|
||||
(nic_id.minor & 0xff));
|
||||
|
||||
priv->firmware_type = determine_firmware_type(&nic_id);
|
||||
|
||||
/* Get the firmware version */
|
||||
|
@ -135,8 +148,9 @@ int determine_fw_capabilities(struct orinoco_private *priv)
|
|||
case FIRMWARE_TYPE_AGERE:
|
||||
/* Lucent Wavelan IEEE, Lucent Orinoco, Cabletron RoamAbout,
|
||||
ELSA, Melco, HP, IBM, Dell 1150, Compaq 110/210 */
|
||||
snprintf(priv->fw_name, sizeof(priv->fw_name) - 1,
|
||||
"Lucent/Agere %d.%02d", sta_id.major, sta_id.minor);
|
||||
if (fw_name)
|
||||
snprintf(fw_name, fw_name_len, "Lucent/Agere %d.%02d",
|
||||
sta_id.major, sta_id.minor);
|
||||
|
||||
firmver = ((unsigned long)sta_id.major << 16) | sta_id.minor;
|
||||
|
||||
|
@ -185,8 +199,8 @@ int determine_fw_capabilities(struct orinoco_private *priv)
|
|||
tmp[SYMBOL_MAX_VER_LEN] = '\0';
|
||||
}
|
||||
|
||||
snprintf(priv->fw_name, sizeof(priv->fw_name) - 1,
|
||||
"Symbol %s", tmp);
|
||||
if (fw_name)
|
||||
snprintf(fw_name, fw_name_len, "Symbol %s", tmp);
|
||||
|
||||
priv->has_ibss = (firmver >= 0x20000);
|
||||
priv->has_wep = (firmver >= 0x15012);
|
||||
|
@ -224,9 +238,9 @@ int determine_fw_capabilities(struct orinoco_private *priv)
|
|||
* different and less well tested */
|
||||
/* D-Link MAC : 00:40:05:* */
|
||||
/* Addtron MAC : 00:90:D1:* */
|
||||
snprintf(priv->fw_name, sizeof(priv->fw_name) - 1,
|
||||
"Intersil %d.%d.%d", sta_id.major, sta_id.minor,
|
||||
sta_id.variant);
|
||||
if (fw_name)
|
||||
snprintf(fw_name, fw_name_len, "Intersil %d.%d.%d",
|
||||
sta_id.major, sta_id.minor, sta_id.variant);
|
||||
|
||||
firmver = ((unsigned long)sta_id.major << 16) |
|
||||
((unsigned long)sta_id.minor << 8) | sta_id.variant;
|
||||
|
@ -245,7 +259,8 @@ int determine_fw_capabilities(struct orinoco_private *priv)
|
|||
}
|
||||
break;
|
||||
}
|
||||
dev_info(dev, "Firmware determined as %s\n", priv->fw_name);
|
||||
if (fw_name)
|
||||
dev_info(dev, "Firmware determined as %s\n", fw_name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -24,7 +24,8 @@
|
|||
struct orinoco_private;
|
||||
struct dev_addr_list;
|
||||
|
||||
int determine_fw_capabilities(struct orinoco_private *priv);
|
||||
int determine_fw_capabilities(struct orinoco_private *priv, char *fw_name,
|
||||
size_t fw_name_len, u32 *hw_ver);
|
||||
int orinoco_hw_read_card_settings(struct orinoco_private *priv, u8 *dev_addr);
|
||||
int orinoco_hw_allocate_fid(struct orinoco_private *priv);
|
||||
int orinoco_get_bitratemode(int bitrate, int automatic);
|
||||
|
|
|
@ -83,7 +83,6 @@
|
|||
#include <linux/device.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <linux/if_arp.h>
|
||||
#include <linux/wireless.h>
|
||||
|
@ -162,8 +161,6 @@ static const u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
|
|||
| HERMES_EV_WTERR | HERMES_EV_INFO \
|
||||
| HERMES_EV_INFDROP)
|
||||
|
||||
static const struct ethtool_ops orinoco_ethtool_ops;
|
||||
|
||||
/********************************************************************/
|
||||
/* Data types */
|
||||
/********************************************************************/
|
||||
|
@ -1994,7 +1991,9 @@ int orinoco_init(struct orinoco_private *priv)
|
|||
goto out;
|
||||
}
|
||||
|
||||
err = determine_fw_capabilities(priv);
|
||||
err = determine_fw_capabilities(priv, wiphy->fw_version,
|
||||
sizeof(wiphy->fw_version),
|
||||
&wiphy->hw_version);
|
||||
if (err != 0) {
|
||||
dev_err(dev, "Incompatible firmware, aborting\n");
|
||||
goto out;
|
||||
|
@ -2010,7 +2009,9 @@ int orinoco_init(struct orinoco_private *priv)
|
|||
priv->do_fw_download = 0;
|
||||
|
||||
/* Check firmware version again */
|
||||
err = determine_fw_capabilities(priv);
|
||||
err = determine_fw_capabilities(priv, wiphy->fw_version,
|
||||
sizeof(wiphy->fw_version),
|
||||
&wiphy->hw_version);
|
||||
if (err != 0) {
|
||||
dev_err(dev, "Incompatible firmware, aborting\n");
|
||||
goto out;
|
||||
|
@ -2212,7 +2213,6 @@ int orinoco_if_add(struct orinoco_private *priv,
|
|||
dev->ieee80211_ptr = wdev;
|
||||
dev->netdev_ops = &orinoco_netdev_ops;
|
||||
dev->watchdog_timeo = HZ; /* 1 second timeout */
|
||||
dev->ethtool_ops = &orinoco_ethtool_ops;
|
||||
dev->wireless_handlers = &orinoco_handler_def;
|
||||
#ifdef WIRELESS_SPY
|
||||
dev->wireless_data = &priv->wireless_data;
|
||||
|
@ -2349,27 +2349,6 @@ void orinoco_down(struct orinoco_private *priv)
|
|||
}
|
||||
EXPORT_SYMBOL(orinoco_down);
|
||||
|
||||
static void orinoco_get_drvinfo(struct net_device *dev,
|
||||
struct ethtool_drvinfo *info)
|
||||
{
|
||||
struct orinoco_private *priv = ndev_priv(dev);
|
||||
|
||||
strncpy(info->driver, DRIVER_NAME, sizeof(info->driver) - 1);
|
||||
strncpy(info->version, DRIVER_VERSION, sizeof(info->version) - 1);
|
||||
strncpy(info->fw_version, priv->fw_name, sizeof(info->fw_version) - 1);
|
||||
if (dev->dev.parent)
|
||||
strncpy(info->bus_info, dev_name(dev->dev.parent),
|
||||
sizeof(info->bus_info) - 1);
|
||||
else
|
||||
snprintf(info->bus_info, sizeof(info->bus_info) - 1,
|
||||
"PCMCIA %p", priv->hw.iobase);
|
||||
}
|
||||
|
||||
static const struct ethtool_ops orinoco_ethtool_ops = {
|
||||
.get_drvinfo = orinoco_get_drvinfo,
|
||||
.get_link = ethtool_op_get_link,
|
||||
};
|
||||
|
||||
/********************************************************************/
|
||||
/* Module initialization */
|
||||
/********************************************************************/
|
||||
|
|
|
@ -93,7 +93,6 @@ struct orinoco_private {
|
|||
|
||||
/* Capabilities of the hardware/firmware */
|
||||
fwtype_t firmware_type;
|
||||
char fw_name[32];
|
||||
int ibss_port;
|
||||
int nicbuf_size;
|
||||
u16 channel_mask;
|
||||
|
|
|
@ -53,6 +53,32 @@ config RT61PCI
|
|||
|
||||
When compiled as a module, this driver will be called rt61pci.
|
||||
|
||||
config RT2800PCI_PCI
|
||||
tristate
|
||||
depends on PCI
|
||||
default y
|
||||
|
||||
config RT2800PCI_SOC
|
||||
tristate
|
||||
depends on RALINK_RT288X || RALINK_RT305X
|
||||
default y
|
||||
|
||||
config RT2800PCI
|
||||
tristate "Ralink rt2800 (PCI/PCMCIA) support"
|
||||
depends on (RT2800PCI_PCI || RT2800PCI_SOC) && EXPERIMENTAL
|
||||
select RT2X00_LIB_PCI if RT2800PCI_PCI
|
||||
select RT2X00_LIB_SOC if RT2800PCI_SOC
|
||||
select RT2X00_LIB_HT
|
||||
select RT2X00_LIB_FIRMWARE
|
||||
select RT2X00_LIB_CRYPTO
|
||||
select CRC_CCITT
|
||||
select EEPROM_93CX6
|
||||
---help---
|
||||
This adds support for rt2800 wireless chipset family.
|
||||
Supported chips: RT2760, RT2790, RT2860, RT2880, RT2890 & RT3052
|
||||
|
||||
When compiled as a module, this driver will be called "rt2800pci.ko".
|
||||
|
||||
config RT2500USB
|
||||
tristate "Ralink rt2500 (USB) support"
|
||||
depends on USB
|
||||
|
@ -95,6 +121,10 @@ config RT2X00_LIB_PCI
|
|||
tristate
|
||||
select RT2X00_LIB
|
||||
|
||||
config RT2X00_LIB_SOC
|
||||
tristate
|
||||
select RT2X00_LIB
|
||||
|
||||
config RT2X00_LIB_USB
|
||||
tristate
|
||||
select RT2X00_LIB
|
||||
|
|
|
@ -11,10 +11,12 @@ rt2x00lib-$(CONFIG_RT2X00_LIB_HT) += rt2x00ht.o
|
|||
|
||||
obj-$(CONFIG_RT2X00_LIB) += rt2x00lib.o
|
||||
obj-$(CONFIG_RT2X00_LIB_PCI) += rt2x00pci.o
|
||||
obj-$(CONFIG_RT2X00_LIB_SOC) += rt2x00soc.o
|
||||
obj-$(CONFIG_RT2X00_LIB_USB) += rt2x00usb.o
|
||||
obj-$(CONFIG_RT2400PCI) += rt2400pci.o
|
||||
obj-$(CONFIG_RT2500PCI) += rt2500pci.o
|
||||
obj-$(CONFIG_RT61PCI) += rt61pci.o
|
||||
obj-$(CONFIG_RT2800PCI) += rt2800pci.o
|
||||
obj-$(CONFIG_RT2500USB) += rt2500usb.o
|
||||
obj-$(CONFIG_RT73USB) += rt73usb.o
|
||||
obj-$(CONFIG_RT2800USB) += rt2800usb.o
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -158,6 +158,13 @@ struct rt2x00_chip {
|
|||
#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 RT2880 0x2880 /* WSOC */
|
||||
#define RT3052 0x3052 /* WSOC */
|
||||
#define RT3090 0x3090 /* 2.4GHz PCIe */
|
||||
#define RT2870 0x1600
|
||||
|
||||
u16 rf;
|
||||
|
|
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
|
||||
<http://rt2x00.serialmonkey.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
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.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
Module: rt2x00soc
|
||||
Abstract: rt2x00 generic soc device routines.
|
||||
*/
|
||||
|
||||
#include <linux/bug.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "rt2x00.h"
|
||||
#include "rt2x00soc.h"
|
||||
|
||||
static void rt2x00soc_free_reg(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
kfree(rt2x00dev->rf);
|
||||
rt2x00dev->rf = NULL;
|
||||
|
||||
kfree(rt2x00dev->eeprom);
|
||||
rt2x00dev->eeprom = NULL;
|
||||
}
|
||||
|
||||
static int rt2x00soc_alloc_reg(struct rt2x00_dev *rt2x00dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(rt2x00dev->dev);
|
||||
struct resource *res;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res)
|
||||
return -ENODEV;
|
||||
|
||||
rt2x00dev->csr.base = (void __iomem *)KSEG1ADDR(res->start);
|
||||
if (!rt2x00dev->csr.base)
|
||||
goto exit;
|
||||
|
||||
rt2x00dev->eeprom = kzalloc(rt2x00dev->ops->eeprom_size, GFP_KERNEL);
|
||||
if (!rt2x00dev->eeprom)
|
||||
goto exit;
|
||||
|
||||
rt2x00dev->rf = kzalloc(rt2x00dev->ops->rf_size, GFP_KERNEL);
|
||||
if (!rt2x00dev->rf)
|
||||
goto exit;
|
||||
|
||||
return 0;
|
||||
|
||||
exit:
|
||||
ERROR_PROBE("Failed to allocate registers.\n");
|
||||
rt2x00soc_free_reg(rt2x00dev);
|
||||
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
int rt2x00soc_probe(struct platform_device *pdev,
|
||||
const unsigned short chipset,
|
||||
const struct rt2x00_ops *ops)
|
||||
{
|
||||
struct ieee80211_hw *hw;
|
||||
struct rt2x00_dev *rt2x00dev;
|
||||
int retval;
|
||||
|
||||
hw = ieee80211_alloc_hw(sizeof(struct rt2x00_dev), ops->hw);
|
||||
if (!hw) {
|
||||
ERROR_PROBE("Failed to allocate hardware.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, hw);
|
||||
|
||||
rt2x00dev = hw->priv;
|
||||
rt2x00dev->dev = &pdev->dev;
|
||||
rt2x00dev->ops = ops;
|
||||
rt2x00dev->hw = hw;
|
||||
rt2x00dev->irq = platform_get_irq(pdev, 0);
|
||||
rt2x00dev->name = pdev->dev.driver->name;
|
||||
|
||||
rt2x00_set_chip_rt(rt2x00dev, chipset);
|
||||
|
||||
retval = rt2x00soc_alloc_reg(rt2x00dev);
|
||||
if (retval)
|
||||
goto exit_free_device;
|
||||
|
||||
retval = rt2x00lib_probe_dev(rt2x00dev);
|
||||
if (retval)
|
||||
goto exit_free_reg;
|
||||
|
||||
return 0;
|
||||
|
||||
exit_free_reg:
|
||||
rt2x00soc_free_reg(rt2x00dev);
|
||||
|
||||
exit_free_device:
|
||||
ieee80211_free_hw(hw);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
int rt2x00soc_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct ieee80211_hw *hw = platform_get_drvdata(pdev);
|
||||
struct rt2x00_dev *rt2x00dev = hw->priv;
|
||||
|
||||
/*
|
||||
* Free all allocated data.
|
||||
*/
|
||||
rt2x00lib_remove_dev(rt2x00dev);
|
||||
rt2x00soc_free_reg(rt2x00dev);
|
||||
ieee80211_free_hw(hw);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2x00soc_remove);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
int rt2x00soc_suspend(struct platform_device *pdev, pm_message_t state)
|
||||
{
|
||||
struct ieee80211_hw *hw = platform_get_drvdata(pdev);
|
||||
struct rt2x00_dev *rt2x00dev = hw->priv;
|
||||
|
||||
return rt2x00lib_suspend(rt2x00dev, state);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2x00soc_suspend);
|
||||
|
||||
int rt2x00soc_resume(struct platform_device *pdev)
|
||||
{
|
||||
struct ieee80211_hw *hw = platform_get_drvdata(pdev);
|
||||
struct rt2x00_dev *rt2x00dev = hw->priv;
|
||||
|
||||
return rt2x00lib_resume(rt2x00dev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2x00soc_resume);
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
/*
|
||||
* rt2x00soc module information.
|
||||
*/
|
||||
MODULE_AUTHOR(DRV_PROJECT);
|
||||
MODULE_VERSION(DRV_VERSION);
|
||||
MODULE_DESCRIPTION("rt2x00 soc library");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
|
||||
<http://rt2x00.serialmonkey.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
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.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
Module: rt2x00soc
|
||||
Abstract: Data structures for the rt2x00soc module.
|
||||
*/
|
||||
|
||||
#ifndef RT2X00SOC_H
|
||||
#define RT2X00SOC_H
|
||||
|
||||
#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_remove(struct platform_device *pdev);
|
||||
#ifdef CONFIG_PM
|
||||
int rt2x00soc_suspend(struct platform_device *pdev, pm_message_t state);
|
||||
int rt2x00soc_resume(struct platform_device *pdev);
|
||||
#else
|
||||
#define rt2x00soc_suspend NULL
|
||||
#define rt2x00soc_resume NULL
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
#endif /* RT2X00SOC_H */
|
|
@ -183,8 +183,11 @@ static int wl1251_chip_wakeup(struct wl1251 *wl)
|
|||
wl1251_debug(DEBUG_BOOT, "chip id 0x%x (1251 PG12)",
|
||||
wl->chip_id);
|
||||
break;
|
||||
case CHIP_ID_1251_PG10:
|
||||
case CHIP_ID_1251_PG11:
|
||||
wl1251_debug(DEBUG_BOOT, "chip id 0x%x (1251 PG11)",
|
||||
wl->chip_id);
|
||||
break;
|
||||
case CHIP_ID_1251_PG10:
|
||||
default:
|
||||
wl1251_error("unsupported chip id: 0x%x", wl->chip_id);
|
||||
ret = -ENODEV;
|
||||
|
@ -1426,4 +1429,4 @@ EXPORT_SYMBOL_GPL(wl1251_free_hw);
|
|||
MODULE_DESCRIPTION("TI wl1251 Wireles LAN Driver Core");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Kalle Valo <kalle.valo@nokia.com>");
|
||||
MODULE_ALIAS("spi:wl12xx");
|
||||
MODULE_ALIAS("spi:wl1251");
|
||||
|
|
|
@ -153,7 +153,7 @@ static void wl1251_rx_body(struct wl1251 *wl,
|
|||
beacon ? "beacon" : "");
|
||||
|
||||
memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
|
||||
ieee80211_rx(wl->hw, skb);
|
||||
ieee80211_rx_ni(wl->hw, skb);
|
||||
}
|
||||
|
||||
static void wl1251_rx_ack(struct wl1251 *wl)
|
||||
|
|
|
@ -307,7 +307,7 @@ static int __devexit wl1251_spi_remove(struct spi_device *spi)
|
|||
|
||||
static struct spi_driver wl1251_spi_driver = {
|
||||
.driver = {
|
||||
.name = "wl12xx",
|
||||
.name = "wl1251",
|
||||
.bus = &spi_bus_type,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
#include <linux/bitops.h>
|
||||
#include <net/mac80211.h>
|
||||
|
||||
#include "wl1271_conf.h"
|
||||
|
||||
#define DRIVER_NAME "wl1271"
|
||||
#define DRIVER_PREFIX DRIVER_NAME ": "
|
||||
|
||||
|
@ -97,21 +99,42 @@ enum {
|
|||
} while (0)
|
||||
|
||||
#define WL1271_DEFAULT_RX_CONFIG (CFG_UNI_FILTER_EN | \
|
||||
CFG_BSSID_FILTER_EN)
|
||||
CFG_BSSID_FILTER_EN | \
|
||||
CFG_MC_FILTER_EN)
|
||||
|
||||
#define WL1271_DEFAULT_RX_FILTER (CFG_RX_RCTS_ACK | CFG_RX_PRSP_EN | \
|
||||
CFG_RX_MGMT_EN | CFG_RX_DATA_EN | \
|
||||
CFG_RX_CTL_EN | CFG_RX_BCN_EN | \
|
||||
CFG_RX_AUTH_EN | CFG_RX_ASSOC_EN)
|
||||
|
||||
#define WL1271_DEFAULT_BASIC_RATE_SET (CONF_TX_RATE_MASK_ALL)
|
||||
|
||||
#define WL1271_FW_NAME "wl1271-fw.bin"
|
||||
#define WL1271_NVS_NAME "wl1271-nvs.bin"
|
||||
|
||||
#define WL1271_BUSY_WORD_LEN 8
|
||||
/*
|
||||
* Enable/disable 802.11a support for WL1273
|
||||
*/
|
||||
#undef WL1271_80211A_ENABLED
|
||||
|
||||
/*
|
||||
* FIXME: for the wl1271, a busy word count of 1 here will result in a more
|
||||
* optimal SPI interface. There is some SPI bug however, causing RXS time outs
|
||||
* with this mode occasionally on boot, so lets have three for now. A value of
|
||||
* three should make sure, that the chipset will always be ready, though this
|
||||
* will impact throughput and latencies slightly.
|
||||
*/
|
||||
#define WL1271_BUSY_WORD_CNT 3
|
||||
#define WL1271_BUSY_WORD_LEN (WL1271_BUSY_WORD_CNT * sizeof(u32))
|
||||
|
||||
#define WL1271_ELP_HW_STATE_ASLEEP 0
|
||||
#define WL1271_ELP_HW_STATE_IRQ 1
|
||||
|
||||
#define WL1271_DEFAULT_BEACON_INT 100
|
||||
#define WL1271_DEFAULT_DTIM_PERIOD 1
|
||||
|
||||
#define ACX_TX_DESCRIPTORS 32
|
||||
|
||||
enum wl1271_state {
|
||||
WL1271_STATE_OFF,
|
||||
WL1271_STATE_ON,
|
||||
|
@ -134,6 +157,8 @@ struct wl1271_partition {
|
|||
struct wl1271_partition_set {
|
||||
struct wl1271_partition mem;
|
||||
struct wl1271_partition reg;
|
||||
struct wl1271_partition mem2;
|
||||
struct wl1271_partition mem3;
|
||||
};
|
||||
|
||||
struct wl1271;
|
||||
|
@ -258,15 +283,15 @@ struct wl1271_debugfs {
|
|||
|
||||
/* FW status registers */
|
||||
struct wl1271_fw_status {
|
||||
u32 intr;
|
||||
__le32 intr;
|
||||
u8 fw_rx_counter;
|
||||
u8 drv_rx_counter;
|
||||
u8 reserved;
|
||||
u8 tx_results_counter;
|
||||
u32 rx_pkt_descs[NUM_RX_PKT_DESC];
|
||||
u32 tx_released_blks[NUM_TX_QUEUES];
|
||||
u32 fw_localtime;
|
||||
u32 padding[2];
|
||||
__le32 rx_pkt_descs[NUM_RX_PKT_DESC];
|
||||
__le32 tx_released_blks[NUM_TX_QUEUES];
|
||||
__le32 fw_localtime;
|
||||
__le32 padding[2];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct wl1271_rx_mem_pool_addr {
|
||||
|
@ -274,6 +299,15 @@ struct wl1271_rx_mem_pool_addr {
|
|||
u32 addr_extra;
|
||||
};
|
||||
|
||||
struct wl1271_scan {
|
||||
u8 state;
|
||||
u8 ssid[IW_ESSID_MAX_SIZE+1];
|
||||
size_t ssid_len;
|
||||
u8 active;
|
||||
u8 high_prio;
|
||||
u8 probe_requests;
|
||||
};
|
||||
|
||||
struct wl1271 {
|
||||
struct ieee80211_hw *hw;
|
||||
bool mac80211_registered;
|
||||
|
@ -288,10 +322,7 @@ struct wl1271 {
|
|||
enum wl1271_state state;
|
||||
struct mutex mutex;
|
||||
|
||||
int physical_mem_addr;
|
||||
int physical_reg_addr;
|
||||
int virtual_mem_addr;
|
||||
int virtual_reg_addr;
|
||||
struct wl1271_partition_set part;
|
||||
|
||||
struct wl1271_chip chip;
|
||||
|
||||
|
@ -308,7 +339,6 @@ struct wl1271 {
|
|||
u8 bss_type;
|
||||
u8 ssid[IW_ESSID_MAX_SIZE + 1];
|
||||
u8 ssid_len;
|
||||
u8 listen_int;
|
||||
int channel;
|
||||
|
||||
struct wl1271_acx_mem_map *target_mem_map;
|
||||
|
@ -332,10 +362,14 @@ struct wl1271 {
|
|||
bool tx_queue_stopped;
|
||||
|
||||
struct work_struct tx_work;
|
||||
struct work_struct filter_work;
|
||||
|
||||
/* Pending TX frames */
|
||||
struct sk_buff *tx_frames[16];
|
||||
struct sk_buff *tx_frames[ACX_TX_DESCRIPTORS];
|
||||
|
||||
/* Security sequence number counters */
|
||||
u8 tx_security_last_seq;
|
||||
u16 tx_security_seq_16;
|
||||
u32 tx_security_seq_32;
|
||||
|
||||
/* FW Rx counter */
|
||||
u32 rx_counter;
|
||||
|
@ -354,10 +388,17 @@ struct wl1271 {
|
|||
|
||||
/* Are we currently scanning */
|
||||
bool scanning;
|
||||
struct wl1271_scan scan;
|
||||
|
||||
/* Our association ID */
|
||||
u16 aid;
|
||||
|
||||
/* currently configured rate set */
|
||||
u32 basic_rate_set;
|
||||
|
||||
/* The current band */
|
||||
enum ieee80211_band band;
|
||||
|
||||
/* Default key (for WEP) */
|
||||
u32 default_key;
|
||||
|
||||
|
@ -368,6 +409,7 @@ struct wl1271 {
|
|||
bool elp;
|
||||
|
||||
struct completion *elp_compl;
|
||||
struct delayed_work elp_work;
|
||||
|
||||
/* we can be in psm, but not in elp, we have to differentiate */
|
||||
bool psm;
|
||||
|
@ -383,11 +425,20 @@ struct wl1271 {
|
|||
|
||||
u32 buffer_32;
|
||||
u32 buffer_cmd;
|
||||
u8 buffer_busyword[WL1271_BUSY_WORD_LEN];
|
||||
struct wl1271_rx_descriptor *rx_descriptor;
|
||||
u32 buffer_busyword[WL1271_BUSY_WORD_CNT];
|
||||
|
||||
struct wl1271_fw_status *fw_status;
|
||||
struct wl1271_tx_hw_res_if *tx_res_if;
|
||||
|
||||
struct ieee80211_vif *vif;
|
||||
|
||||
/* Used for a workaround to send disconnect before rejoining */
|
||||
bool joined;
|
||||
|
||||
/* Current chipset configuration */
|
||||
struct conf_drv_settings conf;
|
||||
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
int wl1271_plt_start(struct wl1271 *wl);
|
||||
|
@ -404,4 +455,13 @@ int wl1271_plt_stop(struct wl1271 *wl);
|
|||
/* WL1271 needs a 200ms sleep after power on */
|
||||
#define WL1271_POWER_ON_SLEEP 200 /* in miliseconds */
|
||||
|
||||
static inline bool wl1271_11a_enabled(void)
|
||||
{
|
||||
#ifdef WL1271_80211A_ENABLED
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue