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