Commit 33e33495 authored by David S. Miller's avatar David S. Miller
parents ad619800 3e2236c1
......@@ -14,18 +14,49 @@ config IWLWIFI_LEDS
default n
config IWLWIFI_RFKILL
boolean "IWLWIFI RF kill support"
boolean "Iwlwifi RF kill support"
depends on IWLCORE
config IWL4965
tristate "Intel Wireless WiFi 4965AGN"
config IWLWIFI_DEBUG
bool "Enable full debugging output in iwlagn driver"
depends on IWLCORE
---help---
This option will enable debug tracing output for the iwlwifi drivers
This will result in the kernel module being ~100k larger. You can
control which debug output is sent to the kernel log by setting the
value in
/sys/class/net/wlan0/device/debug_level
This entry will only exist if this option is enabled.
To set a value, simply echo an 8-byte hex value to the same file:
% echo 0x43fff > /sys/class/net/wlan0/device/debug_level
You can find the list of debug mask values in:
drivers/net/wireless/iwlwifi/iwl-debug.h
If this is your first time using this driver, you should say Y here
as the debug information can assist others in helping you resolve
any problems you may encounter.
config IWLWIFI_DEBUGFS
bool "Iwlwifi debugfs support"
depends on IWLCORE && IWLWIFI_DEBUG && MAC80211_DEBUGFS
---help---
Enable creation of debugfs files for the iwlwifi drivers.
config IWLAGN
tristate "Intel Wireless WiFi Next Gen AGN"
depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL
select FW_LOADER
select IWLCORE
---help---
Select to build the driver supporting the:
Intel Wireless WiFi Link 4965AGN
Intel Wireless WiFi Link Next-Gen AGN
This driver uses the kernel's mac80211 subsystem.
......@@ -42,60 +73,33 @@ config IWL4965
If you want to compile the driver as a module ( = code which can be
inserted in and removed from the running kernel whenever you want),
say M here and read <file:Documentation/kbuild/modules.txt>. The
module will be called iwl4965.ko.
config IWL4965_LEDS
bool "Enable LEDS features in iwl4965 driver"
depends on IWL4965
select IWLWIFI_LEDS
---help---
This option enables LEDS for the iwlwifi drivers
module will be called iwlagn.ko.
config IWL4965_SPECTRUM_MEASUREMENT
bool "Enable Spectrum Measurement in iwl4965 driver"
depends on IWL4965
config IWLAGN_SPECTRUM_MEASUREMENT
bool "Enable Spectrum Measurement in iwlagn driver"
depends on IWLAGN
---help---
This option will enable spectrum measurement for the iwl4965 driver.
This option will enable spectrum measurement for the iwlagn driver.
config IWLWIFI_DEBUG
bool "Enable full debugging output in iwl4965 driver"
depends on IWL4965
config IWLAGN_LEDS
bool "Enable LEDS features in iwlagn driver"
depends on IWLAGN
select IWLWIFI_LEDS
---help---
This option will enable debug tracing output for the iwl4965
driver.
This will result in the kernel module being ~100k larger. You can
control which debug output is sent to the kernel log by setting the
value in
/sys/class/net/wlan0/device/debug_level
This entry will only exist if this option is enabled.
To set a value, simply echo an 8-byte hex value to the same file:
% echo 0x43fff > /sys/class/net/wlan0/device/debug_level
This option enables LEDS for the iwlagn drivers
You can find the list of debug mask values in:
drivers/net/wireless/iwlwifi/iwl-4965-debug.h
If this is your first time using this driver, you should say Y here
as the debug information can assist others in helping you resolve
any problems you may encounter.
config IWL4965
bool "Intel Wireless WiFi 4965AGN"
depends on IWLAGN
---help---
This option enables support for Intel Wireless WiFi Link 4965AGN
config IWL5000
bool "Intel Wireless WiFi 5000AGN"
depends on IWL4965
depends on IWLAGN
---help---
This option enables support for Intel Wireless WiFi Link 5000AGN Family
Dependency on 4965 is temporary
config IWLWIFI_DEBUGFS
bool "Iwlwifi debugfs support"
depends on IWLCORE && IWLWIFI_DEBUG && MAC80211_DEBUGFS
---help---
Enable creation of debugfs files for the iwlwifi drivers.
config IWL3945
tristate "Intel PRO/Wireless 3945ABG/BG Network Connection"
......
......@@ -6,15 +6,14 @@ iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o
iwlcore-$(CONFIG_IWLWIFI_LEDS) += iwl-led.o
iwlcore-$(CONFIG_IWLWIFI_RFKILL) += iwl-rfkill.o
obj-$(CONFIG_IWLAGN) += iwlagn.o
iwlagn-objs := iwl-agn.o iwl-agn-rs.o
iwlagn-$(CONFIG_IWL4965) += iwl-4965.o
iwlagn-$(CONFIG_IWL5000) += iwl-5000.o
obj-$(CONFIG_IWL3945) += iwl3945.o
iwl3945-objs := iwl3945-base.o iwl-3945.o iwl-3945-rs.o
iwl3945-$(CONFIG_IWL3945_LEDS) += iwl-3945-led.o
obj-$(CONFIG_IWL4965) += iwl4965.o
iwl4965-objs := iwl4965-base.o iwl-4965.o iwl-4965-rs.o
ifeq ($(CONFIG_IWL5000),y)
iwl4965-objs += iwl-5000.o
endif
......@@ -206,12 +206,12 @@ static void iwl3945_led_brightness_set(struct led_classdev *led_cdev,
static int iwl3945_led_register_led(struct iwl3945_priv *priv,
struct iwl3945_led *led,
enum led_type type, u8 set_led,
const char *name, char *trigger)
char *trigger)
{
struct device *device = wiphy_dev(priv->hw->wiphy);
int ret;
led->led_dev.name = name;
led->led_dev.name = led->name;
led->led_dev.brightness_set = iwl3945_led_brightness_set;
led->led_dev.default_trigger = trigger;
......@@ -308,7 +308,6 @@ void iwl3945_led_background(struct iwl3945_priv *priv)
int iwl3945_led_register(struct iwl3945_priv *priv)
{
char *trigger;
char name[32];
int ret;
priv->last_blink_rate = 0;
......@@ -318,7 +317,8 @@ int iwl3945_led_register(struct iwl3945_priv *priv)
priv->allow_blinking = 0;
trigger = ieee80211_get_radio_led_name(priv->hw);
snprintf(name, sizeof(name), "iwl-%s:radio",
snprintf(priv->led[IWL_LED_TRG_RADIO].name,
sizeof(priv->led[IWL_LED_TRG_RADIO].name), "iwl-%s:radio",
wiphy_name(priv->hw->wiphy));
priv->led[IWL_LED_TRG_RADIO].led_on = iwl3945_led_on;
......@@ -327,19 +327,20 @@ int iwl3945_led_register(struct iwl3945_priv *priv)
ret = iwl3945_led_register_led(priv,
&priv->led[IWL_LED_TRG_RADIO],
IWL_LED_TRG_RADIO, 1,
name, trigger);
IWL_LED_TRG_RADIO, 1, trigger);
if (ret)
goto exit_fail;
trigger = ieee80211_get_assoc_led_name(priv->hw);
snprintf(name, sizeof(name), "iwl-%s:assoc",
snprintf(priv->led[IWL_LED_TRG_ASSOC].name,
sizeof(priv->led[IWL_LED_TRG_ASSOC].name), "iwl-%s:assoc",
wiphy_name(priv->hw->wiphy));
ret = iwl3945_led_register_led(priv,
&priv->led[IWL_LED_TRG_ASSOC],
IWL_LED_TRG_ASSOC, 0,
name, trigger);
IWL_LED_TRG_ASSOC, 0, trigger);
/* for assoc always turn led on */
priv->led[IWL_LED_TRG_ASSOC].led_on = iwl3945_led_on;
priv->led[IWL_LED_TRG_ASSOC].led_off = iwl3945_led_on;
......@@ -349,14 +350,13 @@ int iwl3945_led_register(struct iwl3945_priv *priv)
goto exit_fail;
trigger = ieee80211_get_rx_led_name(priv->hw);
snprintf(name, sizeof(name), "iwl-%s:RX",
snprintf(priv->led[IWL_LED_TRG_RX].name,
sizeof(priv->led[IWL_LED_TRG_RX].name), "iwl-%s:RX",
wiphy_name(priv->hw->wiphy));
ret = iwl3945_led_register_led(priv,
&priv->led[IWL_LED_TRG_RX],
IWL_LED_TRG_RX, 0,
name, trigger);
IWL_LED_TRG_RX, 0, trigger);
priv->led[IWL_LED_TRG_RX].led_on = iwl3945_led_associated;
priv->led[IWL_LED_TRG_RX].led_off = iwl3945_led_associated;
......@@ -366,13 +366,14 @@ int iwl3945_led_register(struct iwl3945_priv *priv)
goto exit_fail;
trigger = ieee80211_get_tx_led_name(priv->hw);
snprintf(name, sizeof(name), "iwl-%s:TX",
snprintf(priv->led[IWL_LED_TRG_TX].name,
sizeof(priv->led[IWL_LED_TRG_TX].name), "iwl-%s:TX",
wiphy_name(priv->hw->wiphy));
ret = iwl3945_led_register_led(priv,
&priv->led[IWL_LED_TRG_TX],
IWL_LED_TRG_TX, 0,
name, trigger);
IWL_LED_TRG_TX, 0, trigger);
priv->led[IWL_LED_TRG_TX].led_on = iwl3945_led_associated;
priv->led[IWL_LED_TRG_TX].led_off = iwl3945_led_associated;
priv->led[IWL_LED_TRG_TX].led_pattern = iwl3945_led_pattern;
......
......@@ -50,6 +50,7 @@ enum led_type {
struct iwl3945_led {
struct iwl3945_priv *priv;
struct led_classdev led_dev;
char name[32];
int (*led_on) (struct iwl3945_priv *priv, int led_id);
int (*led_off) (struct iwl3945_priv *priv, int led_id);
......
......@@ -795,8 +795,7 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv,
struct ieee80211_mgmt *mgmt =
(struct ieee80211_mgmt *)header;
__le32 *pos;
pos =
(__le32 *) & mgmt->u.beacon.
pos = (__le32 *)&mgmt->u.beacon.
timestamp;
priv->timestamp0 = le32_to_cpu(pos[0]);
priv->timestamp1 = le32_to_cpu(pos[1]);
......@@ -1509,7 +1508,7 @@ static int iwl3945_hw_reg_adjust_power_by_temp(int new_reading, int old_reading)
*/
static inline int iwl3945_hw_reg_temp_out_of_range(int temperature)
{
return (((temperature < -260) || (temperature > 25)) ? 1 : 0);
return ((temperature < -260) || (temperature > 25)) ? 1 : 0;
}
int iwl3945_hw_get_temperature(struct iwl3945_priv *priv)
......@@ -2630,7 +2629,7 @@ unsigned int iwl3945_hw_get_beacon_cmd(struct iwl3945_priv *priv,
tx_beacon_cmd->tx.supp_rates[1] =
(IWL_CCK_BASIC_RATES_MASK & 0xF);
return (sizeof(struct iwl3945_tx_beacon_cmd) + frame_size);
return sizeof(struct iwl3945_tx_beacon_cmd) + frame_size;
}
void iwl3945_hw_rx_handler_setup(struct iwl3945_priv *priv)
......
......@@ -341,39 +341,6 @@ static int iwl4965_eeprom_check_version(struct iwl_priv *priv)
return -EINVAL;
}
int iwl4965_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src)
{
int ret;
unsigned long flags;
spin_lock_irqsave(&priv->lock, flags);
ret = iwl_grab_nic_access(priv);
if (ret) {
spin_unlock_irqrestore(&priv->lock, flags);
return ret;
}
if (src == IWL_PWR_SRC_VAUX) {
u32 val;
ret = pci_read_config_dword(priv->pci_dev, PCI_POWER_SOURCE,
&val);
if (val & PCI_CFG_PMC_PME_FROM_D3COLD_SUPPORT) {
iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
APMG_PS_CTRL_VAL_PWR_SRC_VAUX,
~APMG_PS_CTRL_MSK_PWR_SRC);
}
} else {
iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
APMG_PS_CTRL_VAL_PWR_SRC_VMAIN,
~APMG_PS_CTRL_MSK_PWR_SRC);
}
iwl_release_nic_access(priv);
spin_unlock_irqrestore(&priv->lock, flags);
return ret;
}
/*
* Activate/Deactivat Tx DMA/FIFO channels according tx fifos mask
......@@ -875,18 +842,6 @@ static int iwl4965_hw_set_hw_params(struct iwl_priv *priv)
return 0;
}
/* set card power command */
static int iwl4965_set_power(struct iwl_priv *priv,
void *cmd)
{
int ret = 0;
ret = iwl_send_cmd_pdu_async(priv, POWER_TABLE_CMD,
sizeof(struct iwl4965_powertable_cmd),
cmd, NULL);
return ret;
}
static s32 iwl4965_math_div_round(s32 num, s32 denom, s32 *res)
{
s32 sign = 1;
......@@ -1560,11 +1515,11 @@ static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel,
c, atten_value, power_index,
tx_power.s.radio_tx_gain[c],
tx_power.s.dsp_predis_atten[c]);
}/* for each chain */
} /* for each chain */
tx_power_tbl->power_tbl[i].dw = cpu_to_le32(tx_power.dw);
}/* for each rate */
} /* for each rate */
return 0;
}
......@@ -1701,38 +1656,6 @@ static int iwl4965_shared_mem_rx_idx(struct iwl_priv *priv)
return le32_to_cpu(s->rb_closed) & 0xFFF;
}
unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv,
struct iwl_frame *frame, u8 rate)
{
struct iwl4965_tx_beacon_cmd *tx_beacon_cmd;
unsigned int frame_size;
tx_beacon_cmd = &frame->u.beacon;
memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd));
tx_beacon_cmd->tx.sta_id = priv->hw_params.bcast_sta_id;
tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
frame_size = iwl4965_fill_beacon_frame(priv,
tx_beacon_cmd->frame,
iwl_bcast_addr,
sizeof(frame->u) - sizeof(*tx_beacon_cmd));
BUG_ON(frame_size > MAX_MPDU_SIZE);
tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size);
if ((rate == IWL_RATE_1M_PLCP) || (rate >= IWL_RATE_2M_PLCP))
tx_beacon_cmd->tx.rate_n_flags =
iwl_hw_set_rate_n_flags(rate, RATE_MCS_CCK_MSK);
else
tx_beacon_cmd->tx.rate_n_flags =
iwl_hw_set_rate_n_flags(rate, 0);
tx_beacon_cmd->tx.tx_flags = (TX_CMD_FLG_SEQ_CTL_MSK |
TX_CMD_FLG_TSF_MSK | TX_CMD_FLG_STA_RATE_MSK);
return (sizeof(*tx_beacon_cmd) + frame_size);
}
static int iwl4965_alloc_shared_mem(struct iwl_priv *priv)
{
priv->shared_virt = pci_alloc_consistent(priv->pci_dev,
......@@ -2079,39 +2002,6 @@ static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id,
return 0;
}
int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw,
enum ieee80211_ampdu_mlme_action action,
const u8 *addr, u16 tid, u16 *ssn)
{
struct iwl_priv *priv = hw->priv;
DECLARE_MAC_BUF(mac);
IWL_DEBUG_HT("A-MPDU action on addr %s tid %d\n",
print_mac(mac, addr), tid);
if (!(priv->cfg->sku & IWL_SKU_N))
return -EACCES;
switch (action) {
case IEEE80211_AMPDU_RX_START:
IWL_DEBUG_HT("start Rx\n");
return iwl_rx_agg_start(priv, addr, tid, *ssn);
case IEEE80211_AMPDU_RX_STOP:
IWL_DEBUG_HT("stop Rx\n");
return iwl_rx_agg_stop(priv, addr, tid);
case IEEE80211_AMPDU_TX_START:
IWL_DEBUG_HT("start Tx\n");
return iwl_tx_agg_start(priv, addr, tid, ssn);
case IEEE80211_AMPDU_TX_STOP:
IWL_DEBUG_HT("stop Tx\n");
return iwl_tx_agg_stop(priv, addr, tid);
default:
IWL_DEBUG_HT("unknown\n");
return -EINVAL;
break;
}
return 0;
}
static u16 iwl4965_get_hcmd_size(u8 cmd_id, u16 len)
{
......@@ -2240,9 +2130,9 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv,
bitmap = bitmap << sh;
sh = 0;
}
bitmap |= (1 << sh);
IWL_DEBUG_TX_REPLY("start=%d bitmap=0x%x\n",
start, (u32)(bitmap & 0xFFFFFFFF));
bitmap |= 1ULL << sh;
IWL_DEBUG_TX_REPLY("start=%d bitmap=0x%llx\n",
start, (unsigned long long)bitmap);
}
agg->bitmap = bitmap;
......@@ -2368,6 +2258,40 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
IWL_ERROR("TODO: Implement Tx ABORT REQUIRED!!!\n");
}
static int iwl4965_calc_rssi(struct iwl_priv *priv,
struct iwl_rx_phy_res *rx_resp)
{
/* data from PHY/DSP regarding signal strength, etc.,
* contents are always there, not configurable by host. */
struct iwl4965_rx_non_cfg_phy *ncphy =
(struct iwl4965_rx_non_cfg_phy *)rx_resp->non_cfg_phy_buf;
u32 agc = (le16_to_cpu(ncphy->agc_info) & IWL49_AGC_DB_MASK)
>> IWL49_AGC_DB_POS;
u32 valid_antennae =
(le16_to_cpu(rx_resp->phy_flags) & IWL49_RX_PHY_FLAGS_ANTENNAE_MASK)
>> IWL49_RX_PHY_FLAGS_ANTENNAE_OFFSET;
u8 max_rssi = 0;
u32 i;
/* Find max rssi among 3 possible receivers.
* These values are measured by the digital signal processor (DSP).
* They should stay fairly constant even as the signal strength varies,
* if the radio's automatic gain control (AGC) is working right.
* AGC value (see below) will provide the "interesting" info. */
for (i = 0; i < 3; i++)
if (valid_antennae & (1 << i))
max_rssi = max(ncphy->rssi_info[i << 1], max_rssi);
IWL_DEBUG_STATS("Rssi In A %d B %d C %d Max %d AGC dB %d\n",
ncphy->rssi_info[0], ncphy->rssi_info[2], ncphy->rssi_info[4],
max_rssi, agc);
/* dBm = max_rssi dB - agc dB - constant.
* Higher AGC (higher radio gain) means lower signal. */
return max_rssi - agc - IWL_RSSI_OFFSET;
}
/* Set up 4965-specific Rx frame reply handlers */
static void iwl4965_rx_handler_setup(struct iwl_priv *priv)
......@@ -2399,6 +2323,7 @@ static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = {
.chain_noise_reset = iwl4965_chain_noise_reset,
.gain_computation = iwl4965_gain_computation,
.rts_tx_cmd_flag = iwl4965_rts_tx_cmd_flag,
.calc_rssi = iwl4965_calc_rssi,
};
static struct iwl_lib_ops iwl4965_lib = {
......@@ -2440,7 +2365,6 @@ static struct iwl_lib_ops iwl4965_lib = {
.check_version = iwl4965_eeprom_check_version,
.query_addr = iwlcore_eeprom_query_addr,
},
.set_power = iwl4965_set_power,
.send_tx_power = iwl4965_send_tx_power,
.update_chain_flags = iwl4965_update_chain_flags,
.temperature = iwl4965_temperature_calib,
......
......@@ -93,6 +93,13 @@ static int iwl5000_apm_init(struct iwl_priv *priv)
iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS,
CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX);
/* Set FH wait treshold 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);
iwl_set_bit(priv, CSR_ANA_PLL_CFG, CSR50_ANA_PLL_CFG_VAL);
/* set "initialization complete" bit to move adapter
......@@ -230,6 +237,16 @@ static void iwl5000_nic_config(struct iwl_priv *priv)
CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
CSR_HW_IF_CONFIG_REG_BIT_MAC_SI);
/* W/A : NIC is stuck in a reset state after Early PCIe power off
* (PCIe power is lost before PERST# is asserted),
* causing ME FW to lose ownership and not being able to obtain it back.
*/
iwl_grab_nic_access(priv);
iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS,
~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS);
iwl_release_nic_access(priv);
spin_unlock_irqrestore(&priv->lock, flags);
}
......@@ -924,8 +941,8 @@ static void iwl5000_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE;
if (txq_id != IWL_CMD_QUEUE_NUM) {
sta = txq->cmd[txq->q.write_ptr].cmd.tx.sta_id;
sec_ctl = txq->cmd[txq->q.write_ptr].cmd.tx.sec_ctl;
sta = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id;
sec_ctl = txq->cmd[txq->q.write_ptr]->cmd.tx.sec_ctl;
switch (sec_ctl & TX_CMD_SEC_MSK) {
case TX_CMD_SEC_CCM:
......@@ -964,7 +981,7 @@ static void iwl5000_txq_inval_byte_cnt_tbl(struct iwl_priv *priv,
u8 sta = 0;
if (txq_id != IWL_CMD_QUEUE_NUM)
sta = txq->cmd[txq->q.read_ptr].cmd.tx.sta_id;
sta = txq->cmd[txq->q.read_ptr]->cmd.tx.sta_id;
shared_data->queues_byte_cnt_tbls[txq_id].tfd_offset[txq->q.read_ptr].
val = cpu_to_le16(1 | (sta << 12));
......@@ -1131,7 +1148,7 @@ static void iwl5000_txq_set_sched(struct iwl_priv *priv, u32 mask)
static inline u32 iwl5000_get_scd_ssn(struct iwl5000_tx_resp *tx_resp)
{
return le32_to_cpup((__le32*)&tx_resp->status +
return le32_to_cpup((__le32 *)&tx_resp->status +
tx_resp->frame_count) & MAX_SN;
}
......@@ -1228,9 +1245,9 @@ static int iwl5000_tx_status_reply_tx(struct iwl_priv *priv,
bitmap = bitmap << sh;
sh = 0;
}
bitmap |= (1 << sh);
IWL_DEBUG_TX_REPLY("start=%d bitmap=0x%x\n",
start, (u32)(bitmap & 0xFFFFFFFF));
bitmap |= 1ULL << sh;
IWL_DEBUG_TX_REPLY("start=%d bitmap=0x%llx\n",
start, (unsigned long long)bitmap);
}
agg->bitmap = bitmap;
......@@ -1444,6 +1461,44 @@ static void iwl5000_temperature(struct iwl_priv *priv)
priv->temperature = le32_to_cpu(priv->statistics.general.temperature);
}
/* Calc max signal level (dBm) among 3 possible receivers */
static int iwl5000_calc_rssi(struct iwl_priv *priv,
struct iwl_rx_phy_res *rx_resp)
{
/* data from PHY/DSP regarding signal strength, etc.,
* contents are always there, not configurable by host
*/
struct iwl5000_non_cfg_phy *ncphy =
(struct iwl5000_non_cfg_phy *)rx_resp->non_cfg_phy_buf;
u32 val, rssi_a, rssi_b, rssi_c, max_rssi;
u8 agc;
val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_AGC_IDX]);
agc = (val & IWL50_OFDM_AGC_MSK) >> IWL50_OFDM_AGC_BIT_POS;
/* Find max rssi among 3 possible receivers.
* These values are measured by the digital signal processor (DSP).
* They should stay fairly constant even as the signal strength varies,
* if the radio's automatic gain control (AGC) is working right.
* AGC value (see below) will provide the "interesting" info.
*/
val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_RSSI_AB_IDX]);
rssi_a = (val & IWL50_OFDM_RSSI_A_MSK) >> IWL50_OFDM_RSSI_A_BIT_POS;
rssi_b = (val & IWL50_OFDM_RSSI_B_MSK) >> IWL50_OFDM_RSSI_B_BIT_POS;
val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_RSSI_C_IDX]);
rssi_c = (val & IWL50_OFDM_RSSI_C_MSK) >> IWL50_OFDM_RSSI_C_BIT_POS;
max_rssi = max_t(u32, rssi_a, rssi_b);
max_rssi = max_t(u32, max_rssi, rssi_c);
IWL_DEBUG_STATS("Rssi In A %d B %d C %d Max %d AGC dB %d\n",
rssi_a, rssi_b, rssi_c, max_rssi, agc);
/* dBm = max_rssi dB - agc dB - constant.
* Higher AGC (higher radio gain) means lower signal. */
return max_rssi - agc - IWL_RSSI_OFFSET;
}
static struct iwl_hcmd_ops iwl5000_hcmd = {
.rxon_assoc = iwl5000_send_rxon_assoc,
};
......@@ -1454,6 +1509,7 @@ static struct iwl_hcmd_utils_ops iwl5000_hcmd_utils = {
.gain_computation = iwl5000_gain_computation,
.chain_noise_reset = iwl5000_chain_noise_reset,
.rts_tx_cmd_flag = iwl5000_rts_tx_cmd_flag,
.calc_rssi = iwl5000_calc_rssi,
};
static struct iwl_lib_ops iwl5000_lib = {
......@@ -1474,6 +1530,7 @@ static struct iwl_lib_ops iwl5000_lib = {
.alive_notify = iwl5000_alive_notify,
.send_tx_power = iwl5000_send_tx_power,
.temperature = iwl5000_temperature,
.update_chain_flags = iwl4965_update_chain_flags,
.apm_ops = {
.init = iwl5000_apm_init,
.reset = iwl5000_apm_reset,
......
......@@ -24,8 +24,8 @@
*
*****************************************************************************/
#ifndef __iwl_4965_rs_h__
#define __iwl_4965_rs_h__
#ifndef __iwl_agn_rs_h__
#define __iwl_agn_rs_h__
#include "iwl-dev.h"
......@@ -88,7 +88,7 @@ enum {
#define IWL_RATE_5M_MASK (1 << IWL_RATE_5M_INDEX)
#define IWL_RATE_11M_MASK (1 << IWL_RATE_11M_INDEX)
/* 4965 uCode API values for legacy bit rates, both OFDM and CCK */
/* uCode API values for legacy bit rates, both OFDM and CCK */
enum {
IWL_RATE_6M_PLCP = 13,
IWL_RATE_9M_PLCP = 15,
......@@ -107,7 +107,7 @@ enum {
/*FIXME:RS:add IWL_RATE_LEGACY_INVM_PLCP = 0,*/
};
/* 4965 uCode API values for OFDM high-throughput (HT) bit rates */
/* uCode API values for OFDM high-throughput (HT) bit rates */
enum {
IWL_RATE_SISO_6M_PLCP = 0,
IWL_RATE_SISO_12M_PLCP = 1,
......@@ -286,15 +286,6 @@ static inline u8 iwl4965_get_prev_ieee_rate(u8 rate_index)
return rate;
}
/**
* iwl4965_fill_rs_info - Fill an output text buffer with the rate representation
*
* NOTE: This is provided as a quick mechanism for a user to visualize
* the performance of the rate control algorithm and is not meant to be
* parsed software.
*/
extern int iwl4965_fill_rs_info(struct ieee80211_hw *, char *buf, u8 sta_id);
/**
* iwl4965_rate_control_register - Register the rate control algorithm callbacks
*
......@@ -305,7 +296,7 @@ extern int iwl4965_fill_rs_info(struct ieee80211_hw *, char *buf, u8 sta_id);
* ieee80211_register_hw
*
*/
extern int iwl4965_rate_control_register(void);
extern int iwlagn_rate_control_register(void);
/**
* iwl4965_rate_control_unregister - Unregister the rate control callbacks
......@@ -313,6 +304,6 @@ extern int iwl4965_rate_control_register(void);
* This should be called after calling ieee80211_unregister_hw, but before
* the driver is unloaded.
*/
extern void iwl4965_rate_control_unregister(void);
extern void iwlagn_rate_control_unregister(void);
#endif
#endif /* __iwl_agn__rs__ */
......@@ -666,8 +666,7 @@ struct iwl4965_rxon_assoc_cmd {
__le16 reserved;
} __attribute__ ((packed));
#define IWL_CONN_MAX_LISTEN_INTERVAL 10
/*
* REPLY_RXON_TIMING = 0x14 (command, has simple generic response)
......@@ -1076,10 +1075,12 @@ struct iwl4965_rx_frame {
} __attribute__ ((packed));
/* Fixed (non-configurable) rx data from phy */
#define RX_PHY_FLAGS_ANTENNAE_OFFSET (4)
#define RX_PHY_FLAGS_ANTENNAE_MASK (0x70)
#define IWL_AGC_DB_MASK (0x3f80) /* MASK(7,13) */
#define IWL_AGC_DB_POS (7)
#define IWL49_RX_RES_PHY_CNT 14
#define IWL49_RX_PHY_FLAGS_ANTENNAE_OFFSET (4)
#define IWL49_RX_PHY_FLAGS_ANTENNAE_MASK (0x70)
#define IWL49_AGC_DB_MASK (0x3f80) /* MASK(7,13) */
#define IWL49_AGC_DB_POS (7)
struct iwl4965_rx_non_cfg_phy {
__le16 ant_selection; /* ant A bit 4, ant B bit 5, ant C bit 6 */
__le16 agc_info; /* agc code 0:6, agc dB 7:13, reserved 14:15 */
......@@ -1087,12 +1088,30 @@ struct iwl4965_rx_non_cfg_phy {
u8 pad[0];
} __attribute__ ((packed));
#define IWL50_RX_RES_PHY_CNT 8
#define IWL50_RX_RES_AGC_IDX 1
#define IWL50_RX_RES_RSSI_AB_IDX 2
#define IWL50_RX_RES_RSSI_C_IDX 3
#define IWL50_OFDM_AGC_MSK 0xfe00
#define IWL50_OFDM_AGC_BIT_POS 9
#define IWL50_OFDM_RSSI_A_MSK 0x00ff
#define IWL50_OFDM_RSSI_A_BIT_POS 0
#define IWL50_OFDM_RSSI_B_MSK 0xff0000
#define IWL50_OFDM_RSSI_B_BIT_POS 16
#define IWL50_OFDM_RSSI_C_MSK 0x00ff
#define IWL50_OFDM_RSSI_C_BIT_POS 0
struct iwl5000_non_cfg_phy {
__le32 non_cfg_phy[IWL50_RX_RES_PHY_CNT]; /* upto 8 phy entries */
} __attribute__ ((packed));
/*
* REPLY_RX = 0xc3 (response only, not a command)
* Used only for legacy (non 11n) frames.
*/
#define RX_RES_PHY_CNT 14
struct iwl4965_rx_phy_res {
struct iwl_rx_phy_res {
u8 non_cfg_phy_cnt; /* non configurable DSP phy data byte count */
u8 cfg_phy_cnt; /* configurable DSP phy data byte count */
u8 stat_id; /* configurable DSP phy data set ID */
......@@ -1101,8 +1120,7 @@ struct iwl4965_rx_phy_res {
__le32 beacon_time_stamp; /* beacon at on-air rise */
__le16 phy_flags; /* general phy flags: band, modulation, ... */
__le16 channel; /* channel number */
__le16 non_cfg_phy[RX_RES_PHY_CNT]; /* upto 14 phy entries */
__le32 reserved2;
u8 non_cfg_phy_buf[32]; /* for various implementations of non_cfg_phy */
__le32 rate_n_flags; /* RATE_MCS_* */
__le16 byte_count; /* frame's byte-count */
__le16 reserved3;
......@@ -1993,7 +2011,7 @@ struct iwl4965_spectrum_notification {
*****************************************************************************/
/**
* struct iwl4965_powertable_cmd - Power Table Command
* struct iwl_powertable_cmd - Power Table Command
* @flags: See below:
*
* POWER_TABLE_CMD = 0x77 (command, has simple generic response)
......@@ -2027,7 +2045,7 @@ struct iwl4965_spectrum_notification {
#define IWL_POWER_PCI_PM_MSK __constant_cpu_to_le16(1 << 3)
#define IWL_POWER_FAST_PD __constant_cpu_to_le16(1 << 4)
struct iwl4965_powertable_cmd {
struct iwl_powertable_cmd {
__le16 flags;
u8 keep_alive_seconds;
u8 debug_flags;
......@@ -2324,7 +2342,7 @@ struct iwl4965_beacon_notif {
/*
* REPLY_TX_BEACON = 0x91 (command, has simple generic response)
*/
struct iwl4965_tx_beacon_cmd {
struct iwl_tx_beacon_cmd {
struct iwl_tx_cmd tx;
__le16 tim_idx;
u8 tim_size;
......
......@@ -383,8 +383,8 @@ void iwl_reset_qos(struct iwl_priv *priv)
}
EXPORT_SYMBOL(iwl_reset_qos);
#define MAX_BIT_RATE_40_MHZ 0x96; /* 150 Mbps */
#define MAX_BIT_RATE_20_MHZ 0x48; /* 72 Mbps */
#define MAX_BIT_RATE_40_MHZ 0x96 /* 150 Mbps */
#define MAX_BIT_RATE_20_MHZ 0x48 /* 72 Mbps */
static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv,
struct ieee80211_ht_info *ht_info,
enum ieee80211_band band)
......@@ -815,7 +815,7 @@ int iwl_setup_mac(struct iwl_priv *priv)
{
int ret;
struct ieee80211_hw *hw = priv->hw;
hw->rate_control_algorithm = "iwl-4965-rs";
hw->rate_control_algorithm = "iwl-agn-rs";
/* Tell mac80211 our characteristics */
hw->flags = IEEE80211_HW_SIGNAL_DBM |
......@@ -827,6 +827,7 @@ int iwl_setup_mac(struct iwl_priv *priv)
hw->ampdu_queues = priv->cfg->mod_params->num_of_ampdu_queues;
hw->conf.beacon_int = 100;
hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL;
if (priv->bands[IEEE80211_BAND_2GHZ].n_channels)
priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
......
......@@ -95,6 +95,8 @@ struct iwl_hcmd_utils_ops {
void (*chain_noise_reset)(struct iwl_priv *priv);
void (*rts_tx_cmd_flag)(struct ieee80211_tx_info *info,
__le32 *tx_flags);
int (*calc_rssi)(struct iwl_priv *priv,
struct iwl_rx_phy_res *rx_resp);
};
struct iwl_lib_ops {
......@@ -139,7 +141,6 @@ struct iwl_lib_ops {
int (*set_pwr_src)(struct iwl_priv *priv, enum iwl_pwr_src src);
} apm_ops;
/* power */
int (*set_power)(struct iwl_priv *priv, void *cmd);
int (*send_tx_power) (struct iwl_priv *priv);
void (*update_chain_flags)(struct iwl_priv *priv);
void (*temperature) (struct iwl_priv *priv);
......
......@@ -104,6 +104,7 @@
* 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)
/* Bits for CSR_HW_IF_CONFIG_REG */
#define CSR49_HW_IF_CONFIG_REG_BIT_4965_R (0x00000010)
......@@ -118,7 +119,12 @@
#define CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A (0x00000000)
#define CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B (0x00001000)
#define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM (0x00200000)
#define CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A (0x00080000)
#define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM (0x00200000)
#define CSR_HW_IF_CONFIG_REG_BIT_PCI_OWN_SEM (0x00400000)
#define CSR_HW_IF_CONFIG_REG_BIT_ME_OWN (0x02000000)
#define CSR_HW_IF_CONFIG_REG_BIT_WAKE_ME (0x08000000)
/* interrupt flags in INTA, set by uCode or hardware (e.g. dma),
* acknowledged (reset) by host writing "1" to flagged bits. */
......@@ -236,6 +242,8 @@
#define CSR39_ANA_PLL_CFG_VAL (0x01000000)
#define CSR50_ANA_PLL_CFG_VAL (0x00880300)
/* HPET MEM debug */
#define CSR_DBG_HPET_MEM_REG_VAL (0xFFFF0000)
/*=== HBUS (Host-side Bus) ===*/
#define HBUS_BASE (0x400)
/*
......
......@@ -33,12 +33,12 @@
#define IWL_DEBUG(level, fmt, args...) \
do { if (priv->debug_level & (level)) \
dev_printk(KERN_ERR, &(priv->hw->wiphy->dev), "%c %s " fmt, \
in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0)
in_interrupt() ? 'I' : 'U', __func__ , ## args); } while (0)
#define IWL_DEBUG_LIMIT(level, fmt, args...) \
do { if ((priv->debug_level & (level)) && net_ratelimit()) \
dev_printk(KERN_ERR, &(priv->hw->wiphy->dev), "%c %s " fmt, \
in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0)
in_interrupt() ? 'I' : 'U', __func__ , ## args); } while (0)
#ifdef CONFIG_IWLWIFI_DEBUGFS
struct iwl_debugfs {
......
......@@ -231,7 +231,7 @@ static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
DECLARE_MAC_BUF(mac);
buf = kmalloc(bufsz, GFP_KERNEL);
if(!buf)
if (!buf)
return -ENOMEM;
pos += scnprintf(buf + pos, bufsz - pos, "num of stations: %d\n\n",
......@@ -364,16 +364,19 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
{
struct iwl_debugfs *dbgfs;
struct dentry *phyd = priv->hw->wiphy->debugfsdir;
int ret = 0;
dbgfs = kzalloc(sizeof(struct iwl_debugfs), GFP_KERNEL);
if (!dbgfs) {
ret = -ENOMEM;
goto err;
}
priv->dbgfs = dbgfs;
dbgfs->name = name;
dbgfs->dir_drv = debugfs_create_dir(name, phyd);
if (!dbgfs->dir_drv || IS_ERR(dbgfs->dir_drv)){
if (!dbgfs->dir_drv || IS_ERR(dbgfs->dir_drv)) {
ret = -ENOENT;
goto err;
}
......@@ -394,7 +397,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
err:
IWL_ERROR("Can't open the debugfs directory\n");
iwl_dbgfs_unregister(priv);
return -ENOENT;
return ret;
}
EXPORT_SYMBOL(iwl_dbgfs_register);
......@@ -404,7 +407,7 @@ EXPORT_SYMBOL(iwl_dbgfs_register);
*/
void iwl_dbgfs_unregister(struct iwl_priv *priv)
{
if (!(priv->dbgfs))
if (!priv->dbgfs)
return;
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_eeprom);
......
......@@ -36,7 +36,7 @@
#include <linux/kernel.h>
#include <net/ieee80211_radiotap.h>
#define DRV_NAME "iwl4965"
#define DRV_NAME "iwlagn"
#include "iwl-rfkill.h"
#include "iwl-eeprom.h"
#include "iwl-4965-hw.h"
......@@ -45,6 +45,7 @@
#include "iwl-debug.h"
#include "iwl-led.h"
#include "iwl-power.h"
#include "iwl-agn-rs.h"
/* configuration for the iwl4965 */
extern struct iwl_cfg iwl4965_agn_cfg;
......@@ -134,8 +135,7 @@ struct iwl_tx_info {
struct iwl_tx_queue {
struct iwl_queue q;
struct iwl_tfd_frame *bd;
struct iwl_cmd *cmd;
dma_addr_t dma_addr_cmd;
struct iwl_cmd *cmd[TFD_TX_CMD_SLOTS];
struct iwl_tx_info *txb;
int need_update;
int sched_retry;
......@@ -191,7 +191,6 @@ struct iwl4965_clip_group {
const s8 clip_powers[IWL_MAX_RATES];
};
#include "iwl-4965-rs.h"
#define IWL_TX_FIFO_AC0 0
#define IWL_TX_FIFO_AC1 1
......@@ -219,7 +218,7 @@ enum iwl_pwr_src {
struct iwl_frame {
union {
struct ieee80211_hdr frame;
struct iwl4965_tx_beacon_cmd beacon;
struct iwl_tx_beacon_cmd beacon;
u8 raw[IEEE80211_FRAME_LEN];
u8 cmd[360];
} u;
......@@ -283,10 +282,9 @@ struct iwl_cmd {
u32 val32;
struct iwl4965_bt_cmd bt;
struct iwl4965_rxon_time_cmd rxon_time;
struct iwl4965_powertable_cmd powertable;
struct iwl_powertable_cmd powertable;
struct iwl_qosparam_cmd qosparam;
struct iwl_tx_cmd tx;
struct iwl4965_tx_beacon_cmd tx_beacon;
struct iwl4965_rxon_assoc_cmd rxon_assoc;
struct iwl_rem_sta_cmd rm_sta;
u8 *indirect;
......@@ -590,6 +588,7 @@ extern unsigned int iwl4965_fill_beacon_frame(struct iwl_priv *priv,
const u8 *dest, int left);
extern void iwl4965_update_chain_flags(struct iwl_priv *priv);
int iwl4965_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src);
extern int iwl4965_set_power(struct iwl_priv *priv, void *cmd);
extern const u8 iwl_bcast_addr[ETH_ALEN];
......@@ -642,10 +641,6 @@ struct iwl_priv;
* Forward declare iwl-4965.c functions for iwl-base.c
*/
extern void iwl4965_rf_kill_ct_config(struct iwl_priv *priv);
int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw,
enum ieee80211_ampdu_mlme_action action,
const u8 *addr, u16 tid, u16 *ssn);
int iwl4965_check_empty_hw_queue(struct iwl_priv *priv, int sta_id,
u8 tid, int txq_id);
......@@ -812,14 +807,11 @@ struct iwl_chain_noise_data {
#define EEPROM_SEM_RETRY_LIMIT 1000 /* number of attempts (not time) */
#ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT
enum {
MEASUREMENT_READY = (1 << 0),
MEASUREMENT_ACTIVE = (1 << 1),
};
#endif
#define IWL_MAX_NUM_QUEUES 20 /* FIXME: do dynamic allocation */
......@@ -844,7 +836,7 @@ struct iwl_priv {
struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];
#ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT
#ifdef CONFIG_IWLAGN_SPECTRUM_MEASUREMENT
/* spectrum measurement report caching */
struct iwl4965_spectrum_notification measure_report;
u8 measurement_status;
......
......@@ -273,8 +273,7 @@ EXPORT_SYMBOL(iwl_eeprom_init);
void iwl_eeprom_free(struct iwl_priv *priv)
{
if(priv->eeprom)
kfree(priv->eeprom);
kfree(priv->eeprom);
priv->eeprom = NULL;
}
EXPORT_SYMBOL(iwl_eeprom_free);
......
......@@ -228,7 +228,7 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
* TX cmd queue. Otherwise in case the cmd comes
* in later, it will possibly set an invalid
* address (cmd->meta.source). */
qcmd = &priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_idx];
qcmd = priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_idx];
qcmd->meta.flags &= ~CMD_WANT_SKB;
}
fail:
......
......@@ -161,11 +161,31 @@ int iwl4965_led_off(struct iwl_priv *priv, int led_id)
/* Set led register off */
static int iwl4965_led_off_reg(struct iwl_priv *priv, int led_id)
{
IWL_DEBUG_LED("radio off\n");
IWL_DEBUG_LED("LED Reg off\n");
iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_OFF);
return 0;
}
/*
* Set led register in case of disassociation according to rfkill state
*/
static int iwl_led_associate(struct iwl_priv *priv, int led_id)
{
IWL_DEBUG_LED("Associated\n");
priv->allow_blinking = 1;
return iwl4965_led_on_reg(priv, led_id);
}
static int iwl_led_disassociate(struct iwl_priv *priv, int led_id)
{
priv->allow_blinking = 0;
if (iwl_is_rfkill(priv))
iwl4965_led_off_reg(priv, led_id);
else
iwl4965_led_on_reg(priv, led_id);
return 0;
}
/*
* brightness call back function for Tx/Rx LED
*/
......@@ -199,16 +219,10 @@ static void iwl_led_brightness_set(struct led_classdev *led_cdev,
led_type_str[led->type], brightness);
switch (brightness) {
case LED_FULL:
if (led->type == IWL_LED_TRG_ASSOC)
priv->allow_blinking = 1;
if (led->led_on)
led->led_on(priv, IWL_LED_LINK);
break;
case LED_OFF:
if (led->type == IWL_LED_TRG_ASSOC)
priv->allow_blinking = 0;
if (led->led_off)
led->led_off(priv, IWL_LED_LINK);
break;
......@@ -228,12 +242,12 @@ static void iwl_led_brightness_set(struct led_classdev *led_cdev,
*/
static int iwl_leds_register_led(struct iwl_priv *priv, struct iwl_led *led,
enum led_type type, u8 set_led,
const char *name, char *trigger)
char *trigger)
{
struct device *device = wiphy_dev(priv->hw->wiphy);
int ret;
led->led_dev.name = name;
led->led_dev.name = led->name;
led->led_dev.brightness_set = iwl_led_brightness_set;
led->led_dev.default_trigger = trigger;
......@@ -284,12 +298,6 @@ static int iwl_get_blink_rate(struct iwl_priv *priv)
return i;
}
static inline int is_rf_kill(struct iwl_priv *priv)
{
return test_bit(STATUS_RF_KILL_HW, &priv->status) ||
test_bit(STATUS_RF_KILL_SW, &priv->status);
}
/*
* this function called from handler. Since setting Led command can
* happen very frequent we postpone led command to be called from
......@@ -303,7 +311,7 @@ void iwl_leds_background(struct iwl_priv *priv)
priv->last_blink_time = 0;
return;
}
if (is_rf_kill(priv)) {
if (iwl_is_rfkill(priv)) {
priv->last_blink_time = 0;
return;
}
......@@ -337,7 +345,6 @@ EXPORT_SYMBOL(iwl_leds_background);
int iwl_leds_register(struct iwl_priv *priv)
{
char *trigger;
char name[32];
int ret;
priv->last_blink_rate = 0;
......@@ -346,7 +353,8 @@ int iwl_leds_register(struct iwl_priv *priv)
priv->allow_blinking = 0;
trigger = ieee80211_get_radio_led_name(priv->hw);
snprintf(name, sizeof(name), "iwl-%s:radio",
snprintf(priv->led[IWL_LED_TRG_RADIO].name,
sizeof(priv->led[IWL_LED_TRG_RADIO].name), "iwl-%s:radio",
wiphy_name(priv->hw->wiphy));
priv->led[IWL_LED_TRG_RADIO].led_on = iwl4965_led_on_reg;
......@@ -354,31 +362,33 @@ int iwl_leds_register(struct iwl_priv *priv)
priv->led[IWL_LED_TRG_RADIO].led_pattern = NULL;
ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_RADIO],
IWL_LED_TRG_RADIO, 1, name, trigger);
IWL_LED_TRG_RADIO, 1, trigger);
if (ret)
goto exit_fail;
trigger = ieee80211_get_assoc_led_name(priv->hw);
snprintf(name, sizeof(name), "iwl-%s:assoc",
snprintf(priv->led[IWL_LED_TRG_ASSOC].name,
sizeof(priv->led[IWL_LED_TRG_ASSOC].name), "iwl-%s:assoc",
wiphy_name(priv->hw->wiphy));
ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_ASSOC],
IWL_LED_TRG_ASSOC, 0, name, trigger);
IWL_LED_TRG_ASSOC, 0, trigger);
/* for assoc always turn led on */
priv->led[IWL_LED_TRG_ASSOC].led_on = iwl4965_led_on_reg;
priv->led[IWL_LED_TRG_ASSOC].led_off = iwl4965_led_on_reg;
priv->led[IWL_LED_TRG_ASSOC].led_on = iwl_led_associate;
priv->led[IWL_LED_TRG_ASSOC].led_off = iwl_led_disassociate;
priv->led[IWL_LED_TRG_ASSOC].led_pattern = NULL;
if (ret)
goto exit_fail;
trigger = ieee80211_get_rx_led_name(priv->hw);
snprintf(name, sizeof(name), "iwl-%s:RX", wiphy_name(priv->hw->wiphy));
snprintf(priv->led[IWL_LED_TRG_RX].name,
sizeof(priv->led[IWL_LED_TRG_RX].name), "iwl-%s:RX",
wiphy_name(priv->hw->wiphy));
ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_RX],
IWL_LED_TRG_RX, 0, name, trigger);
IWL_LED_TRG_RX, 0, trigger);
priv->led[IWL_LED_TRG_RX].led_on = iwl_led_associated;
priv->led[IWL_LED_TRG_RX].led_off = iwl_led_associated;
......@@ -388,9 +398,12 @@ int iwl_leds_register(struct iwl_priv *priv)
goto exit_fail;
trigger = ieee80211_get_tx_led_name(priv->hw);
snprintf(name, sizeof(name), "iwl-%s:TX", wiphy_name(priv->hw->wiphy));
snprintf(priv->led[IWL_LED_TRG_TX].name,
sizeof(priv->led[IWL_LED_TRG_TX].name), "iwl-%s:TX",
wiphy_name(priv->hw->wiphy));
ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_TX],
IWL_LED_TRG_TX, 0, name, trigger);
IWL_LED_TRG_TX, 0, trigger);
priv->led[IWL_LED_TRG_TX].led_on = iwl_led_associated;
priv->led[IWL_LED_TRG_TX].led_off = iwl_led_associated;
......
......@@ -52,6 +52,7 @@ enum led_type {
struct iwl_led {
struct iwl_priv *priv;
struct led_classdev led_dev;
char name[32];
int (*led_on) (struct iwl_priv *priv, int led_id);
int (*led_off) (struct iwl_priv *priv, int led_id);
......
......@@ -82,7 +82,7 @@
/* default power management (not Tx power) table values */
/* for tim 0-10 */
static struct iwl_power_vec_entry range_0[IWL_POWER_AC] = {
static struct iwl_power_vec_entry range_0[IWL_POWER_MAX] = {
{{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
{{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0},
{{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0},
......@@ -93,7 +93,7 @@ static struct iwl_power_vec_entry range_0[IWL_POWER_AC] = {
/* for tim = 3-10 */
static struct iwl_power_vec_entry range_1[IWL_POWER_AC] = {
static struct iwl_power_vec_entry range_1[IWL_POWER_MAX] = {
{{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
{{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},
......@@ -103,7 +103,7 @@ static struct iwl_power_vec_entry range_1[IWL_POWER_AC] = {
};
/* for tim > 11 */
static struct iwl_power_vec_entry range_2[IWL_POWER_AC] = {
static struct iwl_power_vec_entry range_2[IWL_POWER_MAX] = {
{{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
{{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},
......@@ -112,12 +112,19 @@ static struct iwl_power_vec_entry range_2[IWL_POWER_AC] = {
{{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(4, 7, 10, 10, 0xFF)}, 0}
};
/* set card power command */
static int iwl_set_power(struct iwl_priv *priv, void *cmd)
{
return iwl_send_cmd_pdu_async(priv, POWER_TABLE_CMD,
sizeof(struct iwl_powertable_cmd),
cmd, NULL);
}
/* decide the right power level according to association status
* and battery status
*/
static u16 iwl_get_auto_power_mode(struct iwl_priv *priv)
{
u16 mode = priv->power_data.user_power_setting;
u16 mode;
switch (priv->power_data.user_power_setting) {
case IWL_POWER_AUTO:
......@@ -129,12 +136,16 @@ static u16 iwl_get_auto_power_mode(struct iwl_priv *priv)
else
mode = IWL_POWER_ON_AC_DISASSOC;
break;
/* FIXME: remove battery and ac from here */
case IWL_POWER_BATTERY:
mode = IWL_POWER_INDEX_3;
break;
case IWL_POWER_AC:
mode = IWL_POWER_MODE_CAM;
break;
default:
mode = priv->power_data.user_power_setting;
break;
}
return mode;
}
......@@ -144,7 +155,7 @@ static int iwl_power_init_handle(struct iwl_priv *priv)
{
int ret = 0, i;
struct iwl_power_mgr *pow_data;
int size = sizeof(struct iwl_power_vec_entry) * IWL_POWER_AC;
int size = sizeof(struct iwl_power_vec_entry) * IWL_POWER_MAX;
u16 pci_pm;
IWL_DEBUG_POWER("Initialize power \n");
......@@ -162,11 +173,11 @@ static int iwl_power_init_handle(struct iwl_priv *priv)
if (ret != 0)
return 0;
else {
struct iwl4965_powertable_cmd *cmd;
struct iwl_powertable_cmd *cmd;
IWL_DEBUG_POWER("adjust power command flags\n");
for (i = 0; i < IWL_POWER_AC; i++) {
for (i = 0; i < IWL_POWER_MAX; i++) {
cmd = &pow_data->pwr_range_0[i].cmd;
if (pci_pm & 0x1)
......@@ -180,7 +191,7 @@ static int iwl_power_init_handle(struct iwl_priv *priv)
/* adjust power command according to dtim period and power level*/
static int iwl_update_power_command(struct iwl_priv *priv,
struct iwl4965_powertable_cmd *cmd,
struct iwl_powertable_cmd *cmd,
u16 mode)
{
int ret = 0, i;
......@@ -204,7 +215,7 @@ static int iwl_update_power_command(struct iwl_priv *priv,
range = &pow_data->pwr_range_2[0];
period = pow_data->dtim_period;
memcpy(cmd, &range[mode].cmd, sizeof(struct iwl4965_powertable_cmd));
memcpy(cmd, &range[mode].cmd, sizeof(struct iwl_powertable_cmd));
if (period == 0) {
period = 1;
......@@ -258,17 +269,18 @@ int iwl_power_update_mode(struct iwl_priv *priv, u8 refresh)
* else user level */
switch (setting->system_power_setting) {
case IWL_POWER_AUTO:
case IWL_POWER_SYS_AUTO:
final_mode = iwl_get_auto_power_mode(priv);
break;
case IWL_POWER_BATTERY:
case IWL_POWER_SYS_BATTERY:
final_mode = IWL_POWER_INDEX_3;
break;
case IWL_POWER_AC:
case IWL_POWER_SYS_AC:
final_mode = IWL_POWER_MODE_CAM;
break;
default:
final_mode = setting->system_power_setting;
final_mode = IWL_POWER_INDEX_3;
WARN_ON(1);
}
if (setting->critical_power_setting > final_mode)
......@@ -280,7 +292,7 @@ int iwl_power_update_mode(struct iwl_priv *priv, u8 refresh)
if (!iwl_is_rfkill(priv) && !setting->power_disabled &&
((setting->power_mode != final_mode) || refresh)) {
struct iwl4965_powertable_cmd cmd;
struct iwl_powertable_cmd cmd;
if (final_mode != IWL_POWER_MODE_CAM)
set_bit(STATUS_POWER_PMI, &priv->status);
......@@ -291,8 +303,7 @@ int iwl_power_update_mode(struct iwl_priv *priv, u8 refresh)
if (final_mode == IWL_POWER_INDEX_5)
cmd.flags |= IWL_POWER_FAST_PD;
if (priv->cfg->ops->lib->set_power)
ret = priv->cfg->ops->lib->set_power(priv, &cmd);
ret = iwl_set_power(priv, &cmd);
if (final_mode == IWL_POWER_MODE_CAM)
clear_bit(STATUS_POWER_PMI, &priv->status);
......@@ -388,7 +399,7 @@ void iwl_power_initialize(struct iwl_priv *priv)
iwl_power_init_handle(priv);
priv->power_data.user_power_setting = IWL_POWER_AUTO;
priv->power_data.power_disabled = 0;
priv->power_data.system_power_setting = IWL_POWER_AUTO;
priv->power_data.system_power_setting = IWL_POWER_SYS_AUTO;
priv->power_data.is_battery_active = 0;
priv->power_data.power_disabled = 0;
priv->power_data.critical_power_setting = 0;
......
......@@ -33,12 +33,25 @@
struct iwl_priv;
#define IWL_POWER_MODE_CAM 0x00 /* Continuously Aware Mode, always on */
#define IWL_POWER_INDEX_3 0x03
#define IWL_POWER_INDEX_5 0x05
#define IWL_POWER_AC 0x06
#define IWL_POWER_BATTERY 0x07
#define IWL_POWER_AUTO 0x08
enum {
IWL_POWER_MODE_CAM, /* Continuously Aware Mode, always on */
IWL_POWER_INDEX_1,
IWL_POWER_INDEX_2,
IWL_POWER_INDEX_3,
IWL_POWER_INDEX_4,
IWL_POWER_INDEX_5,
IWL_POWER_AUTO,
IWL_POWER_MAX = IWL_POWER_AUTO,
IWL_POWER_AC,
IWL_POWER_BATTERY,
};
enum {
IWL_POWER_SYS_AUTO,
IWL_POWER_SYS_AC,
IWL_POWER_SYS_BATTERY,
};
#define IWL_POWER_LIMIT 0x08
#define IWL_POWER_MASK 0x0F
#define IWL_POWER_ENABLED 0x10
......@@ -46,15 +59,15 @@ struct iwl_priv;
/* Power management (not Tx power) structures */
struct iwl_power_vec_entry {
struct iwl4965_powertable_cmd cmd;
struct iwl_powertable_cmd cmd;
u8 no_dtim;
};
struct iwl_power_mgr {
spinlock_t lock;
struct iwl_power_vec_entry pwr_range_0[IWL_POWER_AC];
struct iwl_power_vec_entry pwr_range_1[IWL_POWER_AC];
struct iwl_power_vec_entry pwr_range_2[IWL_POWER_AC];
struct iwl_power_vec_entry pwr_range_0[IWL_POWER_MAX];
struct iwl_power_vec_entry pwr_range_1[IWL_POWER_MAX];
struct iwl_power_vec_entry pwr_range_2[IWL_POWER_MAX];
u32 dtim_period;
/* final power level that used to calculate final power command */
u8 power_mode;
......
......@@ -84,14 +84,16 @@
#define APMG_CLK_VAL_DMA_CLK_RQT (0x00000200)
#define APMG_CLK_VAL_BSM_CLK_RQT (0x00000800)
#define APMG_PS_CTRL_VAL_RESET_REQ (0x04000000)
#define APMG_PCIDEV_STT_VAL_L1_ACT_DIS (0x00000800)
#define APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS (0x00400000)
#define APMG_PS_CTRL_VAL_RESET_REQ (0x04000000)
#define APMG_PS_CTRL_MSK_PWR_SRC (0x03000000)
#define APMG_PS_CTRL_VAL_PWR_SRC_VMAIN (0x00000000)
#define APMG_PS_CTRL_VAL_PWR_SRC_MAX (0x01000000) /* 3945 only */
#define APMG_PS_CTRL_VAL_PWR_SRC_VAUX (0x02000000)
#define APMG_PS_CTRL_MSK_PWR_SRC (0x03000000)
#define APMG_PS_CTRL_VAL_PWR_SRC_VMAIN (0x00000000)
#define APMG_PS_CTRL_VAL_PWR_SRC_VAUX (0x01000000)
#define APMG_PCIDEV_STT_VAL_L1_ACT_DIS (0x00000800)
/**
* BSM (Bootstrap State Machine)
......
......@@ -791,7 +791,7 @@ static inline void iwl_dbg_report_frame(struct iwl_priv *priv,
static void iwl_add_radiotap(struct iwl_priv *priv,
struct sk_buff *skb,
struct iwl4965_rx_phy_res *rx_start,
struct iwl_rx_phy_res *rx_start,
struct ieee80211_rx_status *stats,
u32 ampdu_status)
{
......@@ -1010,8 +1010,8 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,
struct ieee80211_rx_status *stats)
{
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
struct iwl4965_rx_phy_res *rx_start = (include_phy) ?
(struct iwl4965_rx_phy_res *)&(pkt->u.raw[0]) : NULL;
struct iwl_rx_phy_res *rx_start = (include_phy) ?
(struct iwl_rx_phy_res *)&(pkt->u.raw[0]) : NULL;
struct ieee80211_hdr *hdr;
u16 len;
__le32 *rx_end;
......@@ -1020,7 +1020,7 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,
u32 ampdu_status_legacy;
if (!include_phy && priv->last_phy_res[0])
rx_start = (struct iwl4965_rx_phy_res *)&priv->last_phy_res[1];
rx_start = (struct iwl_rx_phy_res *)&priv->last_phy_res[1];
if (!rx_start) {
IWL_ERROR("MPDU frame without a PHY data\n");
......@@ -1032,8 +1032,8 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,
len = le16_to_cpu(rx_start->byte_count);
rx_end = (__le32 *) ((u8 *) &pkt->u.raw[0] +
sizeof(struct iwl4965_rx_phy_res) +
rx_end = (__le32 *)((u8 *) &pkt->u.raw[0] +
sizeof(struct iwl_rx_phy_res) +
rx_start->cfg_phy_cnt + len);
} else {
......@@ -1084,40 +1084,13 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,
}
/* Calc max signal level (dBm) among 3 possible receivers */
static int iwl_calc_rssi(struct iwl_priv *priv,
struct iwl4965_rx_phy_res *rx_resp)
static inline int iwl_calc_rssi(struct iwl_priv *priv,
struct iwl_rx_phy_res *rx_resp)
{
/* data from PHY/DSP regarding signal strength, etc.,
* contents are always there, not configurable by host. */
struct iwl4965_rx_non_cfg_phy *ncphy =
(struct iwl4965_rx_non_cfg_phy *)rx_resp->non_cfg_phy;
u32 agc = (le16_to_cpu(ncphy->agc_info) & IWL_AGC_DB_MASK)
>> IWL_AGC_DB_POS;
u32 valid_antennae =
(le16_to_cpu(rx_resp->phy_flags) & RX_PHY_FLAGS_ANTENNAE_MASK)
>> RX_PHY_FLAGS_ANTENNAE_OFFSET;
u8 max_rssi = 0;
u32 i;
/* Find max rssi among 3 possible receivers.
* These values are measured by the digital signal processor (DSP).
* They should stay fairly constant even as the signal strength varies,
* if the radio's automatic gain control (AGC) is working right.
* AGC value (see below) will provide the "interesting" info. */
for (i = 0; i < 3; i++)
if (valid_antennae & (1 << i))
max_rssi = max(ncphy->rssi_info[i << 1], max_rssi);
IWL_DEBUG_STATS("Rssi In A %d B %d C %d Max %d AGC dB %d\n",
ncphy->rssi_info[0], ncphy->rssi_info[2], ncphy->rssi_info[4],
max_rssi, agc);
/* dBm = max_rssi dB - agc dB - constant.
* Higher AGC (higher radio gain) means lower signal. */
return max_rssi - agc - IWL_RSSI_OFFSET;
return priv->cfg->ops->utils->calc_rssi(priv, rx_resp);
}
static void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id)
{
unsigned long flags;
......@@ -1180,9 +1153,9 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
* this rx packet for legacy frames,
* or phy data cached from REPLY_RX_PHY_CMD for HT frames. */
int include_phy = (pkt->hdr.cmd == REPLY_RX);
struct iwl4965_rx_phy_res *rx_start = (include_phy) ?
(struct iwl4965_rx_phy_res *)&(pkt->u.raw[0]) :
(struct iwl4965_rx_phy_res *)&priv->last_phy_res[1];
struct iwl_rx_phy_res *rx_start = (include_phy) ?
(struct iwl_rx_phy_res *)&(pkt->u.raw[0]) :
(struct iwl_rx_phy_res *)&priv->last_phy_res[1];
__le32 *rx_end;
unsigned int len = 0;
u16 fc;
......@@ -1210,7 +1183,7 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
if (!include_phy) {
if (priv->last_phy_res[0])
rx_start = (struct iwl4965_rx_phy_res *)
rx_start = (struct iwl_rx_phy_res *)
&priv->last_phy_res[1];
else
rx_start = NULL;
......@@ -1227,7 +1200,7 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
len = le16_to_cpu(rx_start->byte_count);
rx_end = (__le32 *)(pkt->u.raw + rx_start->cfg_phy_cnt +
sizeof(struct iwl4965_rx_phy_res) + len);
sizeof(struct iwl_rx_phy_res) + len);
} else {
struct iwl4965_rx_mpdu_res_start *amsdu =
(struct iwl4965_rx_mpdu_res_start *)pkt->u.raw;
......@@ -1316,6 +1289,6 @@ void iwl_rx_reply_rx_phy(struct iwl_priv *priv,
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
priv->last_phy_res[0] = 1;
memcpy(&priv->last_phy_res[1], &(pkt->u.raw[0]),
sizeof(struct iwl4965_rx_phy_res));
sizeof(struct iwl_rx_phy_res));
}
EXPORT_SYMBOL(iwl_rx_reply_rx_phy);
......@@ -202,6 +202,7 @@ static int iwl_send_scan_abort(struct iwl_priv *priv)
clear_bit(STATUS_SCAN_HW, &priv->status);
}
priv->alloc_rxb_skb--;
dev_kfree_skb_any(cmd.meta.u.skb);
return ret;
......
......@@ -823,7 +823,7 @@ int iwl_send_lq_cmd(struct iwl_priv *priv,
if (lq->sta_id == 0xFF)
lq->sta_id = IWL_AP_ID;
iwl_dump_lq_cmd(priv,lq);
iwl_dump_lq_cmd(priv, lq);
if (iwl_is_associated(priv) && priv->assoc_station_added)
return iwl_send_cmd(priv, &cmd);
......@@ -839,7 +839,7 @@ EXPORT_SYMBOL(iwl_send_lq_cmd);
* for automatic fallback during transmission.
*
* NOTE: This sets up a default set of values. These will be replaced later
* if the driver's iwl-4965-rs rate scaling algorithm is used, instead of
* if the driver's iwl-agn-rs rate scaling algorithm is used, instead of
* rc80211_simple.
*
* NOTE: Run REPLY_ADD_STA command to set up station table entry, before
......
......@@ -208,11 +208,12 @@ EXPORT_SYMBOL(iwl_txq_update_write_ptr);
* Free all buffers.
* 0-fill, but do not free "txq" descriptor structure.
*/
static void iwl_tx_queue_free(struct iwl_priv *priv, struct iwl_tx_queue *txq)
static 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 len;
int i, slots_num, len;
if (q->n_bd == 0)
return;
......@@ -227,7 +228,12 @@ static void iwl_tx_queue_free(struct iwl_priv *priv, struct iwl_tx_queue *txq)
len += IWL_MAX_SCAN_SIZE;
/* De-alloc array of command/tx buffers */
pci_free_consistent(dev, len, txq->cmd, txq->dma_addr_cmd);
slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ?
TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
for (i = 0; i < slots_num; i++)
kfree(txq->cmd[i]);
if (txq_id == IWL_CMD_QUEUE_NUM)
kfree(txq->cmd[slots_num]);
/* De-alloc circular buffer of TFDs */
if (txq->q.n_bd)
......@@ -400,8 +406,7 @@ static int iwl_tx_queue_init(struct iwl_priv *priv,
struct iwl_tx_queue *txq,
int slots_num, u32 txq_id)
{
struct pci_dev *dev = priv->pci_dev;
int len;
int i, len;
int rc = 0;
/*
......@@ -412,17 +417,25 @@ static int iwl_tx_queue_init(struct iwl_priv *priv,
* For normal Tx queues (all other queues), no super-size command
* space is needed.
*/
len = sizeof(struct iwl_cmd) * slots_num;
if (txq_id == IWL_CMD_QUEUE_NUM)
len += IWL_MAX_SCAN_SIZE;
txq->cmd = pci_alloc_consistent(dev, len, &txq->dma_addr_cmd);
if (!txq->cmd)
return -ENOMEM;
len = sizeof(struct iwl_cmd);
for (i = 0; i <= slots_num; i++) {
if (i == slots_num) {
if (txq_id == IWL_CMD_QUEUE_NUM)
len += IWL_MAX_SCAN_SIZE;
else
continue;
}
txq->cmd[i] = kmalloc(len, GFP_KERNEL | GFP_DMA);
if (!txq->cmd[i])
return -ENOMEM;
}
/* Alloc driver data array and TFD circular buffer */
rc = iwl_tx_queue_alloc(priv, txq, txq_id);
if (rc) {
pci_free_consistent(dev, len, txq->cmd, txq->dma_addr_cmd);
for (i = 0; i < slots_num; i++)
kfree(txq->cmd[i]);
return -ENOMEM;
}
......@@ -451,7 +464,7 @@ void iwl_hw_txq_ctx_free(struct iwl_priv *priv)
/* Tx queues */
for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
iwl_tx_queue_free(priv, &priv->txq[txq_id]);
iwl_tx_queue_free(priv, txq_id);
/* Keep-warm buffer */
iwl_kw_free(priv);
......@@ -859,7 +872,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
txq->txb[q->write_ptr].skb[0] = skb;
/* Set up first empty entry in queue's array of Tx/cmd buffers */
out_cmd = &txq->cmd[idx];
out_cmd = txq->cmd[idx];
tx_cmd = &out_cmd->cmd.tx;
memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr));
memset(tx_cmd, 0, sizeof(struct iwl_tx_cmd));
......@@ -899,8 +912,9 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
/* Physical address of this Tx command's header (not MAC header!),
* within command buffer array. */
txcmd_phys = txq->dma_addr_cmd + sizeof(struct iwl_cmd) * idx +
offsetof(struct iwl_cmd, hdr);
txcmd_phys = pci_map_single(priv->pci_dev, out_cmd,
sizeof(struct iwl_cmd), PCI_DMA_TODEVICE);
txcmd_phys += offsetof(struct iwl_cmd, hdr);
/* Add buffer containing Tx command and MAC(!) header to TFD's
* first entry */
......@@ -1004,7 +1018,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
u32 idx;
u16 fix_size;
dma_addr_t phys_addr;
int ret;
int len, ret;
unsigned long flags;
cmd->len = priv->cfg->ops->utils->get_hcmd_size(cmd->id, cmd->len);
......@@ -1034,7 +1048,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
control_flags = (u32 *) tfd;
idx = get_cmd_index(q, q->write_ptr, cmd->meta.flags & CMD_SIZE_HUGE);
out_cmd = &txq->cmd[idx];
out_cmd = txq->cmd[idx];
out_cmd->hdr.cmd = cmd->id;
memcpy(&out_cmd->meta, &cmd->meta, sizeof(cmd->meta));
......@@ -1048,9 +1062,11 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
INDEX_TO_SEQ(q->write_ptr));
if (out_cmd->meta.flags & CMD_SIZE_HUGE)
out_cmd->hdr.sequence |= cpu_to_le16(SEQ_HUGE_FRAME);
phys_addr = txq->dma_addr_cmd + sizeof(txq->cmd[0]) * idx +
offsetof(struct iwl_cmd, hdr);
len = (idx == TFD_CMD_SLOTS) ?
IWL_MAX_SCAN_SIZE : sizeof(struct iwl_cmd);
phys_addr = pci_map_single(priv->pci_dev, out_cmd, len,
PCI_DMA_TODEVICE);
phys_addr += offsetof(struct iwl_cmd, hdr);
iwl_hw_txq_attach_buf_to_tfd(priv, tfd, phys_addr, fix_size);
IWL_DEBUG_HC("Sending command %s (#%x), seq: 0x%04X, "
......@@ -1115,6 +1131,9 @@ static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
{
struct iwl_tx_queue *txq = &priv->txq[txq_id];
struct iwl_queue *q = &txq->q;
struct iwl_tfd_frame *bd = &txq->bd[index];
dma_addr_t dma_addr;
int is_odd, buf_len;
int nfreed = 0;
if ((index >= q->n_bd) || (iwl_queue_used(q, index) == 0)) {
......@@ -1132,6 +1151,19 @@ static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
q->write_ptr, q->read_ptr);
queue_work(priv->workqueue, &priv->restart);
}
is_odd = (index/2) & 0x1;
if (is_odd) {
dma_addr = IWL_GET_BITS(bd->pa[index], tb2_addr_lo16) |
(IWL_GET_BITS(bd->pa[index],
tb2_addr_hi20) << 16);
buf_len = IWL_GET_BITS(bd->pa[index], tb2_len);
} else {
dma_addr = le32_to_cpu(bd->pa[index].tb1_addr);
buf_len = IWL_GET_BITS(bd->pa[index], tb1_len);
}
pci_unmap_single(priv->pci_dev, dma_addr, buf_len,
PCI_DMA_TODEVICE);
nfreed++;
}
}
......@@ -1163,7 +1195,7 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
BUG_ON(txq_id != IWL_CMD_QUEUE_NUM);
cmd_index = get_cmd_index(&priv->txq[IWL_CMD_QUEUE_NUM].q, index, huge);
cmd = &priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_index];
cmd = priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_index];
/* Input error checking is done when commands are added to queue. */
if (cmd->meta.flags & CMD_WANT_SKB) {
......@@ -1391,7 +1423,7 @@ static int iwl_tx_status_reply_compressed_ba(struct iwl_priv *priv,
/* For each frame attempted in aggregation,
* update driver's record of tx frame's status. */
for (i = 0; i < agg->frame_count ; i++) {
ack = bitmap & (1 << i);
ack = bitmap & (1ULL << i);
successes += !!ack;
IWL_DEBUG_TX_REPLY("%s ON i=%d idx=%d raw=%d\n",
ack? "ACK":"NACK", i, (agg->start_idx + i) & 0xff,
......
......@@ -275,10 +275,8 @@ static int iwl3945_tx_queue_alloc(struct iwl3945_priv *priv,
return 0;
error:
if (txq->txb) {
kfree(txq->txb);
txq->txb = NULL;
}
kfree(txq->txb);
txq->txb = NULL;
return -ENOMEM;
}
......@@ -365,10 +363,8 @@ void iwl3945_tx_queue_free(struct iwl3945_priv *priv, struct iwl3945_tx_queue *t
txq->q.n_bd, txq->bd, txq->q.dma_addr);
/* De-alloc array of per-TFD driver data */
if (txq->txb) {
kfree(txq->txb);
txq->txb = NULL;
}
kfree(txq->txb);
txq->txb = NULL;
/* 0-fill queue descriptor structure */
memset(txq, 0, sizeof(*txq));
......@@ -2703,9 +2699,8 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, struct sk_buff *skb)
if (!ieee80211_has_morefrags(hdr->frame_control)) {
txq->need_update = 1;
if (qc) {
if (qc)
priv->stations[sta_id].tid[tid].seq_number = seq_number;
}
} else {
wait_write_ptr = 1;
txq->need_update = 0;
......@@ -3813,7 +3808,7 @@ int iwl3945_calc_db_from_ratio(int sig_ratio)
/* 100:1 or higher, divide by 10 and use table,
* add 20 dB to make up for divide by 10 */
if (sig_ratio >= 100)
return (20 + (int)ratio2dB[sig_ratio/10]);
return 20 + (int)ratio2dB[sig_ratio/10];
/* We shouldn't see this */
if (sig_ratio < 1)
......@@ -5088,7 +5083,7 @@ static void iwl3945_dealloc_ucode_pci(struct iwl3945_priv *priv)
* iwl3945_verify_inst_full - verify runtime uCode image in card vs. host,
* looking at all data.
*/
static int iwl3945_verify_inst_full(struct iwl3945_priv *priv, __le32 * image, u32 len)
static int iwl3945_verify_inst_full(struct iwl3945_priv *priv, __le32 *image, u32 len)
{
u32 val;
u32 save_len = len;
......@@ -5237,7 +5232,7 @@ static int iwl3945_verify_bsm(struct iwl3945_priv *priv)
val = iwl3945_read_prph(priv, BSM_WR_DWCOUNT_REG);
for (reg = BSM_SRAM_LOWER_BOUND;
reg < BSM_SRAM_LOWER_BOUND + len;
reg += sizeof(u32), image ++) {
reg += sizeof(u32), image++) {
val = iwl3945_read_prph(priv, reg);
if (val != le32_to_cpu(*image)) {
IWL_ERROR("BSM uCode verification failed at "
......@@ -6336,7 +6331,7 @@ static void iwl3945_bg_post_associate(struct work_struct *data)
DECLARE_MAC_BUF(mac);
if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
IWL_ERROR("%s Should not be called in AP mode\n", __FUNCTION__);
IWL_ERROR("%s Should not be called in AP mode\n", __func__);
return;
}
......@@ -6417,7 +6412,7 @@ static void iwl3945_bg_post_associate(struct work_struct *data)
default:
IWL_ERROR("%s Should not be called in %d mode\n",
__FUNCTION__, priv->iw_mode);
__func__, priv->iw_mode);
break;
}
......@@ -6594,12 +6589,6 @@ static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
IWL_DEBUG_MAC80211("enter\n");
if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) {
IWL_DEBUG_MAC80211("leave - monitor\n");
dev_kfree_skb_any(skb);
return 0;
}
IWL_DEBUG_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len,
ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate);
......@@ -7456,7 +7445,7 @@ static ssize_t show_measurement(struct device *d,
struct iwl3945_priv *priv = dev_get_drvdata(d);
struct iwl3945_spectrum_notification measure_report;
u32 size = sizeof(measure_report), len = 0, ofs = 0;
u8 *data = (u8 *) & measure_report;
u8 *data = (u8 *)&measure_report;
unsigned long flags;
spin_lock_irqsave(&priv->lock, flags);
......@@ -7627,7 +7616,7 @@ static ssize_t show_power_level(struct device *d,
else
p += sprintf(p, " \n");
return (p - buf + 1);
return p - buf + 1;
}
......@@ -7649,7 +7638,7 @@ static ssize_t show_statistics(struct device *d,
struct iwl3945_priv *priv = dev_get_drvdata(d);
u32 size = sizeof(struct iwl3945_notif_statistics);
u32 len = 0, ofs = 0;
u8 *data = (u8 *) & priv->statistics;
u8 *data = (u8 *)&priv->statistics;
int rc = 0;
if (!iwl3945_is_alive(priv))
......@@ -8003,16 +7992,16 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
/* nic init */
iwl3945_set_bit(priv, CSR_GIO_CHICKEN_BITS,
CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
iwl3945_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
err = iwl3945_poll_bit(priv, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
if (err < 0) {
IWL_DEBUG_INFO("Failed to init the card\n");
CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
iwl3945_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
err = iwl3945_poll_bit(priv, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
if (err < 0) {
IWL_DEBUG_INFO("Failed to init the card\n");
goto out_remove_sysfs;
}
}
/* Read the EEPROM */
err = iwl3945_eeprom_init(priv);
if (err) {
......@@ -8114,9 +8103,8 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
iwl3945_unset_hw_setting(priv);
iwl3945_clear_stations_table(priv);
if (priv->mac80211_registered) {
if (priv->mac80211_registered)
ieee80211_unregister_hw(priv->hw);
}
/*netif_stop_queue(dev); */
flush_workqueue(priv->workqueue);
......
......@@ -52,6 +52,7 @@ struct p54_common {
int (*open)(struct ieee80211_hw *dev);
void (*stop)(struct ieee80211_hw *dev);
int mode;
struct mutex conf_mutex;
u8 mac_addr[ETH_ALEN];
u8 bssid[ETH_ALEN];
struct pda_iq_autocal_entry *iq_autocal;
......
......@@ -886,9 +886,12 @@ static void p54_remove_interface(struct ieee80211_hw *dev,
static int p54_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
{
int ret;
struct p54_common *priv = dev->priv;
mutex_lock(&priv->conf_mutex);
ret = p54_set_freq(dev, cpu_to_le16(conf->channel->center_freq));
p54_set_vdcf(dev);
mutex_unlock(&priv->conf_mutex);
return ret;
}
......@@ -898,10 +901,12 @@ static int p54_config_interface(struct ieee80211_hw *dev,
{
struct p54_common *priv = dev->priv;
mutex_lock(&priv->conf_mutex);
p54_set_filter(dev, 0, priv->mac_addr, conf->bssid, 0, 1, 0, 0xF642);
p54_set_filter(dev, 0, priv->mac_addr, conf->bssid, 2, 0, 0, 0);
p54_set_leds(dev, 1, !is_multicast_ether_addr(conf->bssid), 0);
memcpy(priv->bssid, conf->bssid, ETH_ALEN);
mutex_unlock(&priv->conf_mutex);
return 0;
}
......@@ -1009,6 +1014,7 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len)
}
p54_init_vdcf(dev);
mutex_init(&priv->conf_mutex);
return dev;
}
......
......@@ -633,6 +633,16 @@ static void rt2500usb_reset_tuner(struct rt2x00_dev *rt2x00dev)
rt2x00dev->link.vgc_level = value;
}
/*
* NOTE: This function is directly ported from legacy driver, but
* despite it being declared it was never called. Although link tuning
* sounds like a good idea, and usually works well for the other drivers,
* it does _not_ work with rt2500usb. Enabling this function will result
* in TX capabilities only until association kicks in. Immediately
* after the successful association all TX frames will be kept in the
* hardware queue and never transmitted.
*/
#if 0
static void rt2500usb_link_tuner(struct rt2x00_dev *rt2x00dev)
{
int rssi = rt2x00_get_link_rssi(&rt2x00dev->link);
......@@ -752,6 +762,9 @@ static void rt2500usb_link_tuner(struct rt2x00_dev *rt2x00dev)
rt2x00dev->link.vgc_level = r17;
}
}
#else
#define rt2500usb_link_tuner NULL
#endif
/*
* Initialization functions.
......@@ -1737,6 +1750,7 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)
__set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
__set_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags);
__set_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags);
__set_bit(CONFIG_DISABLE_LINK_TUNING, &rt2x00dev->flags);
/*
* Set the rssi offset.
......
......@@ -506,6 +506,19 @@ struct ieee80211_channel_sw_ie {
u8 count;
} __attribute__ ((packed));
/**
* struct ieee80211_tim
*
* This structure refers to "Traffic Indication Map information element"
*/
struct ieee80211_tim_ie {
u8 dtim_count;
u8 dtim_period;
u8 bitmap_ctrl;
/* variable size: 1 - 251 bytes */
u8 virtual_map[0];
} __attribute__ ((packed));
struct ieee80211_mgmt {
__le16 frame_control;
__le16 duration;
......
......@@ -177,9 +177,10 @@ enum ieee80211_bss_change {
* @aid: association ID number, valid only when @assoc is true
* @use_cts_prot: use CTS protection
* @use_short_preamble: use 802.11b short preamble
* @dtim_period: num of beacons before the next DTIM, for PSM
* @timestamp: beacon timestamp
* @beacon_int: beacon interval
* @assoc_capability: capabbilities taken from assoc resp
* @assoc_capability: capabilities taken from assoc resp
* @assoc_ht: association in HT mode
* @ht_conf: ht capabilities
* @ht_bss_conf: ht extended capabilities
......@@ -191,6 +192,7 @@ struct ieee80211_bss_conf {
/* erp related data */
bool use_cts_prot;
bool use_short_preamble;
u8 dtim_period;
u16 beacon_int;
u16 assoc_capability;
u64 timestamp;
......@@ -430,6 +432,7 @@ enum ieee80211_conf_flags {
* @radio_enabled: when zero, driver is required to switch off the radio.
* TODO make a flag
* @beacon_int: beacon interval (TODO make interface config)
* @listen_interval: listen interval in units of beacon interval
* @flags: configuration flags defined above
* @power_level: requested transmit power (in dBm)
* @max_antenna_gain: maximum antenna gain (in dBi)
......@@ -444,6 +447,7 @@ struct ieee80211_conf {
int radio_enabled;
int beacon_int;
u16 listen_interval;
u32 flags;
int power_level;
int max_antenna_gain;
......@@ -785,6 +789,9 @@ enum ieee80211_hw_flags {
* @max_signal: Maximum value for signal (rssi) in RX information, used
* only when @IEEE80211_HW_SIGNAL_UNSPEC or @IEEE80211_HW_SIGNAL_DB
*
* @max_listen_interval: max listen interval in units of beacon interval
* that HW supports
*
* @queues: number of available hardware transmit queues for
* data packets. WMM/QoS requires at least four, these
* queues need to have configurable access parameters.
......@@ -812,7 +819,9 @@ struct ieee80211_hw {
unsigned int extra_tx_headroom;
int channel_change_time;
int vif_data_size;
u16 queues, ampdu_queues;
u16 queues;
u16 ampdu_queues;
u16 max_listen_interval;
s8 max_signal;
};
......
......@@ -82,6 +82,7 @@ struct ieee80211_sta_bss {
u8 bssid[ETH_ALEN];
u8 ssid[IEEE80211_MAX_SSID_LEN];
u8 dtim_period;
u16 capability; /* host byte order */
enum ieee80211_band band;
int freq;
......
......@@ -1689,6 +1689,11 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
if (local->hw.conf.beacon_int < 10)
local->hw.conf.beacon_int = 100;
if (local->hw.max_listen_interval == 0)
local->hw.max_listen_interval = 1;
local->hw.conf.listen_interval = local->hw.max_listen_interval;
local->wstats_flags |= local->hw.flags & (IEEE80211_HW_SIGNAL_UNSPEC |
IEEE80211_HW_SIGNAL_DB |
IEEE80211_HW_SIGNAL_DBM) ?
......
......@@ -551,6 +551,7 @@ static void ieee80211_set_associated(struct net_device *dev,
/* set timing information */
sdata->bss_conf.beacon_int = bss->beacon_int;
sdata->bss_conf.timestamp = bss->timestamp;
sdata->bss_conf.dtim_period = bss->dtim_period;
changed |= ieee80211_handle_bss_capability(sdata, bss);
......@@ -773,7 +774,8 @@ static void ieee80211_send_assoc(struct net_device *dev,
mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
IEEE80211_STYPE_REASSOC_REQ);
mgmt->u.reassoc_req.capab_info = cpu_to_le16(capab);
mgmt->u.reassoc_req.listen_interval = cpu_to_le16(1);
mgmt->u.reassoc_req.listen_interval =
cpu_to_le16(local->hw.conf.listen_interval);
memcpy(mgmt->u.reassoc_req.current_ap, ifsta->prev_bssid,
ETH_ALEN);
} else {
......@@ -781,7 +783,8 @@ static void ieee80211_send_assoc(struct net_device *dev,
mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
IEEE80211_STYPE_ASSOC_REQ);
mgmt->u.assoc_req.capab_info = cpu_to_le16(capab);
mgmt->u.assoc_req.listen_interval = cpu_to_le16(1);
mgmt->u.reassoc_req.listen_interval =
cpu_to_le16(local->hw.conf.listen_interval);
}
/* SSID */
......@@ -2688,6 +2691,16 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int);
bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info);
if (elems->tim) {
struct ieee80211_tim_ie *tim_ie =
(struct ieee80211_tim_ie *)elems->tim;
bss->dtim_period = tim_ie->dtim_period;
}
/* set default value for buggy APs */
if (!elems->tim || bss->dtim_period == 0)
bss->dtim_period = 1;
bss->supp_rates_len = 0;
if (elems->supp_rates) {
clen = IEEE80211_MAX_SUPP_RATES - bss->supp_rates_len;
......@@ -3650,11 +3663,21 @@ static int ieee80211_sta_find_ibss(struct net_device *dev,
"%s\n", print_mac(mac, bssid),
print_mac(mac2, ifsta->bssid));
#endif /* CONFIG_MAC80211_IBSS_DEBUG */
if (found && memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0 &&
(bss = ieee80211_rx_bss_get(dev, bssid,
local->hw.conf.channel->center_freq,
ifsta->ssid, ifsta->ssid_len))) {
if (found && memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0) {
int ret;
int search_freq;
if (ifsta->flags & IEEE80211_STA_AUTO_CHANNEL_SEL)
search_freq = bss->freq;
else
search_freq = local->hw.conf.channel->center_freq;
bss = ieee80211_rx_bss_get(dev, bssid, search_freq,
ifsta->ssid, ifsta->ssid_len);
if (!bss)
goto dont_join;
printk(KERN_DEBUG "%s: Selected IBSS BSSID %s"
" based on configured SSID\n",
dev->name, print_mac(mac, bssid));
......@@ -3662,6 +3685,8 @@ static int ieee80211_sta_find_ibss(struct net_device *dev,
ieee80211_rx_bss_put(local, bss);
return ret;
}
dont_join:
#ifdef CONFIG_MAC80211_IBSS_DEBUG
printk(KERN_DEBUG " did not try to join ibss\n");
#endif /* CONFIG_MAC80211_IBSS_DEBUG */
......@@ -3895,7 +3920,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw)
if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
struct ieee80211_if_sta *ifsta = &sdata->u.sta;
if (!(ifsta->flags & IEEE80211_STA_BSSID_SET) ||
(!ifsta->state == IEEE80211_IBSS_JOINED &&
(!(ifsta->state == IEEE80211_IBSS_JOINED) &&
!ieee80211_sta_active_ibss(dev)))
ieee80211_sta_find_ibss(dev, ifsta);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment